X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=6774088bb864467ffec4c847d9b22a62cd2b702a;hb=6edf0760c5c65c9f0582c5d8036bfa058f2cd6c2;hp=dccbfc1949b74275a5998cf3bfcd97613c8d290c;hpb=3b36097dde707d7f7506359204a55b6a2e163f71;p=binutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index dccbfc1949b..6774088bb86 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 @@ -79,6 +97,7 @@ #include "elf/or32.h" #include "elf/pj.h" #include "elf/ppc.h" +#include "elf/ppc64.h" #include "elf/s390.h" #include "elf/sh.h" #include "elf/sparc.h" @@ -87,11 +106,17 @@ #include "elf/x86-64.h" #include "elf/xstormy16.h" #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; @@ -103,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; @@ -159,224 +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 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_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 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)); -static unsigned char *read_and_display_attr_value - PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, - unsigned long)); -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; @@ -402,7 +211,7 @@ typedef int Elf32_Word; #define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I)) -#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ #define BYTE_GET(field) byte_get (field, sizeof (field)) @@ -428,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; } @@ -485,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; @@ -495,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) { @@ -527,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) @@ -543,11 +344,58 @@ 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 (unsigned char *field, bfd_vma value, int size) +{ + switch (size) + { + case 8: + field[7] = (((value >> 24) >> 24) >> 8) & 0xff; + field[6] = ((value >> 24) >> 24) & 0xff; + field[5] = ((value >> 24) >> 16) & 0xff; + field[4] = ((value >> 24) >> 8) & 0xff; + /* Fall through. */ + case 4: + field[3] = (value >> 24) & 0xff; + field[2] = (value >> 16) & 0xff; + /* Fall through. */ + case 2: + field[1] = (value >> 8) & 0xff; + /* Fall through. */ + case 1: + field[0] = value & 0xff; + break; + + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + /* 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) @@ -555,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 @@ -571,7 +440,7 @@ print_vma (vma, mode) { case FULL_HEX: printf ("0x"); - /* drop through */ + /* Drop through. */ case LONG_HEX: printf_vma (vma); @@ -579,7 +448,7 @@ print_vma (vma, mode) case PREFIX_HEX: printf ("0x"); - /* drop through */ + /* Drop through. */ case HEX: #if BFD_HOST_64BIT_LONG @@ -606,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; @@ -639,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); @@ -652,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) { @@ -684,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) @@ -701,11 +571,42 @@ byte_get_big_endian (field, size) } } +static void +byte_put_big_endian (unsigned char *field, bfd_vma value, int size) +{ + switch (size) + { + case 8: + field[7] = value & 0xff; + field[6] = (value >> 8) & 0xff; + field[5] = (value >> 16) & 0xff; + field[4] = (value >> 24) & 0xff; + value >>= 16; + value >>= 16; + /* Fall through. */ + case 4: + field[3] = value & 0xff; + field[2] = (value >> 8) & 0xff; + value >>= 16; + /* Fall through. */ + case 2: + field[1] = value & 0xff; + value >>= 8; + /* Fall through. */ + case 1: + field[0] = value & 0xff; + break; + + default: + error (_("Unhandled data length: %d\n"), size); + abort (); + } +} + /* 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) { @@ -717,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: @@ -765,6 +665,9 @@ guess_is_rela (e_machine) case EM_IP2K: case EM_IP2K_OLD: case EM_IQ2000: + case EM_XTENSA: + case EM_XTENSA_OLD: + case EM_M32R: return TRUE; case EM_MMA: @@ -791,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; @@ -806,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) { @@ -835,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) { @@ -866,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; @@ -881,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) { @@ -909,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) { @@ -938,16 +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; @@ -989,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")); } @@ -1011,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; @@ -1024,8 +920,22 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) } else { + /* The #ifdef BFD64 below is to prevent a compile time warning. + We know that if we do not have a 64 bit data type that we + will never execute this code anyway. */ +#ifdef BFD64 if (elf_header.e_machine == EM_MIPS) { + /* In little-endian objects, r_info isn't really a 64-bit + little-endian value: it has a 32-bit little-endian + symbol index followed by four individual byte fields. + Reorder INFO accordingly. */ + if (elf_header.e_ident[EI_DATA] != ELFDATA2MSB) + info = (((info & 0xffffffff) << 32) + | ((info >> 56) & 0xff) + | ((info >> 40) & 0xff00) + | ((info >> 24) & 0xff0000) + | ((info >> 8) & 0xff000000)); type = ELF64_MIPS_R_TYPE (info); type2 = ELF64_MIPS_R_TYPE2 (info); type3 = ELF64_MIPS_R_TYPE3 (info); @@ -1034,10 +944,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) type = ELF64_R_TYPE_ID (info); else type = ELF64_R_TYPE (info); - /* The #ifdef BFD64 below is to prevent a compile time warning. - We know that if we do not have a 64 bit data type that we - will never execute this code anyway. */ -#ifdef BFD64 + symtab_index = ELF64_R_SYM (info); #endif } @@ -1165,10 +1072,13 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) break; case EM_PPC: - case EM_PPC64: rtype = elf_ppc_reloc_type (type); break; + case EM_PPC64: + rtype = elf_ppc64_reloc_type (type); + break; + case EM_MIPS: case EM_MIPS_RS3_LE: rtype = elf_mips_reloc_type (type); @@ -1251,6 +1161,11 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) case EM_IQ2000: rtype = elf_iq2000_reloc_type (type); break; + + case EM_XTENSA_OLD: + case EM_XTENSA: + rtype = elf_xtensa_reloc_type (type); + break; } if (rtype == NULL) @@ -1260,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) { @@ -1297,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, "
", @@ -1361,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) { @@ -1415,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) { @@ -1427,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) { @@ -1441,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) { @@ -1465,8 +1380,18 @@ get_parisc_dynamic_type (type) } static const char * -get_dynamic_type (type) - unsigned long type; +get_ia64_dynamic_type (unsigned long type) +{ + switch (type) + { + case DT_IA_64_PLT_RESERVE: return "IA_64_PLT_RESERVE"; + default: + return NULL; + } +} + +static const char * +get_dynamic_type (unsigned long type) { static char buff[32]; @@ -1561,6 +1486,9 @@ get_dynamic_type (type) case EM_PPC64: result = get_ppc64_dynamic_type (type); break; + case EM_IA_64: + result = get_ia64_dynamic_type (type); + break; default: result = NULL; break; @@ -1598,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]; @@ -1623,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 */ @@ -1654,14 +1580,14 @@ get_machine_name (e_machine) case EM_MCORE: return "MCORE"; case EM_ARM: return "ARM"; case EM_OLD_ALPHA: return "Digital Alpha (old)"; - case EM_SH: return "Hitachi SH"; + case EM_SH: return "Renesas / SuperH SH"; case EM_SPARCV9: return "Sparc v9"; case EM_TRICORE: return "Siemens Tricore"; case EM_ARC: return "ARC"; - case EM_H8_300: return "Hitachi H8/300"; - case EM_H8_300H: return "Hitachi H8/300H"; - case EM_H8S: return "Hitachi H8S"; - case EM_H8_500: return "Hitachi H8/500"; + case EM_H8_300: return "Renesas H8/300"; + case EM_H8_300H: return "Renesas H8/300H"; + case EM_H8S: return "Renesas H8S"; + case EM_H8_500: return "Renesas H8/500"; case EM_IA_64: return "Intel IA-64"; case EM_MIPS_X: return "Stanford MIPS-X"; case EM_COLDFIRE: return "Motorola Coldfire"; @@ -1672,7 +1598,7 @@ get_machine_name (e_machine) case EM_CYGNUS_D30V: case EM_D30V: return "d30v"; case EM_CYGNUS_M32R: - case EM_M32R: return "Mitsubishi M32r"; + case EM_M32R: return "Renesas M32R (formerly Mitsubishi M32r)"; case EM_CYGNUS_V850: case EM_V850: return "NEC v850"; case EM_CYGNUS_MN10300: @@ -1721,6 +1647,8 @@ get_machine_name (e_machine) case EM_IP2K_OLD: case EM_IP2K: return "Ubicom IP2xxx 8-bit microcontrollers"; case EM_IQ2000: return "Vitesse IQ2000"; + case EM_XTENSA_OLD: + case EM_XTENSA: return "Tensilica Xtensa Processor"; default: sprintf (buff, _(": %x"), e_machine); return buff; @@ -1728,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; @@ -1858,6 +1784,10 @@ decode_ARM_machine_flags (e_flags, buf) strcat (buf, ", software FP"); break; + case EF_ARM_MAVERICK_FLOAT: + strcat (buf, ", Maverick FP"); + break; + default: unknown = 1; break; @@ -1870,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]; @@ -1911,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; @@ -2003,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; } @@ -2102,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) { @@ -2121,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) { @@ -2148,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) { @@ -2167,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]; @@ -2185,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)) @@ -2243,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) { @@ -2294,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) { @@ -2309,13 +2266,17 @@ 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"; - case SHT_IA_64_UNWIND: return "IA_64_UNWIND"; + case SHT_IA_64_EXT: return "IA_64_EXT"; + case SHT_IA_64_UNWIND: return "IA_64_UNWIND"; + case SHT_IA_64_PRIORITY_INIT: return "IA_64_PRIORITY_INIT"; default: break; } @@ -2323,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]; @@ -2428,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")); @@ -2469,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.")); @@ -2500,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; @@ -2510,7 +2466,7 @@ parse_args (argc, argv) usage (); while ((c = getopt_long - (argc, argv, "ersuahnldSDAIw::x:i:vVW", options, NULL)) != EOF) + (argc, argv, "ersuahnldSDAIw::x:i:vVWH", options, NULL)) != EOF) { char *cp; int section; @@ -2773,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]; @@ -2790,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]; @@ -2806,37 +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_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 @@ -2925,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; @@ -2961,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; @@ -2996,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; @@ -3024,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")); + if (! get_program_headers (file)) 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); - return 0; - } if (do_segments) { @@ -3066,7 +2999,6 @@ process_program_headers (file) } } - loadaddr = -1; dynamic_addr = 0; dynamic_size = 0; @@ -3154,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")); @@ -3175,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 { @@ -3193,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")); @@ -3235,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) { @@ -3288,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) { @@ -3334,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; @@ -3345,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; @@ -3356,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); @@ -3367,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) { @@ -3401,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; @@ -3412,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; @@ -3423,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); @@ -3434,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) { @@ -3468,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]; @@ -3516,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; @@ -3549,9 +3473,12 @@ 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; } @@ -3588,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) { @@ -3750,10 +3676,22 @@ process_section_headers (file) return 1; } +struct +{ + const char *name; + int reloc; + int size; + int rela; +} dynamic_relocations [] = +{ + { "REL", DT_REL, DT_RELSZ, FALSE }, + { "RELA", DT_RELA, DT_RELASZ, TRUE }, + { "PLT", DT_JMPREL, DT_PLTRELSZ, UNKNOWN } +}; + /* Process the reloc section. */ static int -process_relocs (file) - FILE *file; +process_relocs (FILE *file) { unsigned long rel_size; unsigned long rel_offset; @@ -3764,53 +3702,51 @@ process_relocs (file) if (do_using_dynamic) { - int is_rela = FALSE; - - rel_size = 0; - rel_offset = 0; + int is_rela; + const char *name; + int has_dynamic_reloc; + unsigned int i; + + has_dynamic_reloc = 0; - if (dynamic_info[DT_REL]) - { - rel_offset = dynamic_info[DT_REL]; - rel_size = dynamic_info[DT_RELSZ]; - is_rela = FALSE; - } - else if (dynamic_info[DT_RELA]) + for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++) { - rel_offset = dynamic_info[DT_RELA]; - rel_size = dynamic_info[DT_RELASZ]; - is_rela = TRUE; - } - else if (dynamic_info[DT_JMPREL]) - { - rel_offset = dynamic_info[DT_JMPREL]; - rel_size = dynamic_info[DT_PLTRELSZ]; + is_rela = dynamic_relocations [i].rela; + name = dynamic_relocations [i].name; + rel_size = dynamic_info [dynamic_relocations [i].size]; + rel_offset = dynamic_info [dynamic_relocations [i].reloc]; - switch (dynamic_info[DT_PLTREL]) + has_dynamic_reloc |= rel_size; + + if (is_rela == UNKNOWN) { - case DT_REL: - is_rela = FALSE; - break; - case DT_RELA: - is_rela = TRUE; - break; - default: - is_rela = UNKNOWN; - break; + if (dynamic_relocations [i].reloc == DT_JMPREL) + switch (dynamic_info[DT_PLTREL]) + { + case DT_REL: + is_rela = FALSE; + break; + case DT_RELA: + is_rela = TRUE; + break; + } } - } - - if (rel_size) - { - printf - (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"), - rel_offset, rel_size); - dump_relocations (file, rel_offset - loadaddr, rel_size, - dynamic_symbols, num_dynamic_syms, dynamic_strings, - is_rela); + if (rel_size) + { + printf + (_("\n'%s' relocation section at offset 0x%lx contains %ld bytes:\n"), + name, rel_offset, rel_size); + + dump_relocations (file, + offset_from_vma (file, rel_offset, rel_size), + rel_size, + dynamic_symbols, num_dynamic_syms, + dynamic_strings, is_rela); + } } - else + + if (! has_dynamic_reloc) printf (_("\nThere are no dynamic relocations in this file.\n")); } else @@ -3864,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; @@ -3921,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; @@ -3965,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; @@ -4024,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; @@ -4046,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; @@ -4072,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; @@ -4183,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; @@ -4212,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++; @@ -4282,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 ")); @@ -4319,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) { @@ -4394,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) { @@ -4450,16 +4359,34 @@ dynamic_segment_parisc_val (entry) putchar ('\n'); } +static void +dynamic_segment_ia64_val (Elf_Internal_Dyn *entry) +{ + switch (entry->d_tag) + { + 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); + 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; @@ -4470,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) { @@ -4494,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; @@ -4513,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) { @@ -4537,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; @@ -4571,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; @@ -4611,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 (fseek (file, 0, SEEK_END)) - error (_("Unable to seek to end of file!")); + 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!")); + + 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 @@ -4653,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) { @@ -4665,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; } } @@ -4689,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) @@ -4698,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")); @@ -4938,6 +4872,7 @@ process_dynamic_segment (file) break; case DT_PLTREL: + dynamic_info[entry->d_tag] = entry->d_un.d_val; if (do_dynamic) puts (get_dynamic_type (entry->d_un.d_val)); break; @@ -5012,6 +4947,7 @@ process_dynamic_segment (file) case DT_RELAENT : case DT_SYMENT : case DT_RELENT : + dynamic_info[entry->d_tag] = entry->d_un.d_val; case DT_PLTPADSZ: case DT_MOVEENT : case DT_MOVESZ : @@ -5099,6 +5035,9 @@ process_dynamic_segment (file) case EM_PARISC: dynamic_segment_parisc_val (entry); break; + case EM_IA_64: + dynamic_segment_ia64_val (entry); + break; default: print_vma (entry->d_un.d_val, PREFIX_HEX); putchar ('\n'); @@ -5112,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]; @@ -5141,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; @@ -5175,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; @@ -5266,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; @@ -5315,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"), @@ -5345,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; @@ -5355,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; @@ -5370,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), @@ -5429,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 { @@ -5485,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 { @@ -5547,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]; @@ -5569,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]; @@ -5616,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) { @@ -5630,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]; @@ -5641,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); @@ -5656,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) { @@ -5677,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) { @@ -5696,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]; @@ -5713,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; @@ -5816,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; @@ -5844,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")); @@ -5867,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 { @@ -5928,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 { @@ -5991,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")); @@ -6010,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")); @@ -6047,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; @@ -6114,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)); @@ -6128,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; @@ -6139,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)); @@ -6150,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; @@ -6200,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 ("."); @@ -6220,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; @@ -6268,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; @@ -6284,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; @@ -6351,36 +6277,46 @@ process_extended_line_op (data, is_stmt, pointer_size) static int debug_line_pointer_size = 4; 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 ATTRIBUTE_UNUSED) { - DWARF2_External_LineInfo *external; + unsigned char *hdrptr; DWARF2_Internal_LineInfo info; unsigned char *standard_opcodes; unsigned char *data = start; unsigned char *end = start + section->sh_size; unsigned char *end_of_sequence; int i; + int offset_size; + int initial_length_size; printf (_("\nDump of debug contents of section %s:\n\n"), SECTION_NAME (section)); while (data < end) { - external = (DWARF2_External_LineInfo *) data; + hdrptr = data; /* Check the length of the block. */ - info.li_length = BYTE_GET (external->li_length); + info.li_length = byte_get (hdrptr, 4); + hdrptr += 4; if (info.li_length == 0xffffffff) { - warn (_("64-bit DWARF line info is not supported yet.\n")); - break; + /* This section is 64-bit DWARF 3. */ + info.li_length = byte_get (hdrptr, 8); + hdrptr += 8; + offset_size = 8; + initial_length_size = 12; + } + else + { + offset_size = 4; + initial_length_size = 4; } - if (info.li_length + sizeof (external->li_length) > section->sh_size) + if (info.li_length + initial_length_size > section->sh_size) { warn (_("The line info appears to be corrupt - the section is too small\n")); @@ -6388,19 +6324,26 @@ display_debug_lines (section, start, file) } /* Check its version number. */ - info.li_version = BYTE_GET (external->li_version); - if (info.li_version != 2) + info.li_version = byte_get (hdrptr, 2); + hdrptr += 2; + if (info.li_version != 2 && info.li_version != 3) { - warn (_("Only DWARF version 2 line info is currently supported.\n")); + warn (_("Only DWARF version 2 and 3 line info is currently supported.\n")); return 0; } - info.li_prologue_length = BYTE_GET (external->li_prologue_length); - info.li_min_insn_length = BYTE_GET (external->li_min_insn_length); - info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt); - info.li_line_base = BYTE_GET (external->li_line_base); - info.li_line_range = BYTE_GET (external->li_line_range); - info.li_opcode_base = BYTE_GET (external->li_opcode_base); + info.li_prologue_length = byte_get (hdrptr, offset_size); + hdrptr += offset_size; + info.li_min_insn_length = byte_get (hdrptr, 1); + hdrptr++; + info.li_default_is_stmt = byte_get (hdrptr, 1); + hdrptr++; + info.li_line_base = byte_get (hdrptr, 1); + hdrptr++; + info.li_line_range = byte_get (hdrptr, 1); + hdrptr++; + info.li_opcode_base = byte_get (hdrptr, 1); + hdrptr++; /* Sign extend the line base field. */ info.li_line_base <<= 24; @@ -6415,12 +6358,12 @@ display_debug_lines (section, start, file) printf (_(" Line Range: %d\n"), info.li_line_range); printf (_(" Opcode Base: %d\n"), info.li_opcode_base); - end_of_sequence = data + info.li_length + sizeof (external->li_length); + end_of_sequence = data + info.li_length + initial_length_size; reset_state_machine (info.li_default_is_stmt); /* Display the contents of the Opcodes table. */ - standard_opcodes = data + sizeof (*external); + standard_opcodes = hdrptr; printf (_("\n Opcodes:\n")); @@ -6608,12 +6551,10 @@ 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_External_PubNames *external; DWARF2_Internal_PubNames pubnames; unsigned char *end; @@ -6625,30 +6566,41 @@ display_debug_pubnames (section, start, file) { unsigned char *data; unsigned long offset; + int offset_size, initial_length_size; - external = (DWARF2_External_PubNames *) start; - - pubnames.pn_length = BYTE_GET (external->pn_length); - pubnames.pn_version = BYTE_GET (external->pn_version); - pubnames.pn_offset = BYTE_GET (external->pn_offset); - pubnames.pn_size = BYTE_GET (external->pn_size); - - data = start + sizeof (*external); - start += pubnames.pn_length + sizeof (external->pn_length); + data = start; + pubnames.pn_length = byte_get (data, 4); + data += 4; if (pubnames.pn_length == 0xffffffff) { - warn (_("64-bit DWARF pubnames are not supported yet.\n")); - break; + pubnames.pn_length = byte_get (data, 8); + data += 8; + offset_size = 8; + initial_length_size = 12; + } + else + { + offset_size = 4; + initial_length_size = 4; } - if (pubnames.pn_version != 2) + pubnames.pn_version = byte_get (data, 2); + data += 2; + pubnames.pn_offset = byte_get (data, offset_size); + data += offset_size; + pubnames.pn_size = byte_get (data, offset_size); + data += offset_size; + + start += pubnames.pn_length + initial_length_size; + + if (pubnames.pn_version != 2 && pubnames.pn_version != 3) { static int warned = 0; if (! warned) { - warn (_("Only DWARF 2 pubnames are currently supported\n")); + warn (_("Only DWARF 2 and 3 pubnames are currently supported\n")); warned = 1; } @@ -6668,11 +6620,11 @@ display_debug_pubnames (section, start, file) do { - offset = byte_get (data, 4); + offset = byte_get (data, offset_size); if (offset != 0) { - data += 4; + data += offset_size; printf (" %ld\t\t%s\n", offset, data); data += strlen ((char *) data) + 1; } @@ -6685,8 +6637,7 @@ display_debug_pubnames (section, start, file) } static char * -get_TAG_name (tag) - unsigned long tag; +get_TAG_name (unsigned long tag) { switch (tag) { @@ -6766,8 +6717,7 @@ get_TAG_name (tag) } static char * -get_AT_name (attribute) - unsigned long attribute; +get_AT_name (unsigned long attribute) { switch (attribute) { @@ -6880,8 +6830,7 @@ get_AT_name (attribute) } static char * -get_FORM_name (form) - unsigned long form; +get_FORM_name (unsigned long form) { switch (form) { @@ -6916,7 +6865,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 @@ -6942,7 +6891,7 @@ static abbrev_entry *first_abbrev = NULL; static abbrev_entry *last_abbrev = NULL; static void -free_abbrevs () +free_abbrevs (void) { abbrev_entry *abbrev; @@ -6967,14 +6916,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 */ @@ -6996,13 +6942,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 */ @@ -7026,9 +6970,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; @@ -7078,10 +7020,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; @@ -7152,10 +7093,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; @@ -7199,9 +7139,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); @@ -7212,10 +7150,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; @@ -7539,7 +7476,8 @@ decode_location_expression (data, pointer_size, length) } /* Separate the ops. */ - printf ("; "); + if (data < end) + printf ("; "); } } @@ -7547,8 +7485,7 @@ 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; @@ -7569,13 +7506,12 @@ load_debug_loc (file) 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; @@ -7587,10 +7523,9 @@ 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 ATTRIBUTE_UNUSED) { unsigned char *section_end; unsigned long bytes; @@ -7621,13 +7556,12 @@ display_debug_loc (section, start, file) 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. */ + /* 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 + separately 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); @@ -7636,6 +7570,10 @@ display_debug_loc (section, start, file) if (begin == 0 && end == 0) break; + /* For now, skip any base address specifiers. */ + if (begin == 0xffffffff) + continue; + begin += addr; end += addr; @@ -7657,8 +7595,7 @@ 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; @@ -7679,13 +7616,12 @@ load_debug_str (file) 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; @@ -7696,8 +7632,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 _(""); @@ -7709,10 +7644,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; @@ -7769,12 +7703,13 @@ display_debug_str (section, start, file) } static unsigned char * -read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) - unsigned long attribute; - unsigned long form; - unsigned char *data; - unsigned long cu_offset; - unsigned long pointer_size; +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; @@ -7786,14 +7721,30 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) break; case DW_FORM_ref_addr: + if (dwarf_version == 2) + { + uvalue = byte_get (data, pointer_size); + data += pointer_size; + } + else if (dwarf_version == 3) + { + uvalue = byte_get (data, offset_size); + data += offset_size; + } + else + { + error (_("Internal error: DWARF version is not 2 or 3.\n")); + } + break; + case DW_FORM_addr: uvalue = byte_get (data, pointer_size); data += pointer_size; break; case DW_FORM_strp: - uvalue = byte_get (data, /* offset_size */ 4); - data += /* offset_size */ 4; + uvalue = byte_get (data, offset_size); + data += offset_size; break; case DW_FORM_ref1: @@ -7830,7 +7781,8 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) data += bytes_read; printf (" %s", get_FORM_name (form)); return read_and_display_attr_value (attribute, form, data, cu_offset, - pointer_size); + pointer_size, offset_size, + dwarf_version); } switch (form) @@ -7909,7 +7861,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"); @@ -8070,7 +8022,7 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) decode_location_expression (block_start, pointer_size, uvalue); printf (")"); } - else if (form == DW_FORM_data4) + else if (form == DW_FORM_data4 || form == DW_FORM_data8) { printf ("("); printf ("location list"); @@ -8086,25 +8038,25 @@ 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) - unsigned long attribute; - unsigned long form; - unsigned char *data; - unsigned long cu_offset; - unsigned long pointer_size; +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, - pointer_size); + pointer_size, offset_size, dwarf_version); printf ("\n"); return data; } 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; @@ -8116,29 +8068,39 @@ display_debug_info (section, start, file) while (start < end) { - DWARF2_External_CompUnit *external; DWARF2_Internal_CompUnit compunit; Elf_Internal_Shdr *relsec; + unsigned char *hdrptr; + unsigned char *cu_abbrev_offset_ptr; unsigned char *tags; unsigned int i; int level; unsigned long cu_offset; + int offset_size; + int initial_length_size; - external = (DWARF2_External_CompUnit *) start; + hdrptr = start; - compunit.cu_length = BYTE_GET (external->cu_length); - compunit.cu_version = BYTE_GET (external->cu_version); - compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset); - compunit.cu_pointer_size = BYTE_GET (external->cu_pointer_size); + compunit.cu_length = byte_get (hdrptr, 4); + hdrptr += 4; if (compunit.cu_length == 0xffffffff) { - warn (_("64-bit DWARF debug info is not supported yet.\n")); - break; + compunit.cu_length = byte_get (hdrptr, 8); + hdrptr += 8; + offset_size = 8; + initial_length_size = 12; } + else + { + offset_size = 4; + initial_length_size = 4; + } + + compunit.cu_version = byte_get (hdrptr, 2); + hdrptr += 2; - /* Check for RELA relocations in the - abbrev_offset address, and apply them. */ + /* Apply addends of RELA relocations. */ for (relsec = section_headers; relsec < section_headers + elf_header.e_shnum; ++relsec) @@ -8163,9 +8125,13 @@ display_debug_info (section, start, file) for (rp = rela; rp < rela + nrelas; ++rp) { - if (rp->r_offset - != (bfd_vma) ((unsigned char *) &external->cu_abbrev_offset - - section_begin)) + unsigned char *loc; + + if (rp->r_offset >= (bfd_vma) (hdrptr - section_begin) + && section->sh_size > (bfd_vma) offset_size + && rp->r_offset <= section->sh_size - offset_size) + loc = section_begin + rp->r_offset; + else continue; if (is_32bit_elf) @@ -8193,17 +8159,23 @@ display_debug_info (section, start, file) } } - compunit.cu_abbrev_offset = rp->r_addend; - break; + byte_put (loc, rp->r_addend, offset_size); } free (rela); break; } - tags = start + sizeof (*external); + cu_abbrev_offset_ptr = hdrptr; + compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size); + hdrptr += offset_size; + + compunit.cu_pointer_size = byte_get (hdrptr, 1); + hdrptr += 1; + + tags = hdrptr; cu_offset = start - section_begin; - start += compunit.cu_length + sizeof (external->cu_length); + start += compunit.cu_length + initial_length_size; printf (_(" Compilation Unit @ %lx:\n"), cu_offset); printf (_(" Length: %ld\n"), compunit.cu_length); @@ -8211,9 +8183,9 @@ display_debug_info (section, start, file) printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset); printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size); - if (compunit.cu_version != 2) + if (compunit.cu_version != 2 && compunit.cu_version != 3) { - warn (_("Only version 2 DWARF debug information is currently supported.\n")); + warn (_("Only version 2 and 3 DWARF debug information is currently supported.\n")); continue; } @@ -8237,9 +8209,8 @@ display_debug_info (section, start, file) 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; @@ -8291,7 +8262,9 @@ display_debug_info (section, start, file) tags = read_and_display_attr (attr->attribute, attr->form, tags, cu_offset, - compunit.cu_pointer_size); + compunit.cu_pointer_size, + offset_size, + compunit.cu_version); if (entry->children) ++level; @@ -8307,10 +8280,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; @@ -8318,30 +8290,48 @@ display_debug_aranges (section, start, file) while (start < end) { - DWARF2_External_ARange *external; + unsigned char *hdrptr; DWARF2_Internal_ARange arange; unsigned char *ranges; unsigned long length; unsigned long address; int excess; + int offset_size; + int initial_length_size; - external = (DWARF2_External_ARange *) start; + hdrptr = start; - arange.ar_length = BYTE_GET (external->ar_length); - arange.ar_version = BYTE_GET (external->ar_version); - arange.ar_info_offset = BYTE_GET (external->ar_info_offset); - arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size); - arange.ar_segment_size = BYTE_GET (external->ar_segment_size); + arange.ar_length = byte_get (hdrptr, 4); + hdrptr += 4; if (arange.ar_length == 0xffffffff) { - warn (_("64-bit DWARF aranges are not supported yet.\n")); - break; + arange.ar_length = byte_get (hdrptr, 8); + hdrptr += 8; + offset_size = 8; + initial_length_size = 12; + } + else + { + offset_size = 4; + initial_length_size = 4; } - if (arange.ar_version != 2) + arange.ar_version = byte_get (hdrptr, 2); + hdrptr += 2; + + arange.ar_info_offset = byte_get (hdrptr, offset_size); + hdrptr += offset_size; + + arange.ar_pointer_size = byte_get (hdrptr, 1); + hdrptr += 1; + + arange.ar_segment_size = byte_get (hdrptr, 1); + hdrptr += 1; + + if (arange.ar_version != 2 && arange.ar_version != 3) { - warn (_("Only DWARF 2 aranges are currently supported.\n")); + warn (_("Only DWARF 2 and 3 aranges are currently supported.\n")); break; } @@ -8353,10 +8343,10 @@ display_debug_aranges (section, start, file) printf (_("\n Address Length\n")); - ranges = start + sizeof (*external); + ranges = hdrptr; /* Must pad to an alignment boundary that is twice the pointer size. */ - excess = sizeof (*external) % (2 * arange.ar_pointer_size); + excess = (hdrptr - start) % (2 * arange.ar_pointer_size); if (excess) ranges += (2 * arange.ar_pointer_size) - excess; @@ -8377,7 +8367,7 @@ display_debug_aranges (section, start, file) printf (" %8.8lx %lu\n", address, length); } - start += arange.ar_length + sizeof (external->ar_length); + start += arange.ar_length + initial_length_size; } printf ("\n"); @@ -8402,6 +8392,7 @@ typedef struct Frame_Chunk int cfa_offset; int ra; unsigned char fde_encoding; + unsigned char cfa_exp; } Frame_Chunk; @@ -8409,14 +8400,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; @@ -8424,10 +8409,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) { @@ -8438,10 +8421,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]; @@ -8468,7 +8448,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++) @@ -8489,6 +8472,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; @@ -8500,8 +8486,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) { @@ -8513,15 +8498,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; @@ -8547,6 +8541,8 @@ display_debug_frames (section, start, file) unsigned char *augmentation_data = NULL; unsigned long augmentation_data_len = 0; int encoded_ptr_size = addr_size; + int offset_size; + int initial_length_size; saved_start = start; length = byte_get (start, 4); start += 4; @@ -8560,26 +8556,33 @@ display_debug_frames (section, start, file) if (length == 0xffffffff) { - warn (_("64-bit DWARF format frames are not supported yet.\n")); - break; + length = byte_get (start, 8); + start += 8; + offset_size = 8; + initial_length_size = 12; + } + else + { + offset_size = 4; + initial_length_size = 4; } - block_end = saved_start + length + 4; - cie_id = byte_get (start, 4); start += 4; + block_end = saved_start + length + initial_length_size; + cie_id = byte_get (start, offset_size); start += offset_size; if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID)) { 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++; @@ -8682,8 +8685,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 = ""; @@ -8692,8 +8695,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; @@ -8709,7 +8712,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; @@ -8740,8 +8743,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. */ @@ -8750,7 +8757,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; @@ -8818,6 +8825,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); @@ -8829,6 +8847,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; @@ -8890,7 +8911,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; @@ -8972,7 +8993,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; @@ -8980,10 +9001,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; @@ -9006,6 +9027,7 @@ display_debug_frames (section, start, file) 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); @@ -9013,6 +9035,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; @@ -9028,6 +9051,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 (); @@ -9042,6 +9090,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); @@ -9053,6 +9102,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"); @@ -9075,17 +9135,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; @@ -9108,10 +9157,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)); @@ -9123,16 +9171,45 @@ display_debug_not_supported (section, start, file) 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; +prescan_debug_info (Elf_Internal_Shdr *section ATTRIBUTE_UNUSED, + unsigned char *start, + FILE *file ATTRIBUTE_UNUSED) { - DWARF2_External_CompUnit *external; + 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 */ - external = (DWARF2_External_CompUnit *) start; + 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 (external->cu_pointer_size); + debug_line_pointer_size = byte_get (start + 10, 1); + } return 0; } @@ -9143,8 +9220,8 @@ prescan_debug_info (section, start, file) 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 *); + int (*prescan) (Elf_Internal_Shdr *, unsigned char *, FILE *); } debug_displays[] = { @@ -9167,9 +9244,7 @@ debug_displays[] = }; 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; @@ -9183,8 +9258,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; @@ -9212,8 +9287,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; @@ -9244,9 +9318,8 @@ process_section_contents (file) unsigned char *start; length = section->sh_size; - 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; @@ -9280,8 +9353,7 @@ process_section_contents (file) } static void -process_mips_fpe_exception (mask) - int mask; +process_mips_fpe_exception (int mask) { if (mask) { @@ -9302,8 +9374,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; @@ -9321,16 +9392,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; @@ -9344,10 +9419,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", @@ -9431,12 +9505,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")); @@ -9628,7 +9701,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")); @@ -9639,10 +9712,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; @@ -9655,10 +9726,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; @@ -9690,8 +9759,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; @@ -9709,17 +9777,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)) @@ -9770,8 +9836,7 @@ 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]; @@ -9795,8 +9860,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]; @@ -9862,8 +9926,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; @@ -9893,10 +9956,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; @@ -9905,8 +9965,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; @@ -9979,33 +10038,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; @@ -10017,14 +10057,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) @@ -10045,8 +10082,7 @@ process_corefile_contents (file) } static int -process_arch_specific (file) - FILE *file; +process_arch_specific (FILE *file) { if (! do_arch) return 1; @@ -10064,8 +10100,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) @@ -10076,8 +10111,14 @@ get_file_header (file) { default: /* fall through */ case ELFDATANONE: /* fall through */ - case ELFDATA2LSB: byte_get = byte_get_little_endian; break; - case ELFDATA2MSB: byte_get = byte_get_big_endian; break; + case ELFDATA2LSB: + byte_get = byte_get_little_endian; + byte_put = byte_put_little_endian; + break; + case ELFDATA2MSB: + byte_get = byte_get_big_endian; + byte_put = byte_put_big_endian; + break; } /* For now we only support 32 bit and 64 bit ELF files. */ @@ -10112,7 +10153,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\ @@ -10151,31 +10192,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; } @@ -10191,10 +10219,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)) { @@ -10227,7 +10252,11 @@ process_file (file_name) process_arch_specific (file); - fclose (file); + if (program_headers) + { + free (program_headers); + program_headers = NULL; + } if (section_headers) { @@ -10264,6 +10293,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 @@ -10283,12 +10536,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;