X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=6774088bb864467ffec4c847d9b22a62cd2b702a;hb=6edf0760c5c65c9f0582c5d8036bfa058f2cd6c2;hp=ab5955f61b5cf0eea7303f4edb0990e22c4f64eb;hpb=f1ef08cb0196f806d980f98663c3d924f43eba28;p=binutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index ab5955f61b5..6774088bb86 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1,5 +1,5 @@ /* readelf.c -- display contents of an ELF format file - Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Originally developed by Eric Youngdale Modifications by Nick Clifton @@ -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 @@ -31,7 +49,7 @@ #if __GNUC__ >= 2 /* Define BFD64 here, even if our default architecture is 32 bit ELF as this will allow us to read in and parse 64bit and 32bit ELF files. - Only do this if we belive that the compiler can support a 64 bit + Only do this if we believe that the compiler can support a 64 bit data type. For now we only rely on GCC being able to do this. */ #define BFD64 #endif @@ -75,9 +93,11 @@ #include "elf/mmix.h" #include "elf/mn10200.h" #include "elf/mn10300.h" +#include "elf/msp430.h" #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" @@ -85,62 +105,67 @@ #include "elf/vax.h" #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" - -char * program_name = "readelf"; -unsigned int dynamic_addr; -bfd_size_type dynamic_size; -unsigned int rela_addr; -unsigned int rela_size; -char * dynamic_strings; -char * string_table; -unsigned long string_table_length; -unsigned long num_dynamic_syms; -Elf_Internal_Sym * dynamic_symbols; -Elf_Internal_Syminfo * dynamic_syminfo; -unsigned long dynamic_syminfo_offset; -unsigned int dynamic_syminfo_nent; -char program_interpreter [64]; -int dynamic_info[DT_JMPREL + 1]; -int version_info[16]; -int loadaddr = 0; -Elf_Internal_Ehdr elf_header; -Elf_Internal_Shdr * section_headers; -Elf_Internal_Dyn * dynamic_segment; -Elf_Internal_Shdr * symtab_shndx_hdr; -int show_name; -int do_dynamic; -int do_syms; -int do_reloc; -int do_sections; -int do_segments; -int do_unwind; -int do_using_dynamic; -int do_header; -int do_dump; -int do_version; -int do_wide; -int do_histogram; -int do_debugging; -int do_debug_info; -int do_debug_abbrevs; -int do_debug_lines; -int do_debug_pubnames; -int do_debug_aranges; -int do_debug_frames; -int do_debug_frames_interp; -int do_debug_macinfo; -int do_debug_str; -int do_debug_loc; -int do_arch; -int do_notes; -int is_32bit_elf; +#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; +char *string_table; +unsigned long string_table_length; +unsigned long num_dynamic_syms; +Elf_Internal_Sym *dynamic_symbols; +Elf_Internal_Syminfo *dynamic_syminfo; +unsigned long dynamic_syminfo_offset; +unsigned int dynamic_syminfo_nent; +char program_interpreter[64]; +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; +int do_dynamic; +int do_syms; +int do_reloc; +int do_sections; +int do_segments; +int do_unwind; +int do_using_dynamic; +int do_header; +int do_dump; +int do_version; +int do_wide; +int do_histogram; +int do_debugging; +int do_debug_info; +int do_debug_abbrevs; +int do_debug_lines; +int do_debug_pubnames; +int do_debug_aranges; +int do_debug_frames; +int do_debug_frames_interp; +int do_debug_macinfo; +int do_debug_str; +int do_debug_loc; +int do_arch; +int do_notes; +int is_32bit_elf; /* A dynamic array of flags indicating which sections require dumping. */ -char * dump_sects = NULL; -unsigned int num_dump_sects = 0; +char *dump_sects = NULL; +unsigned int num_dump_sects = 0; #define HEX_DUMP (1 << 0) #define DISASS_DUMP (1 << 1) @@ -159,121 +184,11 @@ 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_Rel **, 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 ((Elf32_Internal_Shdr *, FILE *)); -#endif -static int dump_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); -static int display_debug_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); -static int display_debug_info PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int prescan_debug_info PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_lines PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_pubnames PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_abbrev PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_aranges PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_frames PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_macinfo PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_str PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); -static int display_debug_loc PARAMS ((Elf32_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 ((Elf32_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; -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif #define UNKNOWN -1 #define SECTION_NAME(X) ((X) == NULL ? "" : \ @@ -296,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)) @@ -322,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; } @@ -379,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; @@ -389,18 +298,16 @@ 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) { case 1: - return * field; + return *field; case 2: - return ((unsigned int) (field [0])) - | (((unsigned int) (field [1])) << 8); + return ((unsigned int) (field[0])) + | (((unsigned int) (field[1])) << 8); #ifndef BFD64 case 8: @@ -410,10 +317,10 @@ byte_get_little_endian (field, size) /* Fall through. */ #endif case 4: - return ((unsigned long) (field [0])) - | (((unsigned long) (field [1])) << 8) - | (((unsigned long) (field [2])) << 16) - | (((unsigned long) (field [3])) << 24); + return ((unsigned long) (field[0])) + | (((unsigned long) (field[1])) << 8) + | (((unsigned long) (field[2])) << 16) + | (((unsigned long) (field[3])) << 24); #ifdef BFD64 case 8: @@ -421,15 +328,15 @@ 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. */ - return ((bfd_vma) (field [0])) - | (((bfd_vma) (field [1])) << 8) - | (((bfd_vma) (field [2])) << 16) - | (((bfd_vma) (field [3])) << 24) - | (((bfd_vma) (field [4])) << 32) - | (((bfd_vma) (field [5])) << 40) - | (((bfd_vma) (field [6])) << 48) - | (((bfd_vma) (field [7])) << 56); + in an internal structure. */ + return ((bfd_vma) (field[0])) + | (((bfd_vma) (field[1])) << 8) + | (((bfd_vma) (field[2])) << 16) + | (((bfd_vma) (field[3])) << 24) + | (((bfd_vma) (field[4])) << 32) + | (((bfd_vma) (field[5])) << 40) + | (((bfd_vma) (field[6])) << 48) + | (((bfd_vma) (field[7])) << 56); #endif default: error (_("Unhandled data length: %d\n"), size); @@ -437,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) @@ -449,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 @@ -465,7 +440,7 @@ print_vma (vma, mode) { case FULL_HEX: printf ("0x"); - /* drop through */ + /* Drop through. */ case LONG_HEX: printf_vma (vma); @@ -473,7 +448,7 @@ print_vma (vma, mode) case PREFIX_HEX: printf ("0x"); - /* drop through */ + /* Drop through. */ case HEX: #if BFD_HOST_64BIT_LONG @@ -500,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; @@ -533,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); @@ -546,47 +524,45 @@ 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) { case 1: - return * field; + return *field; case 2: - return ((unsigned int) (field [1])) | (((int) (field [0])) << 8); + return ((unsigned int) (field[1])) | (((int) (field[0])) << 8); case 4: - return ((unsigned long) (field [3])) - | (((unsigned long) (field [2])) << 8) - | (((unsigned long) (field [1])) << 16) - | (((unsigned long) (field [0])) << 24); + return ((unsigned long) (field[3])) + | (((unsigned long) (field[2])) << 8) + | (((unsigned long) (field[1])) << 16) + | (((unsigned long) (field[0])) << 24); #ifndef BFD64 case 8: /* Although we are extracing data from an 8 byte wide field, we are returning only 4 bytes of data. */ - return ((unsigned long) (field [7])) - | (((unsigned long) (field [6])) << 8) - | (((unsigned long) (field [5])) << 16) - | (((unsigned long) (field [4])) << 24); + return ((unsigned long) (field[7])) + | (((unsigned long) (field[6])) << 8) + | (((unsigned long) (field[5])) << 16) + | (((unsigned long) (field[4])) << 24); #else case 8: case -8: /* 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. */ - return ((bfd_vma) (field [7])) - | (((bfd_vma) (field [6])) << 8) - | (((bfd_vma) (field [5])) << 16) - | (((bfd_vma) (field [4])) << 24) - | (((bfd_vma) (field [3])) << 32) - | (((bfd_vma) (field [2])) << 40) - | (((bfd_vma) (field [1])) << 48) - | (((bfd_vma) (field [0])) << 56); + in an internal structure. */ + return ((bfd_vma) (field[7])) + | (((bfd_vma) (field[6])) << 8) + | (((bfd_vma) (field[5])) << 16) + | (((bfd_vma) (field[4])) << 24) + | (((bfd_vma) (field[3])) << 32) + | (((bfd_vma) (field[2])) << 40) + | (((bfd_vma) (field[1])) << 48) + | (((bfd_vma) (field[0])) << 56); #endif default: @@ -595,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) { @@ -611,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: @@ -652,10 +658,16 @@ guess_is_rela (e_machine) case EM_S390: case EM_S390_OLD: case EM_MMIX: + case EM_MSP430: + case EM_MSP430_OLD: case EM_XSTORMY16: case EM_VAX: 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: @@ -682,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; @@ -695,17 +706,15 @@ slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp) if (is_32bit_elf) { - Elf32_External_Rela * erelas; + 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) { @@ -724,17 +733,15 @@ slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp) } else { - Elf64_External_Rela * erelas; + 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) { @@ -757,29 +764,27 @@ 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_Rel **relsp; - unsigned long *nrelsp; -{ - Elf_Internal_Rel *rels; +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; unsigned int i; if (is_32bit_elf) { - Elf32_External_Rel * erels; + 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_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel)); + rels = malloc (nrels * sizeof (Elf_Internal_Rela)); if (rels == NULL) { @@ -791,22 +796,22 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp) { rels[i].r_offset = BYTE_GET (erels[i].r_offset); rels[i].r_info = BYTE_GET (erels[i].r_info); + rels[i].r_addend = 0; } free (erels); } else { - Elf64_External_Rel * erels; + 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_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel)); + rels = malloc (nrels * sizeof (Elf_Internal_Rela)); if (rels == NULL) { @@ -818,6 +823,7 @@ slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp) { rels[i].r_offset = BYTE_GET8 (erels[i].r_offset); rels[i].r_info = BYTE_GET8 (erels[i].r_info); + rels[i].r_addend = 0; } free (erels); @@ -827,20 +833,20 @@ 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_Rel * rels; - Elf_Internal_Rela * relas; + unsigned int i; + Elf_Internal_Rela *rels; if (is_rela == UNKNOWN) @@ -848,7 +854,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) if (is_rela) { - if (!slurp_rela_relocs (file, rel_offset, rel_size, &relas, &rel_size)) + if (!slurp_rela_relocs (file, rel_offset, rel_size, &rels, &rel_size)) return 0; } else @@ -879,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")); } @@ -894,26 +900,18 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) for (i = 0; i < rel_size; i++) { - const char * rtype; - const char * rtype2 = NULL; - const char * rtype3 = NULL; - bfd_vma offset; - bfd_vma info; - bfd_vma symtab_index; - bfd_vma type; - bfd_vma type2 = (bfd_vma) NULL; - bfd_vma type3 = (bfd_vma) NULL; + const char *rtype; + const char *rtype2 = NULL; + const char *rtype3 = NULL; + bfd_vma offset; + bfd_vma info; + bfd_vma symtab_index; + bfd_vma type; + bfd_vma type2 = 0; + bfd_vma type3 = 0; - if (is_rela) - { - offset = relas [i].r_offset; - info = relas [i].r_info; - } - else - { - offset = rels [i].r_offset; - info = rels [i].r_info; - } + offset = rels[i].r_offset; + info = rels[i].r_info; if (is_32bit_elf) { @@ -922,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); @@ -932,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 } @@ -1057,11 +1066,19 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) rtype = elf_mmix_reloc_type (type); break; + case EM_MSP430: + case EM_MSP430_OLD: + rtype = elf_msp430_reloc_type (type); + 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); @@ -1140,6 +1157,15 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) case EM_IP2K_OLD: rtype = elf_ip2k_reloc_type (type); break; + + 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) @@ -1149,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) { @@ -1157,7 +1183,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) printf (" bad symbol index: %08lx", (unsigned long) symtab_index); else { - Elf_Internal_Sym * psym; + Elf_Internal_Sym *psym; psym = symtab + symtab_index; @@ -1186,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, "
", @@ -1201,13 +1231,13 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) print_symbol (22, strtab + psym->st_name); if (is_rela) - printf (" + %lx", (unsigned long) relas [i].r_addend); + printf (" + %lx", (unsigned long) rels[i].r_addend); } } else if (is_rela) { printf ("%*c", is_32bit_elf ? (do_wide ? 34 : 28) : (do_wide ? 26 : 20), ' '); - print_vma (relas[i].r_addend, LONG_HEX); + print_vma (rels[i].r_addend, LONG_HEX); } if (elf_header.e_machine == EM_SPARCV9 @@ -1244,17 +1274,13 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) } } - if (is_rela) - free (relas); - else - free (rels); + free (rels); return 1; } static const char * -get_mips_dynamic_type (type) - unsigned long type; +get_mips_dynamic_type (unsigned long type) { switch (type) { @@ -1307,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) { @@ -1319,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) { @@ -1333,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) { @@ -1357,10 +1380,20 @@ 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]; + static char buff[32]; switch (type) { @@ -1439,7 +1472,7 @@ get_dynamic_type (type) default: if ((type >= DT_LOPROC) && (type <= DT_HIPROC)) { - const char * result; + const char *result; switch (elf_header.e_machine) { @@ -1453,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; @@ -1465,7 +1501,7 @@ get_dynamic_type (type) } else if ((type >= DT_LOOS) && (type <= DT_HIOS)) { - const char * result; + const char *result; switch (elf_header.e_machine) { @@ -1490,10 +1526,9 @@ get_dynamic_type (type) } static char * -get_file_type (e_type) - unsigned e_type; +get_file_type (unsigned e_type) { - static char buff [32]; + static char buff[32]; switch (e_type) { @@ -1515,10 +1550,9 @@ 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 */ + static char buff[64]; /* XXX */ switch (e_machine) { @@ -1543,17 +1577,17 @@ get_machine_name (e_machine) case EM_V800: return "NEC V800"; case EM_FR20: return "Fujitsu FR20"; case EM_RH32: return "TRW RH32"; - case EM_MCORE: return "MCORE"; + 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"; @@ -1562,9 +1596,9 @@ get_machine_name (e_machine) case EM_CYGNUS_D10V: case EM_D10V: return "d10v"; case EM_CYGNUS_D30V: - case EM_D30V: return "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: @@ -1573,9 +1607,9 @@ get_machine_name (e_machine) case EM_MN10200: return "mn10200"; case EM_CYGNUS_FR30: case EM_FR30: return "Fujitsu FR30"; - case EM_CYGNUS_FRV: return "Fujitsu FR-V"; + case EM_CYGNUS_FRV: return "Fujitsu FR-V"; case EM_PJ_OLD: - case EM_PJ: return "picoJava"; + case EM_PJ: return "picoJava"; case EM_MMA: return "Fujitsu Multimedia Accelerator"; case EM_PCP: return "Siemens PCP"; case EM_NCPU: return "Sony nCPU embedded RISC processor"; @@ -1595,23 +1629,26 @@ get_machine_name (e_machine) case EM_ST19: return "STMicroelectronics ST19 8-bit microcontroller"; case EM_VAX: return "Digital VAX"; case EM_AVR_OLD: - case EM_AVR: return "Atmel AVR 8-bit microcontroller"; + case EM_AVR: return "Atmel AVR 8-bit microcontroller"; case EM_CRIS: return "Axis Communications 32-bit embedded processor"; case EM_JAVELIN: return "Infineon Technologies 32-bit embedded cpu"; case EM_FIREPATH: return "Element 14 64-bit DSP processor"; case EM_ZSP: return "LSI Logic's 16-bit DSP processor"; - case EM_MMIX: return "Donald Knuth's educational 64-bit processor"; + case EM_MMIX: return "Donald Knuth's educational 64-bit processor"; case EM_HUANY: return "Harvard Universitys's machine-independent object format"; - case EM_PRISM: return "SiTera Prism"; + case EM_PRISM: return "Vitesse Prism"; case EM_X86_64: return "Advanced Micro Devices X86-64"; case EM_S390_OLD: - case EM_S390: return "IBM S/390"; + case EM_S390: return "IBM S/390"; case EM_XSTORMY16: return "Sanyo Xstormy16 CPU core"; case EM_OPENRISC: case EM_OR32: return "OpenRISC"; case EM_DLX: return "OpenDLX"; case EM_IP2K_OLD: - case EM_IP2K: return "Ubicom IP2xxx 8-bit microcontrollers"; + 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; @@ -1619,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; @@ -1749,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; @@ -1761,11 +1800,9 @@ 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]; + static char buf[1024]; buf[0] = '\0'; @@ -1802,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; @@ -1892,7 +1932,9 @@ get_machine_flags (e_flags, e_machine) case E_MIPS_ARCH_4: strcat (buf, ", mips4"); break; case E_MIPS_ARCH_5: strcat (buf, ", mips5"); break; 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; } @@ -1992,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) { @@ -2011,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) { @@ -2038,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) { @@ -2057,29 +2126,29 @@ 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]; + static char buff[32]; switch (p_type) { - case PT_NULL: return "NULL"; - case PT_LOAD: return "LOAD"; + case PT_NULL: return "NULL"; + case PT_LOAD: return "LOAD"; case PT_DYNAMIC: return "DYNAMIC"; - case PT_INTERP: return "INTERP"; - case PT_NOTE: return "NOTE"; - case PT_SHLIB: return "SHLIB"; - case PT_PHDR: return "PHDR"; + case PT_INTERP: return "INTERP"; + case PT_NOTE: return "NOTE"; + case PT_SHLIB: return "SHLIB"; + case PT_PHDR: return "PHDR"; case PT_TLS: return "TLS"; 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)) { - const char * result; + const char *result; switch (elf_header.e_machine) { @@ -2105,7 +2174,7 @@ get_segment_type (p_type) } else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS)) { - const char * result; + const char *result; switch (elf_header.e_machine) { @@ -2133,49 +2202,48 @@ 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) { - case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST"; - case SHT_MIPS_MSYM: return "MIPS_MSYM"; - case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT"; - case SHT_MIPS_GPTAB: return "MIPS_GPTAB"; - case SHT_MIPS_UCODE: return "MIPS_UCODE"; - case SHT_MIPS_DEBUG: return "MIPS_DEBUG"; - case SHT_MIPS_REGINFO: return "MIPS_REGINFO"; - case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE"; - case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM"; - case SHT_MIPS_RELD: return "MIPS_RELD"; - case SHT_MIPS_IFACE: return "MIPS_IFACE"; - case SHT_MIPS_CONTENT: return "MIPS_CONTENT"; - case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS"; - case SHT_MIPS_SHDR: return "MIPS_SHDR"; - case SHT_MIPS_FDESC: return "MIPS_FDESC"; - case SHT_MIPS_EXTSYM: return "MIPS_EXTSYM"; - case SHT_MIPS_DENSE: return "MIPS_DENSE"; - case SHT_MIPS_PDESC: return "MIPS_PDESC"; - case SHT_MIPS_LOCSYM: return "MIPS_LOCSYM"; - case SHT_MIPS_AUXSYM: return "MIPS_AUXSYM"; - case SHT_MIPS_OPTSYM: return "MIPS_OPTSYM"; - case SHT_MIPS_LOCSTR: return "MIPS_LOCSTR"; - case SHT_MIPS_LINE: return "MIPS_LINE"; - case SHT_MIPS_RFDESC: return "MIPS_RFDESC"; - case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM"; - case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST"; - case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS"; - case SHT_MIPS_DWARF: return "MIPS_DWARF"; - case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL"; - case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; - case SHT_MIPS_EVENTS: return "MIPS_EVENTS"; - case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE"; - case SHT_MIPS_PIXIE: return "MIPS_PIXIE"; - case SHT_MIPS_XLATE: return "MIPS_XLATE"; - case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG"; - case SHT_MIPS_WHIRL: return "MIPS_WHIRL"; - case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION"; - case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; + case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST"; + case SHT_MIPS_MSYM: return "MIPS_MSYM"; + case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT"; + case SHT_MIPS_GPTAB: return "MIPS_GPTAB"; + case SHT_MIPS_UCODE: return "MIPS_UCODE"; + case SHT_MIPS_DEBUG: return "MIPS_DEBUG"; + case SHT_MIPS_REGINFO: return "MIPS_REGINFO"; + case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE"; + case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM"; + case SHT_MIPS_RELD: return "MIPS_RELD"; + case SHT_MIPS_IFACE: return "MIPS_IFACE"; + case SHT_MIPS_CONTENT: return "MIPS_CONTENT"; + case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS"; + case SHT_MIPS_SHDR: return "MIPS_SHDR"; + case SHT_MIPS_FDESC: return "MIPS_FDESC"; + case SHT_MIPS_EXTSYM: return "MIPS_EXTSYM"; + case SHT_MIPS_DENSE: return "MIPS_DENSE"; + case SHT_MIPS_PDESC: return "MIPS_PDESC"; + case SHT_MIPS_LOCSYM: return "MIPS_LOCSYM"; + case SHT_MIPS_AUXSYM: return "MIPS_AUXSYM"; + case SHT_MIPS_OPTSYM: return "MIPS_OPTSYM"; + case SHT_MIPS_LOCSTR: return "MIPS_LOCSTR"; + case SHT_MIPS_LINE: return "MIPS_LINE"; + case SHT_MIPS_RFDESC: return "MIPS_RFDESC"; + case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM"; + case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST"; + case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS"; + case SHT_MIPS_DWARF: return "MIPS_DWARF"; + case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL"; + case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; + case SHT_MIPS_EVENTS: return "MIPS_EVENTS"; + case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE"; + case SHT_MIPS_PIXIE: return "MIPS_PIXIE"; + case SHT_MIPS_XLATE: return "MIPS_XLATE"; + case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG"; + case SHT_MIPS_WHIRL: return "MIPS_WHIRL"; + case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION"; + case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION"; default: break; @@ -2184,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) { @@ -2199,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; } @@ -2213,10 +2284,9 @@ 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]; + static char buff[32]; switch (sh_type) { @@ -2240,8 +2310,8 @@ get_section_type_name (sh_type) case SHT_GNU_verdef: return "VERDEF"; case SHT_GNU_verneed: return "VERNEED"; case SHT_GNU_versym: return "VERSYM"; - case 0x6ffffff0: return "VERSYM"; - case 0x6ffffffc: return "VERDEF"; + case 0x6ffffff0: return "VERSYM"; + case 0x6ffffffc: return "VERDEF"; case 0x7ffffffd: return "AUXILIARY"; case 0x7fffffff: return "FILTER"; case SHT_GNU_LIBLIST: return "GNU_LIBLIST"; @@ -2249,7 +2319,7 @@ get_section_type_name (sh_type) default: if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC)) { - const char * result; + const char *result; switch (elf_header.e_machine) { @@ -2286,39 +2356,39 @@ get_section_type_name (sh_type) #define OPTION_DEBUG_DUMP 512 -struct option options [] = +struct option options[] = { - {"all", no_argument, 0, 'a'}, + {"all", no_argument, 0, 'a'}, {"file-header", no_argument, 0, 'h'}, {"program-headers", no_argument, 0, 'l'}, - {"headers", no_argument, 0, 'e'}, - {"histogram", no_argument, 0, 'I'}, - {"segments", no_argument, 0, 'l'}, - {"sections", no_argument, 0, 'S'}, + {"headers", no_argument, 0, 'e'}, + {"histogram", no_argument, 0, 'I'}, + {"segments", no_argument, 0, 'l'}, + {"sections", no_argument, 0, 'S'}, {"section-headers", no_argument, 0, 'S'}, - {"symbols", no_argument, 0, 's'}, - {"syms", no_argument, 0, 's'}, - {"relocs", no_argument, 0, 'r'}, - {"notes", no_argument, 0, 'n'}, - {"dynamic", no_argument, 0, 'd'}, + {"symbols", no_argument, 0, 's'}, + {"syms", no_argument, 0, 's'}, + {"relocs", no_argument, 0, 'r'}, + {"notes", no_argument, 0, 'n'}, + {"dynamic", no_argument, 0, 'd'}, {"arch-specific", no_argument, 0, 'A'}, {"version-info", no_argument, 0, 'V'}, {"use-dynamic", no_argument, 0, 'D'}, - {"hex-dump", required_argument, 0, 'x'}, + {"hex-dump", required_argument, 0, 'x'}, {"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP}, {"unwind", no_argument, 0, 'u'}, #ifdef SUPPORT_DISASSEMBLY {"instruction-dump", required_argument, 0, 'i'}, #endif - {"version", no_argument, 0, 'v'}, - {"wide", no_argument, 0, 'W'}, - {"help", no_argument, 0, 'H'}, - {0, no_argument, 0, 0} + {"version", no_argument, 0, 'v'}, + {"wide", no_argument, 0, 'W'}, + {"help", no_argument, 0, 'H'}, + {0, no_argument, 0, 0} }; 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")); @@ -2359,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; + 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.")); @@ -2384,15 +2452,13 @@ request_dump (section, type) } if (dump_sects) - dump_sects [section] |= type; + dump_sects[section] |= type; return; } static void -parse_args (argc, argv) - int argc; - char ** argv; +parse_args (int argc, char **argv) { int c; @@ -2400,10 +2466,10 @@ 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; + char *cp; + int section; switch (c) { @@ -2415,67 +2481,67 @@ parse_args (argc, argv) break; case 'a': - do_syms ++; - do_reloc ++; - do_unwind ++; - do_dynamic ++; - do_header ++; - do_sections ++; - do_segments ++; - do_version ++; - do_histogram ++; - do_arch ++; - do_notes ++; + do_syms++; + do_reloc++; + do_unwind++; + do_dynamic++; + do_header++; + do_sections++; + do_segments++; + do_version++; + do_histogram++; + do_arch++; + do_notes++; break; case 'e': - do_header ++; - do_sections ++; - do_segments ++; + do_header++; + do_sections++; + do_segments++; break; case 'A': - do_arch ++; + do_arch++; break; case 'D': - do_using_dynamic ++; + do_using_dynamic++; break; case 'r': - do_reloc ++; + do_reloc++; break; case 'u': - do_unwind ++; + do_unwind++; break; case 'h': - do_header ++; + do_header++; break; case 'l': - do_segments ++; + do_segments++; break; case 's': - do_syms ++; + do_syms++; break; case 'S': - do_sections ++; + do_sections++; break; case 'd': - do_dynamic ++; + do_dynamic++; break; case 'I': - do_histogram ++; + do_histogram++; break; case 'n': - do_notes ++; + do_notes++; break; case 'x': - do_dump ++; + do_dump++; section = strtoul (optarg, & cp, 0); - if (! * cp && section >= 0) + if (! *cp && section >= 0) { request_dump (section, HEX_DUMP); break; } goto oops; case 'w': - do_dump ++; + do_dump++; if (optarg == 0) do_debugging = 1; else @@ -2540,7 +2606,7 @@ parse_args (argc, argv) } break; case OPTION_DEBUG_DUMP: - do_dump ++; + do_dump++; if (optarg == 0) do_debugging = 1; else @@ -2623,9 +2689,9 @@ parse_args (argc, argv) break; #ifdef SUPPORT_DISASSEMBLY case 'i': - do_dump ++; + do_dump++; section = strtoul (optarg, & cp, 0); - if (! * cp && section >= 0) + if (! *cp && section >= 0) { request_dump (section, DISASS_DUMP); break; @@ -2636,10 +2702,10 @@ parse_args (argc, argv) print_version (program_name); break; case 'V': - do_version ++; + do_version++; break; case 'W': - do_wide ++; + do_wide++; break; default: oops: @@ -2663,10 +2729,9 @@ 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]; + static char buff[32]; switch (elf_class) { @@ -2680,10 +2745,9 @@ 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]; + static char buff[32]; switch (encoding) { @@ -2696,42 +2760,15 @@ 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 - || elf_header.e_ident [EI_MAG2] != ELFMAG2 - || elf_header.e_ident [EI_MAG3] != ELFMAG3) + if ( elf_header.e_ident[EI_MAG0] != ELFMAG0 + || elf_header.e_ident[EI_MAG1] != ELFMAG1 + || elf_header.e_ident[EI_MAG2] != ELFMAG2 + || elf_header.e_ident[EI_MAG3] != ELFMAG3) { error (_("Not an ELF file - it has the wrong magic bytes at the start\n")); @@ -2744,24 +2781,24 @@ process_file_header () printf (_("ELF Header:\n")); printf (_(" Magic: ")); - for (i = 0; i < EI_NIDENT; i ++) - printf ("%2.2x ", elf_header.e_ident [i]); + for (i = 0; i < EI_NIDENT; i++) + printf ("%2.2x ", elf_header.e_ident[i]); printf ("\n"); printf (_(" Class: %s\n"), - get_elf_class (elf_header.e_ident [EI_CLASS])); + get_elf_class (elf_header.e_ident[EI_CLASS])); printf (_(" Data: %s\n"), - get_data_encoding (elf_header.e_ident [EI_DATA])); + get_data_encoding (elf_header.e_ident[EI_DATA])); printf (_(" Version: %d %s\n"), - elf_header.e_ident [EI_VERSION], - (elf_header.e_ident [EI_VERSION] == EV_CURRENT + elf_header.e_ident[EI_VERSION], + (elf_header.e_ident[EI_VERSION] == EV_CURRENT ? "(current)" - : (elf_header.e_ident [EI_VERSION] != EV_NONE + : (elf_header.e_ident[EI_VERSION] != EV_NONE ? "" : ""))); printf (_(" OS/ABI: %s\n"), - get_osabi_name (elf_header.e_ident [EI_OSABI])); + get_osabi_name (elf_header.e_ident[EI_OSABI])); printf (_(" ABI Version: %d\n"), - elf_header.e_ident [EI_ABIVERSION]); + elf_header.e_ident[EI_ABIVERSION]); printf (_(" Type: %s\n"), get_file_type (elf_header.e_type)); printf (_(" Machine: %s\n"), @@ -2815,25 +2852,22 @@ process_file_header () static int -get_32bit_program_headers (file, program_headers) - FILE * file; - Elf_Internal_Phdr * program_headers; -{ - Elf32_External_Phdr * phdrs; - Elf32_External_Phdr * external; - Elf32_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"))); +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 = get_data (NULL, file, elf_header.e_phoff, + elf_header.e_phentsize * elf_header.e_phnum, + _("program headers")); if (!phdrs) return 0; for (i = 0, internal = program_headers, external = phdrs; i < elf_header.e_phnum; - i ++, internal ++, external ++) + i++, internal++, external++) { internal->p_type = BYTE_GET (external->p_type); internal->p_offset = BYTE_GET (external->p_offset); @@ -2851,25 +2885,22 @@ get_32bit_program_headers (file, program_headers) } static int -get_64bit_program_headers (file, program_headers) - FILE * file; - Elf_Internal_Phdr * program_headers; -{ - Elf64_External_Phdr * phdrs; - Elf64_External_Phdr * external; - Elf64_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"))); +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 = get_data (NULL, file, elf_header.e_phoff, + elf_header.e_phentsize * elf_header.e_phnum, + _("program headers")); if (!phdrs) return 0; for (i = 0, internal = program_headers, external = phdrs; i < elf_header.e_phnum; - i ++, internal ++, external ++) + i++, internal++, external++) { internal->p_type = BYTE_GET (external->p_type); internal->p_flags = BYTE_GET (external->p_flags); @@ -2886,19 +2917,50 @@ 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; + Elf_Internal_Phdr *segment; + unsigned int i; if (elf_header.e_phnum == 0) { if (do_segments) printf (_("\nThere are no program headers in this file.\n")); - return 1; + return 0; } if (do_segments && !do_header) @@ -2912,25 +2974,8 @@ process_program_headers (file) printf ("\n"); } - program_headers = (Elf_Internal_Phdr *) malloc - (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); - - if (program_headers == NULL) - { - error (_("Out of memory\n")); - return 0; - } - - if (is_32bit_elf) - i = get_32bit_program_headers (file, program_headers); - else - i = get_64bit_program_headers (file, program_headers); - - if (i == 0) - { - free (program_headers); + if (! get_program_headers (file)) return 0; - } if (do_segments) { @@ -2954,13 +2999,12 @@ process_program_headers (file) } } - loadaddr = -1; dynamic_addr = 0; dynamic_size = 0; for (i = 0, segment = program_headers; i < elf_header.e_phnum; - i ++, segment ++) + i++, segment++) { if (do_segments) { @@ -3042,12 +3086,6 @@ process_program_headers (file) switch (segment->p_type) { - case PT_LOAD: - if (loadaddr == -1) - loadaddr = (segment->p_vaddr & 0xfffff000) - - (segment->p_offset & 0xfffff000); - break; - case PT_DYNAMIC: if (dynamic_addr) error (_("more than one dynamic segment\n")); @@ -3057,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 { @@ -3075,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")); @@ -3091,14 +3124,14 @@ process_program_headers (file) for (i = 0; i < elf_header.e_phnum; i++) { unsigned int j; - Elf_Internal_Shdr * section; + Elf_Internal_Shdr *section; segment = program_headers + i; section = section_headers; printf (" %2.2d ", i); - for (j = 1; j < elf_header.e_shnum; j++, section ++) + for (j = 1; j < elf_header.e_shnum; j++, section++) { if (section->sh_size > 0 /* Compare allocated sections by VMA, unallocated @@ -3117,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; -{ - Elf32_External_Shdr * shdrs; - Elf32_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"))); +get_32bit_section_headers (FILE *file, unsigned int num) +{ + Elf32_External_Shdr *shdrs; + Elf_Internal_Shdr *internal; + unsigned int i; + + 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) { @@ -3150,7 +3207,7 @@ get_32bit_section_headers (file, num) for (i = 0, internal = section_headers; i < num; - i ++, internal ++) + i++, internal++) { internal->sh_name = BYTE_GET (shdrs[i].sh_name); internal->sh_type = BYTE_GET (shdrs[i].sh_type); @@ -3170,23 +3227,18 @@ get_32bit_section_headers (file, num) } static int -get_64bit_section_headers (file, num) - FILE * file; - unsigned int num; -{ - Elf64_External_Shdr * shdrs; - Elf64_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"))); +get_64bit_section_headers (FILE *file, unsigned int num) +{ + Elf64_External_Shdr *shdrs; + Elf_Internal_Shdr *internal; + unsigned int i; + + 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) { @@ -3196,7 +3248,7 @@ get_64bit_section_headers (file, num) for (i = 0, internal = section_headers; i < num; - i ++, internal ++) + i++, internal++) { internal->sh_name = BYTE_GET (shdrs[i].sh_name); internal->sh_type = BYTE_GET (shdrs[i].sh_type); @@ -3216,20 +3268,17 @@ 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; + Elf32_External_Sym *esyms; Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym * isyms; - Elf_Internal_Sym * psym; - unsigned int j; + Elf_Internal_Sym *isyms; + 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; @@ -3238,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); @@ -3249,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) { @@ -3262,7 +3310,7 @@ get_32bit_elf_symbols (file, section) for (j = 0, psym = isyms; j < number; - j ++, psym ++) + j++, psym++) { psym->st_name = BYTE_GET (esyms[j].st_name); psym->st_value = BYTE_GET (esyms[j].st_value); @@ -3283,20 +3331,17 @@ 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; + Elf64_External_Sym *esyms; Elf_External_Sym_Shndx *shndx; - Elf_Internal_Sym * isyms; - Elf_Internal_Sym * psym; - unsigned int j; + Elf_Internal_Sym *isyms; + 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; @@ -3305,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); @@ -3316,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) { @@ -3329,7 +3373,7 @@ get_64bit_elf_symbols (file, section) for (j = 0, psym = isyms; j < number; - j ++, psym ++) + j++, psym++) { psym->st_name = BYTE_GET (esyms[j].st_name); psym->st_info = BYTE_GET (esyms[j].st_info); @@ -3350,12 +3394,11 @@ 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]; + static char buff[32]; - * buff = 0; + *buff = 0; while (sh_flags) { @@ -3366,15 +3409,15 @@ get_elf_section_flags (sh_flags) switch (flag) { - case SHF_WRITE: strcat (buff, "W"); break; - case SHF_ALLOC: strcat (buff, "A"); break; - case SHF_EXECINSTR: strcat (buff, "X"); break; - case SHF_MERGE: strcat (buff, "M"); break; - case SHF_STRINGS: strcat (buff, "S"); break; - case SHF_INFO_LINK: strcat (buff, "I"); break; - case SHF_LINK_ORDER: strcat (buff, "L"); break; + case SHF_WRITE: strcat (buff, "W"); break; + case SHF_ALLOC: strcat (buff, "A"); break; + case SHF_EXECINSTR: strcat (buff, "X"); break; + case SHF_MERGE: strcat (buff, "M"); break; + case SHF_STRINGS: strcat (buff, "S"); break; + case SHF_INFO_LINK: strcat (buff, "I"); break; + case SHF_LINK_ORDER: strcat (buff, "L"); break; case SHF_OS_NONCONFORMING: strcat (buff, "O"); break; - case SHF_GROUP: strcat (buff, "G"); break; + case SHF_GROUP: strcat (buff, "G"); break; case SHF_TLS: strcat (buff, "T"); break; default: @@ -3398,11 +3441,10 @@ 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; + Elf_Internal_Shdr *section; + unsigned int i; section_headers = NULL; @@ -3431,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; } @@ -3446,9 +3491,9 @@ process_section_headers (file) for (i = 0, section = section_headers; i < elf_header.e_shnum; - i ++, section ++) + i++, section++) { - char * name = SECTION_NAME (section); + char *name = SECTION_NAME (section); if (section->sh_type == SHT_DYNSYM) { @@ -3470,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) { @@ -3534,7 +3578,7 @@ process_section_headers (file) for (i = 0, section = section_headers; i < elf_header.e_shnum; - i ++, section ++) + i++, section++) { printf (" [%2u] %-17.17s %-15.15s ", SECTION_HEADER_NUM (i), @@ -3632,13 +3676,25 @@ 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; + unsigned long rel_size; + unsigned long rel_offset; if (!do_reloc) @@ -3646,63 +3702,62 @@ 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 { - Elf32_Internal_Shdr * section; - unsigned long i; - int found = 0; + Elf_Internal_Shdr *section; + unsigned long i; + int found = 0; for (i = 0, section = section_headers; i < elf_header.e_shnum; - i++, section ++) + i++, section++) { if ( section->sh_type != SHT_RELA && section->sh_type != SHT_REL) @@ -3713,11 +3768,11 @@ process_relocs (file) if (rel_size) { - Elf32_Internal_Shdr * strsec; - Elf_Internal_Sym * symtab; - char * strtab; - int is_rela; - unsigned long nsyms; + Elf_Internal_Shdr *strsec; + Elf_Internal_Sym *symtab; + char *strtab; + int is_rela; + unsigned long nsyms; printf (_("\nRelocation section ")); @@ -3734,7 +3789,7 @@ process_relocs (file) nsyms = 0; if (section->sh_link) { - Elf32_Internal_Shdr * symsec; + Elf_Internal_Shdr *symsec; symsec = SECTION_HEADER (section->sh_link); nsyms = symsec->sh_size / symsec->sh_entsize; @@ -3745,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; @@ -3786,37 +3840,29 @@ struct unw_aux_info { struct unw_table_entry { - struct absaddr start; - struct absaddr end; - struct absaddr info; + struct absaddr start; + struct absaddr end; + struct absaddr info; } - *table; /* Unwind table. */ - unsigned long table_len; /* Length of unwind table. */ - unsigned char * info; /* Unwind info. */ - unsigned long info_size; /* Size of unwind info. */ - bfd_vma info_addr; /* starting address of unwind info. */ - bfd_vma seg_base; /* Starting address of segment. */ - Elf_Internal_Sym * symtab; /* The symbol table. */ - unsigned long nsyms; /* Number of symbols. */ - char * strtab; /* The string table. */ - unsigned long strtab_size; /* Size of string table. */ + *table; /* Unwind table. */ + unsigned long table_len; /* Length of unwind table. */ + unsigned char *info; /* Unwind info. */ + unsigned long info_size; /* Size of unwind info. */ + bfd_vma info_addr; /* starting address of unwind info. */ + bfd_vma seg_base; /* Starting address of segment. */ + Elf_Internal_Sym *symtab; /* The symbol table. */ + unsigned long nsyms; /* Number of symbols. */ + char *strtab; /* The string table. */ + 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 *, - Elf32_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; @@ -3846,11 +3892,10 @@ 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; + struct unw_table_entry *tp; int in_body; addr_size = is_32bit_elf ? 4 : 8; @@ -3859,9 +3904,9 @@ dump_ia64_unwind (aux) { bfd_vma stamp; bfd_vma offset; - const unsigned char * dp; - const unsigned char * head; - const char * procname; + const unsigned char *dp; + const unsigned char *head; + const char *procname; find_symbol_for_address (aux, tp->start, &procname, &offset); @@ -3905,20 +3950,18 @@ dump_ia64_unwind (aux) } static int -slurp_ia64_unwind_table (file, aux, sec) - FILE *file; - struct unw_aux_info *aux; - Elf32_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; - Elf32_Internal_Shdr *relsec; + 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; @@ -3927,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; @@ -3953,19 +3987,16 @@ 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; tep = aux->table = xmalloc (size / (3 * addr_size) * sizeof (aux->table[0])); - for (tp = table; tp < table + size; tp += 3 * addr_size, ++ tep) + for (tp = table; tp < table + size; tp += 3 * addr_size, ++tep) { tep->start.section = SHN_UNDEF; tep->end.section = SHN_UNDEF; @@ -4064,10 +4095,9 @@ slurp_ia64_unwind_table (file, aux, sec) } static int -process_unwind (file) - FILE * file; +process_unwind (FILE *file) { - Elf32_Internal_Shdr *sec, *unwsec = NULL, *strsec; + Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec; unsigned long i, addr_size, unwcount = 0, unwstart = 0; struct unw_aux_info aux; @@ -4093,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++; @@ -4163,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 ")); @@ -4200,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) { @@ -4220,7 +4249,7 @@ dynamic_segment_mips_val (entry) }; unsigned int cnt; int first = 1; - for (cnt = 0; cnt < NUM_ELEM (opts); ++ cnt) + for (cnt = 0; cnt < NUM_ELEM (opts); ++cnt) if (entry->d_un.d_val & (1 << cnt)) { printf ("%s%s", first ? "" : " ", opts[cnt]); @@ -4241,7 +4270,7 @@ dynamic_segment_mips_val (entry) case DT_MIPS_TIME_STAMP: { char timebuf[20]; - struct tm * tmp; + struct tm *tmp; time_t time = entry->d_un.d_val; tmp = gmtime (&time); @@ -4275,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) { @@ -4285,7 +4313,7 @@ dynamic_segment_parisc_val (entry) static struct { long int bit; - const char * str; + const char *str; } flags[] = { @@ -4331,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; + 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; @@ -4348,11 +4394,10 @@ get_32bit_dynamic_segment (file) how large this .dynamic is now. We can do this even before the byte swapping since the DT_NULL tag is recognizable. */ dynamic_size = 0; - while (*(Elf32_Word *) edyn [dynamic_size++].d_tag != DT_NULL) + 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) { @@ -4363,10 +4408,10 @@ get_32bit_dynamic_segment (file) for (i = 0, entry = dynamic_segment; i < dynamic_size; - i ++, entry ++) + i++, entry++) { - entry->d_tag = BYTE_GET (edyn [i].d_tag); - entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val); + entry->d_tag = BYTE_GET (edyn[i].d_tag); + entry->d_un.d_val = BYTE_GET (edyn[i].d_un.d_val); } free (edyn); @@ -4375,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; + 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; @@ -4391,11 +4435,10 @@ get_64bit_dynamic_segment (file) how large this .dynamic is now. We can do this even before the byte swapping since the DT_NULL tag is recognizable. */ dynamic_size = 0; - while (*(bfd_vma *) edyn [dynamic_size ++].d_tag != DT_NULL) + 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) { @@ -4406,10 +4449,10 @@ get_64bit_dynamic_segment (file) for (i = 0, entry = dynamic_segment; i < dynamic_size; - i ++, entry ++) + i++, entry++) { - entry->d_tag = BYTE_GET8 (edyn [i].d_tag); - entry->d_un.d_val = BYTE_GET8 (edyn [i].d_un.d_val); + entry->d_tag = BYTE_GET8 (edyn[i].d_tag); + entry->d_un.d_val = BYTE_GET8 (edyn[i].d_un.d_val); } free (edyn); @@ -4418,10 +4461,9 @@ 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]; + static char buff[128]; char *p = buff; *p = '\0'; @@ -4437,12 +4479,12 @@ get_dynamic_flags (flags) switch (flag) { - case DF_ORIGIN: strcpy (p, "ORIGIN"); break; - case DF_SYMBOLIC: strcpy (p, "SYMBOLIC"); break; - case DF_TEXTREL: strcpy (p, "TEXTREL"); break; - case DF_BIND_NOW: strcpy (p, "BIND_NOW"); break; - case DF_STATIC_TLS: strcpy (p, "STATIC_TLS"); break; - default: strcpy (p, "unknown"); break; + case DF_ORIGIN: strcpy (p, "ORIGIN"); break; + case DF_SYMBOLIC: strcpy (p, "SYMBOLIC"); break; + case DF_TEXTREL: strcpy (p, "TEXTREL"); break; + case DF_BIND_NOW: strcpy (p, "BIND_NOW"); break; + case DF_STATIC_TLS: strcpy (p, "STATIC_TLS"); break; + default: strcpy (p, "unknown"); break; } p = strchr (p, '\0'); @@ -4452,11 +4494,10 @@ 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; + Elf_Internal_Dyn *entry; + bfd_size_type i; if (dynamic_size == 0) { @@ -4479,9 +4520,9 @@ process_dynamic_segment (file) { for (i = 0, entry = dynamic_segment; i < dynamic_size; - ++i, ++ entry) + ++i, ++entry) { - Elf32_Internal_Shdr section; + Elf_Internal_Shdr section; if (entry->d_tag != DT_SYMTAB) continue; @@ -4492,12 +4533,18 @@ process_dynamic_segment (file) we default to reading in the entire file (!) and processing that. This is overkill, I know, but it should work. */ - section.sh_offset = entry->d_un.d_val - loadaddr; + section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0); + + if (archive_file_offset != 0) + section.sh_size = archive_file_size - section.sh_offset; + else + { + if (fseek (file, 0, SEEK_END)) + error (_("Unable to seek to end of file!")); - if (fseek (file, 0, SEEK_END)) - error (_("Unable to seek to end of file!")); + section.sh_size = ftell (file) - section.sh_offset; + } - section.sh_size = ftell (file) - section.sh_offset; if (is_32bit_elf) section.sh_entsize = sizeof (Elf32_External_Sym); else @@ -4519,10 +4566,10 @@ process_dynamic_segment (file) { for (i = 0, entry = dynamic_segment; i < dynamic_size; - ++i, ++ entry) + ++i, ++entry) { unsigned long offset; - long str_tab_len; + long str_tab_len; if (entry->d_tag != DT_STRTAB) continue; @@ -4534,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) { @@ -4546,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; } } @@ -4555,11 +4608,11 @@ process_dynamic_segment (file) /* And find the syminfo section if available. */ if (dynamic_syminfo == NULL) { - unsigned int syminsz = 0; + unsigned long syminsz = 0; for (i = 0, entry = dynamic_segment; i < dynamic_size; - ++i, ++ entry) + ++i, ++entry) { if (entry->d_tag == DT_SYMINENT) { @@ -4570,22 +4623,22 @@ 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) { - Elf_External_Syminfo * extsyminfo; - Elf_Internal_Syminfo * syminfo; + Elf_External_Syminfo *extsyminfo; + 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")); @@ -4605,18 +4658,18 @@ process_dynamic_segment (file) } if (do_dynamic && dynamic_addr) - printf (_("\nDynamic segment at offset 0x%x contains %ld entries:\n"), + printf (_("\nDynamic segment at offset 0x%lx contains %ld entries:\n"), dynamic_addr, (long) dynamic_size); if (do_dynamic) printf (_(" Tag Type Name/Value\n")); for (i = 0, entry = dynamic_segment; i < dynamic_size; - i++, entry ++) + i++, entry++) { if (do_dynamic) { - const char * dtype; + const char *dtype; putchar (' '); print_vma (entry->d_tag, FULL_HEX); @@ -4642,7 +4695,7 @@ process_dynamic_segment (file) if (do_dynamic) { switch (entry->d_tag) - { + { case DT_AUXILIARY: printf (_("Auxiliary library")); break; @@ -4651,7 +4704,7 @@ process_dynamic_segment (file) printf (_("Filter library")); break; - case DT_CONFIG: + case DT_CONFIG: printf (_("Configuration file")); break; @@ -4819,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; @@ -4844,7 +4898,7 @@ process_dynamic_segment (file) if (do_dynamic) { - char * name; + char *name; if (dynamic_strings == NULL) name = NULL; @@ -4893,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 : @@ -4928,11 +4983,11 @@ process_dynamic_segment (file) { if (dynamic_strings != NULL && entry->d_tag == DT_USED) { - char * name; + char *name; name = dynamic_strings + entry->d_un.d_val; - if (* name) + if (*name) { printf (_("Not needed object: [%s]\n"), name); break; @@ -4953,7 +5008,7 @@ process_dynamic_segment (file) case DT_GNU_PRELINKED: if (do_dynamic) { - struct tm * tmp; + struct tm *tmp; time_t time = entry->d_un.d_val; tmp = gmtime (&time); @@ -4966,7 +5021,7 @@ process_dynamic_segment (file) default: if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM)) - version_info [DT_VERSIONTAGIDX (entry->d_tag)] = + version_info[DT_VERSIONTAGIDX (entry->d_tag)] = entry->d_un.d_val; if (do_dynamic) @@ -4980,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'); @@ -4993,10 +5051,9 @@ process_dynamic_segment (file) } static char * -get_ver_flags (flags) - unsigned int flags; +get_ver_flags (unsigned int flags) { - static char buff [32]; + static char buff[32]; buff[0] = 0; @@ -5022,27 +5079,26 @@ get_ver_flags (flags) /* Display the contents of the version sections. */ static int -process_version_sections (file) - FILE * file; +process_version_sections (FILE *file) { - Elf32_Internal_Shdr * section; - unsigned i; - int found = 0; + Elf_Internal_Shdr *section; + unsigned i; + int found = 0; if (! do_version) return 1; for (i = 0, section = section_headers; i < elf_header.e_shnum; - i++, section ++) + i++, section++) { switch (section->sh_type) { case SHT_GNU_verdef: { - Elf_External_Verdef * edefs; - unsigned int idx; - unsigned int cnt; + Elf_External_Verdef *edefs; + unsigned int idx; + unsigned int cnt; found = 1; @@ -5056,22 +5112,20 @@ 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; - for (idx = cnt = 0; cnt < section->sh_info; ++ cnt) + for (idx = cnt = 0; cnt < section->sh_info; ++cnt) { - char * vstart; - Elf_External_Verdef * edef; - Elf_Internal_Verdef ent; - Elf_External_Verdaux * eaux; - Elf_Internal_Verdaux aux; - int j; - int isum; + char *vstart; + Elf_External_Verdef *edef; + Elf_Internal_Verdef ent; + Elf_External_Verdaux *eaux; + Elf_Internal_Verdaux aux; + int j; + int isum; vstart = ((char *) edefs) + idx; @@ -5105,7 +5159,7 @@ process_version_sections (file) isum = idx + ent.vd_aux; - for (j = 1; j < ent.vd_cnt; j ++) + for (j = 1; j < ent.vd_cnt; j++) { isum += aux.vda_next; vstart += aux.vda_next; @@ -5132,9 +5186,9 @@ process_version_sections (file) case SHT_GNU_verneed: { - Elf_External_Verneed * eneed; - unsigned int idx; - unsigned int cnt; + Elf_External_Verneed *eneed; + unsigned int idx; + unsigned int cnt; found = 1; @@ -5147,19 +5201,18 @@ 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; for (idx = cnt = 0; cnt < section->sh_info; ++cnt) { - Elf_External_Verneed * entry; - Elf_Internal_Verneed ent; - int j; - int isum; - char * vstart; + Elf_External_Verneed *entry; + Elf_Internal_Verneed ent; + int j; + int isum; + char *vstart; vstart = ((char *) eneed) + idx; @@ -5184,8 +5237,8 @@ process_version_sections (file) for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j) { - Elf_External_Vernaux * eaux; - Elf_Internal_Vernaux aux; + Elf_External_Vernaux *eaux; + Elf_Internal_Vernaux aux; eaux = (Elf_External_Vernaux *) vstart; @@ -5196,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"), @@ -5218,14 +5271,15 @@ process_version_sections (file) case SHT_GNU_versym: { - Elf32_Internal_Shdr * link_section; - int total; - int cnt; - unsigned char * edata; - unsigned short * data; - char * strtab; - Elf_Internal_Sym * symbols; - Elf32_Internal_Shdr * string_sec; + Elf_Internal_Shdr *link_section; + int total; + int cnt; + unsigned char *edata; + unsigned short *data; + 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; @@ -5236,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; @@ -5251,22 +5304,22 @@ 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), - sizeof (short)); + data[cnt] = byte_get (edata + cnt * sizeof (short), + sizeof (short)); free (edata); @@ -5274,12 +5327,12 @@ process_version_sections (file) { int j, nn; int check_def, check_need; - char * name; + char *name; printf (" %03x:", cnt); for (j = 0; (j < 4) && (cnt + j) < total; ++j) - switch (data [cnt + j]) + switch (data[cnt + j]) { case 0: fputs (_(" 0 (*local*) "), stdout); @@ -5290,35 +5343,36 @@ process_version_sections (file) break; default: - nn = printf ("%4x%c", data [cnt + j] & 0x7fff, - data [cnt + j] & 0x8000 ? 'h' : ' '); + nn = printf ("%4x%c", data[cnt + j] & 0x7fff, + data[cnt + j] & 0x8000 ? 'h' : ' '); check_def = 1; check_need = 1; - if (SECTION_HEADER (symbols [cnt + j].st_shndx)->sh_type + if (SECTION_HEADER (symbols[cnt + j].st_shndx)->sh_type != SHT_NOBITS) { - if (symbols [cnt + j].st_shndx == SHN_UNDEF) + if (symbols[cnt + j].st_shndx == SHN_UNDEF) check_def = 0; else check_need = 0; } if (check_need - && version_info [DT_VERSIONTAGIDX (DT_VERNEED)]) + && version_info[DT_VERSIONTAGIDX (DT_VERNEED)]) { - Elf_Internal_Verneed ivn; - unsigned long offset; + 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 + do { - Elf_Internal_Vernaux ivna; - Elf_External_Verneed evn; - Elf_External_Vernaux evna; - unsigned long a_off; + Elf_Internal_Vernaux ivna; + Elf_External_Verneed evn; + Elf_External_Vernaux evna; + unsigned long a_off; get_data (&evn, file, offset, sizeof (evn), _("version need")); @@ -5338,10 +5392,10 @@ process_version_sections (file) a_off += ivna.vna_next; } - while (ivna.vna_other != data [cnt + j] + while (ivna.vna_other != data[cnt + j] && ivna.vna_next != 0); - if (ivna.vna_other == data [cnt + j]) + if (ivna.vna_other == data[cnt + j]) { ivna.vna_name = BYTE_GET (evna.vna_name); @@ -5359,15 +5413,16 @@ process_version_sections (file) while (ivn.vn_next); } - if (check_def && data [cnt + j] != 0x8001 - && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) + if (check_def && data[cnt + j] != 0x8001 + && version_info[DT_VERSIONTAGIDX (DT_VERDEF)]) { - Elf_Internal_Verdef ivd; - Elf_External_Verdef evd; - unsigned long offset; + Elf_Internal_Verdef ivd; + 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 { @@ -5379,13 +5434,13 @@ process_version_sections (file) offset += ivd.vd_next; } - while (ivd.vd_ndx != (data [cnt + j] & 0x7fff) + while (ivd.vd_ndx != (data[cnt + j] & 0x7fff) && ivd.vd_next != 0); - if (ivd.vd_ndx == (data [cnt + j] & 0x7fff)) + if (ivd.vd_ndx == (data[cnt + j] & 0x7fff)) { - Elf_External_Verdaux evda; - Elf_Internal_Verdaux ivda; + Elf_External_Verdaux evda; + Elf_Internal_Verdaux ivda; ivd.vd_aux = BYTE_GET (evd.vd_aux); @@ -5428,16 +5483,15 @@ process_version_sections (file) } static const char * -get_symbol_binding (binding) - unsigned int binding; +get_symbol_binding (unsigned int binding) { - static char buff [32]; + static char buff[32]; switch (binding) { - case STB_LOCAL: return "LOCAL"; - case STB_GLOBAL: return "GLOBAL"; - case STB_WEAK: return "WEAK"; + case STB_LOCAL: return "LOCAL"; + case STB_GLOBAL: return "GLOBAL"; + case STB_WEAK: return "WEAK"; default: if (binding >= STB_LOPROC && binding <= STB_HIPROC) sprintf (buff, _(": %d"), binding); @@ -5450,20 +5504,19 @@ get_symbol_binding (binding) } static const char * -get_symbol_type (type) - unsigned int type; +get_symbol_type (unsigned int type) { - static char buff [32]; + static char buff[32]; switch (type) { - case STT_NOTYPE: return "NOTYPE"; - case STT_OBJECT: return "OBJECT"; - case STT_FUNC: return "FUNC"; - case STT_SECTION: return "SECTION"; - case STT_FILE: return "FILE"; - case STT_COMMON: return "COMMON"; - case STT_TLS: return "TLS"; + case STT_NOTYPE: return "NOTYPE"; + case STT_OBJECT: return "OBJECT"; + case STT_FUNC: return "FUNC"; + case STT_SECTION: return "SECTION"; + case STT_FILE: return "FILE"; + case STT_COMMON: return "COMMON"; + case STT_TLS: return "TLS"; default: if (type >= STT_LOPROC && type <= STT_HIPROC) { @@ -5497,54 +5550,54 @@ get_symbol_type (type) } static const char * -get_symbol_visibility (visibility) - unsigned int visibility; +get_symbol_visibility (unsigned int visibility) { switch (visibility) { - case STV_DEFAULT: return "DEFAULT"; - case STV_INTERNAL: return "INTERNAL"; - case STV_HIDDEN: return "HIDDEN"; + case STV_DEFAULT: return "DEFAULT"; + case STV_INTERNAL: return "INTERNAL"; + case STV_HIDDEN: return "HIDDEN"; case STV_PROTECTED: return "PROTECTED"; default: abort (); } } static const char * -get_symbol_index_type (type) - unsigned int type; +get_symbol_index_type (unsigned int type) { + static char buff[32]; + switch (type) { - case SHN_UNDEF: return "UND"; - case SHN_ABS: return "ABS"; - case SHN_COMMON: return "COM"; + case SHN_UNDEF: return "UND"; + case SHN_ABS: return "ABS"; + case SHN_COMMON: return "COM"; default: - if (type >= SHN_LOPROC && type <= SHN_HIPROC) - return "PRC"; + 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) - return "OS "; + sprintf (buff, "OS [0x%04x]", type); else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE) - return "RSV"; + sprintf (buff, "RSV[0x%04x]", type); else - { - static char buff [32]; - - sprintf (buff, "%3d", type); - return buff; - } + sprintf (buff, "%3d", type); + break; } + + return buff; } 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; + unsigned char *e_data; + int *i_data; - e_data = (unsigned char *) malloc (number * 4); + e_data = malloc (number * 4); if (e_data == NULL) { @@ -5558,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) { @@ -5568,7 +5621,7 @@ get_dynamic_data (file, number) } while (number--) - i_data [number] = byte_get (e_data + number * 4, 4); + i_data[number] = byte_get (e_data + number * 4, 4); free (e_data); @@ -5577,16 +5630,15 @@ get_dynamic_data (file, number) /* Dump the symbol table. */ static int -process_symbol_table (file) - FILE * file; +process_symbol_table (FILE *file) { - Elf32_Internal_Shdr * section; - unsigned char nb [4]; - unsigned char nc [4]; - int nbuckets = 0; - int nchains = 0; - int * buckets = NULL; - int * chains = NULL; + Elf_Internal_Shdr *section; + unsigned char nb[4]; + unsigned char nc[4]; + int nbuckets = 0; + int nchains = 0; + int *buckets = NULL; + int *chains = NULL; if (! do_syms && !do_histogram) return 1; @@ -5594,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; @@ -5625,8 +5681,8 @@ process_symbol_table (file) if (do_syms && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL) { - int hn; - int si; + int hn; + int si; printf (_("\nSymbol table for image:\n")); if (is_32bit_elf) @@ -5636,12 +5692,12 @@ process_symbol_table (file) for (hn = 0; hn < nbuckets; hn++) { - if (! buckets [hn]) + if (! buckets[hn]) continue; - for (si = buckets [hn]; si < nchains && si > 0; si = chains [si]) + for (si = buckets[hn]; si < nchains && si > 0; si = chains[si]) { - Elf_Internal_Sym * psym; + Elf_Internal_Sym *psym; psym = dynamic_symbols + si; @@ -5661,16 +5717,16 @@ process_symbol_table (file) } else if (do_syms && !do_using_dynamic) { - unsigned int i; + unsigned int i; for (i = 0, section = section_headers; i < elf_header.e_shnum; i++, section++) { - unsigned int si; - char * strtab; - Elf_Internal_Sym * symtab; - Elf_Internal_Sym * psym; + unsigned int si; + char *strtab; + Elf_Internal_Sym *symtab; + Elf_Internal_Sym *psym; if ( section->sh_type != SHT_SYMTAB @@ -5693,18 +5749,17 @@ process_symbol_table (file) strtab = string_table; else { - Elf32_Internal_Shdr * string_sec; + Elf_Internal_Shdr *string_sec; 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; si < section->sh_size / section->sh_entsize; - si ++, psym ++) + si++, psym++) { printf ("%6d: ", si); print_vma (psym->st_value, LONG_HEX); @@ -5717,16 +5772,17 @@ process_symbol_table (file) print_symbol (25, strtab + psym->st_name); if (section->sh_type == SHT_DYNSYM && - version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0) + version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0) { - unsigned char data[2]; - unsigned short vers_data; - unsigned long offset; - int is_nobits; - int check_def; + unsigned char data[2]; + unsigned short vers_data; + unsigned long offset; + 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")); @@ -5740,20 +5796,21 @@ process_symbol_table (file) if ((vers_data & 0x8000) || vers_data > 1) { - if (version_info [DT_VERSIONTAGIDX (DT_VERNEED)] + if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)] && (is_nobits || ! check_def)) { - Elf_External_Verneed evn; - Elf_Internal_Verneed ivn; - Elf_Internal_Vernaux ivna; + Elf_External_Verneed evn; + Elf_Internal_Verneed ivn; + 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 { - unsigned long vna_off; + unsigned long vna_off; get_data (&evn, file, offset, sizeof (evn), _("version need")); @@ -5765,7 +5822,7 @@ process_symbol_table (file) do { - Elf_External_Vernaux evna; + Elf_External_Vernaux evna; get_data (&evna, file, vna_off, sizeof (evna), @@ -5802,26 +5859,27 @@ process_symbol_table (file) if (check_def) { if (vers_data != 0x8001 - && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) + && version_info[DT_VERSIONTAGIDX (DT_VERDEF)]) { - Elf_Internal_Verdef ivd; - Elf_Internal_Verdaux ivda; - Elf_External_Verdaux evda; - unsigned long offset; + Elf_Internal_Verdef ivd; + Elf_Internal_Verdaux ivda; + 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 { - Elf_External_Verdef evd; + Elf_External_Verdef evd; get_data (&evd, file, offset, sizeof (evd), _("version def")); - ivd.vd_ndx = BYTE_GET (evd.vd_ndx); - ivd.vd_aux = BYTE_GET (evd.vd_aux); + ivd.vd_ndx = BYTE_GET (evd.vd_ndx); + ivd.vd_aux = BYTE_GET (evd.vd_aux); ivd.vd_next = BYTE_GET (evd.vd_next); offset += ivd.vd_next; @@ -5860,19 +5918,19 @@ process_symbol_table (file) if (do_histogram && buckets != NULL) { - int * lengths; - int * counts; - int hn; - int si; - int maxlength = 0; - int nzero_counts = 0; - int nsyms = 0; + int *lengths; + int *counts; + int hn; + int si; + int maxlength = 0; + int nzero_counts = 0; + int nsyms = 0; printf (_("\nHistogram for bucket list length (total of %d buckets):\n"), 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")); @@ -5880,18 +5938,18 @@ process_symbol_table (file) } for (hn = 0; hn < nbuckets; ++hn) { - if (! buckets [hn]) + if (! buckets[hn]) continue; for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si]) { - ++ nsyms; + ++nsyms; if (maxlength < ++lengths[hn]) - ++ maxlength; + ++maxlength; } } - counts = (int *) calloc (maxlength + 1, sizeof (int)); + counts = calloc (maxlength + 1, sizeof (int)); if (counts == NULL) { error (_("Out of memory")); @@ -5899,7 +5957,7 @@ process_symbol_table (file) } for (hn = 0; hn < nbuckets; ++hn) - ++ counts [lengths [hn]]; + ++counts[lengths[hn]]; if (nbuckets > 0) { @@ -5928,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; @@ -5967,9 +6024,10 @@ process_syminfo (file) if (dynamic_syminfo[i].si_boundto > 0 && dynamic_syminfo[i].si_boundto < dynamic_size) { - print_symbol (10, dynamic_strings - + dynamic_segment - [dynamic_syminfo[i].si_boundto].d_un.d_val); + print_symbol (10, + dynamic_strings + + (dynamic_segment + [dynamic_syminfo[i].si_boundto].d_un.d_val)); putchar (' ' ); } else @@ -5994,9 +6052,7 @@ process_syminfo (file) #ifdef SUPPORT_DISASSEMBLY static void -disassemble_section (section, file) - Elf32_Internal_Shdr * section; - FILE * file; +disassemble_section (Elf_Internal_Shdr *section, FILE *file) { printf (_("\nAssembly dump of section %s\n"), SECTION_NAME (section)); @@ -6008,18 +6064,16 @@ disassemble_section (section, file) #endif static int -dump_section (section, file) - Elf32_Internal_Shdr * section; - FILE * file; +dump_section (Elf_Internal_Shdr *section, FILE *file) { - bfd_size_type bytes; - bfd_vma addr; - unsigned char * data; - unsigned char * start; + bfd_size_type bytes; + bfd_vma addr; + unsigned char *data; + unsigned char *start; 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)); @@ -6030,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; @@ -6047,14 +6100,14 @@ dump_section (section, file) printf (" 0x%8.8lx ", (unsigned long) addr); - switch (elf_header.e_ident [EI_DATA]) + switch (elf_header.e_ident[EI_DATA]) { default: case ELFDATA2LSB: for (j = 15; j >= 0; j --) { if (j < lbytes) - printf ("%2.2x", data [j]); + printf ("%2.2x", data[j]); else printf (" "); @@ -6067,7 +6120,7 @@ dump_section (section, file) for (j = 0; j < 16; j++) { if (j < lbytes) - printf ("%2.2x", data [j]); + printf ("%2.2x", data[j]); else printf (" "); @@ -6079,8 +6132,8 @@ dump_section (section, file) for (j = 0; j < lbytes; j++) { - k = data [j]; - if (k >= ' ' && k < 0x80) + k = data[j]; + if (k >= ' ' && k < 0x7f) printf ("%c", k); else printf ("."); @@ -6100,20 +6153,17 @@ 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; - int shift = 0; - unsigned char byte; + unsigned int num_read = 0; + int shift = 0; + unsigned char byte; do { - byte = * data ++; - num_read ++; + byte = *data++; + num_read++; result |= (byte & 0x7f) << shift; @@ -6123,7 +6173,7 @@ read_leb128 (data, length_return, sign) while (byte & 0x80); if (length_return != NULL) - * length_return = num_read; + *length_return = num_read; if (sign && (shift < 32) && (byte & 0x40)) result |= -1 << shift; @@ -6133,23 +6183,22 @@ read_leb128 (data, length_return, sign) typedef struct State_Machine_Registers { - unsigned long address; - unsigned int file; - unsigned int line; - unsigned int column; - int is_stmt; - int basic_block; - int end_sequence; + unsigned long address; + unsigned int file; + unsigned int line; + unsigned int column; + int is_stmt; + int basic_block; + int end_sequence; /* This variable hold the number of the last entry seen in the File Table. */ - unsigned int last_file_entry; + unsigned int last_file_entry; } SMR; 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; @@ -6164,16 +6213,13 @@ 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; - unsigned int len; - unsigned char * name; - unsigned long adr; + unsigned char op_code; + int bytes_read; + unsigned int len; + unsigned char *name; + unsigned long adr; len = read_leb128 (data, & bytes_read, 0); data += bytes_read; @@ -6185,7 +6231,7 @@ process_extended_line_op (data, is_stmt, pointer_size) } len += bytes_read; - op_code = * data ++; + op_code = *data++; printf (_(" Extended opcode %d: "), op_code); @@ -6206,7 +6252,7 @@ process_extended_line_op (data, is_stmt, pointer_size) printf (_(" define new File Table entry\n")); printf (_(" Entry\tDir\tTime\tSize\tName\n")); - printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); + printf (_(" %d\t"), ++state_machine_regs.last_file_entry); name = data; data += strlen ((char *) data) + 1; printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); @@ -6231,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) - Elf32_Internal_Shdr * section; - unsigned char * start; - FILE * file ATTRIBUTE_UNUSED; -{ - DWARF2_External_LineInfo * external; - 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; +display_debug_lines (Elf_Internal_Shdr *section, + unsigned char * start, + FILE *file ATTRIBUTE_UNUSED) +{ + 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")); @@ -6268,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; @@ -6295,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")); @@ -6310,13 +6373,13 @@ display_debug_lines (section, start, file) /* Display the contents of the Directory table. */ data = standard_opcodes + info.li_opcode_base - 1; - if (* data == 0) + if (*data == 0) printf (_("\n The Directory Table is empty.\n")); else { printf (_("\n The Directory Table:\n")); - while (* data != 0) + while (*data != 0) { printf (_(" %s\n"), data); @@ -6325,22 +6388,22 @@ display_debug_lines (section, start, file) } /* Skip the NUL at the end of the table. */ - data ++; + data++; /* Display the contents of the File Name table. */ - if (* data == 0) + if (*data == 0) printf (_("\n The File Name Table is empty.\n")); else { printf (_("\n The File Name Table:\n")); printf (_(" Entry\tDir\tTime\tSize\tName\n")); - while (* data != 0) + while (*data != 0) { - unsigned char * name; + unsigned char *name; int bytes_read; - printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); + printf (_(" %d\t"), ++state_machine_regs.last_file_entry); name = data; data += strlen ((char *) data) + 1; @@ -6356,7 +6419,7 @@ display_debug_lines (section, start, file) } /* Skip the NUL at the end of the table. */ - data ++; + data++; /* Now display the statements. */ printf (_("\n Line Number Statements:\n")); @@ -6365,10 +6428,10 @@ display_debug_lines (section, start, file) while (data < end_of_sequence) { unsigned char op_code; - int adv; - int bytes_read; + int adv; + int bytes_read; - op_code = * data ++; + op_code = *data++; if (op_code >= info.li_opcode_base) { @@ -6488,14 +6551,12 @@ display_debug_lines (section, start, file) } static int -display_debug_pubnames (section, start, file) - Elf32_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; + DWARF2_Internal_PubNames pubnames; + unsigned char *end; end = start + section->sh_size; @@ -6503,32 +6564,43 @@ display_debug_pubnames (section, start, file) while (start < end) { - unsigned char * data; - unsigned long offset; - - 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); + unsigned char *data; + unsigned long offset; + int offset_size, initial_length_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; + } + + 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) + 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; } @@ -6548,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; } @@ -6565,75 +6637,78 @@ display_debug_pubnames (section, start, file) } static char * -get_TAG_name (tag) - unsigned long tag; +get_TAG_name (unsigned long tag) { switch (tag) { - case DW_TAG_padding: return "DW_TAG_padding"; - case DW_TAG_array_type: return "DW_TAG_array_type"; - case DW_TAG_class_type: return "DW_TAG_class_type"; - case DW_TAG_entry_point: return "DW_TAG_entry_point"; - case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; - case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; - case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration"; - case DW_TAG_label: return "DW_TAG_label"; - case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; - case DW_TAG_member: return "DW_TAG_member"; - case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; - case DW_TAG_reference_type: return "DW_TAG_reference_type"; - case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; - case DW_TAG_string_type: return "DW_TAG_string_type"; - case DW_TAG_structure_type: return "DW_TAG_structure_type"; - case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; - case DW_TAG_typedef: return "DW_TAG_typedef"; - case DW_TAG_union_type: return "DW_TAG_union_type"; + case DW_TAG_padding: return "DW_TAG_padding"; + case DW_TAG_array_type: return "DW_TAG_array_type"; + case DW_TAG_class_type: return "DW_TAG_class_type"; + case DW_TAG_entry_point: return "DW_TAG_entry_point"; + case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; + case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; + case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration"; + case DW_TAG_label: return "DW_TAG_label"; + case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; + case DW_TAG_member: return "DW_TAG_member"; + case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; + case DW_TAG_reference_type: return "DW_TAG_reference_type"; + case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; + case DW_TAG_string_type: return "DW_TAG_string_type"; + case DW_TAG_structure_type: return "DW_TAG_structure_type"; + case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; + case DW_TAG_typedef: return "DW_TAG_typedef"; + case DW_TAG_union_type: return "DW_TAG_union_type"; case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters"; - case DW_TAG_variant: return "DW_TAG_variant"; - case DW_TAG_common_block: return "DW_TAG_common_block"; - case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; - case DW_TAG_inheritance: return "DW_TAG_inheritance"; - case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine"; - case DW_TAG_module: return "DW_TAG_module"; - case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; - case DW_TAG_set_type: return "DW_TAG_set_type"; - case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; - case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; - case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; - case DW_TAG_base_type: return "DW_TAG_base_type"; - case DW_TAG_catch_block: return "DW_TAG_catch_block"; - case DW_TAG_const_type: return "DW_TAG_const_type"; - case DW_TAG_constant: return "DW_TAG_constant"; - case DW_TAG_enumerator: return "DW_TAG_enumerator"; - case DW_TAG_file_type: return "DW_TAG_file_type"; - case DW_TAG_friend: return "DW_TAG_friend"; - case DW_TAG_namelist: return "DW_TAG_namelist"; - case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; - case DW_TAG_packed_type: return "DW_TAG_packed_type"; - case DW_TAG_subprogram: return "DW_TAG_subprogram"; - case DW_TAG_template_type_param: return "DW_TAG_template_type_param"; - case DW_TAG_template_value_param: return "DW_TAG_template_value_param"; - case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; - case DW_TAG_try_block: return "DW_TAG_try_block"; - case DW_TAG_variant_part: return "DW_TAG_variant_part"; - case DW_TAG_variable: return "DW_TAG_variable"; - case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; - case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; - case DW_TAG_format_label: return "DW_TAG_format_label"; - case DW_TAG_function_template: return "DW_TAG_function_template"; - case DW_TAG_class_template: return "DW_TAG_class_template"; + case DW_TAG_variant: return "DW_TAG_variant"; + case DW_TAG_common_block: return "DW_TAG_common_block"; + case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; + case DW_TAG_inheritance: return "DW_TAG_inheritance"; + case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine"; + case DW_TAG_module: return "DW_TAG_module"; + case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; + case DW_TAG_set_type: return "DW_TAG_set_type"; + case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; + case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; + case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; + case DW_TAG_base_type: return "DW_TAG_base_type"; + case DW_TAG_catch_block: return "DW_TAG_catch_block"; + case DW_TAG_const_type: return "DW_TAG_const_type"; + case DW_TAG_constant: return "DW_TAG_constant"; + case DW_TAG_enumerator: return "DW_TAG_enumerator"; + case DW_TAG_file_type: return "DW_TAG_file_type"; + case DW_TAG_friend: return "DW_TAG_friend"; + case DW_TAG_namelist: return "DW_TAG_namelist"; + case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; + case DW_TAG_packed_type: return "DW_TAG_packed_type"; + case DW_TAG_subprogram: return "DW_TAG_subprogram"; + case DW_TAG_template_type_param: return "DW_TAG_template_type_param"; + case DW_TAG_template_value_param: return "DW_TAG_template_value_param"; + case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; + case DW_TAG_try_block: return "DW_TAG_try_block"; + case DW_TAG_variant_part: return "DW_TAG_variant_part"; + case DW_TAG_variable: return "DW_TAG_variable"; + case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; + case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; + case DW_TAG_format_label: return "DW_TAG_format_label"; + case DW_TAG_function_template: return "DW_TAG_function_template"; + case DW_TAG_class_template: return "DW_TAG_class_template"; /* DWARF 2.1 values. */ - case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure"; - case DW_TAG_restrict_type: return "DW_TAG_restrict_type"; - case DW_TAG_interface_type: return "DW_TAG_interface_type"; - case DW_TAG_namespace: return "DW_TAG_namespace"; - case DW_TAG_imported_module: return "DW_TAG_imported_module"; - case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type"; - case DW_TAG_partial_unit: return "DW_TAG_partial_unit"; - case DW_TAG_imported_unit: return "DW_TAG_imported_unit"; + case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure"; + case DW_TAG_restrict_type: return "DW_TAG_restrict_type"; + case DW_TAG_interface_type: return "DW_TAG_interface_type"; + case DW_TAG_namespace: return "DW_TAG_namespace"; + case DW_TAG_imported_module: return "DW_TAG_imported_module"; + case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type"; + case DW_TAG_partial_unit: return "DW_TAG_partial_unit"; + case DW_TAG_imported_unit: return "DW_TAG_imported_unit"; + /* UPC values. */ + case DW_TAG_upc_shared_type: return "DW_TAG_upc_shared_type"; + case DW_TAG_upc_strict_type: return "DW_TAG_upc_strict_type"; + case DW_TAG_upc_relaxed_type: return "DW_TAG_upc_relaxed_type"; default: { - static char buffer [100]; + static char buffer[100]; sprintf (buffer, _("Unknown TAG value: %lx"), tag); return buffer; @@ -6642,109 +6717,111 @@ get_TAG_name (tag) } static char * -get_AT_name (attribute) - unsigned long attribute; +get_AT_name (unsigned long attribute) { switch (attribute) { - case DW_AT_sibling: return "DW_AT_sibling"; - case DW_AT_location: return "DW_AT_location"; - case DW_AT_name: return "DW_AT_name"; - case DW_AT_ordering: return "DW_AT_ordering"; - case DW_AT_subscr_data: return "DW_AT_subscr_data"; - case DW_AT_byte_size: return "DW_AT_byte_size"; - case DW_AT_bit_offset: return "DW_AT_bit_offset"; - case DW_AT_bit_size: return "DW_AT_bit_size"; - case DW_AT_element_list: return "DW_AT_element_list"; - case DW_AT_stmt_list: return "DW_AT_stmt_list"; - case DW_AT_low_pc: return "DW_AT_low_pc"; - case DW_AT_high_pc: return "DW_AT_high_pc"; - case DW_AT_language: return "DW_AT_language"; - case DW_AT_member: return "DW_AT_member"; - case DW_AT_discr: return "DW_AT_discr"; - case DW_AT_discr_value: return "DW_AT_discr_value"; - case DW_AT_visibility: return "DW_AT_visibility"; - case DW_AT_import: return "DW_AT_import"; - case DW_AT_string_length: return "DW_AT_string_length"; - case DW_AT_common_reference: return "DW_AT_common_reference"; - case DW_AT_comp_dir: return "DW_AT_comp_dir"; - case DW_AT_const_value: return "DW_AT_const_value"; - case DW_AT_containing_type: return "DW_AT_containing_type"; - case DW_AT_default_value: return "DW_AT_default_value"; - case DW_AT_inline: return "DW_AT_inline"; - case DW_AT_is_optional: return "DW_AT_is_optional"; - case DW_AT_lower_bound: return "DW_AT_lower_bound"; - case DW_AT_producer: return "DW_AT_producer"; - case DW_AT_prototyped: return "DW_AT_prototyped"; - case DW_AT_return_addr: return "DW_AT_return_addr"; - case DW_AT_start_scope: return "DW_AT_start_scope"; - case DW_AT_stride_size: return "DW_AT_stride_size"; - case DW_AT_upper_bound: return "DW_AT_upper_bound"; - case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; - case DW_AT_accessibility: return "DW_AT_accessibility"; - case DW_AT_address_class: return "DW_AT_address_class"; - case DW_AT_artificial: return "DW_AT_artificial"; - case DW_AT_base_types: return "DW_AT_base_types"; - case DW_AT_calling_convention: return "DW_AT_calling_convention"; - case DW_AT_count: return "DW_AT_count"; - case DW_AT_data_member_location: return "DW_AT_data_member_location"; - case DW_AT_decl_column: return "DW_AT_decl_column"; - case DW_AT_decl_file: return "DW_AT_decl_file"; - case DW_AT_decl_line: return "DW_AT_decl_line"; - case DW_AT_declaration: return "DW_AT_declaration"; - case DW_AT_discr_list: return "DW_AT_discr_list"; - case DW_AT_encoding: return "DW_AT_encoding"; - case DW_AT_external: return "DW_AT_external"; - case DW_AT_frame_base: return "DW_AT_frame_base"; - case DW_AT_friend: return "DW_AT_friend"; - case DW_AT_identifier_case: return "DW_AT_identifier_case"; - case DW_AT_macro_info: return "DW_AT_macro_info"; - case DW_AT_namelist_items: return "DW_AT_namelist_items"; - case DW_AT_priority: return "DW_AT_priority"; - case DW_AT_segment: return "DW_AT_segment"; - case DW_AT_specification: return "DW_AT_specification"; - case DW_AT_static_link: return "DW_AT_static_link"; - case DW_AT_type: return "DW_AT_type"; - case DW_AT_use_location: return "DW_AT_use_location"; - case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; - case DW_AT_virtuality: return "DW_AT_virtuality"; - case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; + case DW_AT_sibling: return "DW_AT_sibling"; + case DW_AT_location: return "DW_AT_location"; + case DW_AT_name: return "DW_AT_name"; + case DW_AT_ordering: return "DW_AT_ordering"; + case DW_AT_subscr_data: return "DW_AT_subscr_data"; + case DW_AT_byte_size: return "DW_AT_byte_size"; + case DW_AT_bit_offset: return "DW_AT_bit_offset"; + case DW_AT_bit_size: return "DW_AT_bit_size"; + case DW_AT_element_list: return "DW_AT_element_list"; + case DW_AT_stmt_list: return "DW_AT_stmt_list"; + case DW_AT_low_pc: return "DW_AT_low_pc"; + case DW_AT_high_pc: return "DW_AT_high_pc"; + case DW_AT_language: return "DW_AT_language"; + case DW_AT_member: return "DW_AT_member"; + case DW_AT_discr: return "DW_AT_discr"; + case DW_AT_discr_value: return "DW_AT_discr_value"; + case DW_AT_visibility: return "DW_AT_visibility"; + case DW_AT_import: return "DW_AT_import"; + case DW_AT_string_length: return "DW_AT_string_length"; + case DW_AT_common_reference: return "DW_AT_common_reference"; + case DW_AT_comp_dir: return "DW_AT_comp_dir"; + case DW_AT_const_value: return "DW_AT_const_value"; + case DW_AT_containing_type: return "DW_AT_containing_type"; + case DW_AT_default_value: return "DW_AT_default_value"; + case DW_AT_inline: return "DW_AT_inline"; + case DW_AT_is_optional: return "DW_AT_is_optional"; + case DW_AT_lower_bound: return "DW_AT_lower_bound"; + case DW_AT_producer: return "DW_AT_producer"; + case DW_AT_prototyped: return "DW_AT_prototyped"; + case DW_AT_return_addr: return "DW_AT_return_addr"; + case DW_AT_start_scope: return "DW_AT_start_scope"; + case DW_AT_stride_size: return "DW_AT_stride_size"; + case DW_AT_upper_bound: return "DW_AT_upper_bound"; + case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; + case DW_AT_accessibility: return "DW_AT_accessibility"; + case DW_AT_address_class: return "DW_AT_address_class"; + case DW_AT_artificial: return "DW_AT_artificial"; + case DW_AT_base_types: return "DW_AT_base_types"; + case DW_AT_calling_convention: return "DW_AT_calling_convention"; + case DW_AT_count: return "DW_AT_count"; + case DW_AT_data_member_location: return "DW_AT_data_member_location"; + case DW_AT_decl_column: return "DW_AT_decl_column"; + case DW_AT_decl_file: return "DW_AT_decl_file"; + case DW_AT_decl_line: return "DW_AT_decl_line"; + case DW_AT_declaration: return "DW_AT_declaration"; + case DW_AT_discr_list: return "DW_AT_discr_list"; + case DW_AT_encoding: return "DW_AT_encoding"; + case DW_AT_external: return "DW_AT_external"; + case DW_AT_frame_base: return "DW_AT_frame_base"; + case DW_AT_friend: return "DW_AT_friend"; + case DW_AT_identifier_case: return "DW_AT_identifier_case"; + case DW_AT_macro_info: return "DW_AT_macro_info"; + case DW_AT_namelist_items: return "DW_AT_namelist_items"; + case DW_AT_priority: return "DW_AT_priority"; + case DW_AT_segment: return "DW_AT_segment"; + case DW_AT_specification: return "DW_AT_specification"; + case DW_AT_static_link: return "DW_AT_static_link"; + case DW_AT_type: return "DW_AT_type"; + case DW_AT_use_location: return "DW_AT_use_location"; + case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; + case DW_AT_virtuality: return "DW_AT_virtuality"; + case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; /* DWARF 2.1 values. */ - case DW_AT_allocated: return "DW_AT_allocated"; - case DW_AT_associated: return "DW_AT_associated"; - case DW_AT_data_location: return "DW_AT_data_location"; - case DW_AT_stride: return "DW_AT_stride"; - case DW_AT_entry_pc: return "DW_AT_entry_pc"; - case DW_AT_use_UTF8: return "DW_AT_use_UTF8"; - case DW_AT_extension: return "DW_AT_extension"; - case DW_AT_ranges: return "DW_AT_ranges"; - case DW_AT_trampoline: return "DW_AT_trampoline"; - case DW_AT_call_column: return "DW_AT_call_column"; - case DW_AT_call_file: return "DW_AT_call_file"; - case DW_AT_call_line: return "DW_AT_call_line"; + case DW_AT_allocated: return "DW_AT_allocated"; + case DW_AT_associated: return "DW_AT_associated"; + case DW_AT_data_location: return "DW_AT_data_location"; + case DW_AT_stride: return "DW_AT_stride"; + case DW_AT_entry_pc: return "DW_AT_entry_pc"; + case DW_AT_use_UTF8: return "DW_AT_use_UTF8"; + case DW_AT_extension: return "DW_AT_extension"; + case DW_AT_ranges: return "DW_AT_ranges"; + case DW_AT_trampoline: return "DW_AT_trampoline"; + case DW_AT_call_column: return "DW_AT_call_column"; + case DW_AT_call_file: return "DW_AT_call_file"; + case DW_AT_call_line: return "DW_AT_call_line"; /* SGI/MIPS extensions. */ - case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; - case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; - case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin"; - case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin"; + case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; + case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; + case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin"; + case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin"; case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor"; - case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth"; - case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; - case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride"; - case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name"; - case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin"; - case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines"; + case DW_AT_MIPS_software_pipeline_depth: + return "DW_AT_MIPS_software_pipeline_depth"; + case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; + case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride"; + case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name"; + case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin"; + case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines"; /* GNU extensions. */ - case DW_AT_sf_names: return "DW_AT_sf_names"; - case DW_AT_src_info: return "DW_AT_src_info"; - case DW_AT_mac_info: return "DW_AT_mac_info"; - case DW_AT_src_coords: return "DW_AT_src_coords"; - case DW_AT_body_begin: return "DW_AT_body_begin"; - case DW_AT_body_end: return "DW_AT_body_end"; - case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + case DW_AT_sf_names: return "DW_AT_sf_names"; + case DW_AT_src_info: return "DW_AT_src_info"; + case DW_AT_mac_info: return "DW_AT_mac_info"; + case DW_AT_src_coords: return "DW_AT_src_coords"; + case DW_AT_body_begin: return "DW_AT_body_begin"; + case DW_AT_body_end: return "DW_AT_body_end"; + case DW_AT_GNU_vector: return "DW_AT_GNU_vector"; + /* UPC extension. */ + case DW_AT_upc_threads_scaled: return "DW_AT_upc_threads_scaled"; default: { - static char buffer [100]; + static char buffer[100]; sprintf (buffer, _("Unknown AT value: %lx"), attribute); return buffer; @@ -6753,35 +6830,34 @@ get_AT_name (attribute) } static char * -get_FORM_name (form) - unsigned long form; +get_FORM_name (unsigned long form) { switch (form) { - case DW_FORM_addr: return "DW_FORM_addr"; - case DW_FORM_block2: return "DW_FORM_block2"; - case DW_FORM_block4: return "DW_FORM_block4"; - case DW_FORM_data2: return "DW_FORM_data2"; - case DW_FORM_data4: return "DW_FORM_data4"; - case DW_FORM_data8: return "DW_FORM_data8"; - case DW_FORM_string: return "DW_FORM_string"; - case DW_FORM_block: return "DW_FORM_block"; - case DW_FORM_block1: return "DW_FORM_block1"; - case DW_FORM_data1: return "DW_FORM_data1"; - case DW_FORM_flag: return "DW_FORM_flag"; - case DW_FORM_sdata: return "DW_FORM_sdata"; - case DW_FORM_strp: return "DW_FORM_strp"; - case DW_FORM_udata: return "DW_FORM_udata"; - case DW_FORM_ref_addr: return "DW_FORM_ref_addr"; - case DW_FORM_ref1: return "DW_FORM_ref1"; - case DW_FORM_ref2: return "DW_FORM_ref2"; - case DW_FORM_ref4: return "DW_FORM_ref4"; - case DW_FORM_ref8: return "DW_FORM_ref8"; - case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; - case DW_FORM_indirect: return "DW_FORM_indirect"; + case DW_FORM_addr: return "DW_FORM_addr"; + case DW_FORM_block2: return "DW_FORM_block2"; + case DW_FORM_block4: return "DW_FORM_block4"; + case DW_FORM_data2: return "DW_FORM_data2"; + case DW_FORM_data4: return "DW_FORM_data4"; + case DW_FORM_data8: return "DW_FORM_data8"; + case DW_FORM_string: return "DW_FORM_string"; + case DW_FORM_block: return "DW_FORM_block"; + case DW_FORM_block1: return "DW_FORM_block1"; + case DW_FORM_data1: return "DW_FORM_data1"; + case DW_FORM_flag: return "DW_FORM_flag"; + case DW_FORM_sdata: return "DW_FORM_sdata"; + case DW_FORM_strp: return "DW_FORM_strp"; + case DW_FORM_udata: return "DW_FORM_udata"; + case DW_FORM_ref_addr: return "DW_FORM_ref_addr"; + case DW_FORM_ref1: return "DW_FORM_ref1"; + case DW_FORM_ref2: return "DW_FORM_ref2"; + case DW_FORM_ref4: return "DW_FORM_ref4"; + case DW_FORM_ref8: return "DW_FORM_ref8"; + case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; + case DW_FORM_indirect: return "DW_FORM_indirect"; default: { - static char buffer [100]; + static char buffer[100]; sprintf (buffer, _("Unknown FORM value: %lx"), form); return buffer; @@ -6789,44 +6865,44 @@ 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 { - unsigned long attribute; - unsigned long form; - struct abbrev_attr * next; + unsigned long attribute; + unsigned long form; + struct abbrev_attr *next; } abbrev_attr; typedef struct abbrev_entry { - unsigned long entry; - unsigned long tag; - int children; - struct abbrev_attr * first_attr; - struct abbrev_attr * last_attr; - struct abbrev_entry * next; + unsigned long entry; + unsigned long tag; + int children; + struct abbrev_attr *first_attr; + struct abbrev_attr *last_attr; + struct abbrev_entry *next; } abbrev_entry; -static abbrev_entry * first_abbrev = NULL; -static abbrev_entry * last_abbrev = NULL; +static abbrev_entry *first_abbrev = NULL; +static abbrev_entry *last_abbrev = NULL; static void -free_abbrevs PARAMS ((void)) +free_abbrevs (void) { - abbrev_entry * abbrev; + abbrev_entry *abbrev; for (abbrev = first_abbrev; abbrev;) { - abbrev_entry * next = abbrev->next; - abbrev_attr * attr; + abbrev_entry *next = abbrev->next; + abbrev_attr *attr; for (attr = abbrev->first_attr; attr;) { - abbrev_attr * next = attr->next; + abbrev_attr *next = attr->next; free (attr); attr = next; @@ -6840,14 +6916,11 @@ free_abbrevs PARAMS ((void)) } 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; + abbrev_entry *entry; - entry = (abbrev_entry *) malloc (sizeof (* entry)); + entry = malloc (sizeof (*entry)); if (entry == NULL) /* ugg */ @@ -6869,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; + abbrev_attr *attr; - attr = (abbrev_attr *) malloc (sizeof (* attr)); + attr = malloc (sizeof (*attr)); if (attr == NULL) /* ugg */ @@ -6899,20 +6970,18 @@ 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; while (start < end) { - int bytes_read; + int bytes_read; unsigned long entry; unsigned long tag; unsigned long attribute; - int children; + int children; entry = read_leb128 (start, & bytes_read, 0); start += bytes_read; @@ -6926,7 +6995,7 @@ process_abbrev_section (start, end) tag = read_leb128 (start, & bytes_read, 0); start += bytes_read; - children = * start ++; + children = *start++; add_abbrev (entry, tag, children); @@ -6951,13 +7020,12 @@ process_abbrev_section (start, end) static int -display_debug_macinfo (section, start, file) - Elf32_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; + unsigned char *end = start + section->sh_size; + unsigned char *curr = start; unsigned int bytes_read; enum dwarf_macinfo_record_type op; @@ -6966,10 +7034,10 @@ display_debug_macinfo (section, start, file) while (curr < end) { unsigned int lineno; - const char * string; + const char *string; - op = * curr; - curr ++; + op = *curr; + curr++; switch (op) { @@ -7025,13 +7093,12 @@ display_debug_macinfo (section, start, file) static int -display_debug_abbrev (section, start, file) - Elf32_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; + abbrev_entry *entry; + unsigned char *end = start + section->sh_size; printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); @@ -7046,7 +7113,7 @@ display_debug_abbrev (section, start, file) for (entry = first_abbrev; entry; entry = entry->next) { - abbrev_attr * attr; + abbrev_attr *attr; printf (_(" %ld %s [%s]\n"), entry->entry, @@ -7072,32 +7139,29 @@ 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); while (length --) - printf ("%lx ", (unsigned long) byte_get (data ++, 1)); + printf ("%lx ", (unsigned long) byte_get (data++, 1)); return data; } 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; - unsigned long uvalue; - unsigned char * end = data + length; + unsigned op; + int bytes_read; + unsigned long uvalue; + unsigned char *end = data + length; while (data < end) { - op = * data ++; + op = *data++; switch (op) { @@ -7412,19 +7476,19 @@ decode_location_expression (data, pointer_size, length) } /* Separate the ops. */ - printf ("; "); + if (data < end) + printf ("; "); } } -static const char * debug_loc_contents; -static bfd_vma debug_loc_size; +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) { - Elf32_Internal_Shdr * sec; - unsigned int i; + Elf_Internal_Shdr *sec; + unsigned int i; /* If it is already loaded, do nothing. */ if (debug_loc_contents != NULL) @@ -7433,7 +7497,7 @@ load_debug_loc (file) /* Locate the .debug_loc section. */ for (i = 0, sec = section_headers; i < elf_header.e_shnum; - i ++, sec ++) + i++, sec++) if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0) break; @@ -7442,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; @@ -7460,10 +7523,9 @@ free_debug_loc () static int -display_debug_loc (section, start, file) - Elf32_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; @@ -7494,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); @@ -7509,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; @@ -7526,15 +7591,14 @@ display_debug_loc (section, start, file) return 1; } -static const char * debug_str_contents; -static bfd_vma debug_str_size; +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) { - Elf32_Internal_Shdr * sec; - unsigned int i; + Elf_Internal_Shdr *sec; + unsigned int i; /* If it is already loaded, do nothing. */ if (debug_str_contents != NULL) @@ -7543,7 +7607,7 @@ load_debug_str (file) /* Locate the .debug_str section. */ for (i = 0, sec = section_headers; i < elf_header.e_shnum; - i ++, sec ++) + i++, sec++) if (strcmp (SECTION_NAME (sec), ".debug_str") == 0) break; @@ -7552,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; @@ -7569,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 _(""); @@ -7582,13 +7644,12 @@ fetch_indirect_string (offset) } static int -display_debug_str (section, start, file) - Elf32_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; + unsigned long bytes; + bfd_vma addr; addr = section->sh_addr; bytes = section->sh_size; @@ -7614,7 +7675,7 @@ display_debug_str (section, start, file) for (j = 0; j < 16; j++) { if (j < lbytes) - printf ("%2.2x", start [j]); + printf ("%2.2x", start[j]); else printf (" "); @@ -7624,7 +7685,7 @@ display_debug_str (section, start, file) for (j = 0; j < lbytes; j++) { - k = start [j]; + k = start[j]; if (k >= ' ' && k < 0x80) printf ("%c", k); else @@ -7642,16 +7703,17 @@ 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; - int bytes_read; + unsigned long uvalue = 0; + unsigned char *block_start = NULL; + int bytes_read; switch (form) { @@ -7659,20 +7721,36 @@ 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: case DW_FORM_flag: case DW_FORM_data1: - uvalue = byte_get (data ++, 1); + uvalue = byte_get (data++, 1); break; case DW_FORM_ref2: @@ -7703,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) @@ -7782,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"); @@ -7791,51 +7870,65 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) case DW_AT_inline: switch (uvalue) { - case DW_INL_not_inlined: printf (_("(not inlined)")); break; - case DW_INL_inlined: printf (_("(inlined)")); break; - case DW_INL_declared_not_inlined: printf (_("(declared as inline but ignored)")); break; - case DW_INL_declared_inlined: printf (_("(declared as inline and inlined)")); break; - default: printf (_(" (Unknown inline attribute value: %lx)"), uvalue); break; + case DW_INL_not_inlined: + printf (_("(not inlined)")); + break; + case DW_INL_inlined: + printf (_("(inlined)")); + break; + case DW_INL_declared_not_inlined: + printf (_("(declared as inline but ignored)")); + break; + case DW_INL_declared_inlined: + printf (_("(declared as inline and inlined)")); + break; + default: + printf (_(" (Unknown inline attribute value: %lx)"), uvalue); + break; } break; case DW_AT_language: switch (uvalue) { - case DW_LANG_C: printf ("(non-ANSI C)"); break; - case DW_LANG_C89: printf ("(ANSI C)"); break; - case DW_LANG_C_plus_plus: printf ("(C++)"); break; - case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break; - case DW_LANG_Fortran90: printf ("(Fortran 90)"); break; - case DW_LANG_Modula2: printf ("(Modula 2)"); break; - case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break; - case DW_LANG_Ada83: printf ("(Ada)"); break; - case DW_LANG_Cobol74: printf ("(Cobol 74)"); break; - case DW_LANG_Cobol85: printf ("(Cobol 85)"); break; - /* DWARF 2.1 values. */ - case DW_LANG_C99: printf ("(ANSI C99)"); break; - case DW_LANG_Ada95: printf ("(ADA 95)"); break; - case DW_LANG_Fortran95: printf ("(Fortran 95)"); break; + case DW_LANG_C: printf ("(non-ANSI C)"); break; + case DW_LANG_C89: printf ("(ANSI C)"); break; + case DW_LANG_C_plus_plus: printf ("(C++)"); break; + case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break; + case DW_LANG_Fortran90: printf ("(Fortran 90)"); break; + case DW_LANG_Modula2: printf ("(Modula 2)"); break; + case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break; + case DW_LANG_Ada83: printf ("(Ada)"); break; + case DW_LANG_Cobol74: printf ("(Cobol 74)"); break; + case DW_LANG_Cobol85: printf ("(Cobol 85)"); break; + /* DWARF 2.1 values. */ + case DW_LANG_C99: printf ("(ANSI C99)"); break; + case DW_LANG_Ada95: printf ("(ADA 95)"); break; + case DW_LANG_Fortran95: printf ("(Fortran 95)"); break; /* MIPS extension. */ - case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break; - default: printf ("(Unknown: %lx)", uvalue); break; + case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break; + /* UPC extension. */ + case DW_LANG_Upc: printf ("(Unified Parallel C)"); break; + default: + printf ("(Unknown: %lx)", uvalue); + break; } break; case DW_AT_encoding: switch (uvalue) { - case DW_ATE_void: printf ("(void)"); break; - case DW_ATE_address: printf ("(machine address)"); break; - case DW_ATE_boolean: printf ("(boolean)"); break; - case DW_ATE_complex_float: printf ("(complex float)"); break; - case DW_ATE_float: printf ("(float)"); break; - case DW_ATE_signed: printf ("(signed)"); break; - case DW_ATE_signed_char: printf ("(signed char)"); break; - case DW_ATE_unsigned: printf ("(unsigned)"); break; - case DW_ATE_unsigned_char: printf ("(unsigned char)"); break; + case DW_ATE_void: printf ("(void)"); break; + case DW_ATE_address: printf ("(machine address)"); break; + case DW_ATE_boolean: printf ("(boolean)"); break; + case DW_ATE_complex_float: printf ("(complex float)"); break; + case DW_ATE_float: printf ("(float)"); break; + case DW_ATE_signed: printf ("(signed)"); break; + case DW_ATE_signed_char: printf ("(signed char)"); break; + case DW_ATE_unsigned: printf ("(unsigned)"); break; + case DW_ATE_unsigned_char: printf ("(unsigned char)"); break; /* DWARF 2.1 value. */ - case DW_ATE_imaginary_float: printf ("(imaginary float)"); break; + case DW_ATE_imaginary_float: printf ("(imaginary float)"); break; default: if (uvalue >= DW_ATE_lo_user && uvalue <= DW_ATE_hi_user) @@ -7852,17 +7945,19 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) case DW_ACCESS_public: printf ("(public)"); break; case DW_ACCESS_protected: printf ("(protected)"); break; case DW_ACCESS_private: printf ("(private)"); break; - default: printf ("(unknown accessibility)"); break; + default: + printf ("(unknown accessibility)"); + break; } break; case DW_AT_visibility: switch (uvalue) { - case DW_VIS_local: printf ("(local)"); break; - case DW_VIS_exported: printf ("(exported)"); break; - case DW_VIS_qualified: printf ("(qualified)"); break; - default: printf ("(unknown visibility)"); break; + case DW_VIS_local: printf ("(local)"); break; + case DW_VIS_exported: printf ("(exported)"); break; + case DW_VIS_qualified: printf ("(qualified)"); break; + default: printf ("(unknown visibility)"); break; } break; @@ -7872,7 +7967,7 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) case DW_VIRTUALITY_none: printf ("(none)"); break; case DW_VIRTUALITY_virtual: printf ("(virtual)"); break; case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break; - default: printf ("(unknown virtuality)"); break; + default: printf ("(unknown virtuality)"); break; } break; @@ -7883,7 +7978,7 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size) case DW_ID_up_case: printf ("(up_case)"); break; case DW_ID_down_case: printf ("(down_case)"); break; case DW_ID_case_insensitive: printf ("(case_insensitive)"); break; - default: printf ("(unknown case)"); break; + default: printf ("(unknown case)"); break; } break; @@ -7927,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"); @@ -7943,28 +8038,28 @@ 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) - Elf32_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; + unsigned char *end = start + section->sh_size; + unsigned char *section_begin = start; printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); @@ -7973,36 +8068,46 @@ display_debug_info (section, start, file) while (start < end) { - DWARF2_External_CompUnit * external; - DWARF2_Internal_CompUnit compunit; - Elf32_Internal_Shdr * relsec; - unsigned char * tags; - unsigned int i; - int level; - unsigned long cu_offset; + 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; } - /* Check for RELA relocations in the - abbrev_offset address, and apply them. */ + compunit.cu_version = byte_get (hdrptr, 2); + hdrptr += 2; + + /* Apply addends of RELA relocations. */ for (relsec = section_headers; relsec < section_headers + elf_header.e_shnum; ++relsec) { unsigned long nrelas; Elf_Internal_Rela *rela, *rp; - Elf32_Internal_Shdr *symsec; + Elf_Internal_Shdr *symsec; Elf_Internal_Sym *symtab; Elf_Internal_Sym *sym; @@ -8020,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) @@ -8050,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); @@ -8068,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; } @@ -8078,13 +8193,13 @@ display_debug_info (section, start, file) /* Read in the abbrevs used by this compilation unit. */ { - Elf32_Internal_Shdr * sec; - unsigned char * begin; + Elf_Internal_Shdr *sec; + unsigned char *begin; /* Locate the .debug_abbrev section and process it. */ for (i = 0, sec = section_headers; i < elf_header.e_shnum; - i ++, sec ++) + i++, sec++) if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0) break; @@ -8094,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; @@ -8109,10 +8223,10 @@ display_debug_info (section, start, file) level = 0; while (tags < start) { - int bytes_read; - unsigned long abbrev_number; - abbrev_entry * entry; - abbrev_attr * attr; + int bytes_read; + unsigned long abbrev_number; + abbrev_entry *entry; + abbrev_attr *attr; abbrev_number = read_leb128 (tags, & bytes_read, 0); tags += bytes_read; @@ -8148,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; @@ -8164,41 +8280,58 @@ display_debug_info (section, start, file) } static int -display_debug_aranges (section, start, file) - Elf32_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; + unsigned char *end = start + section->sh_size; printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); while (start < end) { - DWARF2_External_ARange * external; - DWARF2_Internal_ARange arange; - unsigned char * ranges; - unsigned long length; - unsigned long address; - int excess; + 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; } @@ -8210,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; @@ -8234,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"); @@ -8244,21 +8377,22 @@ display_debug_aranges (section, start, file) typedef struct Frame_Chunk { - struct Frame_Chunk * next; - unsigned char * chunk_start; - int ncols; + struct Frame_Chunk *next; + unsigned char *chunk_start; + int ncols; /* DW_CFA_{undefined,same_value,offset,register,unreferenced} */ - short int * col_type; - int * col_offset; - char * augmentation; - unsigned int code_factor; - int data_factor; - unsigned long pc_begin; - unsigned long pc_range; - int cfa_reg; - int cfa_offset; - int ra; - unsigned char fde_encoding; + short int *col_type; + int *col_offset; + char *augmentation; + unsigned int code_factor; + int data_factor; + unsigned long pc_begin; + unsigned long pc_range; + int cfa_reg; + int cfa_offset; + int ra; + unsigned char fde_encoding; + unsigned char cfa_exp; } Frame_Chunk; @@ -8266,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; @@ -8281,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) { @@ -8295,24 +8421,21 @@ 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]; - if (* max_regs < fc->ncols) - * max_regs = fc->ncols; + if (*max_regs < fc->ncols) + *max_regs = fc->ncols; - if (* need_col_headers) + if (*need_col_headers) { - * need_col_headers = 0; + *need_col_headers = 0; printf (" LOC CFA "); - for (r = 0; r < * max_regs; r++) + for (r = 0; r < *max_regs; r++) if (fc->col_type[r] != DW_CFA_unreferenced) { if (r == fc->ra) @@ -8325,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++) @@ -8346,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; @@ -8357,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) { @@ -8370,40 +8498,51 @@ 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) - Elf32_Internal_Shdr * section; - unsigned char * start; - FILE * file ATTRIBUTE_UNUSED; -{ - unsigned char * end = start + section->sh_size; - unsigned char * section_start = start; - Frame_Chunk * chunks = 0; - Frame_Chunk * remembered_state = 0; - Frame_Chunk * rs; - int is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0); - int length_return; - int max_regs = 0; - int addr_size = is_32bit_elf ? 4 : 8; +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; + Frame_Chunk *chunks = 0; + Frame_Chunk *remembered_state = 0; + Frame_Chunk *rs; + int is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0); + int length_return; + int max_regs = 0; + int addr_size = is_32bit_elf ? 4 : 8; printf (_("The section %s contains:\n"), SECTION_NAME (section)); while (start < end) { - unsigned char * saved_start; - unsigned char * block_end; - unsigned long length; - unsigned long cie_id; - Frame_Chunk * fc; - Frame_Chunk * cie; - int need_col_headers = 1; - unsigned char * augmentation_data = NULL; - unsigned long augmentation_data_len = 0; - int encoded_ptr_size = addr_size; + unsigned char *saved_start; + unsigned char *block_end; + unsigned long length; + unsigned long cie_id; + Frame_Chunk *fc; + Frame_Chunk *cie; + int need_col_headers = 1; + 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; @@ -8417,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++; @@ -8521,7 +8667,7 @@ display_debug_frames (section, start, file) } else { - unsigned char * look_for; + unsigned char *look_for; static Frame_Chunk fde_fc; fc = & fde_fc; @@ -8539,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 = ""; @@ -8549,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; @@ -8566,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; @@ -8597,19 +8743,23 @@ 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. */ - unsigned char * tmp = start; + unsigned char *tmp = start; while (start < block_end) { unsigned op, opa; - unsigned long reg; + unsigned long reg, tmp; - op = * start ++; + op = *start++; opa = op & 0x3f; if (op & 0xc0) op &= 0xc0; @@ -8675,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); @@ -8686,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; @@ -8711,7 +8875,7 @@ display_debug_frames (section, start, file) long l, ofs; bfd_vma vma; - op = * start ++; + op = *start++; opa = op & 0x3f; if (op & 0xc0) op &= 0xc0; @@ -8747,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; @@ -8829,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; @@ -8837,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; @@ -8863,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); @@ -8870,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; @@ -8885,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 (); @@ -8899,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); @@ -8910,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"); @@ -8932,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; @@ -8965,10 +9157,9 @@ display_debug_frames (section, start, file) #undef SLEB static int -display_debug_not_supported (section, start, file) - Elf32_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)); @@ -8980,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) - Elf32_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: - external = (DWARF2_External_CompUnit *) start; + unit_length: 12 bytes + version: 2 bytes + debug_abbrev_offset: 8 bytes + ----------------------------- + Total: 22 bytes */ - debug_line_pointer_size = BYTE_GET (external->cu_pointer_size); + debug_line_pointer_size = byte_get (start + 22, 1); + } + else + { + /* For 32-bit DWARF, the 1-byte address_size field is 10 bytes from + the start of the section: + unit_length: 4 bytes + version: 2 bytes + debug_abbrev_offset: 4 bytes + ----------------------------- + Total: 10 bytes */ + + debug_line_pointer_size = byte_get (start + 10, 1); + } return 0; } @@ -8999,39 +9219,37 @@ prescan_debug_info (section, start, file) sections. */ struct { - const char * const name; - int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); - int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); + const char *const name; + int (*display) (Elf_Internal_Shdr *, unsigned char *, FILE *); + int (*prescan) (Elf_Internal_Shdr *, unsigned char *, FILE *); } debug_displays[] = { - { ".debug_abbrev", display_debug_abbrev, NULL }, - { ".debug_aranges", display_debug_aranges, NULL }, - { ".debug_frame", display_debug_frames, NULL }, - { ".debug_info", display_debug_info, prescan_debug_info }, - { ".debug_line", display_debug_lines, NULL }, - { ".debug_pubnames", display_debug_pubnames, NULL }, - { ".eh_frame", display_debug_frames, NULL }, - { ".debug_macinfo", display_debug_macinfo, NULL }, - { ".debug_str", display_debug_str, NULL }, - { ".debug_loc", display_debug_loc, NULL }, - { ".debug_pubtypes", display_debug_not_supported, NULL }, - { ".debug_ranges", display_debug_not_supported, NULL }, - { ".debug_static_func", display_debug_not_supported, NULL }, - { ".debug_static_vars", display_debug_not_supported, NULL }, - { ".debug_types", display_debug_not_supported, NULL }, - { ".debug_weaknames", display_debug_not_supported, NULL } + { ".debug_abbrev", display_debug_abbrev, NULL }, + { ".debug_aranges", display_debug_aranges, NULL }, + { ".debug_frame", display_debug_frames, NULL }, + { ".debug_info", display_debug_info, prescan_debug_info }, + { ".debug_line", display_debug_lines, NULL }, + { ".debug_pubnames", display_debug_pubnames, NULL }, + { ".eh_frame", display_debug_frames, NULL }, + { ".debug_macinfo", display_debug_macinfo, NULL }, + { ".debug_str", display_debug_str, NULL }, + { ".debug_loc", display_debug_loc, NULL }, + { ".debug_pubtypes", display_debug_not_supported, NULL }, + { ".debug_ranges", display_debug_not_supported, NULL }, + { ".debug_static_func", display_debug_not_supported, NULL }, + { ".debug_static_vars", display_debug_not_supported, NULL }, + { ".debug_types", display_debug_not_supported, NULL }, + { ".debug_weaknames", display_debug_not_supported, NULL } }; static int -display_debug_section (section, file) - Elf32_Internal_Shdr * section; - FILE * file; +display_debug_section (Elf_Internal_Shdr *section, FILE *file) { - char * name = SECTION_NAME (section); - bfd_size_type length; - unsigned char * start; - int i; + char *name = SECTION_NAME (section); + bfd_size_type length; + unsigned char *start; + int i; length = section->sh_size; if (length == 0) @@ -9040,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; @@ -9069,11 +9287,10 @@ display_debug_section (section, file) } static int -process_section_contents (file) - FILE * file; +process_section_contents (FILE *file) { - Elf32_Internal_Shdr * section; - unsigned int i; + Elf_Internal_Shdr *section; + unsigned int i; if (! do_dump) return 1; @@ -9083,10 +9300,10 @@ process_section_contents (file) size of address (specified in .debug_info and .debug_aranges). */ for (i = 0, section = section_headers; i < elf_header.e_shnum && i < num_dump_sects; - i ++, section ++) + i++, section++) { - char * name = SECTION_NAME (section); - int j; + char *name = SECTION_NAME (section); + int j; if (section->sh_size == 0) continue; @@ -9097,13 +9314,12 @@ process_section_contents (file) { if (debug_displays[j].prescan != NULL) { - bfd_size_type length; - unsigned char * start; + bfd_size_type length; + unsigned char *start; length = section->sh_size; - start = ((unsigned char *) - get_data (NULL, file, section->sh_offset, length, - _("debug section data"))); + start = get_data (NULL, file, section->sh_offset, length, + _("debug section data")); if (!start) return 0; @@ -9117,7 +9333,7 @@ process_section_contents (file) for (i = 0, section = section_headers; i < elf_header.e_shnum && i < num_dump_sects; - i ++, section ++) + i++, section++) { #ifdef SUPPORT_DISASSEMBLY if (dump_sects[i] & DISASS_DUMP) @@ -9137,8 +9353,7 @@ process_section_contents (file) } static void -process_mips_fpe_exception (mask) - int mask; +process_mips_fpe_exception (int mask) { if (mask) { @@ -9159,10 +9374,9 @@ process_mips_fpe_exception (mask) } static int -process_mips_specific (file) - FILE * file; +process_mips_specific (FILE *file) { - Elf_Internal_Dyn * entry; + Elf_Internal_Dyn *entry; size_t liblist_offset = 0; size_t liblistno = 0; size_t conflictsno = 0; @@ -9178,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; @@ -9198,13 +9416,12 @@ process_mips_specific (file) if (liblist_offset != 0 && liblistno != 0 && do_dynamic) { - Elf32_External_Lib * elib; + 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", @@ -9217,7 +9434,7 @@ process_mips_specific (file) Elf32_Lib liblist; time_t time; char timebuf[20]; - struct tm * tmp; + struct tm *tmp; liblist.l_name = BYTE_GET (elib[cnt].l_name); time = BYTE_GET (elib[cnt].l_time_stamp); @@ -9241,7 +9458,7 @@ process_mips_specific (file) { static const struct { - const char * name; + const char *name; int bit; } l_flags_vals[] = @@ -9277,23 +9494,22 @@ process_mips_specific (file) if (options_offset != 0) { - Elf_External_Options * eopt; - Elf_Internal_Shdr * sect = section_headers; - Elf_Internal_Options * iopt; - Elf_Internal_Options * option; + Elf_External_Options *eopt; + Elf_Internal_Shdr *sect = section_headers; + Elf_Internal_Options *iopt; + Elf_Internal_Options *option; size_t offset; int cnt; /* Find the section header so that we get the size. */ while (sect->sh_type != SHT_MIPS_OPTIONS) - ++ sect; + ++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")); @@ -9305,7 +9521,7 @@ process_mips_specific (file) while (offset < sect->sh_size) { - Elf_External_Options * eoption; + Elf_External_Options *eoption; eoption = (Elf_External_Options *) ((char *) eopt + offset); @@ -9340,8 +9556,8 @@ process_mips_specific (file) if (elf_header.e_machine == EM_MIPS) { /* 32bit form. */ - Elf32_External_RegInfo * ereg; - Elf32_RegInfo reginfo; + Elf32_External_RegInfo *ereg; + Elf32_RegInfo reginfo; ereg = (Elf32_External_RegInfo *) (option + 1); reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); @@ -9361,7 +9577,7 @@ process_mips_specific (file) else { /* 64 bit form. */ - Elf64_External_RegInfo * ereg; + Elf64_External_RegInfo *ereg; Elf64_Internal_RegInfo reginfo; ereg = (Elf64_External_RegInfo *) (option + 1); @@ -9458,7 +9674,7 @@ process_mips_specific (file) break; } - len = sizeof (* eopt); + len = sizeof (*eopt); while (len < option->size) if (((char *) option)[len] >= ' ' && ((char *) option)[len] < 0x7f) @@ -9476,7 +9692,7 @@ process_mips_specific (file) if (conflicts_offset != 0 && conflictsno != 0) { - Elf32_Conflict * iconf; + Elf32_Conflict *iconf; size_t cnt; if (dynamic_symbols == NULL) @@ -9485,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")); @@ -9494,12 +9710,10 @@ process_mips_specific (file) if (is_32bit_elf) { - Elf32_External_Conflict * econf32; + 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; @@ -9510,12 +9724,10 @@ process_mips_specific (file) } else { - Elf64_External_Conflict * econf64; + 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; @@ -9531,9 +9743,9 @@ process_mips_specific (file) for (cnt = 0; cnt < conflictsno; ++cnt) { - Elf_Internal_Sym * psym = & dynamic_symbols [iconf [cnt]]; + Elf_Internal_Sym *psym = & dynamic_symbols[iconf[cnt]]; - printf ("%5lu: %8lu ", (unsigned long) cnt, iconf [cnt]); + printf ("%5lu: %8lu ", (unsigned long) cnt, iconf[cnt]); print_vma (psym->st_value, FULL_HEX); putchar (' '); print_symbol (25, dynamic_strings + psym->st_name); @@ -9547,12 +9759,11 @@ 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; - char * strtab; + Elf_Internal_Shdr *section, *string_sec; + Elf32_External_Lib *elib; + char *strtab; size_t cnt; unsigned i; @@ -9561,22 +9772,20 @@ process_gnu_liblist (file) for (i = 0, section = section_headers; i < elf_header.e_shnum; - i++, section ++) + i++, section++) { 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)) @@ -9597,7 +9806,7 @@ process_gnu_liblist (file) Elf32_Lib liblist; time_t time; char timebuf[20]; - struct tm * tmp; + struct tm *tmp; liblist.l_name = BYTE_GET (elib[cnt].l_name); time = BYTE_GET (elib[cnt].l_time_stamp); @@ -9627,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]; @@ -9636,9 +9844,9 @@ get_note_type (e_type) { case NT_PRSTATUS: return _("NT_PRSTATUS (prstatus structure)"); case NT_FPREGSET: return _("NT_FPREGSET (floating point registers)"); - case NT_PRPSINFO: return _("NT_PRPSINFO (prpsinfo structure)"); - case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)"); - case NT_PRXFPREG: return _("NT_PRXFPREG (user_xfpregs structure)"); + case NT_PRPSINFO: return _("NT_PRPSINFO (prpsinfo structure)"); + case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)"); + case NT_PRXFPREG: return _("NT_PRXFPREG (user_xfpregs structure)"); case NT_PSTATUS: return _("NT_PSTATUS (pstatus structure)"); case NT_FPREGS: return _("NT_FPREGS (floating point registers)"); case NT_PSINFO: return _("NT_PSINFO (psinfo structure)"); @@ -9652,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]; @@ -9719,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) - Elf32_Internal_Note * pnote; +process_note (Elf_Internal_Note *pnote) { const char *nt; @@ -9750,20 +9956,16 @@ 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; - int res = 1; + Elf_External_Note *pnotes; + Elf_External_Note *external; + int res = 1; 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; @@ -9775,9 +9977,9 @@ process_corefile_note_segment (file, offset, length) while (external < (Elf_External_Note *)((char *) pnotes + length)) { - Elf_External_Note * next; - Elf32_Internal_Note inote; - char * temp = NULL; + Elf_External_Note *next; + Elf_Internal_Note inote; + char *temp = NULL; inote.type = BYTE_GET (external->type); inote.namesz = BYTE_GET (external->namesz); @@ -9836,37 +10038,18 @@ 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); + Elf_Internal_Phdr *segment; + unsigned int i; + int res = 1; - if (i == 0) - { - free (program_headers); + if (! get_program_headers (file)) return 0; - } for (i = 0, segment = program_headers; i < elf_header.e_phnum; - i ++, segment ++) + i++, segment++) { if (segment->p_type == PT_NOTE) res &= process_corefile_note_segment (file, @@ -9874,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) @@ -9902,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; @@ -9921,24 +10100,29 @@ 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) return 0; /* Determine how to read the rest of the header. */ - switch (elf_header.e_ident [EI_DATA]) + switch (elf_header.e_ident[EI_DATA]) { 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. */ - is_32bit_elf = (elf_header.e_ident [EI_CLASS] != ELFCLASS64); + is_32bit_elf = (elf_header.e_ident[EI_CLASS] != ELFCLASS64); /* Read in the rest of the header. */ if (is_32bit_elf) @@ -9969,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\ @@ -10008,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; } @@ -10048,16 +10219,20 @@ process_file (file_name) printf (_("\nFile: %s\n"), file_name); if (! process_file_header ()) - { - fclose (file); - return 1; - } + return 1; - process_section_headers (file); + if (! process_section_headers (file)) + { + /* Without loaded section headers we + cannot process lots of things. */ + do_unwind = do_version = do_dump = do_arch = 0; - process_program_headers (file); + if (! do_using_dynamic) + do_syms = do_reloc = 0; + } - process_dynamic_segment (file); + if (process_program_headers (file)) + process_dynamic_segment (file); process_relocs (file); @@ -10077,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) { @@ -10114,13 +10293,237 @@ 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 symbols. */ void -print_address (unsigned int addr, FILE * outfile) +print_address (unsigned int addr, FILE *outfile) { fprintf (outfile,"0x%8.8x", addr); } @@ -10133,14 +10536,12 @@ 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; + unsigned num_cmdline_dump_sects = 0; #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) setlocale (LC_MESSAGES, ""); @@ -10156,12 +10557,38 @@ main (argc, argv) if (optind < (argc - 1)) show_name = 1; + /* When processing more than one file remember the dump requests + issued on command line to reset them after each file. */ + if (optind + 1 < argc && dump_sects != NULL) + { + cmdline_dump_sects = malloc (num_dump_sects); + if (cmdline_dump_sects == NULL) + error (_("Out of memory allocating dump request table.")); + else + { + memcpy (cmdline_dump_sects, dump_sects, num_dump_sects); + num_cmdline_dump_sects = num_dump_sects; + } + } + err = 0; while (optind < argc) - err |= process_file (argv [optind ++]); + { + err |= process_file (argv[optind++]); + + /* Reset dump requests. */ + if (optind < argc && dump_sects != NULL) + { + num_dump_sects = num_cmdline_dump_sects; + if (num_cmdline_dump_sects > 0) + memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects); + } + } if (dump_sects != NULL) free (dump_sects); + if (cmdline_dump_sects != NULL) + free (cmdline_dump_sects); return err; }