From mboxrd@z Thu Jan 1 00:00:00 1970 From: Michael Meissner To: gas2@cygnus.com, bfd@cygnus.com Subject: Elfdump Date: Fri, 11 Nov 1994 08:39:00 -0000 Message-id: <9411111638.AA06307@pasta.osf.org> X-SW-Source: 1994/msg00189.html I wrote the following ELF dumper in order to learn ELF, and thought others might find it useful. It is more specific than objdump (and it especially helped when the BFD support for ELF was weak). /* * COPYRIGHT NOTICE * * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * * Permission is hereby granted to use, copy, modify and freely distribute * the software in this file and its documentation for any purpose without * fee, provided that the above copyright notice appears in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. Further, provided that the name of Open * Software Foundation, Inc. ("OSF") not be used in advertising or * publicity pertaining to distribution of the software without prior * written permission from OSF. OSF makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. */ /* * ELF object file dumper. */ /* * HISTORY * $Log: elfdump.c,v $ * Revision 1.1.2.32 1994/04/08 17:10:34 meissner * Correctly print out .lprofil sections when a double word count is used. * [1994/04/08 17:10:25 meissner] * * Revision 1.1.2.31 1994/04/07 13:56:54 meissner * Range check section section index in get_section_name. * Add program header regions to vm/file map printout. * [1994/04/07 13:56:44 meissner] * * Revision 1.1.2.30 1994/03/17 13:28:57 meissner * Cut down on more spaces in output. * Print section name instead of number in symbol. * If -e, add linker generated symbols in vm layout. * Indicate where there are holes in the file/vm layout. * Don't print profil buckets that are 0. * [1994/03/17 13:28:49 meissner] * * Revision 1.1.2.29 1994/03/16 22:27:11 meissner * Print out layout information for the ELF file and virtual memory. * Check layouts printed for overlaps. * Print out end offsets in the program headers. * Lowercase section flags. * Cut down on symbol line length. * [1994/03/16 22:27:02 meissner] * * Revision 1.1.2.28 1994/03/16 18:25:24 meissner * Align summary fields of section headers. * Print out end+1 offset in section headers. * Always print all section header fields. * Skip profiling sections if -p. * [1994/03/16 18:25:14 meissner] * * Revision 1.1.2.27 1994/03/11 22:35:01 chasb * Expand Copyrights * [1994/03/09 19:43:03 chasb] * * Revision 1.1.2.26 1994/02/28 21:36:34 meissner * Correctly print out profil lowpc. * [1994/02/28 21:36:24 meissner] * * Revision 1.1.2.25 1994/02/25 16:55:19 meissner * Add support for printing profile stats on OSF/1. * Allow unsigned long in addition to int for profil sizes. * [1994/02/25 16:55:11 meissner] * * Revision 1.1.2.24 1993/12/23 01:18:10 meissner * On OSF/1 print the uarea for profiling ELF files. * [1993/12/23 01:18:03 meissner] * * Revision 1.1.2.23 1993/11/22 21:14:23 meissner * Add -v option to print the version string. * [1993/11/22 21:14:16 meissner] * * Revision 1.1.2.22 1993/11/22 21:00:50 meissner * Don't print section name for reloc to defined symbol, print symbol name. * [1993/11/22 21:00:42 meissner] * * Revision 1.1.2.21 1993/11/11 21:40:27 meissner * Correctly align gprof/prof output. * Don't print profil ticks in hex. * [1993/11/11 21:40:12 meissner] * * Revision 1.1.2.20 1993/11/11 21:29:19 meissner * CR 77 - Add profile output support. * [1993/11/11 21:29:06 meissner] * * Revision 1.1.2.19 1993/10/15 18:55:56 meissner * Fix mmap call to set the MAP_PRIVATE flag. * [1993/10/15 18:55:44 meissner] * * Revision 1.1.2.18 1993/09/23 21:52:22 meissner * Treat .debug_sfnames as a string section. * [1993/09/23 21:52:09 meissner] * * Revision 1.1.2.17 1993/09/23 21:29:12 meissner * Skip printing null bytes in string sections, except for the first byte. * [1993/09/23 21:28:58 meissner] * * Revision 1.1.2.16 1993/09/23 21:21:20 meissner * Print .stabstr section as strings. * Know about .stab section special format. * [1993/09/23 21:21:07 meissner] * * Revision 1.1.2.15 1993/09/08 22:32:47 meissner * CR 62: Add -t {d,o,x} to specify output formats. * [1993/09/08 22:32:35 meissner] * * Revision 1.1.2.14 1993/07/27 20:37:07 meissner * Print 386 relocations in symbolic format. * [1993/07/27 20:36:52 meissner] * * Revision 1.1.2.13 1993/07/23 15:07:30 meissner * Add definition of STT_STABS if not provided in elf.h. * Remove ifdefs of STT_STABS elsewhere. * If -d, invoke objdump -d -j
to disassemble executable sections. * [1993/07/23 15:07:12 meissner] * * Revision 1.1.2.12 1993/07/21 01:33:23 meissner * Print stabs type symbolically, not numerically. * Rename ELF32_STABS_UNUSED -> ELF32_STABS_OTHER. * [1993/07/21 01:33:05 meissner] * * Left align size field, instead of right align. * [1993/07/18 17:18:12 meissner] * * Add appropriate casts and/or 'l' specifiers to *printf formats. * Add STABS in symbol support. * [1993/07/18 15:07:36 meissner] * * Revision 1.1.2.11 1993/06/14 02:15:26 meissner * Print hash tables again after last change. * Print interp section in string form, even if -p. * [1993/06/14 02:15:12 meissner] * * Revision 1.1.2.10 1993/06/14 02:02:20 meissner * CR 52: * Add -n switch to print a specific section. * Add -p switch to not print the contents of a progbits section. * Add -s switch to print header summary only. * Add -x switch to assume the string table is corrupt. * [1993/06/14 02:02:04 meissner] * * Revision 1.1.2.9 1993/05/27 18:56:26 meissner * Remove 386 hack which was caused by a buggy compiler. * [1993/05/27 18:56:11 meissner] * * Revision 1.1.2.8 1993/05/24 11:46:12 meissner * Hack around i386 problem with case SHN_ABS/SHN_COMMON. * [1993/05/24 11:45:53 meissner] * * Revision 1.1.2.7 1993/05/13 17:38:41 meissner * Add DT_RELAENT. * [1993/05/13 17:38:24 meissner] * * Revision 1.1.2.6 1993/05/12 19:40:17 meissner * Fix printing of implicit addend in relocation to get full word, not byte. * Print section being referenced in relocations, symbol tables and hash tables. * Print name of relocated symbol or section. * Don't assume REL implicit addend is word aligned. * Print the dynamic section in a friendly fashion. * [1993/05/12 19:39:57 meissner] * * Revision 1.1.2.5 1993/05/10 21:01:48 meissner * Fixup so it compiles cleanly on V.4. * Don't abort if implicit addend too large. * Fix GCC warnings. * Relocations for executables have virtual address in r_offset, not section offset. * Split sym/type in relocations. * [1993/05/10 21:01:28 meissner] * * Revision 1.1.2.4 1993/05/10 15:21:18 meissner * Print REL implicit addend. * [1993/05/10 15:20:59 meissner] * * Revision 1.1.2.3 1993/05/10 13:38:56 meissner * Change copyright to OSF_FREE_COPYRIGHT. * Deal with MAP_VARIABLE not being defined. * Add hash table support. * [1993/05/10 13:38:32 meissner] * * Revision 1.1.2.2 1993/05/07 19:44:44 meissner * Initial version. * [1993/05/07 19:44:20 meissner] * * $EndLog$ */ const char elfdump_what_string[] = "@(#)elfdump.c\t$Revision: 1.1.2.32 $ $Date: 1994/04/08 17:10:34 $ $Locker: $"; #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __OSF1__ #include #include #include #endif #ifdef NEW_PROFILE #include static struct profile_profil profhdr; static int profhdr_p; #endif #ifndef DIGIT_OUTPUT_SIZE #define DIGIT_OUTPUT_SIZE 64 /* buffer size needed to format integers, includes prefix/suffix */ #endif extern int getopt (int, char * const [], const char *); extern char *optarg; extern int optind; extern int optopt; extern int opterr; #ifndef MAP_VARIABLE #define MAP_VARIABLE MAP_SHARED #endif #ifndef EM_MIPS #define EM_MIPS 8 #endif #ifndef DT_NULL /* dynamic structure - page 5-15, figure 5-9 */ typedef struct { Elf32_Sword d_tag; union { Elf32_Word d_val; Elf32_Addr d_ptr; } d_un; } Elf32_Dyn; /* Dynamic array tags - page 5-16, figure 5-10. */ #define DT_NULL 0 #define DT_NEEDED 1 #define DT_PLTRELSZ 2 #define DT_PLTGOT 3 #define DT_HASH 4 #define DT_STRTAB 5 #define DT_SYMTAB 6 #define DT_RELA 7 #define DT_RELASZ 8 #define DT_RELAENT 9 #define DT_STRSZ 10 #define DT_SYMENT 11 #define DT_INIT 12 #define DT_FINI 13 #define DT_SONAME 14 #define DT_RPATH 15 #define DT_SYMBOLIC 16 #define DT_REL 17 #define DT_RELSZ 18 #define DT_RELENT 19 #define DT_PLTREL 20 #define DT_DEBUG 21 #define DT_TEXTREL 22 #define DT_JMPREL 23 #endif #ifndef STT_STABS /* GNU extension to encode stabs in elf symbols. The size field is used to encode the unused, type, and desc fields. */ #define STT_STABS STT_HIPROC #define ELF32_STABS_OTHER(s) ((s) >> 24) #define ELF32_STABS_TYPE(s) (((s) >> 16) & 0xff) #define ELF32_STABS_DESC(s) ((short) s) #define ELF32_STABS_SIZE(u,t,d) (((u) << 24) | (((t) & 0xff) << 16) | ((d) & 0xffff)) #endif #ifndef ET_PROF /* OSF extension to encode profiling output as an ELF file. */ #define ET_PROF 0xffff #endif struct sec_list { struct sec_list *next; const char *section; }; typedef struct elf_stab { unsigned int soffset; /* offset to string in .stabstr */ unsigned char type; /* stab type */ unsigned char other; /* stab other field */ unsigned short desc; /* stab desc field */ int value; /* stab value field */ } elf_stab_t; static char *file; /* current file being processed */ static uchar_t *file_bytes = (uchar_t *)-1; /* pointer to current object file data */ static struct stat file_stat; /* file status information */ static int file_fd = -1; /* file descriptor file is openned on */ static Elf32_Ehdr ehdr; /* global header */ static struct sec_list *sections; /* sections to print out */ static int ignore_string = 0; /* ignore the string table */ static int objdump = 0; /* invoke objdump -d to disassemble text */ static int no_progbits = 0; /* skip printing progbits section */ static int no_layout = 0; /* skip printing file/vm layout information */ static int summary = 0; /* print just summary */ static int linker_symbols = 0; /* put etext/edata/end into layout */ static int print_vers = 0; /* print version string */ static int errors = 0; /* # errors found */ static char format = '\0'; /* default format to use */ static int sh_name_width = 0; /* width of section names */ static int sh_type_width = 0; /* width of section types */ static int sh_start_width = 0; /* width of section offset start */ static int sh_end_width = 0; /* width of section offset end */ static int sh_size_width = 0; /* width of section size */ static int sh_addr_width = 0; /* width of section address */ static int sh_align_width = 0; /* width of section alignment */ static int sh_flags_width = 0; /* width of section flag bits */ static int sh_index_width = 0; /* width of section index */ static int sh_info_width = 0; /* width of section info field */ static int sh_link_width = 0; /* width of section link field */ static int sh_esize_width = 0; /* width of section entsize field */ #define SEC_PTR(index) (((Elf32_Shdr *)(file_bytes + ehdr.e_shoff)) + index) #define PROGHDR_PTR(index) (((Elf32_Phdr *)(file_bytes + ehdr.e_phoff)) + index) static const char *const dyn_tag[] = { "null", "needed", "pltrelsz", "pltgot", "hash", "strtab", "symtab", "rela", "relasz", "relaent", "strsz", "syment", "init", "fini", "soname", "rpath", "symbolic", "rel", "relsz", "relent", "pltrel", "debug", "textrel", "jmprel", }; /* Enum that says to free name in layout chain */ typedef enum layout_free { layout_free_no = 0, /* do not free name field */ layout_free_yes = 1 /* free name field */ } layout_free_t; /* Structure that records the information about file/virtual layout */ typedef struct layout { struct layout *next; /* next layout element */ const char *name; /* element name */ unsigned long start; /* start address */ unsigned long size; /* size of region */ layout_free_t free_p; /* whether to free name or not */ } layout_t; static layout_t *file_layout = (layout_t *)0; static layout_t *vm_layout = (layout_t *)0; static const char *get_section_name (Elf32_Word); /* Allocate memory, abort if no memory is available. */ static void * xmalloc (size_t len) { void *p = malloc (len); if (!p) { perror ("malloc"); exit (1); } return p; } /* Convert a number to a string using a format specified by -t or a default one. */ #define MAX_STRINGIFY 32 /* if more concurrent calls are made this needs to be bumped */ static const char * stringify (unsigned long number, int width, int def_format, int skip_lead, const char *prefix, const char *suffix) { static unsigned next_buffer; static char def_buffer[MAX_STRINGIFY][DIGIT_OUTPUT_SIZE]; int use_format = (format) ? format : def_format; char *buffer = &def_buffer[ (next_buffer++) % MAX_STRINGIFY ][0]; switch (use_format) { default: sprintf (buffer, "%s%*ld%s", prefix, width, (long) number, suffix); break; case 'x': sprintf (buffer, "%s%s%0*lx%s", prefix, (skip_lead) ? "" : "0x", width, number, suffix); break; case 'o': sprintf (buffer, "%s%s%0*lo%s", prefix, (skip_lead) ? "" : "0", width, number, suffix); break; case 'u': sprintf (buffer, "%s%*lu%s", prefix, width, number, suffix); break; } return buffer; } /* Return the length of converting a number to a string via stringify. */ static int stringify_len (unsigned long number, int def_format, int skip_lead) { return strlen (stringify (number, 0, def_format, skip_lead, "", "")); } /* Silence -Wconversion */ #define stringify(n, w, d, l, p, s) (stringify)((unsigned long)(n), w, d, l, p, s) #define stringify_len(n, d, l) (stringify_len)((unsigned long)(n), d, l) /* Add an element to the layout linked list. */ static void add_layout (layout_t **head_ptr, const char *name, unsigned long start, unsigned long size, layout_free_t free_p) { layout_t *ptr = xmalloc (sizeof (layout_t)); ptr->next = *head_ptr; ptr->name = name; ptr->start = start; ptr->size = size; ptr->free_p = free_p; *head_ptr = ptr; } /* Silence -Wconversion */ #define add_layout(head_ptr, name, start, size, free_p) \ add_layout (head_ptr, name, (unsigned long)start, (unsigned long)size, free_p) /* * Delete a layout chain */ static void free_layout (layout_t **head_ptr) { layout_t *ptr = *head_ptr; layout_t *next; *head_ptr = (layout_t *)0; while (ptr) { next = ptr->next; if (ptr->free_p) free ((void *)ptr->name); free ((void *)ptr); ptr = next; } } /* Compare two layout pointers, sorting by start address. */ static int compare_layout (const void *a, const void *b) { const layout_t *ptr_a = *(const layout_t **)a; const layout_t *ptr_b = *(const layout_t **)b; return (ptr_a->start != ptr_b->start) ? ptr_a->start - ptr_b->start : ptr_a->size - ptr_b->size; } /* Sort and print a layout linked list */ static void print_layout (layout_t *head, const char *desc) { size_t num_ptrs; size_t i; size_t len; layout_t *ptr; layout_t **ptr_array; int width_start = 0; int width_end = 0; int width_size = 0; unsigned long oend; if (!head) { printf ("\nLayout for %s was empty\n", desc); return; } /* Count the number of pointers */ num_ptrs = 0; for (ptr = head; ptr != (layout_t *)0; ptr = ptr->next) num_ptrs++; /* Sort the layout pointers */ ptr_array = (layout_t **) xmalloc (num_ptrs * sizeof (layout_t *)); i = 0; for (ptr = head; ptr != (layout_t *)0; ptr = ptr->next) ptr_array[i++] = ptr; qsort ((void *)ptr_array, num_ptrs, sizeof (layout_t *), compare_layout); /* Size start, end */ for (i = 0; i < num_ptrs; i++) { ptr = ptr_array[i]; len = stringify_len (ptr->start, 'x', 1); if (len > width_start) width_start = len; len = stringify_len (ptr->start + ptr->size, 'x', 1); if (len > width_end) width_end = len; len = stringify_len (ptr->size, 'd', 1); if (len > width_size) width_size = len; } /* Print out the layout now */ printf ("\nLayout for %s:\n", desc); oend = 0; for (i = 0; i < num_ptrs; i++) { ptr = ptr_array[i]; if (i > 0 && ptr->start > oend) printf (" start= %s, end= %s, size= %s, name= %s", stringify (oend, width_start, 'x', 0, "", ""), stringify (ptr->start, width_end, 'x', 0, "", ""), stringify (ptr->start - oend, width_size, 'd', 0, "", ""), "\n"); printf (" start= %s, end= %s, size= %s, name= %s", stringify (ptr->start, width_start, 'x', 0, "", ""), stringify (ptr->start + ptr->size, width_end, 'x', 0, "", ""), stringify (ptr->size, width_size, 'd', 0, "", ""), ptr->name); if (i > 0 && ptr->start < oend) printf ("%*s**** Overlap!!", (int)strlen (ptr->name) - 32, ""); putchar ('\n'); oend = ptr->start + ptr->size; } free (ptr_array); } /* Convert an elf string reference into a real string. */ static const char * elf_string (Elf32_Word sec_index, Elf32_Word byte_off) { static char bad_string[] = "???"; Elf32_Shdr *sec_hdr = SEC_PTR (sec_index); if (ignore_string) return bad_string; if (sec_index <= 0 || sec_index > (int)ehdr.e_shnum || file_bytes == (uchar_t *)-1 || (sec_hdr->sh_type != SHT_STRTAB && strcmp (get_section_name (sec_index), ".stabstr") != 0)) { fprintf (stderr, "%s section %s is not a string table.\n", file, stringify (sec_index, 0, 'd', 0, "", "")); return bad_string; } if (byte_off > sec_hdr->sh_size) { fprintf (stderr, "%s string offset %s too big for section %s\n", file, stringify (byte_off, 0, 'd', 0, "", ""), stringify (sec_index, 0, 'd', 0, "", "")); return bad_string; } return (char *)(file_bytes + sec_hdr->sh_offset + byte_off); } /* Convert 1..4 bytes into printable notation. */ static char * printable_string (uchar_t *ptr, int num) { static char print_buffer[40]; int i; int ch; char *buffer_ptr = print_buffer; *buffer_ptr++ = '"'; for (i = 0; i < num; i++) { ch = *ptr++; switch (ch) { default: if (isprint (ch)) *buffer_ptr++ = ch; else { sprintf (buffer_ptr, "\\%03o", ch); buffer_ptr += 4; } break; case '\b': *buffer_ptr++ = '\\'; *buffer_ptr++ = 'b'; break; case '\f': *buffer_ptr++ = '\\'; *buffer_ptr++ = 'f'; break; case '\n': *buffer_ptr++ = '\\'; *buffer_ptr++ = 'n'; break; case '\r': *buffer_ptr++ = '\\'; *buffer_ptr++ = 'r'; break; case '\t': *buffer_ptr++ = '\\'; *buffer_ptr++ = 't'; break; case '\v': *buffer_ptr++ = '\\'; *buffer_ptr++ = 'v'; break; case '\"': *buffer_ptr++ = '\\'; *buffer_ptr++ = '"'; break; case '\'': *buffer_ptr++ = '\\'; *buffer_ptr++ = '\''; break; case '\\': *buffer_ptr++ = '\\'; *buffer_ptr++ = '\\'; break; } } *buffer_ptr++ = '"'; *buffer_ptr = '\0'; return print_buffer; } /* Convert a stab type into a string. */ static const char * printable_stab_type (int type) { switch (type) { case 0x20: return "GSYM, "; /* global symbol: name,,0,type,0 */ case 0x22: return "FNAME, "; /* procedure name (f77 kludge): name,,0 */ case 0x24: return "FUN, "; /* procedure: name,,0,linenumber,address */ case 0x26: return "STSYM, "; /* static symbol: name,,0,type,address */ case 0x28: return "LCSYM, "; /* .lcomm symbol: name,,0,type,address */ case 0x2a: return "MAIN, "; /* Name of main routine, not used in C */ case 0x30: return "PC, "; /* global pascal symbol: name,,0,subtype,line */ case 0x40: return "RSYM, "; /* register sym: name,,0,type,register */ case 0x44: return "SLINE, "; /* src line: 0,,0,linenumber,address */ case 0x46: return "DSLINE,"; /* like N_SLINE, except in data segment */ case 0x48: return "BROWS, "; /* source code browser stabs */ case 0x54: return "CATCH, "; /* GNU G++ catch clause */ case 0x60: return "SSYM, "; /* structure elt: name,,0,type,struct_offset */ case 0x64: return "SO, "; /* source file name: name,,0,0,address */ case 0x80: return "LSYM, "; /* local sym: name,,0,type,offset */ case 0x82: return "BINCL, "; /* aux beginning of include file */ case 0x84: return "SOL, "; /* #included file name: name,,0,0,address */ case 0xa0: return "PSYM, "; /* parameter: name,,0,type,offset */ case 0xa2: return "EINCL, "; /* aux end of include file */ case 0xa4: return "ENTRY, "; /* alternate entry: name,linenumber,address */ case 0xc0: return "LBRAC, "; /* left bracket: 0,,0,nesting level,address */ case 0xc2: return "EXCL, "; /* placeholder for deleted include file */ case 0xe0: return "RBRAC, "; /* right bracket: 0,,0,nesting level,address */ case 0xe2: return "BCOMM, "; /* begin common: name,, */ case 0xe4: return "ECOMM, "; /* end common: name,, */ case 0xe8: return "ECOML, "; /* end common (local name): ,,address */ case 0xfe: return "LENG, "; /* second stab entry with length information */ } return stringify (type, 2, 'x', 0, "", ","); } /* Return a section's name. */ static const char * get_section_name (Elf32_Word sec_index) { Elf32_Shdr *sec_hdr; if (sec_index == 0) return ""; if (sec_index >= ehdr.e_shnum || ignore_string) return stringify (sec_index, 0, 'd', 0, "", ""); sec_hdr = SEC_PTR (sec_index); return elf_string ((Elf32_Word)ehdr.e_shstrndx, sec_hdr->sh_name); } /* Print the section body by invoking objdump -d on it. */ static void print_section_objdump (Elf32_Shdr *sec_hdr) { pid_t pid; fflush ((FILE *)0); pid = fork (); if (pid == -1) /* error, no fork */ perror ("fork"); else if (pid == 0) /* child context */ { const char *argv[6]; argv[0] = "objdump"; argv[1] = "-d"; argv[2] = "-j"; argv[3] = elf_string ((Elf32_Word)ehdr.e_shstrndx, sec_hdr->sh_name); argv[4] = file; argv[5] = (char *)0; execvp ("objdump", (char *const *) argv); execv ("/usr/ccs/gcc/objdump", (char *const *) argv); execv ("/usr/ccs/gcc-elf/objdump", (char *const *) argv); perror ("objdump"); fflush (stderr); _exit (1); } else /* parent context */ { int status = 0; void (*sigint)(int) = signal (SIGINT, SIG_IGN); void (*sigquit)(int) = signal (SIGQUIT, SIG_IGN); if (waitpid (pid, &status, 0) < 0) perror ("waitpid"); signal (SIGINT, sigint); signal (SIGQUIT, sigquit); if (status) { if (WIFSIGNALED (status)) fprintf (stderr, "objdump exited with signal %s\n", stringify (WTERMSIG (status), 0, 'd', 0, "", "")); else fprintf (stderr, "objdump exited with %s\n", stringify (WEXITSTATUS (status), 0, 'd', 0, "", "")); } } } /* Print the section body just as a series of integers. */ static void print_section_raw (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; uchar_t *ptr = file_bytes + sec_hdr->sh_offset; int sec_off = 0; int width_off = stringify_len (size-1, 'd', 1); Elf32_Word value; union { Elf32_Word i; char c[4]; } u; if (objdump && (sec_hdr->sh_flags & SHF_EXECINSTR)) { print_section_objdump (sec_hdr); return; } while (size > 0) { if (size >= 4) { if ((((unsigned long)ptr) & ~3u) == 0) value = *(Elf32_Word *)ptr; else { memcpy (u.c, ptr, 4); value = u.i; } printf (" Offset %s: 0x%.8lx %11ld %s\n", stringify (sec_off, width_off, 'd', 0, "", ""), (long)value, (long)value, printable_string (ptr, 4)); sec_off += 4; ptr += 4; size -= 4; } else { value = *ptr; printf (" Offset %s: 0x%.2x %11d %s\n", stringify (sec_off, 5, 'd', 0, "", ""), (int)value, (int)value, printable_string (ptr, 1)); sec_off++; ptr++; size--; } } } /* Print the special .stab section. */ static void print_section_stab (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; elf_stab_t *ptr = (elf_stab_t *)(file_bytes + sec_hdr->sh_offset); elf_stab_t *endptr = (elf_stab_t *)((char *)ptr + size); int width_soffset = 0; int width_type = 0; int width_other = 0; int width_desc = 0; int width_value = 0; int width_stab_num = stringify_len (endptr - ptr, 'd', 1); int stab_num = 0; Elf32_Word string_sect = 0; int len; Elf32_Word i; /* Look for .stabstr section */ for (i = 0; i < ehdr.e_shnum; i++) { if (strcmp (get_section_name (i), ".stabstr") == 0) { string_sect = i; break; } } /* Find lengths for everything. */ while (ptr < endptr) { len = stringify_len (ptr->soffset, 'd', 1); if (len > width_soffset) width_soffset = len; len = strlen (printable_stab_type (ptr->type)); if (len > width_type) width_type = len; len = stringify_len (ptr->desc, 'd', 1); if (len > width_desc) width_desc = len; len = stringify_len (ptr->value, 'd', 1); if (len > width_value) width_value = len; if (ptr->other) { len = stringify_len (ptr->other, 'd', 1); if (len > width_other) width_other = len; } ptr++; } /* Print fields out. */ ptr = (elf_stab_t *)(file_bytes + sec_hdr->sh_offset); while (ptr < endptr) { if (width_other) printf (" Stab #%s: type= %*s other= %s, desc= %s, value= %s, str offset= %s", stringify (++stab_num, width_stab_num, 'd', 0, "", ""), width_type, printable_stab_type (ptr->type), stringify (ptr->other, width_other, 'd', 0, "", ""), stringify (ptr->desc, width_desc, 'd', 0, "", ""), stringify (ptr->value, width_value, 'd', 0, "", ""), stringify (ptr->soffset, width_soffset, 'd', 0, "", "")); else printf (" Stab #%s: type= %*s desc= %s, value= %s, str offset= %s", stringify (++stab_num, width_stab_num, 'd', 0, "", ""), width_type, printable_stab_type (ptr->type), stringify (ptr->desc, width_desc, 'd', 0, "", ""), stringify (ptr->value, width_value, 'd', 0, "", ""), stringify (ptr->soffset, width_soffset, 'd', 0, "", "")); if (string_sect) printf (", str= %s\n", elf_string (string_sect, ptr->soffset)); else printf ("\n"); ptr++; } } /* Print the symbol table entries. */ static void print_section_symtab (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; Elf32_Sym *ptr = (Elf32_Sym *)(file_bytes + sec_hdr->sh_offset); Elf32_Sym *endptr = (Elf32_Sym *)((char *)ptr + size); int sym_num = 0; int width_value = 0; int width_size = 0; int width_shndx = 0; int width_sym_num; int len; const char *type; const char *bind; const char *shndx; char width_buf[DIGIT_OUTPUT_SIZE + 20]; char size_buf[DIGIT_OUTPUT_SIZE + 20]; printf (" String table = \"%s\"\n\n", get_section_name (sec_hdr->sh_link)); /* Calculate minimum lengths */ width_sym_num = stringify_len (endptr - ptr, 'd', 1); while (ptr < endptr) { len = stringify_len (ptr->st_value, 'x', 1); if (width_value < len) width_value = len; if (ELF32_ST_TYPE (ptr->st_info) == STT_STABS) { len = sprintf (width_buf, "type= %s desc= %s,", printable_stab_type ((int)ELF32_STABS_TYPE (ptr->st_size)), stringify (ELF32_STABS_DESC (ptr->st_size), 0, 'd', 0, "", "")); if (ELF32_STABS_OTHER (ptr->st_size)) len += sprintf (width_buf, " other= %s,", stringify (ELF32_STABS_OTHER (ptr->st_size), 0, 'd', 0, "", "")); } else len = sprintf (width_buf, "size= %s,", stringify (ptr->st_size, 0, 'd', 0, "", "")); if (width_size < len) width_size = len; switch (ptr->st_shndx) { default: len = (ignore_string) ? stringify_len (ptr->st_shndx, 'd', 0) : strlen (get_section_name (ptr->st_shndx)); break; case SHN_UNDEF: len = sizeof ("undef")-1; break; case SHN_ABS: len = sizeof ("abs")-1; break; case SHN_COMMON: len = sizeof ("common")-1; break; } if (width_shndx < len) width_shndx = len; ptr++; } ptr = (Elf32_Sym *)(file_bytes + sec_hdr->sh_offset); while (ptr < endptr) { switch (ELF32_ST_BIND (ptr->st_info)) { default: bind = stringify (ELF32_ST_BIND (ptr->st_info), 0, 'd', 0, "", ","); break; case STB_LOCAL: bind = "local,"; break; case STB_GLOBAL: bind = "global,"; break; case STB_WEAK: bind = "weak,"; break; } switch (ELF32_ST_TYPE (ptr->st_info)) { default: type = stringify (ELF32_ST_TYPE (ptr->st_info), 0, 'd', 0, "", ","); break; case STT_NOTYPE: type = "none,"; break; case STT_OBJECT: type = "obj,"; break; case STT_FUNC: type = "func,"; break; case STT_SECTION: type = "sect,"; break; case STT_FILE: type = "file,"; break; case STT_STABS: type = "stab,"; break; } switch ((int)ptr->st_shndx) { default: shndx = (ignore_string) ? stringify (ptr->st_shndx, 0, 'd', 0, "", "") : get_section_name (ptr->st_shndx); break; case (int)SHN_UNDEF: shndx = "undef"; break; case (int)SHN_ABS: shndx = "abs"; break; case (int)SHN_COMMON: shndx = "common"; break; } if (ELF32_ST_TYPE (ptr->st_info) == STT_STABS) { len = sprintf (size_buf, "type= %s desc= %s,", printable_stab_type ((int)ELF32_STABS_TYPE (ptr->st_size)), stringify (ELF32_STABS_DESC (ptr->st_size), 0, 'd', 0, "", "")); if (ELF32_STABS_OTHER (ptr->st_size)) sprintf (size_buf + len, " other= %s,", stringify (ELF32_STABS_OTHER (ptr->st_size), 0, 'd', 0, "", "")); } else sprintf (size_buf, "size= %s,", stringify (ptr->st_size, 0, 'd', 0, "", "")); printf (" Sym %s: value= %s, %-*s sect= %s%-*s type= %-5s bind= %-7s name= %s\n", stringify (sym_num, width_sym_num, 'd', 0, "", ""), stringify (ptr->st_value, width_value, 'x', 0, "", ""), width_size, size_buf, shndx, width_shndx + 1 - (int)strlen (shndx), ",", type, bind, elf_string (sec_hdr->sh_link, ptr->st_name)); ptr++; sym_num++; } } /* Print the hash table. */ static void print_section_hash (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; Elf32_Word *ptr = (Elf32_Word *)(file_bytes + sec_hdr->sh_offset); Elf32_Word *endptr = (Elf32_Word *)((char *)ptr + size); Elf32_Word nbucket = *ptr++; Elf32_Word nchain = *ptr++; Elf32_Word *hchain = ptr + nbucket; int loading; Elf32_Word i; Elf32_Word element; Elf32_Word next; int width; if (endptr != (ptr + nbucket + nchain)) { printf (" \n"); print_section_raw (sec_hdr); return; } width = stringify_len ((nchain > nbucket) ? nchain : nbucket, 'd', 1); printf (" Symbol table = \"%s\"\n", get_section_name (sec_hdr->sh_link)); printf (" # Buckets = %s\n", stringify (nbucket, width, 'd', 0, "", "")); printf (" # Elements = %s\n\n", stringify (nchain, width, 'd', 0, "", "")); for (i = 0; i < nbucket; i++) { loading = 1; element = *ptr; while ((next = hchain[element]) != 0) { loading++; element = next; } printf (" Bucket %s: first: %s, loading: %s\n", stringify (i, width, 'd', 0, "", ""), stringify (*ptr++, width, 'd', 0, "", ""), stringify (loading, width, 'd', 0, "", "")); } putchar ('\n'); for (i = 0; i < nchain; i++) printf (" Chain %s: %s\n", stringify (i, width, 'd', 0, "", ""), stringify (*ptr++, width, 'd', 0, "", "")); } /* Print the string section body. */ static void print_section_string (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; char *ptr = (char *)(file_bytes + sec_hdr->sh_offset); char *endptr = ptr + size; int sec_off = 0; int len = 0; int width_off = stringify_len (size-1, 'd', 1); while (ptr < endptr) { if (*ptr != '\0' || sec_off == 0) printf (" Offset %s: \"%s\"\n", stringify (sec_off, width_off, 'd', 0, "", ""), ptr); len = strlen (ptr) + 1; ptr += len; sec_off += len; } } /* Decode a relocation type into a printable value. */ static const char * get_reloc_type (int type) { static const char *reloc_386[] = { "R_386_NONE,", "R_386_32,", "R_386_PC32,", "R_386_GOT,", "R_386_PLT32,", "R_386_COPY,", "R_386_GLOB_DAT,", "R_386_JMP_SLOT,", "R_386_RELATIVE,", "R_386_GOTOFF,", "R_386_GOTPC,", }; if (ehdr.e_machine == EM_386 && (unsigned)type < (sizeof (reloc_386) / sizeof (char *))) return reloc_386[type]; return stringify (type, 0, 'd', 0, "", ","); } /* Print RELA relocations. */ static void print_section_rela (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; Elf32_Rela *ptr = (Elf32_Rela *)(file_bytes + sec_hdr->sh_offset); Elf32_Rela *endptr = (Elf32_Rela *)((char *)ptr + size); Elf32_Shdr *sym_sec = SEC_PTR (sec_hdr->sh_link); Elf32_Sym *sym_ptr = (Elf32_Sym *)(file_bytes + sym_sec->sh_offset); int rel_object_p = (ehdr.e_type == ET_REL); int rel_num = 0; int width_offset = 0; int width_info = 0; int width_sym = 0; int width_type = 0; int width_addend = 0; int width_rel_num; int sym_num; int len; Elf32_Word offset; const char *sect_or_undef; const char *name; const char *offset_value; printf (" Symbol table section = \"%s\"\n", get_section_name (sec_hdr->sh_link)); printf (" Section being relocated = \"%s\"\n\n", get_section_name (sec_hdr->sh_info)); /* Calculate minimum lengths */ width_rel_num = stringify_len (endptr - ptr, 'd', 1); while (ptr < endptr) { if (rel_object_p) offset = ptr->r_offset; else offset = ptr->r_offset - sec_hdr->sh_addr; len = stringify_len (offset, 'd', 1); if (width_offset < len) width_offset = len; len = stringify_len (ptr->r_info, 'd', 1); if (width_info < len) width_info = len; len = stringify_len (ELF32_R_SYM (ptr->r_info), 'd', 1); if (width_sym < len) width_sym = len; len = strlen (get_reloc_type (ELF32_R_TYPE (ptr->r_info))); if (width_type < len) width_type = len; len = stringify_len (ptr->r_addend, 'd', 0); if (width_addend < len) width_addend = len; ptr++; } ptr = (Elf32_Rela *)(file_bytes + sec_hdr->sh_offset); while (ptr < endptr) { if (rel_object_p) { offset = ptr->r_offset; offset_value = ""; } else { offset = ptr->r_offset - sec_hdr->sh_addr; offset_value = stringify (ptr->r_offset, 8, 'x', 0, " [", "]"); } sym_num = ELF32_R_SYM (ptr->r_info); switch ((int)sym_ptr[sym_num].st_shndx) { default: sect_or_undef = "internal"; break; case (int)SHN_UNDEF: sect_or_undef = "external"; break; case (int)SHN_COMMON: sect_or_undef = "common "; break; case (int)SHN_ABS: sect_or_undef = "absolute"; break; } name = elf_string (sym_sec->sh_link, sym_ptr[sym_num].st_name); printf (" Reloc %s: offset= %s%s, info= %s, sym= %s, type= %-*s addend= %s, %s \"%s\"\n", stringify (rel_num, width_rel_num, 'd', 0, "", ""), stringify (offset, width_offset, 'd', 0, "", ""), offset_value, stringify (ptr->r_info, width_info, 'd', 0, "", ""), stringify (sym_num, width_sym, 'd', 0, "", ""), width_type, get_reloc_type (ELF32_R_TYPE (ptr->r_info)), stringify (ptr->r_addend, width_addend, 'd', 0, "", ""), sect_or_undef, name); ptr++; rel_num++; } } /* Print REL relocations. */ static void print_section_rel (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; Elf32_Rel *ptr = (Elf32_Rel *)(file_bytes + sec_hdr->sh_offset); Elf32_Rel *endptr = (Elf32_Rel *)((char *)ptr + size); Elf32_Shdr *sym_sec = SEC_PTR (sec_hdr->sh_link); Elf32_Sym *sym_ptr = (Elf32_Sym *)(file_bytes + sym_sec->sh_offset); Elf32_Shdr *data_sec = SEC_PTR (sec_hdr->sh_info); char *data_ptr = (char *)(file_bytes + data_sec->sh_offset); int rel_object_p = (ehdr.e_type == ET_REL); int rel_num = 0; int width_offset = 0; int width_info = 0; int width_sym = 0; int width_type = 0; int width_addend = 0; int width_rel_num; int sym_num; int len; Elf32_Word offset; const char *sect_or_undef; const char *name; const char *offset_value; const char *addend_value; union { Elf32_Word i; char c[sizeof (Elf32_Word)]; } addend; printf (" Symbol table section = \"%s\"\n", get_section_name (sec_hdr->sh_link)); printf (" Section being relocated = \"%s\"\n\n", get_section_name (sec_hdr->sh_info)); /* Calculate minimum lengths */ width_rel_num = stringify_len (endptr - ptr, 'd', 1); while (ptr < endptr) { if (rel_object_p) offset = ptr->r_offset; else offset = ptr->r_offset - sec_hdr->sh_addr; len = stringify_len (offset, 'd', 1); if (width_offset < len) width_offset = len; len = stringify_len (ptr->r_info, 'd', 1); if (width_info < len) width_info = len; len = stringify_len (ELF32_R_SYM (ptr->r_info), 'd', 1); if (width_sym < len) width_sym = len; len = strlen (get_reloc_type (ELF32_R_TYPE (ptr->r_info))); if (width_type < len) width_type = len; if (offset < data_sec->sh_size) { memcpy (addend.c, data_ptr + offset, sizeof (Elf32_Word)); len = stringify_len (addend.i, 'd', 0); } else len = sizeof ("error")-1; if (width_addend < len) width_addend = len; ptr++; } ptr = (Elf32_Rel *)(file_bytes + sec_hdr->sh_offset); while (ptr < endptr) { if (rel_object_p) { offset = ptr->r_offset; offset_value = ""; } else { offset = ptr->r_offset - sec_hdr->sh_addr; offset_value = stringify (ptr->r_offset, 8, 'x', 0, " [", "]"); } if (offset < data_sec->sh_size) { memcpy (addend.c, data_ptr + offset, sizeof (Elf32_Word)); addend_value = stringify (addend.i, 0, 'd', 0, "", ""); } else addend_value = "error"; sym_num = ELF32_R_SYM (ptr->r_info); switch ((int)sym_ptr[sym_num].st_shndx) { default: sect_or_undef = "internal"; break; case (int)SHN_UNDEF: sect_or_undef = "external"; break; case (int)SHN_COMMON: sect_or_undef = "common "; break; case (int)SHN_ABS: sect_or_undef = "absolute"; break; } name = elf_string (sym_sec->sh_link, sym_ptr[sym_num].st_name); printf (" Reloc %s: offset= %s%s, info= %s, sym= %s, type= %-*s addend= %*s, %s \"%s\"\n", stringify (rel_num, width_rel_num, 'd', 0, "", ""), stringify (offset, width_offset, 'd', 0, "", ""), offset_value, stringify (ptr->r_info, width_info, 'd', 0, "", ""), stringify (sym_num, width_sym, 'd', 0, "", ""), width_type, get_reloc_type (ELF32_R_TYPE (ptr->r_info)), width_addend, addend_value, sect_or_undef, name); ptr++; rel_num++; } } /* Print the dynamic link structures. */ static void print_section_dynamic (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; Elf32_Dyn *ptr = (Elf32_Dyn *)(file_bytes + sec_hdr->sh_offset); Elf32_Dyn *endptr = (Elf32_Dyn *)((char *)ptr + size); int dyn_num = 0; int width_tag_str = 0; int width_val_num = 0; int width_dyn_num; int len; const char *tag; /* Calculate minimum lengths */ width_dyn_num = stringify_len (endptr - ptr, 'd', 1); while (ptr < endptr) { if (ptr->d_tag >= 0 && ptr->d_tag < sizeof (dyn_tag) / sizeof (dyn_tag[0])) len = strlen (dyn_tag[ ptr->d_tag ]); else len = stringify_len (ptr->d_tag, 'd', 1); if (width_tag_str < len) width_tag_str = len; len = stringify_len (ptr->d_un.d_val, 'd', 1); if (width_val_num < len) width_val_num = len; ptr++; } ptr = (Elf32_Dyn *)(file_bytes + sec_hdr->sh_offset); while (ptr < endptr) { if (ptr->d_tag >= 0 && ptr->d_tag < sizeof (dyn_tag) / sizeof (dyn_tag[0])) tag = dyn_tag[ ptr->d_tag ]; else tag = stringify (ptr->d_tag, 0, 'd', 0, "", ""); printf (" Dynamic record %s: tag= %*s, value= 0x%.8lx, %*ld\n", stringify (dyn_num, width_dyn_num, 'd', 0, "", ""), width_tag_str, tag, (long)ptr->d_un.d_val, width_val_num, (long)ptr->d_un.d_val); ptr++; dyn_num++; } } /* Print the profil section. */ static void print_section_profil (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; uchar_t *ptr = file_bytes + sec_hdr->sh_offset; int sec_off = 0; int width_off = stringify_len (size, 'd', 1); int entsize = sec_hdr->sh_entsize; Elf32_Word value; printf (" Low pc = %s\n", stringify (sec_hdr->sh_link, width_off, 'x', 0, "", "")); printf (" High pc = %s\n\n", stringify (sec_hdr->sh_info, width_off, 'x', 0, "", "")); if ((size % entsize) != 0) { print_section_raw (sec_hdr); return; } if (entsize != sizeof (short) && entsize != sizeof (unsigned) #ifdef NEW_PROFILE && entsize != sizeof (LHISTCOUNTER) #endif && entsize != sizeof (long unsigned)) { print_section_raw (sec_hdr); return; } while (size > 0) { if (entsize == sizeof (short)) { if ((((unsigned long)ptr) & ~(sizeof(short) - 1)) == 0) value = *(short *)ptr; else { union { short i; char c[sizeof (short)]; } u; memcpy (u.c, ptr, sizeof (short)); value = u.i; } if (value) printf (" Offset %s: %s ticks\n", stringify (sec_off, width_off, 'd', 0, "", ""), stringify (value, 6, 'u', 0, "", "")); } else if (entsize == sizeof (unsigned)) { if ((((unsigned long)ptr) & ~(sizeof(unsigned) - 1)) == 0) value = *(unsigned *)ptr; else { union { unsigned i; char c[sizeof (unsigned)]; } u; memcpy (u.c, ptr, sizeof (unsigned)); value = u.i; } if (value) printf (" Offset %s: %s ticks\n", stringify (sec_off, width_off, 'd', 0, "", ""), stringify (value, 11, 'u', 0, "", "")); } else if (entsize == sizeof (long unsigned)) { if ((((unsigned long)ptr) & ~(sizeof(long unsigned) - 1)) == 0) value = *(long unsigned *)ptr; else { union { long unsigned i; char c[sizeof (long unsigned)]; } u; memcpy (u.c, ptr, sizeof (long unsigned)); value = u.i; } if (value) printf (" Offset %s: %s tick(s)\n", stringify (sec_off, width_off, 'd', 0, "", ""), stringify (value, 11, 'd', 0, "", "")); } #ifdef NEW_PROFILE else if (entsize == sizeof (LHISTCOUNTER)) { long double dvalue; if ((((unsigned long)ptr) & ~(sizeof(LHISTCOUNTER) - 1)) == 0) dvalue = LPROF_CNT_TO_LDOUBLE (*(LHISTCOUNTER *)ptr); else { union { LHISTCOUNTER i; char c[sizeof (LHISTCOUNTER)]; } u; memcpy (u.c, ptr, sizeof (LHISTCOUNTER)); dvalue = LPROF_CNT_TO_LDOUBLE (u.i); } if (dvalue) printf (" Offset %s: %16.0Lf tick(s)\n", stringify (sec_off, width_off, 'd', 0, "", ""), dvalue); } #endif else abort (); sec_off += entsize; ptr += entsize; size -= entsize; } } /* Print the gprof section. */ static void print_section_gprof (Elf32_Shdr *sec_hdr) { struct gprof_arc { long frompc; long selfpc; long count; } arc; Elf32_Word size = sec_hdr->sh_size; uchar_t *ptr = file_bytes + sec_hdr->sh_offset; int arc_num = 1; int width_arc = stringify_len ((size / sizeof (arc)), 'd', 1); int width_from = 0; int width_self = 0; int width_cnt = 0; int len; if (sec_hdr->sh_entsize != sizeof (arc) || (size % sizeof (arc)) != 0) { print_section_raw (sec_hdr); return; } while (size > 0) { memcpy ((void *)&arc, ptr, sizeof (arc)); len = stringify_len (arc.frompc, 'x', 1); if (len > width_from) width_from = len; len = stringify_len (arc.selfpc, 'x', 1); if (len > width_self) width_self = len; len = stringify_len (arc.count, 'd', 1); if (len > width_cnt) width_cnt = len; ptr += sizeof (arc); size -= sizeof (arc); } size = sec_hdr->sh_size; ptr = file_bytes + sec_hdr->sh_offset; while (size > 0) { memcpy ((void *)&arc, ptr, sizeof (arc)); printf (" Arc %s: Frompc= %s, Selfpc= %s, Count= %s\n", stringify (arc_num++, width_arc, 'd', 0, "", ""), stringify (arc.frompc, width_from, 'x', 0, "", ""), stringify (arc.selfpc, width_self, 'x', 0, "", ""), stringify (arc.count, width_cnt, 'd', 0, "", "")); ptr += sizeof (arc); size -= sizeof (arc); } } /* Print the prof section. */ static void print_section_prof (Elf32_Shdr *sec_hdr) { struct prof_arc { long selfpc; long count; } record; Elf32_Word size = sec_hdr->sh_size; uchar_t *ptr = file_bytes + sec_hdr->sh_offset; int rec_num = 1; int width_rec = stringify_len ((size / sizeof (record)), 'd', 1); int width_self = 0; int width_cnt = 0; int len; if (sec_hdr->sh_entsize != sizeof (record) || (size % sizeof (record)) != 0) { print_section_raw (sec_hdr); return; } while (size > 0) { memcpy ((void *)&record, ptr, sizeof (record)); len = stringify_len (record.selfpc, 'x', 1); if (len > width_self) width_self = len; len = stringify_len (record.count, 'd', 1); if (len > width_cnt) width_cnt = len; ptr += sizeof (record); size -= sizeof (record); } size = sec_hdr->sh_size; ptr = file_bytes + sec_hdr->sh_offset; while (size > 0) { memcpy ((void *)&record, ptr, sizeof (record)); printf (" Record %s: Selfpc= %s, Count= %s\n", stringify (rec_num++, width_rec, 'd', 0, "", ""), stringify (record.selfpc, width_self, 'x', 0, "", ""), stringify (record.count, width_cnt, 'd', 0, "", "")); ptr += sizeof (record); size -= sizeof (record); } } #ifdef __OSF1__ /* Print the uarea section in the profiling output. */ static void print_section_uarea (Elf32_Shdr *sec_hdr) { Elf32_Word size = sec_hdr->sh_size; struct user *ptr = (struct user *)(file_bytes + sec_hdr->sh_offset); print_section_raw (sec_hdr); if (size == sizeof (struct user)) { int width = 0; int len; time_t t = ptr->u_start.tv_sec; double u_time = ptr->u_ru.ru_utime.tv_sec + (ptr->u_ru.ru_utime.tv_usec / 1000000.0); double s_time = ptr->u_ru.ru_stime.tv_sec + (ptr->u_ru.ru_stime.tv_usec / 1000000.0); char buf[30]; len = sprintf (buf, "%.4f", u_time); if (len > width) width = len; len = sprintf (buf, "%.4f", s_time); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_maxrss, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_ixrss, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_idrss, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_isrss, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_minflt, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_majflt, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_nswap, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_inblock, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_oublock, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_msgsnd, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_msgrcv, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_nsignals, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_nvcsw, 'd', 1); if (len > width) width = len; len = stringify_len (ptr->u_ru.ru_nivcsw, 'd', 1); if (len > width) width = len; putchar ('\n'); printf (" u_comm = %s\n", ptr->u_comm); printf (" u_logname = %s\n", ptr->u_logname); printf (" u_start = %s", ctime (&t)); printf (" u_ru.ru_utime = %*.4f seconds\n", width, u_time); printf (" u_ru.ru_stime = %*.4f seconds\n", width, s_time); printf (" u_ru.ru_maxrss = %s [%s]\n", stringify (ptr->u_ru.ru_maxrss, width, 'd', 0, "", ""), "max memory size"); printf (" u_ru.ru_ixrss = %s [%s]\n", stringify (ptr->u_ru.ru_ixrss, width, 'd', 0, "", ""), "integral shared memory size"); printf (" u_ru.ru_idrss = %s [%s]\n", stringify (ptr->u_ru.ru_idrss, width, 'd', 0, "", ""), "integral unshared data"); printf (" u_ru.ru_isrss = %s [%s]\n", stringify (ptr->u_ru.ru_isrss, width, 'd', 0, "", ""), "integral unshared stack"); printf (" u_ru.ru_minflt = %s [%s]\n", stringify (ptr->u_ru.ru_minflt, width, 'd', 0, "", ""), "page reclaims"); printf (" u_ru.ru_majflt = %s [%s]\n", stringify (ptr->u_ru.ru_majflt, width, 'd', 0, "", ""), "page faults"); printf (" u_ru.ru_nswap = %s [%s]\n", stringify (ptr->u_ru.ru_nswap, width, 'd', 0, "", ""), "swaps"); printf (" u_ru.ru_inblock = %s [%s]\n", stringify (ptr->u_ru.ru_inblock, width, 'd', 0, "", ""), "block input operations"); printf (" u_ru.ru_oublock = %s [%s]\n", stringify (ptr->u_ru.ru_oublock, width, 'd', 0, "", ""), "block output operations"); printf (" u_ru.ru_msgsnd = %s [%s]\n", stringify (ptr->u_ru.ru_msgsnd, width, 'd', 0, "", ""), "messages sent"); printf (" u_ru.ru_msgrcv = %s [%s]\n", stringify (ptr->u_ru.ru_msgrcv, width, 'd', 0, "", ""), "messages received"); printf (" u_ru.ru_nsignals = %s [%s]\n", stringify (ptr->u_ru.ru_nsignals, width, 'd', 0, "", ""), "signals received"); printf (" u_ru.ru_nvcsw = %s [%s]\n", stringify (ptr->u_ru.ru_nvcsw, width, 'd', 0, "", ""), "voluntary context switches"); printf (" u_ru.ru_nivcsw = %s [%s]\n", stringify (ptr->u_ru.ru_nivcsw, width, 'd', 0, "", ""), "involuntary context switches"); } } #endif #ifdef NEW_PROFILE /* Print the stats section. */ static void print_section_stats (Elf32_Shdr *sec_hdr) { struct profile_stats *ptr = (struct profile_stats *)(file_bytes + sec_hdr->sh_offset); if (sec_hdr->sh_size != sizeof (struct profile_stats)) print_section_raw (sec_hdr); else _profile_print_stats(stdout, ptr, (profhdr_p) ? &profhdr : (struct profile_profil *)0); } #endif #ifdef NEW_PROFILE /* Print the profil header section. */ static void print_section_profhdr (Elf32_Shdr *sec_hdr) { struct profile_profil *ptr = (struct profile_profil *)(file_bytes + sec_hdr->sh_offset); if (sec_hdr->sh_size == sizeof (struct profile_profil)) { profhdr = *ptr; profhdr_p = 1; } print_section_raw (sec_hdr); } #endif /* Print the progbits section. */ static void print_section_progbits (Elf32_Shdr *sec_hdr) { const char *name = elf_string ((Elf32_Word)ehdr.e_shstrndx, sec_hdr->sh_name); if (strcmp (name, ".interp") == 0) print_section_string (sec_hdr); else if (no_progbits) printf (" Section body skipped...\n"); else if (strcmp (name, ".comment") == 0) print_section_string (sec_hdr); else if (strcmp (name, ".stab") == 0) print_section_stab (sec_hdr); else if (strcmp (name, ".stabstr") == 0) print_section_string (sec_hdr); else if (strcmp (name, ".debug_sfnames") == 0) print_section_string (sec_hdr); else if (sec_hdr->sh_type == SHT_PROGBITS && ehdr.e_type == ET_PROF) { if (strcmp (name, ".profil") == 0 || strcmp (name, ".lprofil") == 0) print_section_profil (sec_hdr); else if (strcmp (name, ".gprof") == 0) print_section_gprof (sec_hdr); else if (strcmp (name, ".prof") == 0) print_section_prof (sec_hdr); #ifdef __OSF1__ else if (strcmp (name, ".uarea") == 0) print_section_uarea (sec_hdr); #endif #ifdef NEW_PROFILE else if (strcmp (name, ".stats") == 0) print_section_stats (sec_hdr); else if (strcmp (name, ".profhdr") == 0) print_section_profhdr (sec_hdr); else print_section_raw (sec_hdr); #endif } else print_section_raw (sec_hdr); } /* Size the max fields in printing section headers. */ static void size_section (Elf32_Word sec_index) { Elf32_Shdr *sec_hdr = SEC_PTR (sec_index); const char *name; const char *sec_type; struct sec_list *sec_ptr; int len; name = get_section_name (sec_index); if (sec_index) /* skip dummy section */ { add_layout (&file_layout, name, sec_hdr->sh_offset, ((int)sec_hdr->sh_type == SHT_NOBITS) ? 0 : sec_hdr->sh_size, layout_free_no); if (ehdr.e_phnum && (sec_hdr->sh_flags & SHF_ALLOC)) add_layout (&vm_layout, name, sec_hdr->sh_addr, sec_hdr->sh_size, layout_free_no); } if (!summary) return; /* Skip section if desired. */ if (sections) { for (sec_ptr = sections; sec_ptr != (struct sec_list *)0; sec_ptr = sec_ptr->next) { if (strcmp (name, sec_ptr->section) == 0) break; } if (!sec_ptr) return; } len = stringify_len (sec_index, 'd', 1); if (len > sh_index_width) sh_index_width = len; len = strlen (name); if (len > sh_name_width) sh_name_width = len; switch ((int)sec_hdr->sh_type) { default: sec_type = stringify (sec_hdr->sh_type, 0, 'd', 0, "type=", ""); break; case SHT_NULL: sec_type = "none"; break; case SHT_PROGBITS: sec_type = "progbits"; break; case SHT_SYMTAB: sec_type = "symtab"; break; case SHT_STRTAB: sec_type = "strtab"; break; case SHT_RELA: sec_type = "rela"; break; case SHT_HASH: sec_type = "hash"; break; case SHT_DYNAMIC: sec_type = "dynamic"; break; case SHT_NOTE: sec_type = "note"; break; case SHT_NOBITS: sec_type = "nobits"; break; case SHT_REL: sec_type = "rel"; break; case SHT_SHLIB: sec_type = "shlib"; break; case SHT_DYNSYM: sec_type = "dynsym"; break; } len = strlen (sec_type); if (len > sh_type_width) sh_type_width = len; len = stringify_len (sec_hdr->sh_offset, 'd', 1); if (len > sh_start_width) sh_start_width = len; len = stringify_len (sec_hdr->sh_size, 'd', 1); if (len > sh_size_width) sh_size_width = len; len = stringify_len (sec_hdr->sh_offset + (((int)sec_hdr->sh_type == SHT_NOBITS) ? 0 : sec_hdr->sh_size), 'x', 1); if (len > sh_end_width) sh_end_width = len; len = stringify_len (sec_hdr->sh_addr, 'x', 1); if (len > sh_addr_width) sh_addr_width = len; len = stringify_len (sec_hdr->sh_addralign, 'd', 1); if (len > sh_align_width) sh_align_width = len; len = stringify_len (sec_hdr->sh_flags, 'x', 1); if (len > sh_flags_width) sh_flags_width = len; len = stringify_len (sec_hdr->sh_info, 'd', 1); if (len > sh_info_width) sh_info_width = len; len = stringify_len (sec_hdr->sh_link, 'd', 1); if (len > sh_link_width) sh_link_width = len; len = stringify_len (sec_hdr->sh_entsize, 'd', 1); if (len > sh_esize_width) sh_esize_width = len; } /* Print a section header. */ static void print_section (Elf32_Word sec_index) { Elf32_Shdr *sec_hdr = SEC_PTR (sec_index); const char *sec_type; const char *name; struct sec_list *sec_ptr; void (*sec_func)(Elf32_Shdr *); /* Skip section if desired. */ name = get_section_name (sec_index); if (sections) { for (sec_ptr = sections; sec_ptr != (struct sec_list *)0; sec_ptr = sec_ptr->next) { if (strcmp (name, sec_ptr->section) == 0) break; } if (!sec_ptr) return; } switch ((int)sec_hdr->sh_type) { default: sec_type = stringify (sec_hdr->sh_type, 0, 'd', 0, "type=", ""); sec_func = print_section_raw; break; case SHT_NULL: sec_type = "none"; sec_func = print_section_raw; break; case SHT_PROGBITS: sec_type = "progbits"; sec_func = print_section_progbits; break; case SHT_SYMTAB: sec_type = "symtab"; sec_func = print_section_symtab; break; case SHT_STRTAB: sec_type = "strtab"; sec_func = print_section_string; break; case SHT_RELA: sec_type = "rela"; sec_func = print_section_rela; break; case SHT_HASH: sec_type = "hash"; sec_func = print_section_hash; break; case SHT_DYNAMIC: sec_type = "dynamic"; sec_func = print_section_dynamic; break; case SHT_NOTE: sec_type = "note"; sec_func = print_section_raw; break; case SHT_NOBITS: sec_type = "nobits"; sec_func = print_section_raw; break; case SHT_REL: sec_type = "rel"; sec_func = print_section_rel; break; case SHT_SHLIB: sec_type = "shlib"; sec_func = print_section_raw; break; case SHT_DYNSYM: sec_type = "dynsym"; sec_func = print_section_symtab; break; } printf ("%sSect %s %-*s %-*s off=%s %s size=%s addr=%s align=%s flag=%s [%s%s%s] esize=%s info=%s link=%s\n", (!summary || sec_index == 0) ? "\n" : "", stringify (sec_index, sh_index_width, 'd', 0, "", ""), sh_name_width, name, sh_type_width, sec_type, stringify (sec_hdr->sh_offset, sh_start_width, 'x', 0, "", ""), stringify (sec_hdr->sh_offset + ((sec_hdr->sh_type == SHT_NOBITS) ? 0 : sec_hdr->sh_size), sh_end_width, 'x', 0, "", ""), stringify (sec_hdr->sh_size, sh_size_width, 'd', 0, "", ""), stringify (sec_hdr->sh_addr, sh_addr_width, 'x', 0, "", ""), stringify (sec_hdr->sh_addralign, sh_align_width, 'd', 0, "", ""), stringify (sec_hdr->sh_flags, sh_flags_width, 'x', 0, "", ""), (sec_hdr->sh_flags & SHF_EXECINSTR) ? "x" : "-", (sec_hdr->sh_flags & SHF_ALLOC) ? "a" : "-", (sec_hdr->sh_flags & SHF_WRITE) ? "w" : "-", stringify (sec_hdr->sh_entsize, sh_esize_width, 'd', 0, "", ""), stringify (sec_hdr->sh_info, sh_info_width, 'd', 0, "", ""), stringify (sec_hdr->sh_link, sh_link_width, 'd', 0, "", "")); if (sec_hdr->sh_size > 0 && sec_hdr->sh_type != SHT_NOBITS && !summary) { putchar ('\n'); (*sec_func) (sec_hdr); } } /* Print program headers. */ static void print_proghdr (void) { Elf32_Phdr *prog_hdr; const char *type; Elf32_Word ph_index; int width_index = stringify_len (ehdr.e_phnum, 'd', 1); int width_vaddr = 0; int width_vend = 0; int width_type = 0; int width_align = 0; int width_flags = 0; int width_offset = 0; int width_offend = 0; int width_filesz = 0; int width_memsz = 0; int len; char flags[4]; char *load_start; char *load_end; const char *load_num; putchar ('\n'); for (ph_index = 0; ph_index < ehdr.e_phnum; ph_index++) { prog_hdr = PROGHDR_PTR (ph_index); switch ((int)prog_hdr->p_type) { default: type = stringify (prog_hdr->p_type, 0, 'd', 0, "type=", ""); break; case PT_NULL: type = "null,"; break; case PT_LOAD: type = "load,"; break; case PT_DYNAMIC: type = "dynamic,"; break; case PT_INTERP: type = "interp,"; break; case PT_NOTE: type = "note,"; break; case PT_SHLIB: type = "shlib,"; break; case PT_PHDR: type = "proghdr,"; break; } len = strlen (type); if (len > width_type) width_type = len; len = stringify_len (prog_hdr->p_vaddr, 'x', 1); if (len > width_vaddr) width_vaddr = len; len = stringify_len (prog_hdr->p_vaddr + prog_hdr->p_memsz, 'x', 1); if (len > width_vend) width_vend = len; len = stringify_len (prog_hdr->p_align, 'd', 1); if (len > width_align) width_align = len; len = stringify_len (prog_hdr->p_flags, 'x', 1); if (len > width_flags) width_flags = len; len = stringify_len (prog_hdr->p_offset, 'x', 1); if (len > width_offset) width_offset = len; len = stringify_len (prog_hdr->p_offset + prog_hdr->p_filesz, 'x', 1); if (len > width_offend) width_offend = len; len = stringify_len (prog_hdr->p_filesz, 'd', 1); if (len > width_filesz) width_filesz = len; len = stringify_len (prog_hdr->p_memsz, 'd', 1); if (len > width_memsz) width_memsz = len; } for (ph_index = 0; ph_index < ehdr.e_phnum; ph_index++) { prog_hdr = PROGHDR_PTR (ph_index); switch ((int)prog_hdr->p_type) { default: type = stringify (prog_hdr->p_type, 0, 'd', 0, "type=", ""); break; case PT_NULL: type = "null,"; break; case PT_LOAD: type = "load,"; break; case PT_DYNAMIC: type = "dynamic,"; break; case PT_INTERP: type = "interp,"; break; case PT_NOTE: type = "note,"; break; case PT_SHLIB: type = "shlib,"; break; case PT_PHDR: type = "proghdr,"; break; } flags[0] = (prog_hdr->p_flags & PF_R) ? 'r' : '-'; flags[1] = (prog_hdr->p_flags & PF_W) ? 'w' : '-'; flags[2] = (prog_hdr->p_flags & PF_X) ? 'x' : '-'; flags[3] = '\0'; printf ("Hdr %s: %-*s vaddr= %s %s, align= %s, flags= %s [%s], off= %s %s, filesz= %s, memsz= %s\n", stringify (ph_index, width_index, 'd', 0, "", ""), width_type, type, stringify (prog_hdr->p_vaddr, width_vaddr, 'x', 0, "", ""), stringify (prog_hdr->p_vaddr + prog_hdr->p_memsz, width_vend, 'x', 0, "", ""), stringify (prog_hdr->p_align, width_align, 'd', 0, "", ""), stringify (prog_hdr->p_flags, width_flags, 'x', 0, "", ""), flags, stringify (prog_hdr->p_offset, width_offset, 'x', 0, "", ""), stringify (prog_hdr->p_offset + prog_hdr->p_filesz, width_offend, 'x', 0, "", ""), stringify (prog_hdr->p_filesz, width_filesz, 'd', 0, "", ""), stringify (prog_hdr->p_memsz, width_memsz, 'd', 0, "", "")); if ((int)prog_hdr->p_type == PT_LOAD) { load_num = stringify (ph_index, 0, 'd', 0, "", ""); len = strlen (load_num) + strlen (flags); load_start = (char *) xmalloc (sizeof("Load cmd #, region start []") + len); sprintf (load_start, "Load cmd #%s, region start [%s]", load_num, flags); add_layout (&vm_layout, load_start, prog_hdr->p_vaddr, 0, layout_free_no); add_layout (&file_layout, load_start, prog_hdr->p_offset, 0, layout_free_yes); load_end = (char *) xmalloc (sizeof("Load cmd #, region end []") + len); sprintf (load_end, "Load cmd #%s, region end [%s]", load_num, flags); add_layout (&vm_layout, load_end, prog_hdr->p_vaddr + prog_hdr->p_memsz, 0, layout_free_no); add_layout (&file_layout, load_end, prog_hdr->p_offset + prog_hdr->p_filesz, 0, layout_free_yes); } } } /* Scan for linker generated symbols, and put them in the VM layout */ static void find_linker_symbols (void) { int i; Elf32_Shdr *sec_hdr; const char *name; Elf32_Sym *ptr; Elf32_Sym *endptr; layout_t *layout_ptr; for (i = 0; i < ehdr.e_shnum; i++) { sec_hdr = SEC_PTR (i); if ((int)sec_hdr->sh_type != SHT_SYMTAB && (int)sec_hdr->sh_type != SHT_DYNSYM) continue; ptr = (Elf32_Sym *)(file_bytes + sec_hdr->sh_offset); endptr = (Elf32_Sym *)((char *)ptr + sec_hdr->sh_size); for ( ; ptr < endptr; ptr++) { name = elf_string (sec_hdr->sh_link, ptr->st_name); if (name[0] == '\0') continue; switch ((name[0] << 16) | (name[1] << 8) | name[2]) { default: continue; case (('_' << 16) | ('G' << 8) | 'L'): if (strcmp (name, "_GLOBAL_OFFSET_POINTER") != 0) continue; break; case (('_' << 16) | ('e' << 8) | 'n'): if (strcmp (name, "_end") != 0) continue; break; case (('_' << 16) | ('e' << 8) | 'd'): if (strcmp (name, "_edata") != 0) continue; break; case (('_' << 16) | ('e' << 8) | 't'): if (strcmp (name, "_etext") != 0) continue; break; case (('e' << 16) | ('n' << 8) | 'd'): if (strcmp (name, "end") != 0) continue; break; case (('e' << 16) | ('d' << 8) | 'a'): if (strcmp (name, "edata") != 0) continue; break; case (('e' << 16) | ('t' << 8) | 'e'): if (strcmp (name, "etext") != 0) continue; break; } for (layout_ptr = vm_layout; layout_ptr != (layout_t *)0; layout_ptr = layout_ptr->next) { if (layout_ptr->name == name) break; if (layout_ptr->name[0] == name[0] && strcmp (layout_ptr->name, name) == 0) break; } if (layout_ptr == (layout_t *)0) add_layout (&vm_layout, name, ptr->st_value, 0, layout_free_no); } } } int main(int argc, char *argv[]) { int argnum; Elf32_Word i; int letter; int ch; while ((letter = getopt (argc, argv, "deln:pst:vx")) != EOF) { switch (letter) { default: errors++; break; case 'd': /* invoke objdump to disassemble text sections */ objdump = 1; break; case 'e': /* put linker generated symbols in the VM layout */ linker_symbols = 1; break; case 'l': /* skip printing layout information */ no_layout = 1; break; case 'n': /* print a specific section */ { struct sec_list *p = (struct sec_list *) xmalloc (sizeof (struct sec_list)); p->next = sections; p->section = optarg; sections = p; break; } case 'p': /* skip printing the progbits section body */ no_progbits = 1; break; case 's': /* print just the summary information */ summary = 1; break; case 't': /* specify output format */ format = ch = tolower (*optarg); if (optarg[1] != '\0' || (ch != 'd' && ch != 'x' && ch != 'o' && ch != 'u' & ch != 'i')) { fprintf (stderr, "-t %s is not 'i', 'd', 'o', 'u', or 'x'\n", optarg); errors++; } break; case 'v': /* print version string */ print_vers = 1; break; case 'x': /* string table pointer is invalid */ ignore_string = 1; break; } } if (errors || optind >= argc) { fprintf (stderr, "Calling sequence:\n\n"); fprintf (stderr, "\telfdump [-n name]... [-delpsx] [-t format] files...\n"); fprintf (stderr, "\nwhere:\n\n"); fprintf (stderr, "-d\tInvoke objdump -d for executable sections.\n"); fprintf (stderr, "-e\tPut the linker generated symbols in the vm layout.\n"); fprintf (stderr, "-l\tDo not print file/VM layout information.\n"); fprintf (stderr, "-n name\tOnly print section 'name'\n"); fprintf (stderr, "-p\tDo not print the body of a progbits section.\n"); fprintf (stderr, "-s\tOnly print section header summary information.\n"); fprintf (stderr, "-t fmt\tSpecify output format for numbers (i, d, o, u, or x).\n"); fprintf (stderr, "-v\tPrint version number.\n"); fprintf (stderr, "-x\tAssume the string table is corrupt.\n"); return 1; } if (print_vers) printf ("%s\n\n", elfdump_what_string); for (argnum = optind; (file = argv[argnum]) != (char *)0; argnum++) { if (argnum > optind) printf ("\f====================\n\n"); /* Map in the file. */ if (stat (file, &file_stat) < 0 || (file_fd = open (file, O_RDONLY)) < 0 || (file_bytes = (uchar_t *) mmap ((caddr_t)0, (size_t)file_stat.st_size, PROT_READ, MAP_PRIVATE|MAP_FILE|MAP_VARIABLE, file_fd, (off_t)0)) == (uchar_t *)-1) { perror (file); errors++; continue; } ehdr = *(Elf32_Ehdr *)file_bytes; if (file_stat.st_size < sizeof (ehdr) || memcmp (ehdr.e_ident, "\177ELF", 4) != 0) { fprintf (stderr, "%s is not an ELF file.\n", file); errors++; continue; } if (ehdr.e_ehsize != sizeof (ehdr)) { fprintf (stderr, "%s elf header is %s bytes, expected %s\n", file, stringify (ehdr.e_ehsize, 0, 'd', 0, "", ""), stringify (sizeof (ehdr), 0, 'd', 0, "", "")); errors++; continue; } add_layout (&file_layout, "Global header", 0, sizeof (ehdr), layout_free_no); if (ehdr.e_shnum) add_layout (&file_layout, "Section headers", ehdr.e_shoff, ehdr.e_shnum * ehdr.e_shentsize, layout_free_no); if (ehdr.e_phnum) add_layout (&file_layout, "Program headers", ehdr.e_phoff, ehdr.e_phnum * ehdr.e_phentsize, layout_free_no); printf ("File: %s", file); switch (ehdr.e_type) { default: printf (", type %d", ehdr.e_type); break; case ET_NONE: printf (", no file type"); break; case ET_REL: printf (", relocatable"); break; case ET_EXEC: printf (", executable"); break; case ET_DYN: printf (", shared object"); break; case ET_CORE: printf (", core file"); break; case ET_PROF: printf (", profile output"); break; } switch (ehdr.e_machine) { default: printf (", machine %d", ehdr.e_machine); break; case EM_NONE: printf (", no machine"); break; case EM_M32: printf (", we 32100"); break; case EM_SPARC: printf (", sparc"); break; case EM_386: printf (", i386"); break; case EM_68K: printf (", m68k"); break; case EM_88K: printf (", m88k"); break; case EM_860: printf (", i860"); break; case EM_MIPS: printf (", mips"); break; } switch (ehdr.e_ident[EI_CLASS]) { default: printf (", class %d", ehdr.e_ident[EI_CLASS]); break; case ELFCLASS32: printf (", 32-bit"); break; case ELFCLASS64: printf (", 64-bit"); break; } switch (ehdr.e_ident[EI_DATA]) { default: printf (", data %d", ehdr.e_ident[EI_DATA]); break; case ELFDATA2LSB: printf (", little endian"); break; case ELFDATA2MSB: printf (", big endian"); break; } printf ("\nversion = %s, elf header size = %s, entry = %s\n", stringify (ehdr.e_version, 0, 'd', 0, "", ""), stringify (ehdr.e_ehsize, 0, 'd', 0, "", ""), stringify (ehdr.e_entry, 8, 'x', 0, "", "")); printf ("flags = %s, section header string index = %s\n", stringify (ehdr.e_flags, 8, 'x', 0, "", ""), stringify (ehdr.e_shstrndx, 0, 'd', 0, "", "")); printf ("# sections = %s, section element size = %s, section offset = %s\n", stringify (ehdr.e_shnum, 2, 'd', 0, "", ""), stringify (ehdr.e_shentsize, 2, 'd', 0, "", ""), stringify (ehdr.e_shoff, 6, 'd', 0, "", "")); printf ("# headers = %s, header element size = %s, header offset = %s\n\n", stringify (ehdr.e_phnum, 2, 'd', 0, "", ""), stringify (ehdr.e_phentsize, 2, 'd', 0, "", ""), stringify (ehdr.e_phoff, 6, 'd', 0, "", "")); /* Print each of the sections now. */ for (i = 0; i < ehdr.e_shnum; i++) size_section (i); for (i = 0; i < ehdr.e_shnum; i++) print_section (i); /* Print each of the program headers now. */ if (ehdr.e_phnum != 0) print_proghdr (); /* Print the layout information if desired */ if (!no_layout) { print_layout (file_layout, "ELF file"); if (ehdr.e_phnum) { if (linker_symbols) find_linker_symbols (); print_layout (vm_layout, "Virtual Memory"); } } if (file_bytes != (uchar_t *)-1) munmap ((caddr_t)file_bytes, (size_t)file_stat.st_size); if (file_fd >= 0) close (file_fd); if (file_layout) free_layout (&file_layout); if (vm_layout) free_layout (&vm_layout); } return (errors) ? 1 : 0; }