X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=3561eff0a6eb915372dc99bd3777c4cd51a57b5d;hb=8c9a987975e3bda9ed098c87ece7a2140bf9fffa;hp=790a609b86c6c13e8a508e9e020af11c6f161e1d;hpb=ef23021837539a0b98c7761a62f0fb316a82a9de;p=binutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index 790a609b86c..3561eff0a6e 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -21,7 +21,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* The difference between readelf and objdump: + Both programs are capabale of displaying the contents of ELF format files, + so why does the binutils project have two file dumpers ? + + The reason is that objdump sees an ELF file through a BFD filter of the + world; if BFD has a bug where, say, it disagrees about a machine constant + in e_flags, then the odds are good that it will remain internally + consistent. The linker sees it the BFD way, objdump sees it the BFD way, + GAS sees it the BFD way. There was need for a tool to go find out what + the file actually says. + + This is why the readelf program does not link against the BFD library - it + exists as an independent program to help verify the correct working of BFD. + + There is also the case that readelf can provide more information about an + ELF file than is provided by objdump. In particular it can display DWARF + debugging information which (at the moment) objdump cannot. */ + #include #include #include @@ -90,11 +108,15 @@ #include "elf/iq2000.h" #include "elf/xtensa.h" +#include "aout/ar.h" + #include "bucomm.h" #include "getopt.h" #include "libiberty.h" char *program_name = "readelf"; +long archive_file_offset; +unsigned long archive_file_size; unsigned long dynamic_addr; bfd_size_type dynamic_size; char *dynamic_strings; @@ -106,11 +128,11 @@ Elf_Internal_Syminfo *dynamic_syminfo; unsigned long dynamic_syminfo_offset; unsigned int dynamic_syminfo_nent; char program_interpreter[64]; -long dynamic_info[DT_JMPREL + 1]; -long version_info[16]; -long loadaddr = 0; +bfd_vma dynamic_info[DT_JMPREL + 1]; +bfd_vma version_info[16]; Elf_Internal_Ehdr elf_header; Elf_Internal_Shdr *section_headers; +Elf_Internal_Phdr *program_headers; Elf_Internal_Dyn *dynamic_segment; Elf_Internal_Shdr *symtab_shndx_hdr; int show_name; @@ -162,234 +184,8 @@ typedef enum print_mode } print_mode; -/* Forward declarations for dumb compilers. */ -static void print_vma - PARAMS ((bfd_vma, print_mode)); -static void print_symbol - PARAMS ((int, const char *)); -static bfd_vma (*byte_get) - PARAMS ((unsigned char *, int)); -static bfd_vma byte_get_little_endian - PARAMS ((unsigned char *, int)); -static bfd_vma byte_get_big_endian - PARAMS ((unsigned char *, int)); -static void (*byte_put) - PARAMS ((unsigned char *, bfd_vma, int)); -static void byte_put_little_endian - PARAMS ((unsigned char *, bfd_vma, int)); -static void byte_put_big_endian - PARAMS ((unsigned char *, bfd_vma, int)); -static const char *get_mips_dynamic_type - PARAMS ((unsigned long)); -static const char *get_sparc64_dynamic_type - PARAMS ((unsigned long)); -static const char *get_ppc64_dynamic_type - PARAMS ((unsigned long)); -static const char *get_parisc_dynamic_type - PARAMS ((unsigned long)); -static const char *get_ia64_dynamic_type - PARAMS ((unsigned long)); -static const char *get_dynamic_type - PARAMS ((unsigned long)); -static int slurp_rela_relocs - PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **, - unsigned long *)); -static int slurp_rel_relocs - PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **, - unsigned long *)); -static int dump_relocations - PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, - unsigned long, char *, int)); -static char *get_file_type - PARAMS ((unsigned)); -static char *get_machine_name - PARAMS ((unsigned)); -static void decode_ARM_machine_flags - PARAMS ((unsigned, char[])); -static char *get_machine_flags - PARAMS ((unsigned, unsigned)); -static const char *get_mips_segment_type - PARAMS ((unsigned long)); -static const char *get_parisc_segment_type - PARAMS ((unsigned long)); -static const char *get_ia64_segment_type - PARAMS ((unsigned long)); -static const char *get_segment_type - PARAMS ((unsigned long)); -static const char *get_mips_section_type_name - PARAMS ((unsigned int)); -static const char *get_parisc_section_type_name - PARAMS ((unsigned int)); -static const char *get_ia64_section_type_name - PARAMS ((unsigned int)); -static const char *get_section_type_name - PARAMS ((unsigned int)); -static const char *get_symbol_binding - PARAMS ((unsigned int)); -static const char *get_symbol_type - PARAMS ((unsigned int)); -static const char *get_symbol_visibility - PARAMS ((unsigned int)); -static const char *get_symbol_index_type - PARAMS ((unsigned int)); -static const char *get_dynamic_flags - PARAMS ((bfd_vma)); -static void usage - PARAMS ((void)); -static void parse_args - PARAMS ((int, char **)); -static int process_file_header - PARAMS ((void)); -static int process_program_headers - PARAMS ((FILE *)); -static int process_section_headers - PARAMS ((FILE *)); -static int process_unwind - PARAMS ((FILE *)); -static void dynamic_segment_mips_val - PARAMS ((Elf_Internal_Dyn *)); -static void dynamic_segment_parisc_val - PARAMS ((Elf_Internal_Dyn *)); -static void dynamic_segment_ia64_val - PARAMS ((Elf_Internal_Dyn *)); -static int process_dynamic_segment - PARAMS ((FILE *)); -static int process_symbol_table - PARAMS ((FILE *)); -static int process_syminfo - PARAMS ((FILE *)); -static int process_section_contents - PARAMS ((FILE *)); -static void process_mips_fpe_exception - PARAMS ((int)); -static int process_mips_specific - PARAMS ((FILE *)); -static int process_file - PARAMS ((char *)); -static int process_relocs - PARAMS ((FILE *)); -static int process_version_sections - PARAMS ((FILE *)); -static char *get_ver_flags - PARAMS ((unsigned int)); -static int get_32bit_section_headers - PARAMS ((FILE *, unsigned int)); -static int get_64bit_section_headers - PARAMS ((FILE *, unsigned int)); -static int get_32bit_program_headers - PARAMS ((FILE *, Elf_Internal_Phdr *)); -static int get_64bit_program_headers - PARAMS ((FILE *, Elf_Internal_Phdr *)); -static int get_file_header - PARAMS ((FILE *)); -static Elf_Internal_Sym *get_32bit_elf_symbols - PARAMS ((FILE *, Elf_Internal_Shdr *)); -static Elf_Internal_Sym *get_64bit_elf_symbols - PARAMS ((FILE *, Elf_Internal_Shdr *)); -static const char *get_elf_section_flags - PARAMS ((bfd_vma)); -static int *get_dynamic_data - PARAMS ((FILE *, unsigned int)); -static int get_32bit_dynamic_segment - PARAMS ((FILE *)); -static int get_64bit_dynamic_segment - PARAMS ((FILE *)); -#ifdef SUPPORT_DISASSEMBLY -static int disassemble_section - PARAMS ((Elf_Internal_Shdr *, FILE *)); -#endif -static int dump_section - PARAMS ((Elf_Internal_Shdr *, FILE *)); -static int display_debug_section - PARAMS ((Elf_Internal_Shdr *, FILE *)); -static int display_debug_info - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_not_supported - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int prescan_debug_info - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_lines - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_pubnames - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_abbrev - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_aranges - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_frames - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_macinfo - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_str - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_loc - PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); -static unsigned char *process_abbrev_section - PARAMS ((unsigned char *, unsigned char *)); -static void load_debug_str - PARAMS ((FILE *)); -static void free_debug_str - PARAMS ((void)); -static const char *fetch_indirect_string - PARAMS ((unsigned long)); -static void load_debug_loc - PARAMS ((FILE *)); -static void free_debug_loc - PARAMS ((void)); -static unsigned long read_leb128 - PARAMS ((unsigned char *, int *, int)); -static int process_extended_line_op - PARAMS ((unsigned char *, int, int)); -static void reset_state_machine - PARAMS ((int)); -static char *get_TAG_name - PARAMS ((unsigned long)); -static char *get_AT_name - PARAMS ((unsigned long)); -static char *get_FORM_name - PARAMS ((unsigned long)); -static void free_abbrevs - PARAMS ((void)); -static void add_abbrev - PARAMS ((unsigned long, unsigned long, int)); -static void add_abbrev_attr - PARAMS ((unsigned long, unsigned long)); -static unsigned char *read_and_display_attr - PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, - unsigned long, unsigned long, int)); -static unsigned char *read_and_display_attr_value - PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, - unsigned long, unsigned long, int)); -static unsigned char *display_block - PARAMS ((unsigned char *, unsigned long)); -static void decode_location_expression - PARAMS ((unsigned char *, unsigned int, unsigned long)); -static void request_dump - PARAMS ((unsigned int, int)); -static const char *get_elf_class - PARAMS ((unsigned int)); -static const char *get_data_encoding - PARAMS ((unsigned int)); -static const char *get_osabi_name - PARAMS ((unsigned int)); -static int guess_is_rela - PARAMS ((unsigned long)); -static const char *get_note_type - PARAMS ((unsigned int)); -static const char *get_netbsd_elfcore_note_type - PARAMS ((unsigned int)); -static int process_note - PARAMS ((Elf_Internal_Note *)); -static int process_corefile_note_segment - PARAMS ((FILE *, bfd_vma, bfd_vma)); -static int process_corefile_note_segments - PARAMS ((FILE *)); -static int process_corefile_contents - PARAMS ((FILE *)); -static int process_arch_specific - PARAMS ((FILE *)); -static int process_gnu_liblist - PARAMS ((FILE *)); +static bfd_vma (*byte_get) (unsigned char *, int); +static void (*byte_put) (unsigned char *, bfd_vma, int); typedef int Elf32_Word; @@ -441,56 +237,50 @@ typedef int Elf32_Word; static void -error VPARAMS ((const char *message, ...)) +error (const char *message, ...) { - VA_OPEN (args, message); - VA_FIXEDARG (args, const char *, message); + va_list args; + va_start (args, message); fprintf (stderr, _("%s: Error: "), program_name); vfprintf (stderr, message, args); - VA_CLOSE (args); + va_end (args); } static void -warn VPARAMS ((const char *message, ...)) +warn (const char *message, ...) { - VA_OPEN (args, message); - VA_FIXEDARG (args, const char *, message); + va_list args; + va_start (args, message); fprintf (stderr, _("%s: Warning: "), program_name); vfprintf (stderr, message, args); - VA_CLOSE (args); + va_end (args); } -static PTR get_data PARAMS ((PTR, FILE *, long, size_t, const char *)); - -static PTR -get_data (var, file, offset, size, reason) - PTR var; - FILE *file; - long offset; - size_t size; - const char *reason; +static void * +get_data (void *var, FILE *file, long offset, size_t size, const char *reason) { - PTR mvar; + void *mvar; if (size == 0) return NULL; - if (fseek (file, offset, SEEK_SET)) + if (fseek (file, archive_file_offset + offset, SEEK_SET)) { - error (_("Unable to seek to %x for %s\n"), offset, reason); + error (_("Unable to seek to 0x%x for %s\n"), + archive_file_offset + offset, reason); return NULL; } mvar = var; if (mvar == NULL) { - mvar = (PTR) malloc (size); + mvar = malloc (size); if (mvar == NULL) { - error (_("Out of memory allocating %d bytes for %s\n"), + error (_("Out of memory allocating 0x%x bytes for %s\n"), size, reason); return NULL; } @@ -498,7 +288,7 @@ get_data (var, file, offset, size, reason) if (fread (mvar, size, 1, file) != 1) { - error (_("Unable to read in %d bytes of %s\n"), size, reason); + error (_("Unable to read in 0x%x bytes of %s\n"), size, reason); if (mvar != var) free (mvar); return NULL; @@ -508,9 +298,7 @@ get_data (var, file, offset, size, reason) } static bfd_vma -byte_get_little_endian (field, size) - unsigned char *field; - int size; +byte_get_little_endian (unsigned char *field, int size) { switch (size) { @@ -540,7 +328,7 @@ byte_get_little_endian (field, size) /* This is a special case, generated by the BYTE_GET8 macro. It means that we are loading an 8 byte value from a field in an external structure into an 8 byte value in a field - in an internal strcuture. */ + in an internal structure. */ return ((bfd_vma) (field[0])) | (((bfd_vma) (field[1])) << 8) | (((bfd_vma) (field[2])) << 16) @@ -556,11 +344,29 @@ byte_get_little_endian (field, size) } } +static bfd_vma +byte_get_signed (unsigned char *field, int size) +{ + bfd_vma x = byte_get (field, size); + + switch (size) + { + case 1: + return (x ^ 0x80) - 0x80; + case 2: + return (x ^ 0x8000) - 0x8000; + case 4: + return (x ^ 0x80000000) - 0x80000000; + case 8: + case -8: + return x; + default: + abort (); + } +} + static void -byte_put_little_endian (field, value, size) - unsigned char * field; - bfd_vma value; - int size; +byte_put_little_endian (unsigned char *field, bfd_vma value, int size) { switch (size) { @@ -589,9 +395,7 @@ byte_put_little_endian (field, value, size) /* Print a VMA value. */ static void -print_vma (vma, mode) - bfd_vma vma; - print_mode mode; +print_vma (bfd_vma vma, print_mode mode) { #ifdef BFD64 if (is_32bit_elf) @@ -599,13 +403,34 @@ print_vma (vma, mode) { switch (mode) { - case FULL_HEX: printf ("0x"); /* drop through */ - case LONG_HEX: printf ("%8.8lx", (unsigned long) vma); break; - case PREFIX_HEX: printf ("0x"); /* drop through */ - case HEX: printf ("%lx", (unsigned long) vma); break; - case DEC: printf ("%ld", (unsigned long) vma); break; - case DEC_5: printf ("%5ld", (long) vma); break; - case UNSIGNED: printf ("%lu", (unsigned long) vma); break; + case FULL_HEX: + printf ("0x"); + /* Drop through. */ + case LONG_HEX: + printf ("%8.8lx", (unsigned long) vma); + break; + + case DEC_5: + if (vma <= 99999) + { + printf ("%5ld", (long) vma); + break; + } + /* Drop through. */ + case PREFIX_HEX: + printf ("0x"); + /* Drop through. */ + case HEX: + printf ("%lx", (unsigned long) vma); + break; + + case DEC: + printf ("%ld", (unsigned long) vma); + break; + + case UNSIGNED: + printf ("%lu", (unsigned long) vma); + break; } } #ifdef BFD64 @@ -615,7 +440,7 @@ print_vma (vma, mode) { case FULL_HEX: printf ("0x"); - /* drop through */ + /* Drop through. */ case LONG_HEX: printf_vma (vma); @@ -623,7 +448,7 @@ print_vma (vma, mode) case PREFIX_HEX: printf ("0x"); - /* drop through */ + /* Drop through. */ case HEX: #if BFD_HOST_64BIT_LONG @@ -650,13 +475,18 @@ print_vma (vma, mode) case DEC_5: #if BFD_HOST_64BIT_LONG - printf ("%5ld", vma); + if (vma <= 99999) + printf ("%5ld", vma); + else + printf ("%#lx", vma); #else if (_bfd_int64_high (vma)) /* ugg */ printf ("++%ld", _bfd_int64_low (vma)); - else + else if (vma <= 99999) printf ("%5ld", _bfd_int64_low (vma)); + else + printf ("%#lx", _bfd_int64_low (vma)); #endif break; @@ -683,9 +513,7 @@ print_vma (vma, mode) truncating or padding as necessary. */ static void -print_symbol (width, symbol) - int width; - const char *symbol; +print_symbol (int width, const char *symbol) { if (do_wide) printf ("%s", symbol); @@ -696,9 +524,7 @@ print_symbol (width, symbol) } static bfd_vma -byte_get_big_endian (field, size) - unsigned char *field; - int size; +byte_get_big_endian (unsigned char *field, int size) { switch (size) { @@ -728,7 +554,7 @@ byte_get_big_endian (field, size) /* This is a special case, generated by the BYTE_GET8 macro. It means that we are loading an 8 byte value from a field in an external structure into an 8 byte value in a field - in an internal strcuture. */ + in an internal structure. */ return ((bfd_vma) (field[7])) | (((bfd_vma) (field[6])) << 8) | (((bfd_vma) (field[5])) << 16) @@ -746,10 +572,7 @@ byte_get_big_endian (field, size) } static void -byte_put_big_endian (field, value, size) - unsigned char * field; - bfd_vma value; - int size; +byte_put_big_endian (unsigned char *field, bfd_vma value, int size) { switch (size) { @@ -783,8 +606,7 @@ byte_put_big_endian (field, value, size) /* Guess the relocation size commonly used by the specific machines. */ static int -guess_is_rela (e_machine) - unsigned long e_machine; +guess_is_rela (unsigned long e_machine) { switch (e_machine) { @@ -796,7 +618,6 @@ guess_is_rela (e_machine) case EM_DLX: case EM_OPENRISC: case EM_OR32: - case EM_M32R: case EM_CYGNUS_M32R: case EM_D10V: case EM_CYGNUS_D10V: @@ -846,6 +667,7 @@ guess_is_rela (e_machine) case EM_IQ2000: case EM_XTENSA: case EM_XTENSA_OLD: + case EM_M32R: return TRUE; case EM_MMA: @@ -872,12 +694,11 @@ guess_is_rela (e_machine) } static int -slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp) - FILE *file; - unsigned long rel_offset; - unsigned long rel_size; - Elf_Internal_Rela **relasp; - unsigned long *nrelasp; +slurp_rela_relocs (FILE *file, + unsigned long rel_offset, + unsigned long rel_size, + Elf_Internal_Rela **relasp, + unsigned long *nrelasp) { Elf_Internal_Rela *relas; unsigned long nrelas; @@ -887,15 +708,13 @@ slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp) { Elf32_External_Rela *erelas; - erelas = (Elf32_External_Rela *) get_data (NULL, file, rel_offset, - rel_size, _("relocs")); + erelas = get_data (NULL, file, rel_offset, rel_size, _("relocs")); if (!erelas) return 0; nrelas = rel_size / sizeof (Elf32_External_Rela); - relas = (Elf_Internal_Rela *) - malloc (nrelas * sizeof (Elf_Internal_Rela)); + relas = malloc (nrelas * sizeof (Elf_Internal_Rela)); if (relas == NULL) { @@ -916,15 +735,13 @@ slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp) { Elf64_External_Rela *erelas; - erelas = (Elf64_External_Rela *) get_data (NULL, file, rel_offset, - rel_size, _("relocs")); + erelas = get_data (NULL, file, rel_offset, rel_size, _("relocs")); if (!erelas) return 0; nrelas = rel_size / sizeof (Elf64_External_Rela); - relas = (Elf_Internal_Rela *) - malloc (nrelas * sizeof (Elf_Internal_Rela)); + relas = malloc (nrelas * sizeof (Elf_Internal_Rela)); if (relas == NULL) { @@ -947,12 +764,11 @@ slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp) } static int -slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp) - FILE *file; - unsigned long rel_offset; - unsigned long rel_size; - Elf_Internal_Rela **relsp; - unsigned long *nrelsp; +slurp_rel_relocs (FILE *file, + unsigned long rel_offset, + unsigned long rel_size, + Elf_Internal_Rela **relsp, + unsigned long *nrelsp) { Elf_Internal_Rela *rels; unsigned long nrels; @@ -962,14 +778,13 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp) { Elf32_External_Rel *erels; - erels = (Elf32_External_Rel *) get_data (NULL, file, rel_offset, - rel_size, _("relocs")); + erels = get_data (NULL, file, rel_offset, rel_size, _("relocs")); if (!erels) return 0; nrels = rel_size / sizeof (Elf32_External_Rel); - rels = (Elf_Internal_Rela *) malloc (nrels * sizeof (Elf_Internal_Rela)); + rels = malloc (nrels * sizeof (Elf_Internal_Rela)); if (rels == NULL) { @@ -990,14 +805,13 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp) { Elf64_External_Rel *erels; - erels = (Elf64_External_Rel *) get_data (NULL, file, rel_offset, - rel_size, _("relocs")); + erels = get_data (NULL, file, rel_offset, rel_size, _("relocs")); if (!erels) return 0; nrels = rel_size / sizeof (Elf64_External_Rel); - rels = (Elf_Internal_Rela *) malloc (nrels * sizeof (Elf_Internal_Rela)); + rels = malloc (nrels * sizeof (Elf_Internal_Rela)); if (rels == NULL) { @@ -1019,17 +833,17 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp) return 1; } -/* Display the contents of the relocation data found at the specified offset. */ +/* Display the contents of the relocation data found at the specified + offset. */ static int -dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) - FILE *file; - unsigned long rel_offset; - unsigned long rel_size; - Elf_Internal_Sym *symtab; - unsigned long nsyms; - char *strtab; - int is_rela; +dump_relocations (FILE *file, + unsigned long rel_offset, + unsigned long rel_size, + Elf_Internal_Sym *symtab, + unsigned long nsyms, + char *strtab, + int is_rela) { unsigned int i; Elf_Internal_Rela *rels; @@ -1071,14 +885,14 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) if (is_rela) { if (do_wide) - printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n")); + printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n")); else printf (_(" Offset Info Type Sym. Value Sym. Name + Addend\n")); } else { if (do_wide) - printf (_(" Offset Info Type Symbol's Value Symbol's Name\n")); + printf (_(" Offset Info Type Symbol's Value Symbol's Name\n")); else printf (_(" Offset Info Type Sym. Value Sym. Name\n")); } @@ -1093,8 +907,8 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) bfd_vma info; bfd_vma symtab_index; bfd_vma type; - bfd_vma type2 = (bfd_vma) NULL; - bfd_vma type3 = (bfd_vma) NULL; + bfd_vma type2 = 0; + bfd_vma type3 = 0; offset = rels[i].r_offset; info = rels[i].r_info; @@ -1361,7 +1175,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) printf (_("unrecognized: %-7lx"), type); #endif else - printf (do_wide ? "%-21.21s" : "%-17.17s", rtype); + printf (do_wide ? "%-22.22s" : "%-17.17s", rtype); if (symtab_index) { @@ -1398,6 +1212,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) sec_name = "ABS"; else if (psym->st_shndx == SHN_COMMON) sec_name = "COMMON"; + else if (elf_header.e_machine == EM_IA_64 + && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX + && psym->st_shndx == SHN_IA_64_ANSI_COMMON) + sec_name = "ANSI_COM"; else { sprintf (name_buf, "
", @@ -1462,8 +1280,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) } static const char * -get_mips_dynamic_type (type) - unsigned long type; +get_mips_dynamic_type (unsigned long type) { switch (type) { @@ -1516,8 +1333,7 @@ get_mips_dynamic_type (type) } static const char * -get_sparc64_dynamic_type (type) - unsigned long type; +get_sparc64_dynamic_type (unsigned long type) { switch (type) { @@ -1528,8 +1344,7 @@ get_sparc64_dynamic_type (type) } static const char * -get_ppc64_dynamic_type (type) - unsigned long type; +get_ppc64_dynamic_type (unsigned long type) { switch (type) { @@ -1542,8 +1357,7 @@ get_ppc64_dynamic_type (type) } static const char * -get_parisc_dynamic_type (type) - unsigned long type; +get_parisc_dynamic_type (unsigned long type) { switch (type) { @@ -1566,8 +1380,7 @@ get_parisc_dynamic_type (type) } static const char * -get_ia64_dynamic_type (type) - unsigned long type; +get_ia64_dynamic_type (unsigned long type) { switch (type) { @@ -1578,8 +1391,7 @@ get_ia64_dynamic_type (type) } static const char * -get_dynamic_type (type) - unsigned long type; +get_dynamic_type (unsigned long type) { static char buff[32]; @@ -1714,8 +1526,7 @@ get_dynamic_type (type) } static char * -get_file_type (e_type) - unsigned e_type; +get_file_type (unsigned e_type) { static char buff[32]; @@ -1739,8 +1550,7 @@ get_file_type (e_type) } static char * -get_machine_name (e_machine) - unsigned e_machine; +get_machine_name (unsigned e_machine) { static char buff[64]; /* XXX */ @@ -1846,9 +1656,7 @@ get_machine_name (e_machine) } static void -decode_ARM_machine_flags (e_flags, buf) - unsigned e_flags; - char buf[]; +decode_ARM_machine_flags (unsigned e_flags, char buf[]) { unsigned eabi; int unknown = 0; @@ -1992,9 +1800,7 @@ decode_ARM_machine_flags (e_flags, buf) } static char * -get_machine_flags (e_flags, e_machine) - unsigned e_flags; - unsigned e_machine; +get_machine_flags (unsigned e_flags, unsigned e_machine) { static char buf[1024]; @@ -2033,6 +1839,9 @@ get_machine_flags (e_flags, e_machine) case EM_CYGNUS_V850: switch (e_flags & EF_V850_ARCH) { + case E_V850E1_ARCH: + strcat (buf, ", v850e1"); + break; case E_V850E_ARCH: strcat (buf, ", v850e"); break; @@ -2125,6 +1934,7 @@ get_machine_flags (e_flags, e_machine) case E_MIPS_ARCH_32: strcat (buf, ", mips32"); break; case E_MIPS_ARCH_32R2: strcat (buf, ", mips32r2"); break; case E_MIPS_ARCH_64: strcat (buf, ", mips64"); break; + case E_MIPS_ARCH_64R2: strcat (buf, ", mips64r2"); break; default: strcat (buf, ", unknown ISA"); break; } @@ -2224,8 +2034,37 @@ get_machine_flags (e_flags, e_machine) } static const char * -get_mips_segment_type (type) - unsigned long type; +get_osabi_name (unsigned int osabi) +{ + static char buff[32]; + + switch (osabi) + { + case ELFOSABI_NONE: return "UNIX - System V"; + case ELFOSABI_HPUX: return "UNIX - HP-UX"; + case ELFOSABI_NETBSD: return "UNIX - NetBSD"; + case ELFOSABI_LINUX: return "UNIX - Linux"; + case ELFOSABI_HURD: return "GNU/Hurd"; + case ELFOSABI_SOLARIS: return "UNIX - Solaris"; + case ELFOSABI_AIX: return "UNIX - AIX"; + case ELFOSABI_IRIX: return "UNIX - IRIX"; + case ELFOSABI_FREEBSD: return "UNIX - FreeBSD"; + case ELFOSABI_TRU64: return "UNIX - TRU64"; + case ELFOSABI_MODESTO: return "Novell - Modesto"; + case ELFOSABI_OPENBSD: return "UNIX - OpenBSD"; + case ELFOSABI_OPENVMS: return "VMS - OpenVMS"; + case ELFOSABI_NSK: return "HP - Non-Stop Kernel"; + case ELFOSABI_AROS: return "Amiga Research OS"; + case ELFOSABI_STANDALONE: return _("Standalone App"); + case ELFOSABI_ARM: return "ARM"; + default: + sprintf (buff, _(""), osabi); + return buff; + } +} + +static const char * +get_mips_segment_type (unsigned long type) { switch (type) { @@ -2243,8 +2082,7 @@ get_mips_segment_type (type) } static const char * -get_parisc_segment_type (type) - unsigned long type; +get_parisc_segment_type (unsigned long type) { switch (type) { @@ -2270,8 +2108,7 @@ get_parisc_segment_type (type) } static const char * -get_ia64_segment_type (type) - unsigned long type; +get_ia64_segment_type (unsigned long type) { switch (type) { @@ -2289,8 +2126,7 @@ get_ia64_segment_type (type) } static const char * -get_segment_type (p_type) - unsigned long p_type; +get_segment_type (unsigned long p_type) { static char buff[32]; @@ -2307,6 +2143,7 @@ get_segment_type (p_type) case PT_GNU_EH_FRAME: return "GNU_EH_FRAME"; + case PT_GNU_STACK: return "STACK"; default: if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) @@ -2365,8 +2202,7 @@ get_segment_type (p_type) } static const char * -get_mips_section_type_name (sh_type) - unsigned int sh_type; +get_mips_section_type_name (unsigned int sh_type) { switch (sh_type) { @@ -2416,8 +2252,7 @@ get_mips_section_type_name (sh_type) } static const char * -get_parisc_section_type_name (sh_type) - unsigned int sh_type; +get_parisc_section_type_name (unsigned int sh_type) { switch (sh_type) { @@ -2431,13 +2266,12 @@ get_parisc_section_type_name (sh_type) } static const char * -get_ia64_section_type_name (sh_type) - unsigned int sh_type; +get_ia64_section_type_name (unsigned int sh_type) { /* If the top 8 bits are 0x78 the next 8 are the os/abi ID. */ if ((sh_type & 0xFF000000) == SHT_IA_64_LOPSREG) return get_osabi_name ((sh_type & 0x00FF0000) >> 16); - + switch (sh_type) { case SHT_IA_64_EXT: return "IA_64_EXT"; @@ -2450,8 +2284,7 @@ get_ia64_section_type_name (sh_type) } static const char * -get_section_type_name (sh_type) - unsigned int sh_type; +get_section_type_name (unsigned int sh_type) { static char buff[32]; @@ -2555,7 +2388,7 @@ struct option options[] = }; static void -usage () +usage (void) { fprintf (stdout, _("Usage: readelf elf-file(s)\n")); fprintf (stdout, _(" Display information about the contents of ELF format files\n")); @@ -2596,15 +2429,13 @@ usage () } static void -request_dump (section, type) - unsigned int section; - int type; +request_dump (unsigned int section, int type) { if (section >= num_dump_sects) { char *new_dump_sects; - new_dump_sects = (char *) calloc (section + 1, 1); + new_dump_sects = calloc (section + 1, 1); if (new_dump_sects == NULL) error (_("Out of memory allocating dump request table.")); @@ -2627,9 +2458,7 @@ request_dump (section, type) } static void -parse_args (argc, argv) - int argc; - char **argv; +parse_args (int argc, char **argv) { int c; @@ -2900,8 +2729,7 @@ parse_args (argc, argv) } static const char * -get_elf_class (elf_class) - unsigned int elf_class; +get_elf_class (unsigned int elf_class) { static char buff[32]; @@ -2917,8 +2745,7 @@ get_elf_class (elf_class) } static const char * -get_data_encoding (encoding) - unsigned int encoding; +get_data_encoding (unsigned int encoding) { static char buff[32]; @@ -2933,41 +2760,10 @@ get_data_encoding (encoding) } } -static const char * -get_osabi_name (osabi) - unsigned int osabi; -{ - static char buff[32]; - - switch (osabi) - { - case ELFOSABI_NONE: return "UNIX - System V"; - case ELFOSABI_HPUX: return "UNIX - HP-UX"; - case ELFOSABI_NETBSD: return "UNIX - NetBSD"; - case ELFOSABI_LINUX: return "UNIX - Linux"; - case ELFOSABI_HURD: return "GNU/Hurd"; - case ELFOSABI_SOLARIS: return "UNIX - Solaris"; - case ELFOSABI_AIX: return "UNIX - AIX"; - case ELFOSABI_IRIX: return "UNIX - IRIX"; - case ELFOSABI_FREEBSD: return "UNIX - FreeBSD"; - case ELFOSABI_TRU64: return "UNIX - TRU64"; - case ELFOSABI_MODESTO: return "Novell - Modesto"; - case ELFOSABI_OPENBSD: return "UNIX - OpenBSD"; - case ELFOSABI_OPENVMS: return "VMS - OpenVMS"; - case ELFOSABI_NSK: return "HP - Non-Stop Kernel"; - case ELFOSABI_AROS: return "Amiga Research OS"; - case ELFOSABI_STANDALONE: return _("Standalone App"); - case ELFOSABI_ARM: return "ARM"; - default: - sprintf (buff, _(""), osabi); - return buff; - } -} - /* Decode the data held in 'elf_header'. */ static int -process_file_header () +process_file_header (void) { if ( elf_header.e_ident[EI_MAG0] != ELFMAG0 || elf_header.e_ident[EI_MAG1] != ELFMAG1 @@ -3056,19 +2852,16 @@ process_file_header () static int -get_32bit_program_headers (file, program_headers) - FILE *file; - Elf_Internal_Phdr *program_headers; +get_32bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers) { Elf32_External_Phdr *phdrs; Elf32_External_Phdr *external; Elf_Internal_Phdr *internal; unsigned int i; - phdrs = ((Elf32_External_Phdr *) - get_data (NULL, file, elf_header.e_phoff, - elf_header.e_phentsize * elf_header.e_phnum, - _("program headers"))); + phdrs = get_data (NULL, file, elf_header.e_phoff, + elf_header.e_phentsize * elf_header.e_phnum, + _("program headers")); if (!phdrs) return 0; @@ -3092,19 +2885,16 @@ get_32bit_program_headers (file, program_headers) } static int -get_64bit_program_headers (file, program_headers) - FILE *file; - Elf_Internal_Phdr *program_headers; +get_64bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers) { Elf64_External_Phdr *phdrs; Elf64_External_Phdr *external; Elf_Internal_Phdr *internal; unsigned int i; - phdrs = ((Elf64_External_Phdr *) - get_data (NULL, file, elf_header.e_phoff, - elf_header.e_phentsize * elf_header.e_phnum, - _("program headers"))); + phdrs = get_data (NULL, file, elf_header.e_phoff, + elf_header.e_phentsize * elf_header.e_phnum, + _("program headers")); if (!phdrs) return 0; @@ -3127,13 +2917,42 @@ get_64bit_program_headers (file, program_headers) return 1; } +/* Returns 1 if the program headers were read into `program_headers'. */ + +static int +get_program_headers (FILE *file) +{ + Elf_Internal_Phdr *phdrs; + + /* Check cache of prior read. */ + if (program_headers != NULL) + return 1; + + phdrs = malloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); + + if (phdrs == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + if (is_32bit_elf + ? get_32bit_program_headers (file, phdrs) + : get_64bit_program_headers (file, phdrs)) + { + program_headers = phdrs; + return 1; + } + + free (phdrs); + return 0; +} + /* Returns 1 if the program headers were loaded. */ static int -process_program_headers (file) - FILE *file; +process_program_headers (FILE *file) { - Elf_Internal_Phdr *program_headers; Elf_Internal_Phdr *segment; unsigned int i; @@ -3155,25 +2974,8 @@ process_program_headers (file) printf ("\n"); } - program_headers = (Elf_Internal_Phdr *) malloc - (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); - - if (program_headers == NULL) - { - error (_("Out of memory\n")); - return 0; - } - - if (is_32bit_elf) - i = get_32bit_program_headers (file, program_headers); - else - i = get_64bit_program_headers (file, program_headers); - - if (i == 0) - { - free (program_headers); + if (! get_program_headers (file)) return 0; - } if (do_segments) { @@ -3197,7 +2999,6 @@ process_program_headers (file) } } - loadaddr = -1; dynamic_addr = 0; dynamic_size = 0; @@ -3285,18 +3086,6 @@ process_program_headers (file) switch (segment->p_type) { - case PT_LOAD: - if (loadaddr == -1) - { - unsigned long align_mask = -segment->p_align; - - if (align_mask == 0) - --align_mask; - loadaddr = ((segment->p_vaddr & align_mask) - - (segment->p_offset & align_mask)); - } - break; - case PT_DYNAMIC: if (dynamic_addr) error (_("more than one dynamic segment\n")); @@ -3306,7 +3095,8 @@ process_program_headers (file) break; case PT_INTERP: - if (fseek (file, (long) segment->p_offset, SEEK_SET)) + if (fseek (file, archive_file_offset + (long) segment->p_offset, + SEEK_SET)) error (_("Unable to find program interpreter name\n")); else { @@ -3324,12 +3114,6 @@ process_program_headers (file) putc ('\n', stdout); } - if (loadaddr == -1) - { - /* Very strange. */ - loadaddr = 0; - } - if (do_segments && section_headers != NULL) { printf (_("\n Section to Segment mapping:\n")); @@ -3366,30 +3150,54 @@ process_program_headers (file) } } - free (program_headers); - return 1; } +/* Find the file offset corresponding to VMA by using the program headers. */ + +static long +offset_from_vma (FILE *file, bfd_vma vma, bfd_size_type size) +{ + Elf_Internal_Phdr *seg; + + if (! get_program_headers (file)) + { + warn (_("Cannot interpret virtual addresses without program headers.\n")); + return (long) vma; + } + + for (seg = program_headers; + seg < program_headers + elf_header.e_phnum; + ++seg) + { + if (seg->p_type != PT_LOAD) + continue; + + if (vma >= (seg->p_vaddr & -seg->p_align) + && vma + size <= seg->p_vaddr + seg->p_filesz) + return vma - seg->p_vaddr + seg->p_offset; + } + + warn (_("Virtual address 0x%lx not located in any PT_LOAD segment.\n"), + (long) vma); + return (long) vma; +} + + static int -get_32bit_section_headers (file, num) - FILE *file; - unsigned int num; +get_32bit_section_headers (FILE *file, unsigned int num) { Elf32_External_Shdr *shdrs; Elf_Internal_Shdr *internal; unsigned int i; - shdrs = ((Elf32_External_Shdr *) - get_data (NULL, file, elf_header.e_shoff, - elf_header.e_shentsize * num, - _("section headers"))); + shdrs = get_data (NULL, file, elf_header.e_shoff, + elf_header.e_shentsize * num, _("section headers")); if (!shdrs) return 0; - section_headers = ((Elf_Internal_Shdr *) - malloc (num * sizeof (Elf_Internal_Shdr))); + section_headers = malloc (num * sizeof (Elf_Internal_Shdr)); if (section_headers == NULL) { @@ -3419,23 +3227,18 @@ get_32bit_section_headers (file, num) } static int -get_64bit_section_headers (file, num) - FILE *file; - unsigned int num; +get_64bit_section_headers (FILE *file, unsigned int num) { Elf64_External_Shdr *shdrs; Elf_Internal_Shdr *internal; unsigned int i; - shdrs = ((Elf64_External_Shdr *) - get_data (NULL, file, elf_header.e_shoff, - elf_header.e_shentsize * num, - _("section headers"))); + shdrs = get_data (NULL, file, elf_header.e_shoff, + elf_header.e_shentsize * num, _("section headers")); if (!shdrs) return 0; - section_headers = ((Elf_Internal_Shdr *) - malloc (num * sizeof (Elf_Internal_Shdr))); + section_headers = malloc (num * sizeof (Elf_Internal_Shdr)); if (section_headers == NULL) { @@ -3465,9 +3268,7 @@ get_64bit_section_headers (file, num) } static Elf_Internal_Sym * -get_32bit_elf_symbols (file, section) - FILE *file; - Elf_Internal_Shdr *section; +get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section) { unsigned long number; Elf32_External_Sym *esyms; @@ -3476,9 +3277,8 @@ get_32bit_elf_symbols (file, section) Elf_Internal_Sym *psym; unsigned int j; - esyms = ((Elf32_External_Sym *) - get_data (NULL, file, section->sh_offset, - section->sh_size, _("symbols"))); + esyms = get_data (NULL, file, section->sh_offset, section->sh_size, + _("symbols")); if (!esyms) return NULL; @@ -3487,9 +3287,8 @@ get_32bit_elf_symbols (file, section) && (symtab_shndx_hdr->sh_link == (unsigned long) SECTION_HEADER_NUM (section - section_headers))) { - shndx = ((Elf_External_Sym_Shndx *) - get_data (NULL, file, symtab_shndx_hdr->sh_offset, - symtab_shndx_hdr->sh_size, _("symtab shndx"))); + shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset, + symtab_shndx_hdr->sh_size, _("symtab shndx")); if (!shndx) { free (esyms); @@ -3498,7 +3297,7 @@ get_32bit_elf_symbols (file, section) } number = section->sh_size / section->sh_entsize; - isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); + isyms = malloc (number * sizeof (Elf_Internal_Sym)); if (isyms == NULL) { @@ -3532,9 +3331,7 @@ get_32bit_elf_symbols (file, section) } static Elf_Internal_Sym * -get_64bit_elf_symbols (file, section) - FILE *file; - Elf_Internal_Shdr *section; +get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section) { unsigned long number; Elf64_External_Sym *esyms; @@ -3543,9 +3340,8 @@ get_64bit_elf_symbols (file, section) Elf_Internal_Sym *psym; unsigned int j; - esyms = ((Elf64_External_Sym *) - get_data (NULL, file, section->sh_offset, - section->sh_size, _("symbols"))); + esyms = get_data (NULL, file, section->sh_offset, section->sh_size, + _("symbols")); if (!esyms) return NULL; @@ -3554,9 +3350,8 @@ get_64bit_elf_symbols (file, section) && (symtab_shndx_hdr->sh_link == (unsigned long) SECTION_HEADER_NUM (section - section_headers))) { - shndx = ((Elf_External_Sym_Shndx *) - get_data (NULL, file, symtab_shndx_hdr->sh_offset, - symtab_shndx_hdr->sh_size, _("symtab shndx"))); + shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset, + symtab_shndx_hdr->sh_size, _("symtab shndx")); if (!shndx) { free (esyms); @@ -3565,7 +3360,7 @@ get_64bit_elf_symbols (file, section) } number = section->sh_size / section->sh_entsize; - isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); + isyms = malloc (number * sizeof (Elf_Internal_Sym)); if (isyms == NULL) { @@ -3599,8 +3394,7 @@ get_64bit_elf_symbols (file, section) } static const char * -get_elf_section_flags (sh_flags) - bfd_vma sh_flags; +get_elf_section_flags (bfd_vma sh_flags) { static char buff[32]; @@ -3647,8 +3441,7 @@ get_elf_section_flags (sh_flags) } static int -process_section_headers (file) - FILE *file; +process_section_headers (FILE *file) { Elf_Internal_Shdr *section; unsigned int i; @@ -3680,8 +3473,11 @@ process_section_headers (file) if (section->sh_size != 0) { - string_table = (char *) get_data (NULL, file, section->sh_offset, - section->sh_size, _("string table")); + string_table = get_data (NULL, file, section->sh_offset, + section->sh_size, _("string table")); + + if (string_table == NULL) + return 0; string_table_length = section->sh_size; } @@ -3719,9 +3515,8 @@ process_section_headers (file) continue; } - dynamic_strings = (char *) get_data (NULL, file, section->sh_offset, - section->sh_size, - _("dynamic strings")); + dynamic_strings = get_data (NULL, file, section->sh_offset, + section->sh_size, _("dynamic strings")); } else if (section->sh_type == SHT_SYMTAB_SHNDX) { @@ -3896,8 +3691,7 @@ struct /* Process the reloc section. */ static int -process_relocs (file) - FILE *file; +process_relocs (FILE *file) { unsigned long rel_size; unsigned long rel_offset; @@ -3912,7 +3706,7 @@ process_relocs (file) const char *name; int has_dynamic_reloc; unsigned int i; - + has_dynamic_reloc = 0; for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++) @@ -3944,7 +3738,9 @@ process_relocs (file) (_("\n'%s' relocation section at offset 0x%lx contains %ld bytes:\n"), name, rel_offset, rel_size); - dump_relocations (file, rel_offset - loadaddr, rel_size, + dump_relocations (file, + offset_from_vma (file, rel_offset, rel_size), + rel_size, dynamic_symbols, num_dynamic_syms, dynamic_strings, is_rela); } @@ -4004,9 +3800,8 @@ process_relocs (file) strsec = SECTION_HEADER (symsec->sh_link); - strtab = (char *) get_data (NULL, file, strsec->sh_offset, - strsec->sh_size, - _("string table")); + strtab = get_data (NULL, file, strsec->sh_offset, + strsec->sh_size, _("string table")); } is_rela = section->sh_type == SHT_RELA; @@ -4061,21 +3856,13 @@ struct unw_aux_info unsigned long strtab_size; /* Size of string table. */ }; -static void find_symbol_for_address - PARAMS ((struct unw_aux_info *, struct absaddr, const char **, bfd_vma *)); -static void dump_ia64_unwind - PARAMS ((struct unw_aux_info *)); -static int slurp_ia64_unwind_table - PARAMS ((FILE *, struct unw_aux_info *, Elf_Internal_Shdr *)); - static void -find_symbol_for_address (aux, addr, symname, offset) - struct unw_aux_info *aux; - struct absaddr addr; - const char **symname; - bfd_vma *offset; +find_symbol_for_address (struct unw_aux_info *aux, + struct absaddr addr, + const char **symname, + bfd_vma *offset) { - bfd_vma dist = (bfd_vma) 0x100000; + bfd_vma dist = 0x100000; Elf_Internal_Sym *sym, *best = NULL; unsigned long i; @@ -4105,8 +3892,7 @@ find_symbol_for_address (aux, addr, symname, offset) } static void -dump_ia64_unwind (aux) - struct unw_aux_info *aux; +dump_ia64_unwind (struct unw_aux_info *aux) { bfd_vma addr_size; struct unw_table_entry *tp; @@ -4164,20 +3950,18 @@ dump_ia64_unwind (aux) } static int -slurp_ia64_unwind_table (file, aux, sec) - FILE *file; - struct unw_aux_info *aux; - Elf_Internal_Shdr *sec; +slurp_ia64_unwind_table (FILE *file, + struct unw_aux_info *aux, + Elf_Internal_Shdr *sec) { unsigned long size, addr_size, nrelas, i; - Elf_Internal_Phdr *prog_hdrs, *seg; + Elf_Internal_Phdr *seg; struct unw_table_entry *tep; Elf_Internal_Shdr *relsec; Elf_Internal_Rela *rela, *rp; unsigned char *table, *tp; Elf_Internal_Sym *sym; const char *relname; - int result; addr_size = is_32bit_elf ? 4 : 8; @@ -4186,21 +3970,12 @@ slurp_ia64_unwind_table (file, aux, sec) if (elf_header.e_phnum) { - prog_hdrs = (Elf_Internal_Phdr *) - xmalloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); - - if (is_32bit_elf) - result = get_32bit_program_headers (file, prog_hdrs); - else - result = get_64bit_program_headers (file, prog_hdrs); - - if (!result) - { - free (prog_hdrs); + if (! get_program_headers (file)) return 0; - } - for (seg = prog_hdrs; seg < prog_hdrs + elf_header.e_phnum; ++seg) + for (seg = program_headers; + seg < program_headers + elf_header.e_phnum; + ++seg) { if (seg->p_type != PT_LOAD) continue; @@ -4212,14 +3987,11 @@ slurp_ia64_unwind_table (file, aux, sec) break; } } - - free (prog_hdrs); } /* Second, build the unwind table from the contents of the unwind section: */ size = sec->sh_size; - table = (char *) get_data (NULL, file, sec->sh_offset, - size, _("unwind table")); + table = get_data (NULL, file, sec->sh_offset, size, _("unwind table")); if (!table) return 0; @@ -4323,8 +4095,7 @@ slurp_ia64_unwind_table (file, aux, sec) } static int -process_unwind (file) - FILE *file; +process_unwind (FILE *file) { Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec; unsigned long i, addr_size, unwcount = 0, unwstart = 0; @@ -4352,8 +4123,8 @@ process_unwind (file) strsec = SECTION_HEADER (sec->sh_link); aux.strtab_size = strsec->sh_size; - aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset, - aux.strtab_size, _("string table")); + aux.strtab = get_data (NULL, file, strsec->sh_offset, + aux.strtab_size, _("string table")); } else if (sec->sh_type == SHT_IA_64_UNWIND) unwcount++; @@ -4422,8 +4193,8 @@ process_unwind (file) { aux.info_size = sec->sh_size; aux.info_addr = sec->sh_addr; - aux.info = (char *) get_data (NULL, file, sec->sh_offset, - aux.info_size, _("unwind info")); + aux.info = get_data (NULL, file, sec->sh_offset, aux.info_size, + _("unwind info")); printf (_("\nUnwind section ")); @@ -4459,8 +4230,7 @@ process_unwind (file) } static void -dynamic_segment_mips_val (entry) - Elf_Internal_Dyn *entry; +dynamic_segment_mips_val (Elf_Internal_Dyn *entry) { switch (entry->d_tag) { @@ -4534,8 +4304,7 @@ dynamic_segment_mips_val (entry) static void -dynamic_segment_parisc_val (entry) - Elf_Internal_Dyn *entry; +dynamic_segment_parisc_val (Elf_Internal_Dyn *entry) { switch (entry->d_tag) { @@ -4591,30 +4360,33 @@ dynamic_segment_parisc_val (entry) } static void -dynamic_segment_ia64_val (entry) - Elf_Internal_Dyn *entry; +dynamic_segment_ia64_val (Elf_Internal_Dyn *entry) { switch (entry->d_tag) { - case DT_IA_64_PLT_RESERVE: - /* First 3 bytes reserved. */ + case DT_IA_64_PLT_RESERVE: + /* First 3 slots reserved. */ print_vma (entry->d_un.d_ptr, PREFIX_HEX); printf (" -- "); print_vma (entry->d_un.d_ptr + (3 * 8), PREFIX_HEX); - printf ("\n"); + break; + + default: + print_vma (entry->d_un.d_ptr, PREFIX_HEX); + break; } + putchar ('\n'); } static int -get_32bit_dynamic_segment (file) - FILE *file; +get_32bit_dynamic_segment (FILE *file) { Elf32_External_Dyn *edyn; Elf_Internal_Dyn *entry; bfd_size_type i; - edyn = (Elf32_External_Dyn *) get_data (NULL, file, dynamic_addr, - dynamic_size, _("dynamic segment")); + edyn = get_data (NULL, file, dynamic_addr, dynamic_size, + _("dynamic segment")); if (!edyn) return 0; @@ -4625,8 +4397,7 @@ get_32bit_dynamic_segment (file) while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL) ; - dynamic_segment = (Elf_Internal_Dyn *) - malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); + dynamic_segment = malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); if (dynamic_segment == NULL) { @@ -4649,15 +4420,14 @@ get_32bit_dynamic_segment (file) } static int -get_64bit_dynamic_segment (file) - FILE *file; +get_64bit_dynamic_segment (FILE *file) { Elf64_External_Dyn *edyn; Elf_Internal_Dyn *entry; bfd_size_type i; - edyn = (Elf64_External_Dyn *) get_data (NULL, file, dynamic_addr, - dynamic_size, _("dynamic segment")); + edyn = get_data (NULL, file, dynamic_addr, dynamic_size, + _("dynamic segment")); if (!edyn) return 0; @@ -4668,8 +4438,7 @@ get_64bit_dynamic_segment (file) while (*(bfd_vma *) edyn[dynamic_size++].d_tag != DT_NULL) ; - dynamic_segment = (Elf_Internal_Dyn *) - malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); + dynamic_segment = malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); if (dynamic_segment == NULL) { @@ -4692,8 +4461,7 @@ get_64bit_dynamic_segment (file) } static const char * -get_dynamic_flags (flags) - bfd_vma flags; +get_dynamic_flags (bfd_vma flags) { static char buff[128]; char *p = buff; @@ -4726,8 +4494,7 @@ get_dynamic_flags (flags) /* Parse and display the contents of the dynamic segment. */ static int -process_dynamic_segment (file) - FILE *file; +process_dynamic_segment (FILE *file) { Elf_Internal_Dyn *entry; bfd_size_type i; @@ -4766,12 +4533,18 @@ process_dynamic_segment (file) we default to reading in the entire file (!) and processing that. This is overkill, I know, but it should work. */ - section.sh_offset = entry->d_un.d_val - loadaddr; + section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0); + + if (archive_file_offset != 0) + section.sh_size = archive_file_size - section.sh_offset; + else + { + if (fseek (file, 0, SEEK_END)) + error (_("Unable to seek to end of file!")); - if (fseek (file, 0, SEEK_END)) - error (_("Unable to seek to end of file!")); + section.sh_size = ftell (file) - section.sh_offset; + } - section.sh_size = ftell (file) - section.sh_offset; if (is_32bit_elf) section.sh_entsize = sizeof (Elf32_External_Sym); else @@ -4808,10 +4581,16 @@ process_dynamic_segment (file) processing that. This is overkill, I know, but it should work. */ - offset = entry->d_un.d_val - loadaddr; - if (fseek (file, 0, SEEK_END)) - error (_("Unable to seek to end of file\n")); - str_tab_len = ftell (file) - offset; + offset = offset_from_vma (file, entry->d_un.d_val, 0); + + if (archive_file_offset != 0) + str_tab_len = archive_file_size - offset; + else + { + if (fseek (file, 0, SEEK_END)) + error (_("Unable to seek to end of file\n")); + str_tab_len = ftell (file) - offset; + } if (str_tab_len < 1) { @@ -4820,8 +4599,8 @@ process_dynamic_segment (file) continue; } - dynamic_strings = (char *) get_data (NULL, file, offset, str_tab_len, - _("dynamic string table")); + dynamic_strings = get_data (NULL, file, offset, str_tab_len, + _("dynamic string table")); break; } } @@ -4844,7 +4623,8 @@ process_dynamic_segment (file) else if (entry->d_tag == DT_SYMINSZ) syminsz = entry->d_un.d_val; else if (entry->d_tag == DT_SYMINFO) - dynamic_syminfo_offset = entry->d_un.d_val - loadaddr; + dynamic_syminfo_offset = offset_from_vma (file, entry->d_un.d_val, + syminsz); } if (dynamic_syminfo_offset != 0 && syminsz != 0) @@ -4853,13 +4633,12 @@ process_dynamic_segment (file) Elf_Internal_Syminfo *syminfo; /* There is a syminfo section. Read the data. */ - extsyminfo = ((Elf_External_Syminfo *) - get_data (NULL, file, dynamic_syminfo_offset, - syminsz, _("symbol information"))); + extsyminfo = get_data (NULL, file, dynamic_syminfo_offset, syminsz, + _("symbol information")); if (!extsyminfo) return 0; - dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz); + dynamic_syminfo = malloc (syminsz); if (dynamic_syminfo == NULL) { error (_("Out of memory\n")); @@ -5272,8 +5051,7 @@ process_dynamic_segment (file) } static char * -get_ver_flags (flags) - unsigned int flags; +get_ver_flags (unsigned int flags) { static char buff[32]; @@ -5301,8 +5079,7 @@ get_ver_flags (flags) /* Display the contents of the version sections. */ static int -process_version_sections (file) - FILE *file; +process_version_sections (FILE *file) { Elf_Internal_Shdr *section; unsigned i; @@ -5335,10 +5112,8 @@ process_version_sections (file) (unsigned long) section->sh_offset, section->sh_link, SECTION_NAME (SECTION_HEADER (section->sh_link))); - edefs = ((Elf_External_Verdef *) - get_data (NULL, file, section->sh_offset, - section->sh_size, - _("version definition section"))); + edefs = get_data (NULL, file, section->sh_offset, section->sh_size, + _("version definition section")); if (!edefs) break; @@ -5426,9 +5201,8 @@ process_version_sections (file) (unsigned long) section->sh_offset, section->sh_link, SECTION_NAME (SECTION_HEADER (section->sh_link))); - eneed = ((Elf_External_Verneed *) - get_data (NULL, file, section->sh_offset, - section->sh_size, _("version need section"))); + eneed = get_data (NULL, file, section->sh_offset, section->sh_size, + _("version need section")); if (!eneed) break; @@ -5475,10 +5249,10 @@ process_version_sections (file) aux.vna_next = BYTE_GET (eaux->vna_next); if (dynamic_strings) - printf (_(" %#06x: Name: %s"), + printf (_(" %#06x: Name: %s"), isum, dynamic_strings + aux.vna_name); else - printf (_(" %#06x: Name index: %lx"), + printf (_(" %#06x: Name index: %lx"), isum, aux.vna_name); printf (_(" Flags: %s Version: %d\n"), @@ -5505,6 +5279,7 @@ process_version_sections (file) char *strtab; Elf_Internal_Sym *symbols; Elf_Internal_Shdr *string_sec; + long off; link_section = SECTION_HEADER (section->sh_link); total = section->sh_size / section->sh_entsize; @@ -5515,9 +5290,8 @@ process_version_sections (file) string_sec = SECTION_HEADER (link_section->sh_link); - strtab = (char *) get_data (NULL, file, string_sec->sh_offset, - string_sec->sh_size, - _("version string table")); + strtab = get_data (NULL, file, string_sec->sh_offset, + string_sec->sh_size, _("version string table")); if (!strtab) break; @@ -5530,18 +5304,18 @@ process_version_sections (file) (unsigned long) section->sh_offset, section->sh_link, SECTION_NAME (link_section)); - edata = - ((unsigned char *) - get_data (NULL, file, - version_info[DT_VERSIONTAGIDX (DT_VERSYM)] - loadaddr, - total * sizeof (short), _("version symbol data"))); + off = offset_from_vma (file, + version_info[DT_VERSIONTAGIDX (DT_VERSYM)], + total * sizeof (short)); + edata = get_data (NULL, file, off, total * sizeof (short), + _("version symbol data")); if (!edata) { free (strtab); break; } - data = (unsigned short *) malloc (total * sizeof (short)); + data = malloc (total * sizeof (short)); for (cnt = total; cnt --;) data[cnt] = byte_get (edata + cnt * sizeof (short), @@ -5589,8 +5363,9 @@ process_version_sections (file) Elf_Internal_Verneed ivn; unsigned long offset; - offset = version_info[DT_VERSIONTAGIDX (DT_VERNEED)] - - loadaddr; + offset = offset_from_vma + (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)], + sizeof (Elf_External_Verneed)); do { @@ -5645,8 +5420,9 @@ process_version_sections (file) Elf_External_Verdef evd; unsigned long offset; - offset = (version_info[DT_VERSIONTAGIDX (DT_VERDEF)] - - loadaddr); + offset = offset_from_vma + (file, version_info[DT_VERSIONTAGIDX (DT_VERDEF)], + sizeof evd); do { @@ -5707,8 +5483,7 @@ process_version_sections (file) } static const char * -get_symbol_binding (binding) - unsigned int binding; +get_symbol_binding (unsigned int binding) { static char buff[32]; @@ -5729,8 +5504,7 @@ get_symbol_binding (binding) } static const char * -get_symbol_type (type) - unsigned int type; +get_symbol_type (unsigned int type) { static char buff[32]; @@ -5776,8 +5550,7 @@ get_symbol_type (type) } static const char * -get_symbol_visibility (visibility) - unsigned int visibility; +get_symbol_visibility (unsigned int visibility) { switch (visibility) { @@ -5790,8 +5563,7 @@ get_symbol_visibility (visibility) } static const char * -get_symbol_index_type (type) - unsigned int type; +get_symbol_index_type (unsigned int type) { static char buff[32]; @@ -5801,7 +5573,11 @@ get_symbol_index_type (type) case SHN_ABS: return "ABS"; case SHN_COMMON: return "COM"; default: - if (type >= SHN_LOPROC && type <= SHN_HIPROC) + if (type == SHN_IA_64_ANSI_COMMON + && elf_header.e_machine == EM_IA_64 + && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX) + return "ANSI_COM"; + else if (type >= SHN_LOPROC && type <= SHN_HIPROC) sprintf (buff, "PRC[0x%04x]", type); else if (type >= SHN_LOOS && type <= SHN_HIOS) sprintf (buff, "OS [0x%04x]", type); @@ -5816,14 +5592,12 @@ get_symbol_index_type (type) } static int * -get_dynamic_data (file, number) - FILE *file; - unsigned int number; +get_dynamic_data (FILE *file, unsigned int number) { unsigned char *e_data; int *i_data; - e_data = (unsigned char *) malloc (number * 4); + e_data = malloc (number * 4); if (e_data == NULL) { @@ -5837,7 +5611,7 @@ get_dynamic_data (file, number) return NULL; } - i_data = (int *) malloc (number * sizeof (*i_data)); + i_data = malloc (number * sizeof (*i_data)); if (i_data == NULL) { @@ -5856,8 +5630,7 @@ get_dynamic_data (file, number) /* Dump the symbol table. */ static int -process_symbol_table (file) - FILE *file; +process_symbol_table (FILE *file) { Elf_Internal_Shdr *section; unsigned char nb[4]; @@ -5873,7 +5646,11 @@ process_symbol_table (file) if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL) || do_histogram)) { - if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET)) + if (fseek (file, + (archive_file_offset + + offset_from_vma (file, dynamic_info[DT_HASH], + sizeof nb + sizeof nc)), + SEEK_SET)) { error (_("Unable to seek to start of dynamic information")); return 0; @@ -5976,9 +5753,8 @@ process_symbol_table (file) string_sec = SECTION_HEADER (section->sh_link); - strtab = (char *) get_data (NULL, file, string_sec->sh_offset, - string_sec->sh_size, - _("string table")); + strtab = get_data (NULL, file, string_sec->sh_offset, + string_sec->sh_size, _("string table")); } for (si = 0, psym = symtab; @@ -6004,8 +5780,9 @@ process_symbol_table (file) int is_nobits; int check_def; - offset = version_info[DT_VERSIONTAGIDX (DT_VERSYM)] - - loadaddr; + offset = offset_from_vma + (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)], + sizeof data + si * sizeof (vers_data)); get_data (&data, file, offset + si * sizeof (vers_data), sizeof (data), _("version data")); @@ -6027,8 +5804,9 @@ process_symbol_table (file) Elf_Internal_Vernaux ivna; /* We must test both. */ - offset = (version_info[DT_VERSIONTAGIDX (DT_VERNEED)] - - loadaddr); + offset = offset_from_vma + (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)], + sizeof evn); do { @@ -6088,9 +5866,10 @@ process_symbol_table (file) Elf_External_Verdaux evda; unsigned long offset; - offset - = (version_info[DT_VERSIONTAGIDX (DT_VERDEF)] - - loadaddr); + offset = offset_from_vma + (file, + version_info[DT_VERSIONTAGIDX (DT_VERDEF)], + sizeof (Elf_External_Verdef)); do { @@ -6151,7 +5930,7 @@ process_symbol_table (file) nbuckets); printf (_(" Length Number %% of total Coverage\n")); - lengths = (int *) calloc (nbuckets, sizeof (int)); + lengths = calloc (nbuckets, sizeof (int)); if (lengths == NULL) { error (_("Out of memory")); @@ -6170,7 +5949,7 @@ process_symbol_table (file) } } - counts = (int *) calloc (maxlength + 1, sizeof (int)); + counts = calloc (maxlength + 1, sizeof (int)); if (counts == NULL) { error (_("Out of memory")); @@ -6207,8 +5986,7 @@ process_symbol_table (file) } static int -process_syminfo (file) - FILE *file ATTRIBUTE_UNUSED; +process_syminfo (FILE *file ATTRIBUTE_UNUSED) { unsigned int i; @@ -6274,9 +6052,7 @@ process_syminfo (file) #ifdef SUPPORT_DISASSEMBLY static void -disassemble_section (section, file) - Elf_Internal_Shdr *section; - FILE *file; +disassemble_section (Elf_Internal_Shdr *section, FILE *file) { printf (_("\nAssembly dump of section %s\n"), SECTION_NAME (section)); @@ -6288,9 +6064,7 @@ disassemble_section (section, file) #endif static int -dump_section (section, file) - Elf_Internal_Shdr *section; - FILE *file; +dump_section (Elf_Internal_Shdr *section, FILE *file) { bfd_size_type bytes; bfd_vma addr; @@ -6299,7 +6073,7 @@ dump_section (section, file) bytes = section->sh_size; - if (bytes == 0) + if (bytes == 0 || section->sh_type == SHT_NOBITS) { printf (_("\nSection '%s' has no data to dump.\n"), SECTION_NAME (section)); @@ -6310,8 +6084,7 @@ dump_section (section, file) addr = section->sh_addr; - start = (unsigned char *) get_data (NULL, file, section->sh_offset, bytes, - _("section data")); + start = get_data (NULL, file, section->sh_offset, bytes, _("section data")); if (!start) return 0; @@ -6360,7 +6133,7 @@ dump_section (section, file) for (j = 0; j < lbytes; j++) { k = data[j]; - if (k >= ' ' && k < 0x80) + if (k >= ' ' && k < 0x7f) printf ("%c", k); else printf ("."); @@ -6380,10 +6153,7 @@ dump_section (section, file) static unsigned long int -read_leb128 (data, length_return, sign) - unsigned char *data; - int *length_return; - int sign; +read_leb128 (unsigned char *data, int *length_return, int sign) { unsigned long int result = 0; unsigned int num_read = 0; @@ -6428,8 +6198,7 @@ typedef struct State_Machine_Registers static SMR state_machine_regs; static void -reset_state_machine (is_stmt) - int is_stmt; +reset_state_machine (int is_stmt) { state_machine_regs.address = 0; state_machine_regs.file = 1; @@ -6444,10 +6213,7 @@ reset_state_machine (is_stmt) /* Handled an extend line op. Returns true if this is the end of sequence. */ static int -process_extended_line_op (data, is_stmt, pointer_size) - unsigned char *data; - int is_stmt; - int pointer_size; +process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size) { unsigned char op_code; int bytes_read; @@ -6505,16 +6271,137 @@ process_extended_line_op (data, is_stmt, pointer_size) return len; } +/* Finds section NAME inside FILE and returns a + pointer to it, or NULL upon failure. */ + +static Elf_Internal_Shdr * +find_section (const char * name) +{ + Elf_Internal_Shdr *sec; + unsigned int i; + + for (i = elf_header.e_shnum, sec = section_headers + i - 1; + i; --i, --sec) + if (strcmp (SECTION_NAME (sec), name) == 0) + break; + + if (i && sec && sec->sh_size != 0) + return sec; + + return NULL; +} + /* Size of pointers in the .debug_line section. This information is not really present in that section. It's obtained before dumping the debug sections by doing some pre-scan of the .debug_info section. */ -static int debug_line_pointer_size = 4; +static unsigned int * debug_line_pointer_sizes = NULL; +static unsigned int num_debug_line_pointer_sizes = 0; + +/* Locate and scan the .debug_info section in the file and record the pointer + sizes for the compilation units in it. Usually an executable will have + just one pointer size, but this is not guaranteed, and so we try not to + make any assumptions. Returns zero upon failure, or the number of + compilation units upon success. */ + +static unsigned int +get_debug_line_pointer_sizes (FILE * file) +{ + Elf_Internal_Shdr * section; + unsigned char * start; + unsigned char * end; + unsigned char * begin; + unsigned long length; + unsigned int num_units; + unsigned int unit; + + section = find_section (".debug_info"); + if (section == NULL) + return 0; + + length = section->sh_size; + start = get_data (NULL, file, section->sh_offset, section->sh_size, + _("extracting pointer sizes from .debug_info section")); + if (start == NULL) + return 0; + + end = start + section->sh_size; + /* First scan the section to get the number of comp units. */ + for (begin = start, num_units = 0; begin < end; num_units++) + { + /* Read the first 4 bytes. For a 32-bit DWARF section, this will + be the length. For a 64-bit DWARF section, it'll be the escape + code 0xffffffff followed by an 8 byte length. */ + length = byte_get (begin, 4); + + if (length == 0xffffffff) + { + length = byte_get (begin + 4, 8); + begin += length + 12; + } + else + begin += length + 4; + } + + if (num_units == 0) + { + error (_("No comp units in .debug_info section ?")); + free (start); + return 0; + } + + /* Then allocate an array to hold the pointer sizes. */ + debug_line_pointer_sizes = malloc (num_units * sizeof * debug_line_pointer_sizes); + if (debug_line_pointer_sizes == NULL) + { + error (_("Not enough memory for a pointer size array of %u entries"), + num_units); + free (start); + return 0; + } + + /* Populate the array. */ + for (begin = start, unit = 0; begin < end; unit++) + { + length = byte_get (begin, 4); + if (length == 0xffffffff) + { + /* For 64-bit DWARF, the 1-byte address_size field is 22 bytes + from the start of the section. This is computed as follows: + + unit_length: 12 bytes + version: 2 bytes + debug_abbrev_offset: 8 bytes + ----------------------------- + Total: 22 bytes */ + + debug_line_pointer_sizes [unit] = byte_get (begin + 22, 1); + length = byte_get (begin + 4, 8); + begin += length + 12; + } + else + { + /* For 32-bit DWARF, the 1-byte address_size field is 10 bytes from + the start of the section: + + unit_length: 4 bytes + version: 2 bytes + debug_abbrev_offset: 4 bytes + ----------------------------- + Total: 10 bytes */ + + debug_line_pointer_sizes [unit] = byte_get (begin + 10, 1); + begin += length + 4; + } + } + + free (start); + num_debug_line_pointer_sizes = num_units; + return num_units; +} static int -display_debug_lines (section, start, file) - Elf_Internal_Shdr *section; - unsigned char * start; - FILE *file ATTRIBUTE_UNUSED; +display_debug_lines (Elf_Internal_Shdr *section, + unsigned char *start, FILE *file) { unsigned char *hdrptr; DWARF2_Internal_LineInfo info; @@ -6525,12 +6412,18 @@ display_debug_lines (section, start, file) int i; int offset_size; int initial_length_size; + unsigned int comp_unit = 0; printf (_("\nDump of debug contents of section %s:\n\n"), SECTION_NAME (section)); + if (num_debug_line_pointer_sizes == 0) + get_debug_line_pointer_sizes (file); + while (data < end) { + unsigned int pointer_size; + hdrptr = data; /* Check the length of the block. */ @@ -6584,6 +6477,19 @@ display_debug_lines (section, start, file) info.li_line_base <<= 24; info.li_line_base >>= 24; + /* Get the pointer size from the comp unit associated + with this block of line number information. */ + if (comp_unit >= num_debug_line_pointer_sizes) + { + error (_("Not enough comp units for .debug_lines section\n")); + return 0; + } + else + { + pointer_size = debug_line_pointer_sizes [comp_unit]; + comp_unit ++; + } + printf (_(" Length: %ld\n"), info.li_length); printf (_(" DWARF Version: %d\n"), info.li_version); printf (_(" Prologue Length: %d\n"), info.li_prologue_length); @@ -6592,6 +6498,7 @@ display_debug_lines (section, start, file) printf (_(" Line Base: %d\n"), info.li_line_base); printf (_(" Line Range: %d\n"), info.li_line_range); printf (_(" Opcode Base: %d\n"), info.li_opcode_base); + printf (_(" (Pointer size: %u)\n"), pointer_size); end_of_sequence = data + info.li_length + initial_length_size; @@ -6684,7 +6591,7 @@ display_debug_lines (section, start, file) { case DW_LNS_extended_op: data += process_extended_line_op (data, info.li_default_is_stmt, - debug_line_pointer_size); + pointer_size); break; case DW_LNS_copy: @@ -6786,10 +6693,9 @@ display_debug_lines (section, start, file) } static int -display_debug_pubnames (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start; - FILE *file ATTRIBUTE_UNUSED; +display_debug_pubnames (Elf_Internal_Shdr *section, + unsigned char *start, + FILE *file ATTRIBUTE_UNUSED) { DWARF2_Internal_PubNames pubnames; unsigned char *end; @@ -6873,8 +6779,7 @@ display_debug_pubnames (section, start, file) } static char * -get_TAG_name (tag) - unsigned long tag; +get_TAG_name (unsigned long tag) { switch (tag) { @@ -6954,8 +6859,7 @@ get_TAG_name (tag) } static char * -get_AT_name (attribute) - unsigned long attribute; +get_AT_name (unsigned long attribute) { switch (attribute) { @@ -7068,8 +6972,7 @@ get_AT_name (attribute) } static char * -get_FORM_name (form) - unsigned long form; +get_FORM_name (unsigned long form) { switch (form) { @@ -7104,7 +7007,7 @@ get_FORM_name (form) } } -/* FIXME: There are better and more effiecint ways to handle +/* FIXME: There are better and more efficient ways to handle these structures. For now though, I just want something that is simple to implement. */ typedef struct abbrev_attr @@ -7130,7 +7033,7 @@ static abbrev_entry *first_abbrev = NULL; static abbrev_entry *last_abbrev = NULL; static void -free_abbrevs () +free_abbrevs (void) { abbrev_entry *abbrev; @@ -7155,14 +7058,11 @@ free_abbrevs () } static void -add_abbrev (number, tag, children) - unsigned long number; - unsigned long tag; - int children; +add_abbrev (unsigned long number, unsigned long tag, int children) { abbrev_entry *entry; - entry = (abbrev_entry *) malloc (sizeof (*entry)); + entry = malloc (sizeof (*entry)); if (entry == NULL) /* ugg */ @@ -7184,13 +7084,11 @@ add_abbrev (number, tag, children) } static void -add_abbrev_attr (attribute, form) - unsigned long attribute; - unsigned long form; +add_abbrev_attr (unsigned long attribute, unsigned long form) { abbrev_attr *attr; - attr = (abbrev_attr *) malloc (sizeof (*attr)); + attr = malloc (sizeof (*attr)); if (attr == NULL) /* ugg */ @@ -7214,9 +7112,7 @@ add_abbrev_attr (attribute, form) an abbreviation set was found. */ static unsigned char * -process_abbrev_section (start, end) - unsigned char *start; - unsigned char *end; +process_abbrev_section (unsigned char *start, unsigned char *end) { if (first_abbrev != NULL) return NULL; @@ -7266,10 +7162,9 @@ process_abbrev_section (start, end) static int -display_debug_macinfo (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start; - FILE *file ATTRIBUTE_UNUSED; +display_debug_macinfo (Elf_Internal_Shdr *section, + unsigned char *start, + FILE *file ATTRIBUTE_UNUSED) { unsigned char *end = start + section->sh_size; unsigned char *curr = start; @@ -7340,10 +7235,9 @@ display_debug_macinfo (section, start, file) static int -display_debug_abbrev (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start; - FILE *file ATTRIBUTE_UNUSED; +display_debug_abbrev (Elf_Internal_Shdr *section, + unsigned char *start, + FILE *file ATTRIBUTE_UNUSED) { abbrev_entry *entry; unsigned char *end = start + section->sh_size; @@ -7387,9 +7281,7 @@ display_debug_abbrev (section, start, file) static unsigned char * -display_block (data, length) - unsigned char *data; - unsigned long length; +display_block (unsigned char *data, unsigned long length) { printf (_(" %lu byte block: "), length); @@ -7400,10 +7292,9 @@ display_block (data, length) } static void -decode_location_expression (data, pointer_size, length) - unsigned char * data; - unsigned int pointer_size; - unsigned long length; +decode_location_expression (unsigned char * data, + unsigned int pointer_size, + unsigned long length) { unsigned op; int bytes_read; @@ -7736,35 +7627,27 @@ static const char *debug_loc_contents; static bfd_vma debug_loc_size; static void -load_debug_loc (file) - FILE *file; +load_debug_loc (FILE *file) { Elf_Internal_Shdr *sec; - unsigned int i; /* If it is already loaded, do nothing. */ if (debug_loc_contents != NULL) return; /* Locate the .debug_loc section. */ - for (i = 0, sec = section_headers; - i < elf_header.e_shnum; - i++, sec++) - if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0) - break; - - if (i == elf_header.e_shnum || sec->sh_size == 0) + sec = find_section (".debug_loc"); + if (sec == NULL) return; debug_loc_size = sec->sh_size; - debug_loc_contents = ((char *) - get_data (NULL, file, sec->sh_offset, sec->sh_size, - _("debug_loc section data"))); + debug_loc_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size, + _("debug_loc section data")); } static void -free_debug_loc () +free_debug_loc (void) { if (debug_loc_contents == NULL) return; @@ -7776,15 +7659,14 @@ free_debug_loc () static int -display_debug_loc (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start; - FILE *file ATTRIBUTE_UNUSED; +display_debug_loc (Elf_Internal_Shdr *section, + unsigned char *start, FILE *file) { unsigned char *section_end; unsigned long bytes; unsigned char *section_begin = start; bfd_vma addr; + unsigned int comp_unit = 0; addr = section->sh_addr; bytes = section->sh_size; @@ -7796,6 +7678,9 @@ display_debug_loc (section, start, file) return 0; } + if (num_debug_line_pointer_sizes == 0) + get_debug_line_pointer_sizes (file); + printf (_("Contents of the .debug_loc section:\n\n")); printf (_("\n Offset Begin End Expression\n")); @@ -7805,21 +7690,29 @@ display_debug_loc (section, start, file) unsigned long end; unsigned short length; unsigned long offset; + unsigned int pointer_size; offset = start - section_begin; + /* Get the pointer size from the comp unit associated + with this block of location information. */ + if (comp_unit >= num_debug_line_pointer_sizes) + { + error (_("Not enough comp units for .debug_loc section\n")); + return 0; + } + else + { + pointer_size = debug_line_pointer_sizes [comp_unit]; + comp_unit ++; + } + while (1) { - /* Normally, the lists in the debug_loc section are related to a - given compilation unit, and thus, we would use the pointer size - of that compilation unit. However, since we are displaying it - seperately here, we either have to store pointer sizes of all - compilation units, or assume they don't change. We assume, - like the debug_line display, that it doesn't change. */ - begin = byte_get (start, debug_line_pointer_size); - start += debug_line_pointer_size; - end = byte_get (start, debug_line_pointer_size); - start += debug_line_pointer_size; + begin = byte_get (start, pointer_size); + start += pointer_size; + end = byte_get (start, pointer_size); + start += pointer_size; if (begin == 0 && end == 0) break; @@ -7835,7 +7728,7 @@ display_debug_loc (section, start, file) start += 2; printf (" %8.8lx %8.8lx %8.8lx (", offset, begin, end); - decode_location_expression (start, debug_line_pointer_size, length); + decode_location_expression (start, pointer_size, length); printf (")\n"); start += length; @@ -7849,35 +7742,27 @@ static const char *debug_str_contents; static bfd_vma debug_str_size; static void -load_debug_str (file) - FILE *file; +load_debug_str (FILE *file) { Elf_Internal_Shdr *sec; - unsigned int i; /* If it is already loaded, do nothing. */ if (debug_str_contents != NULL) return; /* Locate the .debug_str section. */ - for (i = 0, sec = section_headers; - i < elf_header.e_shnum; - i++, sec++) - if (strcmp (SECTION_NAME (sec), ".debug_str") == 0) - break; - - if (i == elf_header.e_shnum || sec->sh_size == 0) + sec = find_section (".debug_str"); + if (sec == NULL) return; debug_str_size = sec->sh_size; - debug_str_contents = ((char *) - get_data (NULL, file, sec->sh_offset, sec->sh_size, - _("debug_str section data"))); + debug_str_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size, + _("debug_str section data")); } static void -free_debug_str () +free_debug_str (void) { if (debug_str_contents == NULL) return; @@ -7888,8 +7773,7 @@ free_debug_str () } static const char * -fetch_indirect_string (offset) - unsigned long offset; +fetch_indirect_string (unsigned long offset) { if (debug_str_contents == NULL) return _(""); @@ -7901,10 +7785,9 @@ fetch_indirect_string (offset) } static int -display_debug_str (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start; - FILE *file ATTRIBUTE_UNUSED; +display_debug_str (Elf_Internal_Shdr *section, + unsigned char *start, + FILE *file ATTRIBUTE_UNUSED) { unsigned long bytes; bfd_vma addr; @@ -7961,15 +7844,13 @@ display_debug_str (section, start, file) } static unsigned char * -read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size, - offset_size, dwarf_version) - unsigned long attribute; - unsigned long form; - unsigned char *data; - unsigned long cu_offset; - unsigned long pointer_size; - unsigned long offset_size; - int dwarf_version; +read_and_display_attr_value (unsigned long attribute, + unsigned long form, + unsigned char *data, + unsigned long cu_offset, + unsigned long pointer_size, + unsigned long offset_size, + int dwarf_version) { unsigned long uvalue = 0; unsigned char *block_start = NULL; @@ -8121,7 +8002,7 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size, break; } - /* For some attributes we can display futher information. */ + /* For some attributes we can display further information. */ printf ("\t"); @@ -8298,15 +8179,13 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size, } static unsigned char * -read_and_display_attr (attribute, form, data, cu_offset, pointer_size, - offset_size, dwarf_version) - unsigned long attribute; - unsigned long form; - unsigned char *data; - unsigned long cu_offset; - unsigned long pointer_size; - unsigned long offset_size; - int dwarf_version; +read_and_display_attr (unsigned long attribute, + unsigned long form, + unsigned char *data, + unsigned long cu_offset, + unsigned long pointer_size, + unsigned long offset_size, + int dwarf_version) { printf (" %-18s:", get_AT_name (attribute)); data = read_and_display_attr_value (attribute, form, data, cu_offset, @@ -8316,10 +8195,9 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size, } static int -display_debug_info (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start; - FILE *file; +display_debug_info (Elf_Internal_Shdr *section, + unsigned char *start, + FILE *file) { unsigned char *end = start + section->sh_size; unsigned char *section_begin = start; @@ -8336,7 +8214,6 @@ display_debug_info (section, start, file) unsigned char *hdrptr; unsigned char *cu_abbrev_offset_ptr; unsigned char *tags; - unsigned int i; int level; unsigned long cu_offset; int offset_size; @@ -8460,21 +8337,15 @@ display_debug_info (section, start, file) unsigned char *begin; /* Locate the .debug_abbrev section and process it. */ - for (i = 0, sec = section_headers; - i < elf_header.e_shnum; - i++, sec++) - if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0) - break; - - if (i == elf_header.e_shnum || sec->sh_size == 0) + sec = find_section (".debug_abbrev"); + if (sec == NULL) { warn (_("Unable to locate .debug_abbrev section!\n")); return 0; } - begin = ((unsigned char *) - get_data (NULL, file, sec->sh_offset, sec->sh_size, - _("debug_abbrev section data"))); + begin = get_data (NULL, file, sec->sh_offset, sec->sh_size, + _("debug_abbrev section data")); if (!begin) return 0; @@ -8544,10 +8415,9 @@ display_debug_info (section, start, file) } static int -display_debug_aranges (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start; - FILE *file ATTRIBUTE_UNUSED; +display_debug_aranges (Elf_Internal_Shdr *section, + unsigned char *start, + FILE *file ATTRIBUTE_UNUSED) { unsigned char *end = start + section->sh_size; @@ -8657,6 +8527,7 @@ typedef struct Frame_Chunk int cfa_offset; int ra; unsigned char fde_encoding; + unsigned char cfa_exp; } Frame_Chunk; @@ -8664,14 +8535,8 @@ Frame_Chunk; in the frame info. */ #define DW_CFA_unreferenced (-1) -static void frame_need_space PARAMS ((Frame_Chunk *, int)); -static void frame_display_row PARAMS ((Frame_Chunk *, int *, int *)); -static int size_of_encoded_value PARAMS ((int)); - static void -frame_need_space (fc, reg) - Frame_Chunk *fc; - int reg; +frame_need_space (Frame_Chunk *fc, int reg) { int prev = fc->ncols; @@ -8679,10 +8544,8 @@ frame_need_space (fc, reg) return; fc->ncols = reg + 1; - fc->col_type = (short int *) xrealloc (fc->col_type, - fc->ncols * sizeof (short int)); - fc->col_offset = (int *) xrealloc (fc->col_offset, - fc->ncols * sizeof (int)); + fc->col_type = xrealloc (fc->col_type, fc->ncols * sizeof (short int)); + fc->col_offset = xrealloc (fc->col_offset, fc->ncols * sizeof (int)); while (prev < fc->ncols) { @@ -8693,10 +8556,7 @@ frame_need_space (fc, reg) } static void -frame_display_row (fc, need_col_headers, max_regs) - Frame_Chunk *fc; - int *need_col_headers; - int *max_regs; +frame_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs) { int r; char tmp[100]; @@ -8723,7 +8583,10 @@ frame_display_row (fc, need_col_headers, max_regs) } printf ("%08lx ", fc->pc_begin); - sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset); + if (fc->cfa_exp) + strcpy (tmp, "exp"); + else + sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset); printf ("%-8s ", tmp); for (r = 0; r < fc->ncols; r++) @@ -8744,6 +8607,9 @@ frame_display_row (fc, need_col_headers, max_regs) case DW_CFA_register: sprintf (tmp, "r%d", fc->col_offset[r]); break; + case DW_CFA_expression: + strcpy (tmp, "exp"); + break; default: strcpy (tmp, "n/a"); break; @@ -8755,8 +8621,7 @@ frame_display_row (fc, need_col_headers, max_regs) } static int -size_of_encoded_value (encoding) - int encoding; +size_of_encoded_value (int encoding) { switch (encoding & 0x7) { @@ -8768,15 +8633,24 @@ size_of_encoded_value (encoding) } } +static bfd_vma +get_encoded_value (unsigned char *data, int encoding) +{ + int size = size_of_encoded_value (encoding); + if (encoding & DW_EH_PE_signed) + return byte_get_signed (data, size); + else + return byte_get (data, size); +} + #define GET(N) byte_get (start, N); start += N #define LEB() read_leb128 (start, & length_return, 0); start += length_return #define SLEB() read_leb128 (start, & length_return, 1); start += length_return static int -display_debug_frames (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start; - FILE *file ATTRIBUTE_UNUSED; +display_debug_frames (Elf_Internal_Shdr *section, + unsigned char *start, + FILE *file ATTRIBUTE_UNUSED) { unsigned char *end = start + section->sh_size; unsigned char *section_start = start; @@ -8835,15 +8709,15 @@ display_debug_frames (section, start, file) { int version; - fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk)); + fc = xmalloc (sizeof (Frame_Chunk)); memset (fc, 0, sizeof (Frame_Chunk)); fc->next = chunks; chunks = fc; fc->chunk_start = saved_start; fc->ncols = 0; - fc->col_type = (short int *) xmalloc (sizeof (short int)); - fc->col_offset = (int *) xmalloc (sizeof (int)); + fc->col_type = xmalloc (sizeof (short int)); + fc->col_offset = xmalloc (sizeof (int)); frame_need_space (fc, max_regs-1); version = *start++; @@ -8946,8 +8820,8 @@ display_debug_frames (section, start, file) cie_id, saved_start); start = block_end; fc->ncols = 0; - fc->col_type = (short int *) xmalloc (sizeof (short int)); - fc->col_offset = (int *) xmalloc (sizeof (int)); + fc->col_type = xmalloc (sizeof (short int)); + fc->col_offset = xmalloc (sizeof (int)); frame_need_space (fc, max_regs - 1); cie = fc; fc->augmentation = ""; @@ -8956,8 +8830,8 @@ display_debug_frames (section, start, file) else { fc->ncols = cie->ncols; - fc->col_type = (short int *) xmalloc (fc->ncols * sizeof (short int)); - fc->col_offset = (int *) xmalloc (fc->ncols * sizeof (int)); + fc->col_type = xmalloc (fc->ncols * sizeof (short int)); + fc->col_offset = xmalloc (fc->ncols * sizeof (int)); memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int)); memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int)); fc->augmentation = cie->augmentation; @@ -8973,7 +8847,7 @@ display_debug_frames (section, start, file) if (fc->fde_encoding) encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); - fc->pc_begin = byte_get (start, encoded_ptr_size); + fc->pc_begin = get_encoded_value (start, fc->fde_encoding); if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel) fc->pc_begin += section->sh_addr + (start - section_start); start += encoded_ptr_size; @@ -9004,8 +8878,12 @@ display_debug_frames (section, start, file) /* At this point, fc is the current chunk, cie (if any) is set, and we're about to interpret instructions for the chunk. */ - - if (do_debug_frames_interp) + /* ??? At present we need to do this always, since this sizes the + fc->col_type and fc->col_offset arrays, which we write into always. + We should probably split the interpreted and non-interpreted bits + into two different routines, since there's so much that doesn't + really overlap between them. */ + if (1 || do_debug_frames_interp) { /* Start by making a pass over the chunk, allocating storage and taking note of what registers are used. */ @@ -9014,7 +8892,7 @@ display_debug_frames (section, start, file) while (start < block_end) { unsigned op, opa; - unsigned long reg; + unsigned long reg, tmp; op = *start++; opa = op & 0x3f; @@ -9082,6 +8960,17 @@ display_debug_frames (section, start, file) case DW_CFA_def_cfa_offset: LEB (); break; + case DW_CFA_def_cfa_expression: + tmp = LEB (); + start += tmp; + break; + case DW_CFA_expression: + reg = LEB (); + tmp = LEB (); + start += tmp; + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; case DW_CFA_offset_extended_sf: reg = LEB (); SLEB (); frame_need_space (fc, reg); @@ -9093,6 +8982,9 @@ display_debug_frames (section, start, file) case DW_CFA_def_cfa_offset_sf: SLEB (); break; + case DW_CFA_MIPS_advance_loc8: + start += 8; + break; case DW_CFA_GNU_args_size: LEB (); break; @@ -9154,7 +9046,7 @@ display_debug_frames (section, start, file) break; case DW_CFA_set_loc: - vma = byte_get (start, encoded_ptr_size); + vma = get_encoded_value (start, fc->fde_encoding); if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel) vma += section->sh_addr + (start - section_start); start += encoded_ptr_size; @@ -9236,7 +9128,7 @@ display_debug_frames (section, start, file) reg = LEB (); roffs = LEB (); if (! do_debug_frames_interp) - printf (" DW_CFA_register: r%ld\n", reg); + printf (" DW_CFA_register: r%ld in r%ld\n", reg, roffs); fc->col_type[reg] = DW_CFA_register; fc->col_offset[reg] = roffs; break; @@ -9244,10 +9136,10 @@ display_debug_frames (section, start, file) case DW_CFA_remember_state: if (! do_debug_frames_interp) printf (" DW_CFA_remember_state\n"); - rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk)); + rs = xmalloc (sizeof (Frame_Chunk)); rs->ncols = fc->ncols; - rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int)); - rs->col_offset = (int *) xmalloc (rs->ncols * sizeof (int)); + rs->col_type = xmalloc (rs->ncols * sizeof (short int)); + rs->col_offset = xmalloc (rs->ncols * sizeof (int)); memcpy (rs->col_type, fc->col_type, rs->ncols); memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int)); rs->next = remembered_state; @@ -9258,18 +9150,25 @@ display_debug_frames (section, start, file) if (! do_debug_frames_interp) printf (" DW_CFA_restore_state\n"); rs = remembered_state; - remembered_state = rs->next; - frame_need_space (fc, rs->ncols-1); - memcpy (fc->col_type, rs->col_type, rs->ncols); - memcpy (fc->col_offset, rs->col_offset, rs->ncols * sizeof (int)); - free (rs->col_type); - free (rs->col_offset); - free (rs); + if (rs) + { + remembered_state = rs->next; + frame_need_space (fc, rs->ncols-1); + memcpy (fc->col_type, rs->col_type, rs->ncols); + memcpy (fc->col_offset, rs->col_offset, + rs->ncols * sizeof (int)); + free (rs->col_type); + free (rs->col_offset); + free (rs); + } + else if (do_debug_frames_interp) + printf ("Mismatched DW_CFA_restore_state\n"); break; case DW_CFA_def_cfa: fc->cfa_reg = LEB (); fc->cfa_offset = LEB (); + fc->cfa_exp = 0; if (! do_debug_frames_interp) printf (" DW_CFA_def_cfa: r%d ofs %d\n", fc->cfa_reg, fc->cfa_offset); @@ -9277,6 +9176,7 @@ display_debug_frames (section, start, file) case DW_CFA_def_cfa_register: fc->cfa_reg = LEB (); + fc->cfa_exp = 0; if (! do_debug_frames_interp) printf (" DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg); break; @@ -9292,6 +9192,31 @@ display_debug_frames (section, start, file) printf (" DW_CFA_nop\n"); break; + case DW_CFA_def_cfa_expression: + ul = LEB (); + if (! do_debug_frames_interp) + { + printf (" DW_CFA_def_cfa_expression ("); + decode_location_expression (start, addr_size, ul); + printf (")\n"); + } + fc->cfa_exp = 1; + start += ul; + break; + + case DW_CFA_expression: + reg = LEB (); + ul = LEB (); + if (! do_debug_frames_interp) + { + printf (" DW_CFA_expression: r%ld (", reg); + decode_location_expression (start, addr_size, ul); + printf (")\n"); + } + fc->col_type[reg] = DW_CFA_expression; + start += ul; + break; + case DW_CFA_offset_extended_sf: reg = LEB (); l = SLEB (); @@ -9306,6 +9231,7 @@ display_debug_frames (section, start, file) case DW_CFA_def_cfa_sf: fc->cfa_reg = LEB (); fc->cfa_offset = SLEB (); + fc->cfa_exp = 0; if (! do_debug_frames_interp) printf (" DW_CFA_def_cfa_sf: r%d ofs %d\n", fc->cfa_reg, fc->cfa_offset); @@ -9317,6 +9243,17 @@ display_debug_frames (section, start, file) printf (" DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset); break; + case DW_CFA_MIPS_advance_loc8: + ofs = byte_get (start, 8); start += 8; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_MIPS_advance_loc8: %ld to %08lx\n", + ofs * fc->code_factor, + fc->pc_begin + ofs * fc->code_factor); + fc->pc_begin += ofs * fc->code_factor; + break; + case DW_CFA_GNU_window_save: if (! do_debug_frames_interp) printf (" DW_CFA_GNU_window_save\n"); @@ -9339,17 +9276,6 @@ display_debug_frames (section, start, file) fc->col_offset[reg] = l * fc->data_factor; break; - /* FIXME: How do we handle these? */ - case DW_CFA_def_cfa_expression: - fprintf (stderr, "unsupported DW_CFA_def_cfa_expression\n"); - start = block_end; - break; - - case DW_CFA_expression: - fprintf (stderr, "unsupported DW_CFA_expression\n"); - start = block_end; - break; - default: fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op); start = block_end; @@ -9372,10 +9298,9 @@ display_debug_frames (section, start, file) #undef SLEB static int -display_debug_not_supported (section, start, file) - Elf_Internal_Shdr *section; - unsigned char *start ATTRIBUTE_UNUSED; - FILE *file ATTRIBUTE_UNUSED; +display_debug_not_supported (Elf_Internal_Shdr *section, + unsigned char *start ATTRIBUTE_UNUSED, + FILE *file ATTRIBUTE_UNUSED) { printf (_("Displaying the debug contents of section %s is not yet supported.\n"), SECTION_NAME (section)); @@ -9383,87 +9308,35 @@ display_debug_not_supported (section, start, file) return 1; } -/* Pre-scan the .debug_info section to record the size of address. - When dumping the .debug_line, we use that size information, assuming - that all compilation units have the same address size. */ -static int -prescan_debug_info (section, start, file) - Elf_Internal_Shdr *section ATTRIBUTE_UNUSED; - unsigned char *start; - FILE *file ATTRIBUTE_UNUSED; -{ - unsigned long length; - - /* Read the first 4 bytes. For a 32-bit DWARF section, this will - be the length. For a 64-bit DWARF section, it'll be the escape - code 0xffffffff followed by an 8 byte length. For the purposes - of this prescan, we don't care about the actual length, but the - presence of the escape bytes does affect the location of the byte - which describes the address size. */ - length = byte_get (start, 4); - - if (length == 0xffffffff) - { - /* For 64-bit DWARF, the 1-byte address_size field is 22 bytes - from the start of the section. This is computed as follows: - - unit_length: 12 bytes - version: 2 bytes - debug_abbrev_offset: 8 bytes - ----------------------------- - Total: 22 bytes */ - - debug_line_pointer_size = byte_get (start + 22, 1); - } - else - { - /* For 32-bit DWARF, the 1-byte address_size field is 10 bytes from - the start of the section: - unit_length: 4 bytes - version: 2 bytes - debug_abbrev_offset: 4 bytes - ----------------------------- - Total: 10 bytes */ - - debug_line_pointer_size = byte_get (start + 10, 1); - } - return 0; -} - - /* A structure containing the name of a debug section and a pointer - to a function that can decode it. The third field is a prescan - function to be run over the section before displaying any of the - sections. */ +/* A structure containing the name of a debug section + and a pointer to a function that can decode it. */ struct { const char *const name; - int (*display) PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); - int (*prescan) PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *)); + int (*display) (Elf_Internal_Shdr *, unsigned char *, FILE *); } debug_displays[] = { - { ".debug_abbrev", display_debug_abbrev, NULL }, - { ".debug_aranges", display_debug_aranges, NULL }, - { ".debug_frame", display_debug_frames, NULL }, - { ".debug_info", display_debug_info, prescan_debug_info }, - { ".debug_line", display_debug_lines, NULL }, - { ".debug_pubnames", display_debug_pubnames, NULL }, - { ".eh_frame", display_debug_frames, NULL }, - { ".debug_macinfo", display_debug_macinfo, NULL }, - { ".debug_str", display_debug_str, NULL }, - { ".debug_loc", display_debug_loc, NULL }, - { ".debug_pubtypes", display_debug_not_supported, NULL }, - { ".debug_ranges", display_debug_not_supported, NULL }, - { ".debug_static_func", display_debug_not_supported, NULL }, - { ".debug_static_vars", display_debug_not_supported, NULL }, - { ".debug_types", display_debug_not_supported, NULL }, - { ".debug_weaknames", display_debug_not_supported, NULL } + { ".debug_abbrev", display_debug_abbrev }, + { ".debug_aranges", display_debug_aranges }, + { ".debug_frame", display_debug_frames }, + { ".debug_info", display_debug_info }, + { ".debug_line", display_debug_lines }, + { ".debug_pubnames", display_debug_pubnames }, + { ".eh_frame", display_debug_frames }, + { ".debug_macinfo", display_debug_macinfo }, + { ".debug_str", display_debug_str }, + { ".debug_loc", display_debug_loc }, + { ".debug_pubtypes", display_debug_not_supported }, + { ".debug_ranges", display_debug_not_supported }, + { ".debug_static_func", display_debug_not_supported }, + { ".debug_static_vars", display_debug_not_supported }, + { ".debug_types", display_debug_not_supported }, + { ".debug_weaknames", display_debug_not_supported } }; static int -display_debug_section (section, file) - Elf_Internal_Shdr *section; - FILE *file; +display_debug_section (Elf_Internal_Shdr *section, FILE *file) { char *name = SECTION_NAME (section); bfd_size_type length; @@ -9477,8 +9350,8 @@ display_debug_section (section, file) return 0; } - start = (unsigned char *) get_data (NULL, file, section->sh_offset, length, - _("debug section data")); + start = get_data (NULL, file, section->sh_offset, length, + _("debug section data")); if (!start) return 0; @@ -9506,8 +9379,7 @@ display_debug_section (section, file) } static int -process_section_contents (file) - FILE *file; +process_section_contents (FILE *file) { Elf_Internal_Shdr *section; unsigned int i; @@ -9515,43 +9387,6 @@ process_section_contents (file) if (! do_dump) return 1; - /* Pre-scan the debug sections to find some debug information not - present in some of them. For the .debug_line, we must find out the - size of address (specified in .debug_info and .debug_aranges). */ - for (i = 0, section = section_headers; - i < elf_header.e_shnum && i < num_dump_sects; - i++, section++) - { - char *name = SECTION_NAME (section); - int j; - - if (section->sh_size == 0) - continue; - - /* See if there is some pre-scan operation for this section. */ - for (j = NUM_ELEM (debug_displays); j--;) - if (strcmp (debug_displays[j].name, name) == 0) - { - if (debug_displays[j].prescan != NULL) - { - bfd_size_type length; - unsigned char *start; - - length = section->sh_size; - start = ((unsigned char *) - get_data (NULL, file, section->sh_offset, length, - _("debug section data"))); - if (!start) - return 0; - - debug_displays[j].prescan (section, start, file); - free (start); - } - - break; - } - } - for (i = 0, section = section_headers; i < elf_header.e_shnum && i < num_dump_sects; i++, section++) @@ -9574,8 +9409,7 @@ process_section_contents (file) } static void -process_mips_fpe_exception (mask) - int mask; +process_mips_fpe_exception (int mask) { if (mask) { @@ -9596,8 +9430,7 @@ process_mips_fpe_exception (mask) } static int -process_mips_specific (file) - FILE *file; +process_mips_specific (FILE *file) { Elf_Internal_Dyn *entry; size_t liblist_offset = 0; @@ -9615,16 +9448,20 @@ process_mips_specific (file) switch (entry->d_tag) { case DT_MIPS_LIBLIST: - liblist_offset = entry->d_un.d_val - loadaddr; + liblist_offset + = offset_from_vma (file, entry->d_un.d_val, + liblistno * sizeof (Elf32_External_Lib)); break; case DT_MIPS_LIBLISTNO: liblistno = entry->d_un.d_val; break; case DT_MIPS_OPTIONS: - options_offset = entry->d_un.d_val - loadaddr; + options_offset = offset_from_vma (file, entry->d_un.d_val, 0); break; case DT_MIPS_CONFLICT: - conflicts_offset = entry->d_un.d_val - loadaddr; + conflicts_offset + = offset_from_vma (file, entry->d_un.d_val, + conflictsno * sizeof (Elf32_External_Conflict)); break; case DT_MIPS_CONFLICTNO: conflictsno = entry->d_un.d_val; @@ -9638,10 +9475,9 @@ process_mips_specific (file) Elf32_External_Lib *elib; size_t cnt; - elib = ((Elf32_External_Lib *) - get_data (NULL, file, liblist_offset, - liblistno * sizeof (Elf32_External_Lib), - _("liblist"))); + elib = get_data (NULL, file, liblist_offset, + liblistno * sizeof (Elf32_External_Lib), + _("liblist")); if (elib) { printf ("\nSection '.liblist' contains %lu entries:\n", @@ -9725,12 +9561,11 @@ process_mips_specific (file) while (sect->sh_type != SHT_MIPS_OPTIONS) ++sect; - eopt = (Elf_External_Options *) get_data (NULL, file, options_offset, - sect->sh_size, _("options")); + eopt = get_data (NULL, file, options_offset, sect->sh_size, + _("options")); if (eopt) { - iopt = ((Elf_Internal_Options *) - malloc ((sect->sh_size / sizeof (eopt)) * sizeof (*iopt))); + iopt = malloc ((sect->sh_size / sizeof (eopt)) * sizeof (*iopt)); if (iopt == NULL) { error (_("Out of memory")); @@ -9922,7 +9757,7 @@ process_mips_specific (file) return 0; } - iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (*iconf)); + iconf = malloc (conflictsno * sizeof (*iconf)); if (iconf == NULL) { error (_("Out of memory")); @@ -9933,10 +9768,8 @@ process_mips_specific (file) { Elf32_External_Conflict *econf32; - econf32 = ((Elf32_External_Conflict *) - get_data (NULL, file, conflicts_offset, - conflictsno * sizeof (*econf32), - _("conflict"))); + econf32 = get_data (NULL, file, conflicts_offset, + conflictsno * sizeof (*econf32), _("conflict")); if (!econf32) return 0; @@ -9949,10 +9782,8 @@ process_mips_specific (file) { Elf64_External_Conflict *econf64; - econf64 = ((Elf64_External_Conflict *) - get_data (NULL, file, conflicts_offset, - conflictsno * sizeof (*econf64), - _("conflict"))); + econf64 = get_data (NULL, file, conflicts_offset, + conflictsno * sizeof (*econf64), _("conflict")); if (!econf64) return 0; @@ -9962,8 +9793,8 @@ process_mips_specific (file) free (econf64); } - printf (_("\nSection '.conflict' contains %ld entries:\n"), - (long) conflictsno); + printf (_("\nSection '.conflict' contains %lu entries:\n"), + (unsigned long) conflictsno); puts (_(" Num: Index Value Name")); for (cnt = 0; cnt < conflictsno; ++cnt) @@ -9984,8 +9815,7 @@ process_mips_specific (file) } static int -process_gnu_liblist (file) - FILE *file; +process_gnu_liblist (FILE *file) { Elf_Internal_Shdr *section, *string_sec; Elf32_External_Lib *elib; @@ -10003,17 +9833,15 @@ process_gnu_liblist (file) switch (section->sh_type) { case SHT_GNU_LIBLIST: - elib = ((Elf32_External_Lib *) - get_data (NULL, file, section->sh_offset, section->sh_size, - _("liblist"))); + elib = get_data (NULL, file, section->sh_offset, section->sh_size, + _("liblist")); if (elib == NULL) break; string_sec = SECTION_HEADER (section->sh_link); - strtab = (char *) get_data (NULL, file, string_sec->sh_offset, - string_sec->sh_size, - _("liblist string table")); + strtab = get_data (NULL, file, string_sec->sh_offset, + string_sec->sh_size, _("liblist string table")); if (strtab == NULL || section->sh_entsize != sizeof (Elf32_External_Lib)) @@ -10064,13 +9892,13 @@ process_gnu_liblist (file) } static const char * -get_note_type (e_type) - unsigned e_type; +get_note_type (unsigned e_type) { static char buff[64]; switch (e_type) { + case NT_AUXV: return _("NT_AUXV (auxiliary vector)"); case NT_PRSTATUS: return _("NT_PRSTATUS (prstatus structure)"); case NT_FPREGSET: return _("NT_FPREGSET (floating point registers)"); case NT_PRPSINFO: return _("NT_PRPSINFO (prpsinfo structure)"); @@ -10089,8 +9917,7 @@ get_note_type (e_type) } static const char * -get_netbsd_elfcore_note_type (e_type) - unsigned e_type; +get_netbsd_elfcore_note_type (unsigned e_type) { static char buff[64]; @@ -10156,8 +9983,7 @@ get_netbsd_elfcore_note_type (e_type) If the value of namesz is zero, there is no name present. */ static int -process_note (pnote) - Elf_Internal_Note *pnote; +process_note (Elf_Internal_Note *pnote) { const char *nt; @@ -10187,10 +10013,7 @@ process_note (pnote) static int -process_corefile_note_segment (file, offset, length) - FILE *file; - bfd_vma offset; - bfd_vma length; +process_corefile_note_segment (FILE *file, bfd_vma offset, bfd_vma length) { Elf_External_Note *pnotes; Elf_External_Note *external; @@ -10199,8 +10022,7 @@ process_corefile_note_segment (file, offset, length) if (length <= 0) return 0; - pnotes = (Elf_External_Note *) get_data (NULL, file, offset, length, - _("notes")); + pnotes = get_data (NULL, file, offset, length, _("notes")); if (!pnotes) return 0; @@ -10273,33 +10095,14 @@ process_corefile_note_segment (file, offset, length) } static int -process_corefile_note_segments (file) - FILE *file; +process_corefile_note_segments (FILE *file) { - Elf_Internal_Phdr *program_headers; Elf_Internal_Phdr *segment; unsigned int i; int res = 1; - program_headers = (Elf_Internal_Phdr *) malloc - (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); - - if (program_headers == NULL) - { - error (_("Out of memory\n")); - return 0; - } - - if (is_32bit_elf) - i = get_32bit_program_headers (file, program_headers); - else - i = get_64bit_program_headers (file, program_headers); - - if (i == 0) - { - free (program_headers); + if (! get_program_headers (file)) return 0; - } for (i = 0, segment = program_headers; i < elf_header.e_phnum; @@ -10311,14 +10114,11 @@ process_corefile_note_segments (file) (bfd_vma) segment->p_filesz); } - free (program_headers); - return res; } static int -process_corefile_contents (file) - FILE *file; +process_corefile_contents (FILE *file) { /* If we have not been asked to display the notes then do nothing. */ if (! do_notes) @@ -10339,8 +10139,7 @@ process_corefile_contents (file) } static int -process_arch_specific (file) - FILE *file; +process_arch_specific (FILE *file) { if (! do_arch) return 1; @@ -10358,8 +10157,7 @@ process_arch_specific (file) } static int -get_file_header (file) - FILE *file; +get_file_header (FILE *file) { /* Read in the identity array. */ if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1) @@ -10412,7 +10210,7 @@ get_file_header (file) /* If we have been compiled with sizeof (bfd_vma) == 4, then we will not be able to cope with the 64bit data found in 64 ELF files. Detect this now and abort before we start - overwritting things. */ + overwriting things. */ if (sizeof (bfd_vma) < 8) { error (_("This instance of readelf has been built without support for a\n\ @@ -10451,31 +10249,18 @@ get_file_header (file) return 1; } +/* Process one ELF object file according to the command line options. + This file may actually be stored in an archive. The file is + positioned at the start of the ELF object. */ + static int -process_file (file_name) - char *file_name; +process_object (char *file_name, FILE *file) { - FILE *file; - struct stat statbuf; unsigned int i; - if (stat (file_name, & statbuf) < 0) - { - error (_("Cannot stat input file %s.\n"), file_name); - return 1; - } - - file = fopen (file_name, "rb"); - if (file == NULL) - { - error (_("Input file %s not found.\n"), file_name); - return 1; - } - if (! get_file_header (file)) { error (_("%s: Failed to read file header\n"), file_name); - fclose (file); return 1; } @@ -10491,10 +10276,7 @@ process_file (file_name) printf (_("\nFile: %s\n"), file_name); if (! process_file_header ()) - { - fclose (file); - return 1; - } + return 1; if (! process_section_headers (file)) { @@ -10527,7 +10309,11 @@ process_file (file_name) process_arch_specific (file); - fclose (file); + if (program_headers) + { + free (program_headers); + program_headers = NULL; + } if (section_headers) { @@ -10564,6 +10350,230 @@ process_file (file_name) return 0; } +/* Process an ELF archive. The file is positioned just after the + ARMAG string. */ + +static int +process_archive (char *file_name, FILE *file) +{ + struct ar_hdr arhdr; + size_t got; + unsigned long size; + char *longnames = NULL; + unsigned long longnames_size = 0; + size_t file_name_size; + int ret; + + show_name = 1; + + got = fread (&arhdr, 1, sizeof arhdr, file); + if (got != sizeof arhdr) + { + if (got == 0) + return 0; + + error (_("%s: failed to read archive header\n"), file_name); + return 1; + } + + if (memcmp (arhdr.ar_name, "/ ", 16) == 0) + { + /* This is the archive symbol table. Skip it. + FIXME: We should have an option to dump it. */ + size = strtoul (arhdr.ar_size, NULL, 10); + if (fseek (file, size + (size & 1), SEEK_CUR) != 0) + { + error (_("%s: failed to skip archive symbol table\n"), file_name); + return 1; + } + + got = fread (&arhdr, 1, sizeof arhdr, file); + if (got != sizeof arhdr) + { + if (got == 0) + return 0; + + error (_("%s: failed to read archive header\n"), file_name); + return 1; + } + } + + if (memcmp (arhdr.ar_name, "// ", 16) == 0) + { + /* This is the archive string table holding long member + names. */ + + longnames_size = strtoul (arhdr.ar_size, NULL, 10); + + longnames = malloc (longnames_size); + if (longnames == NULL) + { + error (_("Out of memory\n")); + return 1; + } + + if (fread (longnames, longnames_size, 1, file) != 1) + { + free (longnames); + error(_("%s: failed to read string table\n"), file_name); + return 1; + } + + if ((longnames_size & 1) != 0) + getc (file); + + got = fread (&arhdr, 1, sizeof arhdr, file); + if (got != sizeof arhdr) + { + free (longnames); + + if (got == 0) + return 0; + + error (_("%s: failed to read archive header\n"), file_name); + return 1; + } + } + + file_name_size = strlen (file_name); + ret = 0; + + while (1) + { + char *name; + char *nameend; + char *namealc; + + if (arhdr.ar_name[0] == '/') + { + unsigned long off; + + off = strtoul (arhdr.ar_name + 1, NULL, 10); + if (off >= longnames_size) + { + error (_("%s: invalid archive string table offset %lu\n"), off); + ret = 1; + break; + } + + name = longnames + off; + nameend = memchr (name, '/', longnames_size - off); + } + else + { + name = arhdr.ar_name; + nameend = memchr (name, '/', 16); + } + + if (nameend == NULL) + { + error (_("%s: bad archive file name\n")); + ret = 1; + break; + } + + namealc = malloc (file_name_size + (nameend - name) + 3); + if (namealc == NULL) + { + error (_("Out of memory\n")); + ret = 1; + break; + } + + memcpy (namealc, file_name, file_name_size); + namealc[file_name_size] = '('; + memcpy (namealc + file_name_size + 1, name, nameend - name); + namealc[file_name_size + 1 + (nameend - name)] = ')'; + namealc[file_name_size + 2 + (nameend - name)] = '\0'; + + archive_file_offset = ftell (file); + archive_file_size = strtoul (arhdr.ar_size, NULL, 10); + + ret |= process_object (namealc, file); + + free (namealc); + + if (fseek (file, + (archive_file_offset + + archive_file_size + + (archive_file_size & 1)), + SEEK_SET) != 0) + { + error (_("%s: failed to seek to next archive header\n"), file_name); + ret = 1; + break; + } + + got = fread (&arhdr, 1, sizeof arhdr, file); + if (got != sizeof arhdr) + { + if (got == 0) + break; + + error (_("%s: failed to read archive header\n"), file_name); + ret = 1; + break; + } + } + + if (longnames != 0) + free (longnames); + + return ret; +} + +static int +process_file (char *file_name) +{ + FILE *file; + struct stat statbuf; + char armag[SARMAG]; + int ret; + + if (stat (file_name, &statbuf) < 0) + { + if (errno == ENOENT) + error (_("'%s': No such file\n"), file_name); + else + error (_("Could not locate '%s'. System error message: %s\n"), + file_name, strerror (errno)); + return 1; + } + + if (! S_ISREG (statbuf.st_mode)) + { + error (_("'%s' is not an ordinary file\n"), file_name); + return 1; + } + + file = fopen (file_name, "rb"); + if (file == NULL) + { + error (_("Input file '%s' is not readable.\n"), file_name); + return 1; + } + + if (fread (armag, SARMAG, 1, file) != 1) + { + error (_("%s: Failed to read file header\n"), file_name); + fclose (file); + return 1; + } + + if (memcmp (armag, ARMAG, SARMAG) == 0) + ret = process_archive (file_name, file); + else + { + rewind (file); + archive_file_size = archive_file_offset = 0; + ret = process_object (file_name, file); + } + + fclose (file); + + return ret; +} + #ifdef SUPPORT_DISASSEMBLY /* Needed by the i386 disassembler. For extra credit, someone could fix this so that we insert symbolic addresses here, esp for GOT/PLT @@ -10583,12 +10593,8 @@ db_task_printsym (unsigned int addr) } #endif -int main PARAMS ((int, char **)); - int -main (argc, argv) - int argc; - char **argv; +main (int argc, char **argv) { int err; char *cmdline_dump_sects = NULL;