source: trunk/src/win32k/elf2lx/elfdumper.cpp@ 10367

Last change on this file since 10367 was 4787, checked in by bird, 25 years ago

Changed email address... (may some dll fixes changes too.)

File size: 32.7 KB
Line 
1/* $Id: elfdumper.cpp,v 1.3 2000-12-11 06:53:49 bird Exp $
2 *
3 * ELF dumper utility
4 *
5 * Copyright (c) 1999-2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants And Macros *
13*******************************************************************************/
14#define TRUE 1
15#define FALSE 0
16
17#define PRINTCASE(Level,Value) \
18 case Value: printData(Level, #Value); break
19
20#define PRINTFLAG(Flags,Flag) \
21 if (((Flags) & (Flag)) == (Flag)) \
22 printData(#Flag " ")
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <stdarg.h>
31#include <assert.h>
32
33#include "elf.h"
34
35/*******************************************************************************
36* Structures and Typedefs *
37*******************************************************************************/
38typedef unsigned long BOOL;
39typedef struct
40{
41 BOOL fdummy;
42} OPTIONS, *POPTIONS;
43
44/*******************************************************************************
45* Global Variables *
46*******************************************************************************/
47BOOL fPrintLongData = FALSE;
48BOOL fPrintLongDataIndented = FALSE;
49int iPrintLongDataIndentLevel = -1;
50
51/*******************************************************************************
52* Internal Functions *
53*******************************************************************************/
54static BOOL read(FILE *phFile, void *pv, unsigned long cb, unsigned long off);
55static void syntax(void);
56void * loadELFImage(FILE *phFile);
57int dumpELFImage(void *pv);
58int dumpELFHdr(Elf32_Ehdr *pHdr32);
59
60int dumpELFSectionHeader(Elf32_Ehdr * pHdr32, int iShdr);
61int dumpELFSectionHeaderTable(Elf32_Ehdr * pHdr32);
62char * getELFSectionNameStringTable(Elf32_Ehdr * pHdr32);
63int dumpELFSymbolTable(Elf32_Ehdr * pHdr32, Elf32_Shdr * pShdr);
64int dumpELFRelcations(Elf32_Ehdr * pHdr32, Elf32_Shdr * pShdr);
65int dumpELFRelcationsA(Elf32_Ehdr * pHdr32, Elf32_Shdr * pShdr);
66
67int dumpELFProgramHeader(Elf32_Ehdr * pHdr32, int iPhdr);
68int dumpELFProgramHeaderTable(Elf32_Ehdr * pHdr32);
69int dumpELFDynamicSegment(Elf32_Ehdr * pHdr32, Elf32_Phdr * pPhdr);
70int getELFDynmaicTagValue(Elf32_Dyn *pDyn, Elf32_Sword tag, Elf32_Word *pword);
71int dumpELFInterpreterSegment(Elf32_Ehdr * pHdr32, Elf32_Phdr * pPhdr);
72int dumpELFNoteSegment(Elf32_Ehdr * pHdr32, Elf32_Phdr * pPhdr);
73
74
75
76/* output helpers */
77void printHeader(char *pszHeader);
78void print(int iIndentLevel, char *pszName, char *pszDataFormat, ...);
79void print(int iIndentLevel, char *pszText);
80void printBeginLongData(int iIndentLevel);
81void printEndLongData(void);
82void printData(char *pszDataFormat, ...);
83void printData(int iIndentLevel, char *pszDataFormat, ...);
84int printGetIndentData(int iIndentLevel);
85int printGetIndent(int iIndentLevel);
86void printerr(const char *pszMsg, ...);
87
88
89/**
90 * Main function.
91 * @returns Number of signals.
92 * @param argc Argument count.
93 * @param argv Argument array.
94 */
95int main(int argc, char **argv)
96{
97 OPTIONS options = {TRUE};
98 BOOL fFatal = FALSE;
99 int iRc = 0;
100 int argi;
101
102 /**************************************************************************
103 * parse arguments.
104 * options: -h or -? Syntax help.
105 **************************************************************************/
106 argi = 1;
107 while (argi < argc && !fFatal)
108 {
109 if(argv[argi][0] == '-' || argv[argi][0] == '/')
110 {
111 switch (argv[argi][1])
112 {
113 case 'h':
114 case 'H':
115 case '?':
116 syntax();
117 return 0;
118
119 default:
120 printerr("incorrect parameter. (argi=%d, argv[argi]=%s)", argi, argv[argi]);
121 fFatal = TRUE;
122 break;
123 }
124 }
125 else
126 {
127 FILE *phFile;
128
129 phFile = fopen(argv[argi], "rb");
130 if (phFile != NULL)
131 {
132 void *pv = loadELFImage(phFile);
133 if (pv != NULL)
134 {
135 dumpELFImage(pv);
136 free(pv);
137 }
138 fclose(phFile);
139 }
140 else
141 {
142 printerr("failed to open file '%s'.", argv[argi]);
143 iRc++;
144 }
145 }
146 argi++;
147 }
148 return iRc;
149}
150
151
152static void syntax(void)
153{
154 printf("\n"
155 "ELFDumper v0.0.0 - \"Not Implemented\"\n"
156 "------------------------------------\n"
157 "syntax: ELFDumper.exe [-?] <files to dump>\n"
158 );
159}
160
161
162/**
163 * Loads an ELF image into memory for dumping.
164 * @returns Pointer to ELF image.
165 * @param phFile File handle to the ELF image file.
166 * @author knut st. osmundsen
167 */
168void * loadELFImage(FILE *phFile)
169{
170 size_t cbFile;
171
172 fseek(phFile, 0, SEEK_END);
173 cbFile = (size_t)ftell(phFile);
174
175 if (cbFile > sizeof(Elf32_Ehdr))
176 {
177 void *pv = malloc(cbFile);
178 if (pv != NULL)
179 {
180 if (read(phFile, pv, cbFile, 0))
181 {
182 return pv;
183 }
184 else
185 printerr("failed to read file.");
186 free(pv);
187 }
188 else
189 printerr("failed to allocate memory!. (%d bytes)", cbFile);
190 }
191 else
192 printerr("file is less than the size of the elf header! (%d)", cbFile);
193 return NULL;
194}
195
196
197/**
198 * Dumps the loaded ELF image.
199 * @returns Error code. (0 is success)
200 * @param pv Pointer to the base of the ...
201 * @author knut st. osmundsen
202 */
203int dumpELFImage(void *pv)
204{
205 Elf32_Ehdr *pHdr32 = (Elf32_Ehdr *)pv;
206 int rc = 0;
207
208 if (*(unsigned long *)pv == ELFMAGICLSB)
209 {
210 rc = dumpELFHdr(pHdr32);
211 if (rc == 0)
212 rc = dumpELFSectionHeaderTable(pHdr32);
213 if (rc == 0)
214 rc = dumpELFProgramHeaderTable(pHdr32);
215 }
216 else
217 {
218 printerr("no ELF signature was found");
219 rc = -1;
220 }
221 return rc;
222}
223
224
225/**
226 * Dumps the ELF header.
227 * @returns 0 on success, errorcode on error (-1).
228 * @param pHdr32 Pointer to the ELF32 header to dump.
229 * @author knut st. osmundsen
230 */
231int dumpELFHdr(Elf32_Ehdr *pHdr32)
232{
233 int i;
234 int iRc = 0;
235 printHeader("ELF Header");
236 printBeginLongData(0);
237 print(0, "e_ident");
238
239 for (i = 0; i < EI_INDENT; i++)
240 printData(i > 0 && i <= 3 ? "%c " : "%02x ", pHdr32->e_ident[i]);
241 printEndLongData();
242
243 for (i = 0; i < EI_INDENT; i++)
244 {
245 switch (i)
246 {
247 case EI_CLASS:
248 switch (pHdr32->e_ident[i])
249 {
250 PRINTCASE(0,ELFCLASS32);
251 case ELFCLASS64:
252 printData(0, "ELFCLASS64");
253 printerr("class not supported");
254 iRc = -1;
255 break;
256 case ELFCLASSNUM:
257 printData(0, "ELFCLASSNUM");
258 printerr("class not supported");
259 iRc = -1;
260 break;
261
262 default:
263 printData(0, "Invalid class 0x%02x", pHdr32->e_ident[i]);
264 printerr("class not supported");
265 iRc = -1;
266 }
267 break;
268 case EI_DATA:
269 switch (pHdr32->e_ident[i])
270 {
271 PRINTCASE(0,ELFDATA2LSB);
272 case ELFDATA2MSB:
273 printData(0, "ELFDATA2MSB");
274 printerr("Data encoding not supported");
275 iRc = -1;
276 break;
277 default:
278 printData(0, "Invalid data encoding 0x%02x", pHdr32->e_ident[i]);
279 printerr("Data encoding not supported");
280 iRc = -1;
281 }
282 break;
283 case EI_VERSION:
284 switch (pHdr32->e_ident[i])
285 {
286 PRINTCASE(0,EV_CURRENT);
287 PRINTCASE(0,EV_NUM);
288 default:
289 printData(0, "Unknown ELF version 0x%02x", pHdr32->e_ident[i]);
290 iRc = -1;
291 }
292 break;
293 }
294 }
295
296 if (iRc == 0)
297 {
298 print(0, "e_type", "0x%04x", pHdr32->e_type);
299 switch (pHdr32->e_type)
300 {
301 PRINTCASE(1,ET_NONE);
302 PRINTCASE(1,ET_REL);
303 PRINTCASE(1,ET_EXEC);
304 PRINTCASE(1,ET_DYN);
305 PRINTCASE(1,ET_CORE);
306 //default:
307 }
308 print(0, "e_machine", "0x%04x", pHdr32->e_machine);
309 switch (pHdr32->e_machine)
310 {
311 PRINTCASE(1,EM_NONE);
312 PRINTCASE(1,EM_M32);
313 PRINTCASE(1,EM_SPARC);
314 PRINTCASE(1,EM_386);
315 PRINTCASE(1,EM_68K);
316 PRINTCASE(1,EM_88K);
317 PRINTCASE(1,EM_486);
318 PRINTCASE(1,EM_860);
319 PRINTCASE(1,EM_MIPS);
320 PRINTCASE(1,EM_MIPS_RS4_BE);
321 PRINTCASE(1,EM_SPARC64);
322 PRINTCASE(1,EM_PARISC);
323 PRINTCASE(1,EM_SPARC32PLUS);
324 PRINTCASE(1,EM_PPC);
325 PRINTCASE(1,EM_ALPHA);
326 //default:
327 }
328 print(0, "e_version", "%d (%s)", pHdr32->e_version,
329 pHdr32->e_version == EV_CURRENT ? "EV_CURRENT"
330 : pHdr32->e_version == EV_NUM ? "EV_NUM" : "unknown/invalid");
331 print(0, "e_entry", "0x%08x", pHdr32->e_entry);
332 print(0, "e_phoff", "0x%08x", pHdr32->e_phoff);
333 print(0, "e_shoff", "0x%08x", pHdr32->e_shoff);
334 print(0, "e_flags", "0x%08x", pHdr32->e_flags);
335 print(0, "e_ehsize", "%d (Current=%d)", pHdr32->e_ehsize, sizeof(Elf32_Ehdr));
336 print(0, "e_phentsize", "%d (Current=%d)", pHdr32->e_phentsize, -1/* sizeof(Elf32_Phdr)*/);
337 print(0, "e_phnum", "0x%04x", pHdr32->e_phnum);
338 print(0, "e_shentsize", "%d (Current=%d)", pHdr32->e_shentsize, sizeof(Elf32_Shdr));
339 print(0, "e_shnum", "0x%04x", pHdr32->e_shnum);
340 print(0, "e_shstrndx", "0x%04x", pHdr32->e_shstrndx);
341 }
342
343 return iRc;
344}
345
346
347
348/**
349 * Dumps the section header table of an ELF image.
350 * @returns 0 on success. Errorcode on error (-1).
351 * @param pHdr32 Pointer to the image.
352 * @author knut st. osmundsen
353 */
354int dumpELFSectionHeaderTable(Elf32_Ehdr * pHdr32)
355{
356 int i;
357 int rc = 0;
358
359 printHeader("Section Header Table");
360
361 for (i = 0; i < pHdr32->e_shnum && rc == 0; i++)
362 {
363 if (i > 0)
364 print(0,"");
365 rc = dumpELFSectionHeader(pHdr32, i);
366 }
367 return rc;
368}
369
370
371/**
372 * Dumps the section header table of an ELF image.
373 * @returns 0 on success. Errorcode on error (-1).
374 * @param pHdr32 Pointer to the image.
375 * @param iShdr Section number.
376 * @author knut st. osmundsen
377 */
378int dumpELFSectionHeader(Elf32_Ehdr * pHdr32, int iShdr)
379{
380 Elf32_Shdr * pShdr = (Elf32_Shdr*)((unsigned)pHdr32 + pHdr32->e_shoff + pHdr32->e_shentsize*iShdr);
381 char * paszStrings = getELFSectionNameStringTable(pHdr32);
382 print(0, "Section Header", "no. %d offset 0x%08x", iShdr, (unsigned)pShdr - (unsigned)pHdr32);
383 if (paszStrings != NULL && pShdr->sh_name != 0)
384 print(1, "sh_name", "%s (0x%01x)", paszStrings + pShdr->sh_name, pShdr->sh_name);
385 else
386 print(1, "sh_name", "0x%08x", pShdr->sh_name);
387 print(1, "sh_type", "0x%08x", pShdr->sh_type);
388 switch (pShdr->sh_type)
389 {
390 PRINTCASE(1,SHT_NULL);
391 PRINTCASE(1,SHT_PROGBITS);
392 PRINTCASE(1,SHT_SYMTAB);
393 PRINTCASE(1,SHT_STRTAB);
394 PRINTCASE(1,SHT_RELA);
395 PRINTCASE(1,SHT_HASH);
396 PRINTCASE(1,SHT_DYNAMIC);
397 PRINTCASE(1,SHT_NOTE);
398 PRINTCASE(1,SHT_NOBITS);
399 PRINTCASE(1,SHT_REL);
400 PRINTCASE(1,SHT_SHLIB);
401 PRINTCASE(1,SHT_DYNSYM);
402 PRINTCASE(1,SHT_NUM);
403 default:
404 if (pShdr->sh_type >= SHT_LOPROC && pShdr->sh_type <= SHT_HIPROC)
405 printData(1, "Processor-specific");
406 else if (pShdr->sh_type >= SHT_LOUSER && pShdr->sh_type <= SHT_HIUSER)
407 printData(1, "Application program specific");
408 else
409 printData(1, "unknown");
410 }
411 print(1, "sh_flags", "0x%08x", pShdr->sh_flags);
412 printBeginLongData(1);
413 PRINTFLAG(pShdr->sh_flags,SHF_WRITE);
414 PRINTFLAG(pShdr->sh_flags,SHF_ALLOC);
415 PRINTFLAG(pShdr->sh_flags,SHF_EXECINSTR);
416 if (pShdr->sh_flags & SHF_MASKPROC)
417 printData("SHF_MASKPROC");
418 printEndLongData();
419 print(1, "sh_addr", "0x%08x", pShdr->sh_addr);
420 print(1, "sh_offset", "0x%08x", pShdr->sh_offset);
421 print(1, "sh_size", "0x%08x", pShdr->sh_size);
422 print(1, "sh_link", "0x%08x", pShdr->sh_link);
423 print(1, "sh_info", "0x%08x", pShdr->sh_info);
424 print(1, "sh_addralign", "0x%08x", pShdr->sh_addralign);
425 print(1, "sh_entsize", "0x%08x", pShdr->sh_entsize);
426
427 /* process evt. known contents. */
428 switch (pShdr->sh_type)
429 {
430 case SHT_SYMTAB:
431 case SHT_DYNSYM:
432 dumpELFSymbolTable(pHdr32, pShdr);
433 break;
434 case SHT_REL:
435 dumpELFRelcations(pHdr32, pShdr);
436 break;
437 case SHT_RELA:
438 break;
439 case SHT_HASH:
440 break;
441 case SHT_NOTE:
442 break;
443 }
444
445 return 0;
446}
447
448
449/**
450 * Gets the Section Name String Table.
451 * @returns Pointer to the string table.
452 * @param pHdr32 Pointer to the image.
453 * @author knut st. osmundsen
454 */
455char *getELFSectionNameStringTable(Elf32_Ehdr * pHdr32)
456{
457 if (pHdr32->e_shstrndx != SHN_UNDEF)
458 {
459 Elf32_Shdr * pShdr = (Elf32_Shdr*)((unsigned)pHdr32 + pHdr32->e_shoff + pHdr32->e_shentsize * pHdr32->e_shstrndx);
460 return (char*)((unsigned)pHdr32 + pShdr->sh_offset);
461 }
462 return NULL;
463}
464
465
466/**
467 * Dumps a symboltable.
468 * @returns 0 on success. Errorcode on error.
469 * @param pHdr32 Pointer to the image.
470 * @param pShdr Pointer to the section containing the symboltable.
471 * @author knut st. osmundsen
472 */
473int dumpELFSymbolTable(Elf32_Ehdr * pHdr32, Elf32_Shdr * pShdr)
474{
475 Elf32_Shdr * pShdrStr = (Elf32_Shdr*)((unsigned)pHdr32 + pHdr32->e_shoff + pHdr32->e_shentsize*pShdr->sh_link);
476 Elf32_Sym * pSym = (Elf32_Sym*)((unsigned)pHdr32 + pShdr->sh_offset);
477 unsigned off = 0;
478 char * paszStrings = (char *)((unsigned)pHdr32 + pShdrStr->sh_offset);
479
480 /* Fixme?: sh_info - One greater than the symbol table index of the last local symbol (binding STB_LOCAL). */
481
482 print(2, "Symbol table:");
483 while (off < pShdr->sh_size)
484 {
485 flushall();
486 print(2, "st_name", "%s", paszStrings + pSym->st_name);
487 print(3, "st_value", "0x%08x", pSym->st_value);
488 print(3, "st_size", "%d", pSym->st_size);
489 printBeginLongData(3);
490 print(3, "st_info", "0x%02x", pSym->st_info);
491 printData(" ");
492 switch (ELF32_ST_BIND(pSym->st_info))
493 {
494 PRINTCASE(3,STB_LOCAL);
495 PRINTCASE(3,STB_GLOBAL);
496 PRINTCASE(3,STB_WEAK);
497 default:
498 printData("unknown binding");
499 }
500 printData(" ");
501 switch (ELF32_ST_TYPE(pSym->st_info))
502 {
503 PRINTCASE(3,STT_NOTYPE);
504 PRINTCASE(3,STT_OBJECT);
505 PRINTCASE(3,STT_FUNC);
506 PRINTCASE(3,STT_SECTION);
507 PRINTCASE(3,STT_FILE);
508 default:
509 printData("unknown type");
510 }
511 printEndLongData();
512 print(3, "st_other", "0x%02x", pSym->st_other);
513 print(3, "st_shndx", "0x%04x", pSym->st_shndx);
514
515 /* next */
516 pSym = (Elf32_Sym*)((unsigned)pSym + pShdr->sh_entsize);
517 off += pShdr->sh_entsize;
518 }
519 return 0;
520}
521
522
523int dumpELFRelcations(Elf32_Ehdr * pHdr32, Elf32_Shdr * pShdr)
524{
525 Elf32_Rel * pRel = (Elf32_Rel*)((unsigned)pHdr32 + pShdr->sh_offset);
526 unsigned off = 0;
527
528 while (off < pShdr->sh_size)
529 {
530 printBeginLongData(2);
531 print(2, "Relocation", "off=0x%08x type=", pRel->r_offset);
532 switch (ELF32_R_TYPE(pRel->r_info))
533 {
534 PRINTCASE(2,R_386_NONE);
535 PRINTCASE(2,R_386_32);
536 PRINTCASE(2,R_386_PC32);
537 PRINTCASE(2,R_386_GOT32);
538 PRINTCASE(2,R_386_PLT32);
539 PRINTCASE(2,R_386_COPY);
540 PRINTCASE(2,R_386_GLOB_DAT);
541 PRINTCASE(2,R_386_JMP_SLOT);
542 PRINTCASE(2,R_386_RELATIVE);
543 PRINTCASE(2,R_386_GOT_OFF);
544 PRINTCASE(2,R_386_GOTPC);
545 default:
546 printData("<unknown type>");
547 }
548 if (ELF32_R_SYM(pRel->r_info) != STN_UNDEF)
549 printData(" sym=STN_UNDEF");
550 else
551 printData(" sym=0x%08x", ELF32_R_SYM(pRel->r_info));
552 printEndLongData();
553
554 /* next */
555 pRel = (Elf32_Rel*)((unsigned)pRel + pShdr->sh_entsize);
556 off += pShdr->sh_entsize;
557 }
558 return 0;
559}
560
561int dumpELFRelcationsA(Elf32_Ehdr * pHdr32, Elf32_Shdr * pShdr)
562{
563 Elf32_Rela * pRela = (Elf32_Rela*)((unsigned)pHdr32 + pShdr->sh_offset);
564 unsigned off = 0;
565
566 while (off < pShdr->sh_size)
567 {
568 printBeginLongData(2);
569 print(2, "Relocation+Addend", "off=0x%08x type=", pRela->r_offset);
570 switch (ELF32_R_TYPE(pRela->r_info))
571 {
572 PRINTCASE(2,R_386_NONE);
573 PRINTCASE(2,R_386_32);
574 PRINTCASE(2,R_386_PC32);
575 PRINTCASE(2,R_386_GOT32);
576 PRINTCASE(2,R_386_PLT32);
577 PRINTCASE(2,R_386_COPY);
578 PRINTCASE(2,R_386_GLOB_DAT);
579 PRINTCASE(2,R_386_JMP_SLOT);
580 PRINTCASE(2,R_386_RELATIVE);
581 PRINTCASE(2,R_386_GOT_OFF);
582 PRINTCASE(2,R_386_GOTPC);
583 default:
584 printData("<unknown type>");
585 }
586 if (ELF32_R_SYM(pRela->r_info) != STN_UNDEF)
587 printData(" sym=STN_UNDEF");
588 else
589 printData(" sym=0x%08x", ELF32_R_SYM(pRela->r_info));
590 printData(" add=0x%08x", pRela->r_addend);
591 printEndLongData();
592
593 /* next */
594 pRela = (Elf32_Rela*)((unsigned)pRela + pShdr->sh_entsize);
595 off += pShdr->sh_entsize;
596 }
597 return 0;
598}
599
600
601/**
602 * Dumps the program header tables.
603 * @returns 0 on success. Errorcode on error (-1).
604 * @param pHdr32 Pointer to the image.
605 * @author knut st. osmundsen
606 */
607int dumpELFProgramHeaderTable(Elf32_Ehdr * pHdr32)
608{
609 int i;
610 int rc = 0;
611
612 printHeader("Program Header Table");
613
614 for (i = 0; i < pHdr32->e_phnum && rc == 0; i++)
615 {
616 if (i > 0)
617 print(0,"");
618 rc = dumpELFProgramHeader(pHdr32, i);
619 }
620 return rc;
621}
622
623
624/**
625 * Dumps a program header of an ELF image.
626 * @returns 0 on success. Errorcode on error (-1).
627 * @param pHdr32 Pointer to the image.
628 * @param iPhdr Program header number.
629 * @author knut st. osmundsen
630 */
631int dumpELFProgramHeader(Elf32_Ehdr * pHdr32, int iPhdr)
632{
633 Elf32_Phdr * pPhdr = (Elf32_Phdr*)((unsigned)pHdr32 + pHdr32->e_phoff + pHdr32->e_phentsize*iPhdr);
634
635
636 print(0, "Program Header", "no. %d offset 0x%08x", iPhdr, (unsigned)pPhdr - (unsigned)pHdr32);
637
638 print(1, "p_type", "0x%08x", pPhdr->p_type);
639 switch (pPhdr->p_type)
640 {
641 PRINTCASE(1,PT_NULL );
642 PRINTCASE(1,PT_LOAD );
643 PRINTCASE(1,PT_DYNAMIC);
644 PRINTCASE(1,PT_INTERP );
645 PRINTCASE(1,PT_NOTE );
646 PRINTCASE(1,PT_SHLIB );
647 PRINTCASE(1,PT_PHDR );
648 default:
649 if (pPhdr->p_type >= PT_LOPROC && pPhdr->p_type <= PT_HIPROC)
650 printData(1, "Processor-specific");
651 else
652 printData(1, "unknown");
653 }
654 print(1, "p_offset", "0x%08x", pPhdr->p_offset);
655 print(1, "p_vaddr", "0x%08x", pPhdr->p_vaddr);
656 print(1, "p_paddr", "0x%08x", pPhdr->p_paddr);
657 print(1, "p_filesz", "0x%08x", pPhdr->p_filesz);
658 print(1, "p_memsz", "0x%08x", pPhdr->p_memsz);
659 print(1, "p_flags", "0x%08x", pPhdr->p_flags);
660 printBeginLongData(1);
661 PRINTFLAG(pPhdr->p_flags, PF_X);
662 PRINTFLAG(pPhdr->p_flags, PF_W);
663 PRINTFLAG(pPhdr->p_flags, PF_R);
664 printEndLongData();
665 print(1, "p_align", "0x%08x", pPhdr->p_align);
666 printBeginLongData(1);
667 if (pPhdr->p_align &&
668 (pPhdr->p_vaddr % pPhdr->p_align != pPhdr->p_offset % pPhdr->p_align))
669 printData(1, "alignment error?");
670 printEndLongData();
671
672
673 switch (pPhdr->p_type)
674 {
675 case PT_DYNAMIC:
676 dumpELFDynamicSegment(pHdr32, pPhdr);
677 break;
678
679 case PT_INTERP:
680 dumpELFInterpreterSegment(pHdr32, pPhdr);
681 break;
682
683 case PT_NOTE:
684 dumpELFNoteSegment(pHdr32, pPhdr);
685 break;
686 }
687 return 0;
688}
689
690
691/**
692 * Dumps a dynamic segment.
693 * @returns 0 on success.
694 * @param pHdr32 Pointer to ELF header (and base of the loaded file).
695 * @param pPhdr Pointer to program header.
696 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
697 */
698int dumpELFDynamicSegment(Elf32_Ehdr * pHdr32, Elf32_Phdr * pPhdr)
699{
700 Elf32_Word word;
701 Elf32_Addr base;
702 int i;
703 Elf32_Dyn * pDyn = (Elf32_Dyn*) ((unsigned)pHdr32 + pPhdr->p_offset);
704 Elf32_Phdr * pPhdrs = (Elf32_Phdr*)((unsigned)pHdr32 + pHdr32->e_phoff);
705 char * paszStrings;
706
707 /* find base address */
708 i = 0;
709 while (i < pHdr32->e_phnum && pPhdrs->p_type != PT_LOAD)
710 {
711 i++;
712 pPhdrs = (Elf32_Phdr*)((unsigned)pPhdrs + pHdr32->e_phentsize);
713 }
714 if (i < pHdr32->e_phnum)
715 base = pPhdrs->p_vaddr;
716
717 /* find string table */
718 if (getELFDynmaicTagValue(pDyn, DT_STRTAB, &word) == 0)
719 paszStrings = (char*)(word - base + (int)pHdr32);
720 else
721 paszStrings = NULL; /* no string table - funny! */
722
723 /*
724 * Loop thru the entries.
725 */
726 i = 0;
727 while (pDyn[i].d_tag != DT_NULL)
728 {
729 switch (pDyn[i].d_tag)
730 {
731 case DT_NULL: /* - - - Marks the end of the dynamic array. */
732 break;
733 case DT_NEEDED: /* d_val * * Holds the string table offset of a null-terminated
734 string, giving the name of a needed library. The
735 offset is an index into the table recoreded in the
736 DT_STRTAB entry. */
737 print(2, "DT_NEEDED", "0x%08x", pDyn[i].d_un.d_val);
738 if (paszStrings != NULL)
739 printData(2, "%s", paszStrings + pDyn[i].d_un.d_val);
740 else
741 printData(2, "(no string table)");
742 break;
743
744 case DT_PLTRELSZ:
745 print(2, "DT_PLTRELSZ", "0x%08x", pDyn[i].d_un.d_val);
746 break;
747
748 case DT_PLTGOT:
749 print(2, "DT_PLTGOT", "0x%08x", pDyn[i].d_un.d_val);
750 break;
751 case DT_HASH:
752 print(2, "DT_HASH", "0x%08x", pDyn[i].d_un.d_val);
753 break;
754 case DT_STRTAB:
755 print(2, "DT_STRTAB", "0x%08x", pDyn[i].d_un.d_val);
756 break;
757 case DT_SYMTAB:
758 print(2, "DT_SYMTAB", "0x%08x", pDyn[i].d_un.d_val);
759 break;
760 case DT_RELA:
761 print(2, "DT_RELA", "0x%08x", pDyn[i].d_un.d_val);
762 break;
763 case DT_RELASZ:
764 print(2, "DT_RELASZ", "0x%08x", pDyn[i].d_un.d_val);
765 break;
766 case DT_RELAENT:
767 print(2, "DT_RELAENT", "0x%08x", pDyn[i].d_un.d_val);
768 break;
769
770 case DT_STRSZ: /* d_ptr + + This element holds the address of the string table.
771 Symbol names, library names, and other strings reside
772 in this table. */
773 print(2, "DT_STRSZ", "0x%08x", pDyn[i].d_un.d_ptr);
774 break;
775
776 case DT_SYMENT:
777 print(2, "DT_SYMENT", "0x%08x", pDyn[i].d_un.d_val);
778 break;
779
780 case DT_INIT: /* d_ptr * * This element holds the address of the initialization function. */
781 print(2, "DT_INIT", "0x%08x (init function)", pDyn[i].d_un.d_val);
782 break;
783
784 case DT_FINI: /* d_ptr * * This element holds the address of the termination function. */
785 print(2, "DT_FINI", "0x%08x (term function)", pDyn[i].d_un.d_val);
786 break;
787
788 case DT_SONAME: /* d_val - * This element holds the string table offset of a
789 null-terminated string, giving the name of the shared
790 object. The offset is an index into the table recorded
791 in the DT_STRTAB entry. */
792
793 print(2, "DT_SONAME", "0x%08x", pDyn[i].d_un.d_val);
794 if (paszStrings != NULL)
795 printData(2, "%s", paszStrings + pDyn[i].d_un.d_val);
796 else
797 printData(2, "(no string table)");
798 break;
799
800 case DT_RPATH: /* d_val + + This element holds the string table offset of a null-terminated
801 search library search path string. The offset is an index int
802 the table recorded in the DT_STRTAB entry. */
803 print(2, "DT_RPATH", "0x%08x", pDyn[i].d_un.d_val);
804 if (paszStrings != NULL)
805 printData(2, "%s", paszStrings + pDyn[i].d_un.d_val);
806 else
807 printData(2, "(no string table)");
808 break;
809
810 case DT_SYMBOLIC: /* - - * This element's presence in a shared object library alters the
811 dynamic linker's symbol resolution algorithm for references
812 within the library. Instead of starting a symbol search with
813 the executable file, the dynamic linker starts from the shared
814 object file itself. If the shared object fails to supply the
815 referenced symbol, the dynamic linker then searches the
816 executable file and other shared objects as usual. */
817 print(2, "DT_SYMBOLIC", "(%d)", pDyn[i].d_un.d_val);
818 printData(2, "Searches within the library before the executable.");
819 break;
820
821 case DT_REL:
822 print(2, "DT_REL", "0x%08x", pDyn[i].d_un.d_val);
823 break;
824 case DT_RELSZ:
825 print(2, "DT_RELSZ", "0x%08x", pDyn[i].d_un.d_val);
826 break;
827 case DT_RELENT:
828 print(2, "DT_RELENT", "0x%08x", pDyn[i].d_un.d_val);
829 break;
830 case DT_PLTREL:
831 print(2, "DT_PLTREL", "0x%08x", pDyn[i].d_un.d_val);
832 break;
833 case DT_DEBUG:
834 print(2, "DT_DEBUG", "0x%08x", pDyn[i].d_un.d_val);
835 break;
836 case DT_TEXTREL:
837 print(2, "DT_TEXTREL", "0x%08x", pDyn[i].d_un.d_val);
838 break;
839 case DT_JMPREL:
840 print(2, "DT_JMPREL", "0x%08x", pDyn[i].d_un.d_val);
841 break;
842
843 }
844 /* next */
845 i++;
846 }
847 return 0;
848}
849
850
851/**
852 *
853 * @returns 0 on succes.
854 * @param pDyn Pointer to start of tag array.
855 * @param tag Tag type to find.
856 * @param pword Pointer to Elf32_Word which will hold the tag value if found.
857 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
858 */
859int getELFDynmaicTagValue(Elf32_Dyn *pDyn, Elf32_Sword tag, Elf32_Word *pword)
860{
861 while (pDyn->d_tag != tag && pDyn->d_tag != DT_NULL)
862 pDyn++;
863 if (pDyn->d_tag != DT_NULL)
864 {
865 *pword = pDyn->d_un.d_val;
866 return 0;
867 }
868 return -1;
869}
870
871
872/**
873 * Dumps a Interpreter segment.
874 * @returns 0 on success.
875 * @param pHdr32 Pointer to ELF header (and base of the loaded file).
876 * @param pPhdr Pointer to program header.
877 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
878 */
879int dumpELFInterpreterSegment(Elf32_Ehdr * pHdr32, Elf32_Phdr * pPhdr)
880{
881 print(2, "Interpreter name", "%s", (char*)pHdr32 + pPhdr->p_offset);
882 return 0;
883}
884
885
886/**
887 * Dumps a note segment.
888 * @returns 0 on success.
889 * @param pHdr32 Pointer to ELF header (and base of the loaded file).
890 * @param pPhdr Pointer to program header.
891 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
892 */
893int dumpELFNoteSegment(Elf32_Ehdr * pHdr32, Elf32_Phdr * pPhdr)
894{
895 pPhdr = pPhdr;
896 pHdr32 = pHdr32;
897 return 0;
898}
899
900
901
902
903
904/*
905 * Helper functions
906 */
907
908/**
909 * Reads for the given file at a specific offset.
910 * @returns Success indicator (TRUE/FALSE).
911 * @param phFile File handle.
912 * @param pv Pointer to output buffer.
913 * @param cb The count of bytes to read.
914 * @param off Offset (from the begining of the file) to start reading from.
915 * @status completely implemented.
916 * @author knut st. osmundsen
917 */
918static BOOL read(FILE *phFile, void *pv, unsigned long cb, unsigned long off)
919{
920 if (fseek(phFile, off, SEEK_SET) == 0)
921 {
922 if (fread(pv, (size_t)cb, 1, phFile) == 1)
923 return 1;
924 else
925 return 0;
926 }
927 else
928 return 0;
929}
930
931void printHeader(char *pszHeader)
932{
933 static BOOL fFirst = TRUE;
934 if (!fFirst)
935 putchar('\n');
936 else
937 fFirst = FALSE;
938
939 int i = strlen(pszHeader);
940 puts(pszHeader);
941 for (i=i; i >= 0; i--)
942 putchar('-');
943 putchar('\n');
944}
945
946
947void print(int iIndentLevel, char *pszName, char *pszDataFormat, ...)
948{
949 va_list arg;
950 int i = printf("%*s%s", printGetIndent(iIndentLevel), "", pszName);
951 i = printGetIndentData(iIndentLevel) - i;
952 for (i = i > 0 ? i : 1; i > 0; i--)
953 putchar(' ');
954 va_start(arg, pszDataFormat);
955 vprintf(pszDataFormat, arg);
956 va_end(arg);
957
958 if (!fPrintLongData)
959 {
960 putchar('\n');
961 fPrintLongDataIndented = FALSE;
962 }
963 else
964 fPrintLongDataIndented = TRUE;
965}
966
967void print(int iIndentLevel, char *pszText)
968{
969 int i = printf("%*s%s", printGetIndent(iIndentLevel), "", pszText);
970 if (!fPrintLongData)
971 {
972 putchar('\n');
973 fPrintLongDataIndented = FALSE;
974 }
975 else
976 {
977 i = printGetIndentData(iIndentLevel) - i;
978 printf("%*s", i > 0 ? i : 1, "");
979 fPrintLongDataIndented = TRUE;
980 }
981}
982
983void printBeginLongData(int iIndentLevel)
984{
985 assert(!fPrintLongData);
986 fPrintLongData = TRUE;
987 iPrintLongDataIndentLevel = iIndentLevel;
988 fPrintLongDataIndented = FALSE;
989}
990
991void printEndLongData(void)
992{
993 assert(fPrintLongData == TRUE);
994 fPrintLongData = FALSE;
995 putchar('\n');
996}
997
998void printData(char *pszDataFormat, ...)
999{
1000 va_list arg;
1001
1002 if (!fPrintLongDataIndented)
1003 {
1004 printf("%*s", printGetIndentData(iPrintLongDataIndentLevel), "");
1005 fPrintLongDataIndented = TRUE;
1006 }
1007
1008 va_start(arg, pszDataFormat);
1009 vprintf(pszDataFormat, arg);
1010 va_end(arg);
1011}
1012
1013
1014void printData(int iIndentLevel, char *pszDataFormat, ...)
1015{
1016 va_list arg;
1017
1018 if (!fPrintLongDataIndented)
1019 {
1020 printf("%*s", printGetIndentData(iIndentLevel), "");
1021 fPrintLongDataIndented = TRUE;
1022 }
1023
1024 va_start(arg, pszDataFormat);
1025 vprintf(pszDataFormat, arg);
1026 va_end(arg);
1027
1028 if (!fPrintLongData)
1029 putchar('\n');
1030}
1031
1032int printGetIndentData(int iIndentLevel)
1033{
1034 static int idata[4] = {23, 27, 30, 33};
1035 assert(iIndentLevel < 4);
1036 return idata[iIndentLevel];
1037}
1038
1039int printGetIndent(int iIndentLevel)
1040{
1041 static int idata[4] = {3, 6, 9, 12};
1042 assert(iIndentLevel < 4);
1043 return idata[iIndentLevel];
1044}
1045
1046void printerr(const char *pszMsg, ...)
1047{
1048 va_list arg;
1049
1050 printf("error: ");
1051
1052 va_start(arg, pszMsg);
1053 vprintf(pszMsg, arg);
1054 va_end(arg);
1055
1056 putchar('\n');
1057}
1058
Note: See TracBrowser for help on using the repository browser.