X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=4ec5ec09e4250550d352a072a4b354c67567e98f;hb=e0c60db2304c4c0db3f666d0d41b18a1406f68fc;hp=152ce1e937f81a44c0a083888436e80808810806;hpb=12ff5d5690066cac0467274b17afc1fbabaa04a4;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index 152ce1e937..4ec5ec09e4 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1,8 +1,8 @@ /* readelf.c -- display contents of an ELF format file - Copyright (C) 1998, 99, 2000 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Originally developed by Eric Youngdale - Modifications by Nick Clifton + Modifications by Nick Clifton This file is part of GNU Binutils. @@ -70,39 +70,46 @@ #include "elf/i960.h" #include "elf/pj.h" #include "elf/avr.h" +#include "elf/ia64.h" +#include "elf/cris.h" +#include "elf/i860.h" +#include "elf/x86-64.h" +#include "elf/s390.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 * 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_Sym * dynamic_symbols; Elf_Internal_Syminfo * dynamic_syminfo; -unsigned long dynamic_syminfo_offset; +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; +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; -int show_name; -int do_dynamic; -int do_syms; -int do_reloc; -int do_sections; -int do_segments; -int do_using_dynamic; -int do_header; -int do_dump; -int do_version; +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_histogram; int do_debugging; int do_debug_info; @@ -110,6 +117,9 @@ 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_arch; int do_notes; int is_32bit_elf; @@ -144,6 +154,8 @@ static const char * get_mips_dynamic_type PARAMS ((unsigned long)); static const char * get_sparc64_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)); @@ -151,20 +163,23 @@ 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 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 *)); @@ -181,19 +196,22 @@ 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 *, unsigned long, unsigned long)); static Elf_Internal_Sym * get_64bit_elf_symbols PARAMS ((FILE *, unsigned long, unsigned long)); +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 *)); +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 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 display_debug_lines 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 unsigned char * process_abbrev_section PARAMS ((unsigned char *, unsigned char *)); static unsigned long read_leb128 PARAMS ((unsigned char *, int *, int)); static int process_extended_line_op PARAMS ((unsigned char *, int, int)); @@ -212,11 +230,11 @@ static const char * get_elf_class PARAMS ((unsigned char)); static const char * get_data_encoding PARAMS ((unsigned char)); static const char * get_osabi_name PARAMS ((unsigned char)); static int guess_is_rela PARAMS ((unsigned long)); -static char * get_note_type PARAMS ((unsigned int)); +static char * get_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_corefile_contents PARAMS ((FILE *)); typedef int Elf32_Word; @@ -226,63 +244,29 @@ typedef int Elf32_Word; #endif #define UNKNOWN -1 -#define SECTION_NAME(X) (string_table + (X)->sh_name) +#define SECTION_NAME(X) ((X) == NULL ? "" : \ + ((X)->sh_name >= string_table_length \ + ? "" : string_table + (X)->sh_name)) #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ -#define BYTE_GET(field) byte_get (field, sizeof (field)) +#define BYTE_GET(field) byte_get (field, sizeof (field)) /* If we can support a 64 bit data type then BFD64 should be defined and sizeof (bfd_vma) == 8. In this case when translating from an external 8 byte field to an internal field, we can assume that the - internal field is also 8 bytes wide and so we can extact all the data. + internal field is also 8 bytes wide and so we can extract all the data. If, however, BFD64 is not defined, then we must assume that the internal data structure only has 4 byte wide fields that are the equivalent of the 8 byte wide external counterparts, and so we must truncate the data. */ #ifdef BFD64 -#define BYTE_GET8(field) byte_get (field, -8) +#define BYTE_GET8(field) byte_get (field, -8) #else -#define BYTE_GET8(field) byte_get (field, 8) +#define BYTE_GET8(field) byte_get (field, 8) #endif -#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0])) - -#define GET_DATA_ALLOC(offset, size, var, type, reason) \ - if (fseek (file, offset, SEEK_SET)) \ - { \ - error (_("Unable to seek to start of %s at %x\n"), reason, offset); \ - return 0; \ - } \ - \ - var = (type) malloc (size); \ - \ - if (var == NULL) \ - { \ - error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \ - return 0; \ - } \ - \ - if (fread (var, size, 1, file) != 1) \ - { \ - error (_("Unable to read in %d bytes of %s\n"), size, reason); \ - free (var); \ - var = NULL; \ - return 0; \ - } - - -#define GET_DATA(offset, var, reason) \ - if (fseek (file, offset, SEEK_SET)) \ - { \ - error (_("Unable to seek to %x for %s\n"), offset, reason); \ - return 0; \ - } \ - else if (fread (& var, sizeof (var), 1, file) != 1) \ - { \ - error (_("Unable to read data at %x for %s\n"), offset, reason); \ - return 0; \ - } +#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0])) #define GET_ELF_SYMBOLS(file, offset, size) \ (is_32bit_elf ? get_32bit_elf_symbols (file, offset, size) \ @@ -345,6 +329,51 @@ warn (va_alist) } #endif +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; +{ + PTR mvar; + + if (size == 0) + return NULL; + + if (fseek (file, offset, SEEK_SET)) + { + error (_("Unable to seek to %x for %s\n"), offset, reason); + return NULL; + } + + mvar = var; + if (mvar == NULL) + { + mvar = (PTR) malloc (size); + + if (mvar == NULL) + { + error (_("Out of memory allocating %d bytes for %s\n"), + size, reason); + return NULL; + } + } + + if (fread (mvar, size, 1, file) != 1) + { + error (_("Unable to read in %d bytes of %s\n"), size, reason); + if (mvar != var) + free (mvar); + return NULL; + } + + return mvar; +} + static bfd_vma byte_get_little_endian (field, size) unsigned char * field; @@ -359,11 +388,13 @@ byte_get_little_endian (field, size) return ((unsigned int) (field [0])) | (((unsigned int) (field [1])) << 8); +#ifndef BFD64 case 8: /* We want to extract data from an 8 byte wide field and place it into a 4 byte wide field. Since this is a little endian source we can juts use the 4 byte extraction code. */ /* Fall through. */ +#endif case 4: return ((unsigned long) (field [0])) | (((unsigned long) (field [1])) << 8) @@ -371,6 +402,7 @@ byte_get_little_endian (field, size) | (((unsigned long) (field [3])) << 24); #ifdef BFD64 + 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 @@ -420,15 +452,15 @@ print_vma (vma, mode) case FULL_HEX: printf ("0x"); /* drop through */ - + case LONG_HEX: printf_vma (vma); break; - + case PREFIX_HEX: printf ("0x"); /* drop through */ - + case HEX: #if BFD_HOST_64BIT_LONG printf ("%lx", vma); @@ -449,7 +481,7 @@ print_vma (vma, mode) printf ("++%ld", _bfd_int64_low (vma)); else printf ("%ld", _bfd_int64_low (vma)); -#endif +#endif break; case DEC_5: @@ -461,13 +493,13 @@ print_vma (vma, mode) printf ("++%ld", _bfd_int64_low (vma)); else printf ("%5ld", _bfd_int64_low (vma)); -#endif +#endif break; - + case UNSIGNED: #if BFD_HOST_64BIT_LONG printf ("%lu", vma); -#else +#else if (_bfd_int64_high (vma)) /* ugg */ printf ("++%lu", _bfd_int64_low (vma)); @@ -499,6 +531,7 @@ byte_get_big_endian (field, size) | (((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. */ @@ -506,8 +539,8 @@ byte_get_big_endian (field, size) | (((unsigned long) (field [6])) << 8) | (((unsigned long) (field [5])) << 16) | (((unsigned long) (field [4])) << 24); - -#ifdef BFD64 +#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 @@ -529,8 +562,8 @@ byte_get_big_endian (field, size) } } +/* Guess the relocation size commonly used by the specific machines. */ -/* Guess the relocation sized based on the sized commonly used by the specific machine. */ static int guess_is_rela (e_machine) unsigned long e_machine; @@ -545,7 +578,7 @@ guess_is_rela (e_machine) case EM_CYGNUS_M32R: case EM_CYGNUS_D10V: case EM_MIPS: - case EM_MIPS_RS4_BE: + case EM_MIPS_RS3_LE: return FALSE; /* Targets that use RELA relocations. */ @@ -562,6 +595,13 @@ guess_is_rela (e_machine) case EM_SH: case EM_ALPHA: case EM_MCORE: + case EM_IA_64: + case EM_AVR: + case EM_CRIS: + case EM_860: + case EM_X86_64: + case EM_S390: + case EM_S390_OLD: return TRUE; case EM_MMA: @@ -588,144 +628,180 @@ guess_is_rela (e_machine) } } -/* 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; +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; { - unsigned int i; - Elf_Internal_Rel * rels; - Elf_Internal_Rela * relas; + Elf_Internal_Rela *relas; + unsigned long nrelas; + unsigned int i; + if (is_32bit_elf) + { + Elf32_External_Rela * erelas; - if (is_rela == UNKNOWN) - is_rela = guess_is_rela (elf_header.e_machine); + erelas = (Elf32_External_Rela *) get_data (NULL, file, rel_offset, + rel_size, _("relocs")); + if (!erelas) + return 0; - if (is_rela) - { - if (is_32bit_elf) - { - Elf32_External_Rela * erelas; + nrelas = rel_size / sizeof (Elf32_External_Rela); - GET_DATA_ALLOC (rel_offset, rel_size, erelas, - Elf32_External_Rela *, "relocs"); + relas = (Elf_Internal_Rela *) + malloc (nrelas * sizeof (Elf_Internal_Rela)); - rel_size = rel_size / sizeof (Elf32_External_Rela); + if (relas == NULL) + { + error(_("out of memory parsing relocs")); + return 0; + } - relas = (Elf_Internal_Rela *) - malloc (rel_size * sizeof (Elf_Internal_Rela)); + for (i = 0; i < nrelas; i++) + { + relas[i].r_offset = BYTE_GET (erelas[i].r_offset); + relas[i].r_info = BYTE_GET (erelas[i].r_info); + relas[i].r_addend = BYTE_GET (erelas[i].r_addend); + } - if (relas == NULL) - { - error(_("out of memory parsing relocs")); - return 0; - } + free (erelas); + } + else + { + Elf64_External_Rela * erelas; - for (i = 0; i < rel_size; i++) - { - relas[i].r_offset = BYTE_GET (erelas[i].r_offset); - relas[i].r_info = BYTE_GET (erelas[i].r_info); - relas[i].r_addend = BYTE_GET (erelas[i].r_addend); - } + erelas = (Elf64_External_Rela *) get_data (NULL, file, rel_offset, + rel_size, _("relocs")); + if (!erelas) + return 0; + + nrelas = rel_size / sizeof (Elf64_External_Rela); - free (erelas); + relas = (Elf_Internal_Rela *) + malloc (nrelas * sizeof (Elf_Internal_Rela)); - rels = (Elf_Internal_Rel *) relas; + if (relas == NULL) + { + error(_("out of memory parsing relocs")); + return 0; } - else + + for (i = 0; i < nrelas; i++) { - Elf64_External_Rela * erelas; + relas[i].r_offset = BYTE_GET8 (erelas[i].r_offset); + relas[i].r_info = BYTE_GET8 (erelas[i].r_info); + relas[i].r_addend = BYTE_GET8 (erelas[i].r_addend); + } + + free (erelas); + } + *relasp = relas; + *nrelasp = nrelas; + return 1; +} - GET_DATA_ALLOC (rel_offset, rel_size, erelas, - Elf64_External_Rela *, "relocs"); +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; + unsigned long nrels; + unsigned int i; - rel_size = rel_size / sizeof (Elf64_External_Rela); + if (is_32bit_elf) + { + Elf32_External_Rel * erels; - relas = (Elf_Internal_Rela *) - malloc (rel_size * sizeof (Elf_Internal_Rela)); + erels = (Elf32_External_Rel *) get_data (NULL, file, rel_offset, + rel_size, _("relocs")); + if (!erels) + return 0; - if (relas == NULL) - { - error(_("out of memory parsing relocs")); - return 0; - } + nrels = rel_size / sizeof (Elf32_External_Rel); - for (i = 0; i < rel_size; i++) - { - relas[i].r_offset = BYTE_GET8 (erelas[i].r_offset); - relas[i].r_info = BYTE_GET8 (erelas[i].r_info); - relas[i].r_addend = BYTE_GET8 (erelas[i].r_addend); - } + rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel)); - free (erelas); + if (rels == NULL) + { + error(_("out of memory parsing relocs")); + return 0; + } - rels = (Elf_Internal_Rel *) relas; + for (i = 0; i < nrels; i++) + { + rels[i].r_offset = BYTE_GET (erels[i].r_offset); + rels[i].r_info = BYTE_GET (erels[i].r_info); } + + free (erels); } else { - if (is_32bit_elf) - { - Elf32_External_Rel * erels; - - GET_DATA_ALLOC (rel_offset, rel_size, erels, - Elf32_External_Rel *, "relocs"); + Elf64_External_Rel * erels; - rel_size = rel_size / sizeof (Elf32_External_Rel); - - rels = (Elf_Internal_Rel *) - malloc (rel_size * sizeof (Elf_Internal_Rel)); - - if (rels == NULL) - { - error(_("out of memory parsing relocs")); - return 0; - } + erels = (Elf64_External_Rel *) get_data (NULL, file, rel_offset, + rel_size, _("relocs")); + if (!erels) + return 0; - for (i = 0; i < rel_size; i++) - { - rels[i].r_offset = BYTE_GET (erels[i].r_offset); - rels[i].r_info = BYTE_GET (erels[i].r_info); - } + nrels = rel_size / sizeof (Elf64_External_Rel); - free (erels); + rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel)); - relas = (Elf_Internal_Rela *) rels; - } - else + if (rels == NULL) { - Elf64_External_Rel * erels; - - GET_DATA_ALLOC (rel_offset, rel_size, erels, - Elf64_External_Rel *, "relocs"); + error(_("out of memory parsing relocs")); + return 0; + } - rel_size = rel_size / sizeof (Elf64_External_Rel); + for (i = 0; i < nrels; i++) + { + rels[i].r_offset = BYTE_GET8 (erels[i].r_offset); + rels[i].r_info = BYTE_GET8 (erels[i].r_info); + } - rels = (Elf_Internal_Rel *) - malloc (rel_size * sizeof (Elf_Internal_Rel)); + free (erels); + } + *relsp = rels; + *nrelsp = nrels; + return 1; +} - if (rels == NULL) - { - error(_("out of memory parsing relocs")); - return 0; - } +/* 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; +{ + unsigned int i; + Elf_Internal_Rel * rels; + Elf_Internal_Rela * relas; - for (i = 0; i < rel_size; i++) - { - rels[i].r_offset = BYTE_GET8 (erels[i].r_offset); - rels[i].r_info = BYTE_GET8 (erels[i].r_info); - } - free (erels); + if (is_rela == UNKNOWN) + is_rela = guess_is_rela (elf_header.e_machine); - relas = (Elf_Internal_Rela *) rels; - } + if (is_rela) + { + if (!slurp_rela_relocs (file, rel_offset, rel_size, &relas, &rel_size)) + return 0; + } + else + { + if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size)) + return 0; } if (is_rela) @@ -850,7 +926,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) break; case EM_MIPS: - case EM_MIPS_RS4_BE: + case EM_MIPS_RS3_LE: rtype = elf_mips_reloc_type (type); break; @@ -863,6 +939,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) break; case EM_CYGNUS_ARC: + case EM_ARC: rtype = elf_arc_reloc_type (type); break; @@ -873,6 +950,26 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) case EM_PJ: rtype = elf_pj_reloc_type (type); break; + case EM_IA_64: + rtype = elf_ia64_reloc_type (type); + break; + + case EM_CRIS: + rtype = elf_cris_reloc_type (type); + break; + + case EM_860: + rtype = elf_i860_reloc_type (type); + break; + + case EM_X86_64: + rtype = elf_x86_64_reloc_type (type); + break; + + case EM_S390_OLD: + case EM_S390: + rtype = elf_s390_reloc_type (type); + break; } if (rtype == NULL) @@ -886,31 +983,28 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) if (symtab_index) { - if (symtab != NULL) + if (symtab == NULL || symtab_index >= nsyms) + printf (" bad symbol index: %08lx", (unsigned long) symtab_index); + else { - if (symtab_index >= nsyms) - printf (" bad symbol index: %08lx", (unsigned long) symtab_index); - else - { - Elf_Internal_Sym * psym; + Elf_Internal_Sym * psym; - psym = symtab + symtab_index; + psym = symtab + symtab_index; - printf (" "); - print_vma (psym->st_value, LONG_HEX); - printf (" "); + printf (" "); + print_vma (psym->st_value, LONG_HEX); + printf (" "); - if (psym->st_name == 0) - printf ("%-25.25s", - SECTION_NAME (section_headers + psym->st_shndx)); - else if (strtab == NULL) - printf (_(""), psym->st_name); - else - printf ("%-25.25s", strtab + psym->st_name); + if (psym->st_name == 0) + printf ("%-25.25s", + SECTION_NAME (section_headers + psym->st_shndx)); + else if (strtab == NULL) + printf (_(""), psym->st_name); + else + printf ("%-25.25s", strtab + psym->st_name); - if (is_rela) - printf (" + %lx", (unsigned long) relas [i].r_addend); - } + if (is_rela) + printf (" + %lx", (unsigned long) relas [i].r_addend); } } else if (is_rela) @@ -926,7 +1020,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) putchar ('\n'); } - free (relas); + if (is_rela) + free (relas); + else + free (rels); return 1; } @@ -1064,15 +1161,21 @@ get_dynamic_type (type) case DT_PREINIT_ARRAY: return "PREINIT_ARRAY"; case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; + case DT_CHECKSUM: return "CHECKSUM"; case DT_PLTPADSZ: return "PLTPADSZ"; case DT_MOVEENT: return "MOVEENT"; case DT_MOVESZ: return "MOVESZ"; - case DT_FEATURE_1: return "FEATURE_1"; + case DT_FEATURE: return "FEATURE"; case DT_POSFLAG_1: return "POSFLAG_1"; case DT_SYMINSZ: return "SYMINSZ"; case DT_SYMINENT: return "SYMINENT"; /* aka VALRNGHI */ case DT_ADDRRNGLO: return "ADDRRNGLO"; + case DT_CONFIG: return "CONFIG"; + case DT_DEPAUDIT: return "DEPAUDIT"; + case DT_AUDIT: return "AUDIT"; + case DT_PLTPAD: return "PLTPAD"; + case DT_MOVETAB: return "MOVETAB"; case DT_SYMINFO: return "SYMINFO"; /* aka ADDRRNGHI */ case DT_VERSYM: return "VERSYM"; @@ -1085,7 +1188,7 @@ get_dynamic_type (type) case DT_VERNEED: return "VERNEED"; case DT_VERNEEDNUM: return "VERNEEDNUM"; - case DT_AUXILIARY: return "AUXILARY"; + case DT_AUXILIARY: return "AUXILIARY"; case DT_USED: return "USED"; case DT_FILTER: return "FILTER"; @@ -1097,7 +1200,7 @@ get_dynamic_type (type) switch (elf_header.e_machine) { case EM_MIPS: - case EM_MIPS_RS4_BE: + case EM_MIPS_RS3_LE: result = get_mips_dynamic_type (type); break; case EM_SPARCV9: @@ -1172,33 +1275,33 @@ get_machine_name (e_machine) switch (e_machine) { - case EM_NONE: return _("None"); - case EM_M32: return "WE32100"; - case EM_SPARC: return "Sparc"; - case EM_386: return "Intel 80386"; - case EM_68K: return "MC68000"; - case EM_88K: return "MC88000"; - case EM_486: return "Intel 80486"; - case EM_860: return "Intel 80860"; - case EM_MIPS: return "MIPS R3000"; - case EM_S370: return "IBM System/370"; - case EM_MIPS_RS4_BE: return "MIPS R4000 big-endian"; + case EM_NONE: return _("None"); + case EM_M32: return "WE32100"; + case EM_SPARC: return "Sparc"; + case EM_386: return "Intel 80386"; + case EM_68K: return "MC68000"; + case EM_88K: return "MC88000"; + case EM_486: return "Intel 80486"; + case EM_860: return "Intel 80860"; + case EM_MIPS: return "MIPS R3000"; + case EM_S370: return "IBM System/370"; + case EM_MIPS_RS3_LE: return "MIPS R4000 big-endian"; case EM_OLD_SPARCV9: return "Sparc v9 (old)"; - case EM_PARISC: return "HPPA"; + case EM_PARISC: return "HPPA"; case EM_PPC_OLD: return "Power PC (old)"; - case EM_SPARC32PLUS: return "Sparc v8+" ; - case EM_960: return "Intel 90860"; - case EM_PPC: return "PowerPC"; - case EM_V800: return "NEC V800"; - case EM_FR20: return "Fujitsu FR20"; - case EM_RH32: return "TRW RH32"; + case EM_SPARC32PLUS: return "Sparc v8+" ; + case EM_960: return "Intel 90860"; + case EM_PPC: return "PowerPC"; + 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_ARM: return "ARM"; - case EM_OLD_ALPHA: return "Digital Alpha (old)"; - case EM_SH: return "Hitachi SH"; - case EM_SPARCV9: return "Sparc v9"; - case EM_TRICORE: return "Siemens Tricore"; - case EM_ARC: return "Argonaut RISC Core"; + case EM_ARM: return "ARM"; + case EM_OLD_ALPHA: return "Digital Alpha (old)"; + case EM_SH: return "Hitachi 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"; @@ -1207,35 +1310,45 @@ get_machine_name (e_machine) case EM_MIPS_X: return "Stanford MIPS-X"; case EM_COLDFIRE: return "Motorola Coldfire"; case EM_68HC12: return "Motorola M68HC12"; - case EM_ALPHA: return "Alpha"; + case EM_ALPHA: return "Alpha"; case EM_CYGNUS_D10V: return "d10v"; case EM_CYGNUS_D30V: return "d30v"; - case EM_CYGNUS_ARC: return "Arc"; + case EM_CYGNUS_ARC: return "ARC"; case EM_CYGNUS_M32R: return "Mitsubishi M32r"; case EM_CYGNUS_V850: return "NEC v850"; case EM_CYGNUS_MN10300: return "mn10300"; case EM_CYGNUS_MN10200: return "mn10200"; case EM_CYGNUS_FR30: return "Fujitsu FR30"; 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"; - case EM_NDR1: return "Denso NDR1 microprocesspr"; - case EM_STARCORE: return "Motorola Star*Core processor"; - case EM_ME16: return "Toyota ME16 processor"; - case EM_ST100: return "STMicroelectronics ST100 processor"; - case EM_TINYJ: return "Advanced Logic Corp. TinyJ embedded processor"; - case EM_FX66: return "Siemens FX66 microcontroller"; - case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 bit microcontroller"; - case EM_ST7: return "STMicroelectronics ST7 8-bit microcontroller"; - case EM_68HC16: return "Motorola MC68HC16 Microcontroller"; - case EM_68HC11: return "Motorola MC68HC11 Microcontroller"; - case EM_68HC08: return "Motorola MC68HC08 Microcontroller"; - case EM_68HC05: return "Motorola MC68HC05 Microcontroller"; - case EM_SVX: return "Silicon Graphics SVx"; - case EM_ST19: return "STMicroelectronics ST19 8-bit microcontroller"; - case EM_VAX: return "Digital VAX"; - case EM_AVR: return "AVR"; + case EM_MMA: return "Fujitsu Multimedia Accelerator"; + case EM_PCP: return "Siemens PCP"; + case EM_NCPU: return "Sony nCPU embedded RISC processor"; + case EM_NDR1: return "Denso NDR1 microprocesspr"; + case EM_STARCORE: return "Motorola Star*Core processor"; + case EM_ME16: return "Toyota ME16 processor"; + case EM_ST100: return "STMicroelectronics ST100 processor"; + case EM_TINYJ: return "Advanced Logic Corp. TinyJ embedded processor"; + case EM_FX66: return "Siemens FX66 microcontroller"; + case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 bit microcontroller"; + case EM_ST7: return "STMicroelectronics ST7 8-bit microcontroller"; + case EM_68HC16: return "Motorola MC68HC16 Microcontroller"; + case EM_68HC11: return "Motorola MC68HC11 Microcontroller"; + case EM_68HC08: return "Motorola MC68HC08 Microcontroller"; + case EM_68HC05: return "Motorola MC68HC05 Microcontroller"; + case EM_SVX: return "Silicon Graphics SVx"; + case EM_ST19: return "STMicroelectronics ST19 8-bit microcontroller"; + case EM_VAX: return "Digital VAX"; + 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_HUANY: return "Harvard Universitys's machine-independent object format"; + case EM_PRISM: return "SiTera Prism"; + case EM_X86_64: return "Advanced Micro Devices X86-64"; + case EM_S390_OLD: + case EM_S390: return "IBM S/390"; default: sprintf (buff, _(": %x"), e_machine); return buff; @@ -1259,87 +1372,120 @@ decode_ARM_machine_flags (e_flags, buf) strcat (buf, ", relocatable executable"); e_flags &= ~ EF_ARM_RELEXEC; } - + if (e_flags & EF_ARM_HASENTRY) { strcat (buf, ", has entry point"); e_flags &= ~ EF_ARM_HASENTRY; } - + /* Now handle EABI specific flags. */ switch (eabi) { default: - strcat (buf, ", "); + strcat (buf, ", "); if (e_flags) unknown = 1; break; case EF_ARM_EABI_VER1: + strcat (buf, ", Version1 EABI"); + while (e_flags) + { + unsigned flag; + + /* Process flags one bit at a time. */ + flag = e_flags & - e_flags; + e_flags &= ~ flag; + + switch (flag) + { + case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK. */ + strcat (buf, ", sorted symbol tables"); + break; + + default: + unknown = 1; + break; + } + } + break; + + case EF_ARM_EABI_VER2: + strcat (buf, ", Version2 EABI"); while (e_flags) { unsigned flag; - + /* Process flags one bit at a time. */ flag = e_flags & - e_flags; e_flags &= ~ flag; - + switch (flag) { - case EF_ARM_SYMSARESORTED: /* Conflicts with EF_INTERWORK. */ + case EF_ARM_SYMSARESORTED: /* Conflicts with EF_ARM_INTERWORK. */ strcat (buf, ", sorted symbol tables"); break; - + + case EF_ARM_DYNSYMSUSESEGIDX: + strcat (buf, ", dynamic symbols use segment index"); + break; + + case EF_ARM_MAPSYMSFIRST: + strcat (buf, ", mapping symbols precede others"); + break; + default: unknown = 1; break; } } break; - + case EF_ARM_EABI_UNKNOWN: + strcat (buf, ", GNU EABI"); while (e_flags) { unsigned flag; - + /* Process flags one bit at a time. */ flag = e_flags & - e_flags; e_flags &= ~ flag; - + switch (flag) { - case EF_INTERWORK: + case EF_ARM_INTERWORK: strcat (buf, ", interworking enabled"); break; - - case EF_APCS_26: + + case EF_ARM_APCS_26: strcat (buf, ", uses APCS/26"); break; - - case EF_APCS_FLOAT: + + case EF_ARM_APCS_FLOAT: strcat (buf, ", uses APCS/float"); break; - - case EF_PIC: + + case EF_ARM_PIC: strcat (buf, ", position independent"); break; - - case EF_ALIGN8: + + case EF_ARM_ALIGN8: strcat (buf, ", 8 bit structure alignment"); break; - - case EF_NEW_ABI: + + case EF_ARM_NEW_ABI: strcat (buf, ", uses new ABI"); break; - - case EF_OLD_ABI: + + case EF_ARM_OLD_ABI: strcat (buf, ", uses old ABI"); break; - - case EF_SOFT_FLOAT: + + case EF_ARM_SOFT_FLOAT: strcat (buf, ", software FP"); break; - + default: unknown = 1; break; @@ -1359,7 +1505,7 @@ get_machine_flags (e_flags, e_machine) static char buf [1024]; buf[0] = '\0'; - + if (e_flags) { switch (e_machine) @@ -1370,7 +1516,7 @@ get_machine_flags (e_flags, e_machine) case EM_ARM: decode_ARM_machine_flags (e_flags, buf); break; - + case EM_68K: if (e_flags & EF_CPU32) strcat (buf, ", cpu32"); @@ -1412,7 +1558,7 @@ get_machine_flags (e_flags, e_machine) break; case EM_MIPS: - case EM_MIPS_RS4_BE: + case EM_MIPS_RS3_LE: if (e_flags & EF_MIPS_NOREORDER) strcat (buf, ", noreorder"); @@ -1436,6 +1582,27 @@ get_machine_flags (e_flags, e_machine) if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4) strcat (buf, ", mips4"); + + if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_5) + strcat (buf, ", mips5"); + + if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32) + strcat (buf, ", mips32"); + + if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64) + strcat (buf, ", mips64"); + + switch ((e_flags & EF_MIPS_MACH)) + { + case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break; + case E_MIPS_MACH_4010: strcat (buf, ", 4010"); break; + case E_MIPS_MACH_4100: strcat (buf, ", 4100"); break; + case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break; + case E_MIPS_MACH_4111: strcat (buf, ", 4111"); break; + case E_MIPS_MACH_MIPS32_4K: strcat (buf, ", mips32-4k"); break; + case E_MIPS_MACH_SB1: strcat (buf, ", sb1"); break; + default: strcat (buf, " UNKNOWN"); break; + } break; case EM_SPARCV9: @@ -1492,7 +1659,7 @@ get_machine_flags (e_flags, e_machine) if (e_flags & EF_PARISC_LAZYSWAP) strcat (buf, ", lazyswap"); break; - + case EM_PJ: if ((e_flags & EF_PICOJAVA_NEWCALLS) == EF_PICOJAVA_NEWCALLS) strcat (buf, ", new calling convention"); @@ -1500,6 +1667,21 @@ get_machine_flags (e_flags, e_machine) if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS) strcat (buf, ", gnu calling convention"); break; + + case EM_IA_64: + if ((e_flags & EF_IA_64_ABI64)) + strcat (buf, ", 64-bit"); + else + strcat (buf, ", 32-bit"); + if ((e_flags & EF_IA_64_REDUCEDFP)) + strcat (buf, ", reduced fp model"); + if ((e_flags & EF_IA_64_NOFUNCDESC_CONS_GP)) + strcat (buf, ", no function descriptors, constant gp"); + else if ((e_flags & EF_IA_64_CONS_GP)) + strcat (buf, ", constant gp"); + if ((e_flags & EF_IA_64_ABSOLUTE)) + strcat (buf, ", absolute"); + break; } } @@ -1552,6 +1734,21 @@ get_parisc_segment_type (type) return NULL; } +static const char * +get_ia64_segment_type (type) + unsigned long type; +{ + switch (type) + { + case PT_IA_64_ARCHEXT: return "IA_64_ARCHEXT"; + case PT_IA_64_UNWIND: return "IA_64_UNWIND"; + default: + break; + } + + return NULL; +} + static const char * get_segment_type (p_type) unsigned long p_type; @@ -1576,12 +1773,15 @@ get_segment_type (p_type) switch (elf_header.e_machine) { case EM_MIPS: - case EM_MIPS_RS4_BE: + case EM_MIPS_RS3_LE: result = get_mips_segment_type (p_type); break; case EM_PARISC: result = get_parisc_segment_type (p_type); break; + case EM_IA_64: + result = get_ia64_segment_type (p_type); + break; default: result = NULL; break; @@ -1684,6 +1884,20 @@ get_parisc_section_type_name (sh_type) return NULL; } +static const char * +get_ia64_section_type_name (sh_type) + unsigned int sh_type; +{ + switch (sh_type) + { + case SHT_IA_64_EXT: return "IA_64_EXT"; + case SHT_IA_64_UNWIND: return "IA_64_UNWIND"; + default: + break; + } + return NULL; +} + static const char * get_section_type_name (sh_type) unsigned int sh_type; @@ -1707,6 +1921,8 @@ get_section_type_name (sh_type) case SHT_INIT_ARRAY: return "INIT_ARRAY"; case SHT_FINI_ARRAY: return "FINI_ARRAY"; case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY"; + case SHT_GROUP: return "GROUP"; + case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICIES"; case SHT_GNU_verdef: return "VERDEF"; case SHT_GNU_verneed: return "VERNEED"; case SHT_GNU_versym: return "VERSYM"; @@ -1723,12 +1939,15 @@ get_section_type_name (sh_type) switch (elf_header.e_machine) { case EM_MIPS: - case EM_MIPS_RS4_BE: + case EM_MIPS_RS3_LE: result = get_mips_section_type_name (sh_type); break; case EM_PARISC: result = get_parisc_section_type_name (sh_type); break; + case EM_IA_64: + result = get_ia64_section_type_name (sh_type); + break; default: result = NULL; break; @@ -1770,6 +1989,7 @@ struct option options [] = {"use-dynamic", no_argument, 0, 'D'}, {"hex-dump", required_argument, 0, 'x'}, {"debug-dump", optional_argument, 0, 'w'}, + {"unwind", no_argument, 0, 'u'}, #ifdef SUPPORT_DISASSEMBLY {"instruction-dump", required_argument, 0, 'i'}, #endif @@ -1794,13 +2014,14 @@ usage () fprintf (stdout, _(" -s or --syms or --symbols Display the symbol table\n")); fprintf (stdout, _(" -n or --notes Display the core notes (if present)\n")); fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n")); + fprintf (stdout, _(" -u or --unwind Display the unwind info (if present)\n")); fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (if present)\n")); fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n")); fprintf (stdout, _(" -A or --arch-specific Display architecture specific information (if any).\n")); fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n")); fprintf (stdout, _(" -x or --hex-dump=\n")); fprintf (stdout, _(" Dump the contents of section \n")); - fprintf (stdout, _(" -w[liapr] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges]\n")); + fprintf (stdout, _(" -w[liaprmf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames]\n")); fprintf (stdout, _(" Display the contents of DWARF2 debug sections\n")); #ifdef SUPPORT_DISASSEMBLY fprintf (stdout, _(" -i or --instruction-dump=\n")); @@ -1856,7 +2077,7 @@ parse_args (argc, argv) usage (); while ((c = getopt_long - (argc, argv, "ersahnldSDAIw::x:i:vV", options, NULL)) != EOF) + (argc, argv, "ersuahnldSDAIw::x:i:vV", options, NULL)) != EOF) { char * cp; int section; @@ -1873,6 +2094,7 @@ parse_args (argc, argv) case 'a': do_syms ++; do_reloc ++; + do_unwind ++; do_dynamic ++; do_header ++; do_sections ++; @@ -1896,6 +2118,9 @@ parse_args (argc, argv) case 'r': do_reloc ++; break; + case 'u': + do_unwind ++; + break; case 'h': do_header ++; break; @@ -1960,6 +2185,17 @@ parse_args (argc, argv) do_debug_aranges = 1; break; + case 'F': + do_debug_frames_interp = 1; + case 'f': + do_debug_frames = 1; + break; + + case 'm': + case 'M': + do_debug_macinfo = 1; + break; + default: warn (_("Unrecognised debug option '%s'\n"), optarg); break; @@ -1993,7 +2229,7 @@ parse_args (argc, argv) } } - if (!do_dynamic && !do_syms && !do_reloc && !do_sections + if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections && !do_segments && !do_header && !do_dump && !do_version && !do_histogram && !do_debugging && !do_arch && !do_notes) usage (); @@ -2046,9 +2282,18 @@ get_osabi_name (osabi) switch (osabi) { - case ELFOSABI_SYSV: return _("UNIX - System V"); + 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: @@ -2101,7 +2346,7 @@ process_file_header () get_machine_name (elf_header.e_machine)); printf (_(" Version: 0x%lx\n"), (unsigned long) elf_header.e_version); - + printf (_(" Entry point address: ")); print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX); printf (_("\n Start of program headers: ")); @@ -2109,7 +2354,7 @@ process_file_header () printf (_(" (bytes into file)\n Start of section headers: ")); print_vma ((bfd_vma) elf_header.e_shoff, DEC); printf (_(" (bytes into file)\n")); - + printf (_(" Flags: 0x%lx%s\n"), (unsigned long) elf_header.e_flags, get_machine_flags (elf_header.e_flags, elf_header.e_machine)); @@ -2141,9 +2386,12 @@ get_32bit_program_headers (file, program_headers) Elf32_Internal_Phdr * internal; unsigned int i; - GET_DATA_ALLOC (elf_header.e_phoff, - elf_header.e_phentsize * elf_header.e_phnum, - phdrs, Elf32_External_Phdr *, "program headers"); + phdrs = ((Elf32_External_Phdr *) + 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; @@ -2174,9 +2422,12 @@ get_64bit_program_headers (file, program_headers) Elf64_Internal_Phdr * internal; unsigned int i; - GET_DATA_ALLOC (elf_header.e_phoff, - elf_header.e_phentsize * elf_header.e_phnum, - phdrs, Elf64_External_Phdr *, "program headers"); + phdrs = ((Elf64_External_Phdr *) + 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; @@ -2247,7 +2498,7 @@ process_program_headers (file) { printf (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : ""); - + if (is_32bit_elf) printf (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n")); @@ -2395,9 +2646,12 @@ get_32bit_section_headers (file) Elf32_Internal_Shdr * internal; unsigned int i; - GET_DATA_ALLOC (elf_header.e_shoff, - elf_header.e_shentsize * elf_header.e_shnum, - shdrs, Elf32_External_Shdr *, "section headers"); + shdrs = ((Elf32_External_Shdr *) + get_data (NULL, file, elf_header.e_shoff, + elf_header.e_shentsize * elf_header.e_shnum, + _("section headers"))); + if (!shdrs) + return 0; section_headers = (Elf_Internal_Shdr *) malloc (elf_header.e_shnum * sizeof (Elf_Internal_Shdr)); @@ -2437,9 +2691,12 @@ get_64bit_section_headers (file) Elf64_Internal_Shdr * internal; unsigned int i; - GET_DATA_ALLOC (elf_header.e_shoff, - elf_header.e_shentsize * elf_header.e_shnum, - shdrs, Elf64_External_Shdr *, "section headers"); + shdrs = ((Elf64_External_Shdr *) + get_data (NULL, file, elf_header.e_shoff, + elf_header.e_shentsize * elf_header.e_shnum, + _("section headers"))); + if (!shdrs) + return 0; section_headers = (Elf_Internal_Shdr *) malloc (elf_header.e_shnum * sizeof (Elf_Internal_Shdr)); @@ -2482,8 +2739,11 @@ get_32bit_elf_symbols (file, offset, number) Elf_Internal_Sym * psym; unsigned int j; - GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym), - esyms, Elf32_External_Sym *, "symbols"); + esyms = ((Elf32_External_Sym *) + get_data (NULL, file, offset, + number * sizeof (Elf32_External_Sym), _("symbols"))); + if (!esyms) + return NULL; isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); @@ -2523,8 +2783,11 @@ get_64bit_elf_symbols (file, offset, number) Elf_Internal_Sym * psym; unsigned int j; - GET_DATA_ALLOC (offset, number * sizeof (Elf64_External_Sym), - esyms, Elf64_External_Sym *, "symbols"); + esyms = ((Elf64_External_Sym *) + get_data (NULL, file, offset, + number * sizeof (Elf64_External_Sym), _("symbols"))); + if (!esyms) + return NULL; isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); @@ -2560,14 +2823,14 @@ get_elf_section_flags (sh_flags) static char buff [32]; * buff = 0; - + while (sh_flags) { bfd_vma flag; flag = sh_flags & - sh_flags; sh_flags &= ~ flag; - + switch (flag) { case SHF_WRITE: strcat (buff, "W"); break; @@ -2578,7 +2841,8 @@ get_elf_section_flags (sh_flags) 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; + default: if (flag & SHF_MASKOS) { @@ -2595,7 +2859,7 @@ get_elf_section_flags (sh_flags) break; } } - + return buff; } @@ -2633,12 +2897,10 @@ process_section_headers (file) if (section->sh_size != 0) { - unsigned long string_table_offset; - - string_table_offset = section->sh_offset; + string_table = (char *) get_data (NULL, file, section->sh_offset, + section->sh_size, _("string table")); - GET_DATA_ALLOC (section->sh_offset, section->sh_size, - string_table, char *, "string table"); + string_table_length = section->sh_size; } /* Scan the sections for the dynamic symbol table @@ -2674,11 +2936,13 @@ process_section_headers (file) continue; } - GET_DATA_ALLOC (section->sh_offset, section->sh_size, - dynamic_strings, char *, "dynamic strings"); + dynamic_strings = (char *) get_data (NULL, file, section->sh_offset, + section->sh_size, + _("dynamic strings")); } else if ((do_debugging || do_debug_info || do_debug_abbrevs - || do_debug_lines || do_debug_pubnames || do_debug_aranges) + || do_debug_lines || do_debug_pubnames || do_debug_aranges + || do_debug_frames || do_debug_macinfo) && strncmp (name, ".debug_", 7) == 0) { name += 7; @@ -2689,16 +2953,24 @@ process_section_headers (file) || (do_debug_lines && (strcmp (name, "line") == 0)) || (do_debug_pubnames && (strcmp (name, "pubnames") == 0)) || (do_debug_aranges && (strcmp (name, "aranges") == 0)) + || (do_debug_frames && (strcmp (name, "frame") == 0)) + || (do_debug_macinfo && (strcmp (name, "macinfo") == 0)) ) request_dump (i, DEBUG_DUMP); } + /* linkonce section to be combined with .debug_info at link time. */ + else if ((do_debugging || do_debug_info) + && strncmp (name, ".gnu.linkonce.wi.", 17) == 0) + request_dump (i, DEBUG_DUMP); + else if (do_debug_frames && strcmp (name, ".eh_frame") == 0) + request_dump (i, DEBUG_DUMP); } if (! do_sections) return 1; printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : ""); - + if (is_32bit_elf) printf (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n")); @@ -2720,15 +2992,15 @@ process_section_headers (file) if (is_32bit_elf) { print_vma (section->sh_addr, LONG_HEX); - + printf ( " %6.6lx %6.6lx %2.2lx", (unsigned long) section->sh_offset, (unsigned long) section->sh_size, (unsigned long) section->sh_entsize); printf (" %3s ", get_elf_section_flags (section->sh_flags)); - - printf (" %2ld %3lx %ld\n", + + printf ("%2ld %3lx %2ld\n", (unsigned long) section->sh_link, (unsigned long) section->sh_info, (unsigned long) section->sh_addralign); @@ -2742,9 +3014,9 @@ process_section_headers (file) print_vma (section->sh_size, LONG_HEX); printf (" "); print_vma (section->sh_entsize, LONG_HEX); - + printf (" %3s ", get_elf_section_flags (section->sh_flags)); - + printf (" %2ld %3lx %ld\n", (unsigned long) section->sh_link, (unsigned long) section->sh_info, @@ -2752,9 +3024,10 @@ process_section_headers (file) } } - printf (_("Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings)\n")); - printf (_(" I (info), L (link order), O (extra OS processing required)\n")); - printf (_(" o (os specific), p (processor specific) x (unknown)\n")); + printf (_("Key to Flags:\n")); + printf (_(" W (write), A (alloc), X (execute), M (merge), S (strings)\n")); + printf (_(" I (info), L (link order), G (group), x (unknown)\n")); + printf (_(" O (extra OS processing required) o (OS specific), p (processor specific)\n")); return 1; } @@ -2824,8 +3097,8 @@ process_relocs (file) else { Elf32_Internal_Shdr * section; - unsigned long i; - int found = 0; + unsigned long i; + int found = 0; for (i = 0, section = section_headers; i < elf_header.e_shnum; @@ -2841,7 +3114,6 @@ process_relocs (file) if (rel_size) { Elf32_Internal_Shdr * strsec; - Elf32_Internal_Shdr * symsec; Elf_Internal_Sym * symtab; char * strtab; int is_rela; @@ -2857,25 +3129,35 @@ process_relocs (file) printf (_(" at offset 0x%lx contains %lu entries:\n"), rel_offset, (unsigned long) (rel_size / section->sh_entsize)); - symsec = section_headers + section->sh_link; - - nsyms = symsec->sh_size / symsec->sh_entsize; - symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms); + symtab = NULL; + strtab = NULL; + nsyms = 0; + if (section->sh_link) + { + Elf32_Internal_Shdr * symsec; - if (symtab == NULL) - continue; + symsec = section_headers + section->sh_link; + nsyms = symsec->sh_size / symsec->sh_entsize; + symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms); - strsec = section_headers + symsec->sh_link; + if (symtab == NULL) + continue; - GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab, - char *, "string table"); + strsec = section_headers + symsec->sh_link; + strtab = (char *) get_data (NULL, file, strsec->sh_offset, + strsec->sh_size, + _("string table")); + } is_rela = section->sh_type == SHT_RELA; - dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela); + dump_relocations (file, rel_offset, rel_size, + symtab, nsyms, strtab, is_rela); - free (strtab); - free (symtab); + if (strtab) + free (strtab); + if (symtab) + free (symtab); found = 1; } @@ -2888,6 +3170,434 @@ process_relocs (file) return 1; } +#include "unwind-ia64.h" + +/* An absolute address consists of a section and an offset. If the + section is NULL, the offset itself is the address, otherwise, the + address equals to LOAD_ADDRESS(section) + offset. */ + +struct absaddr + { + unsigned short section; + bfd_vma offset; + }; + +struct unw_aux_info + { + struct unw_table_entry + { + 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. */ + }; + +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; +{ + bfd_vma dist = (bfd_vma) 0x100000; + Elf_Internal_Sym *sym, *best = NULL; + unsigned long i; + + for (i = 0, sym = aux->symtab; i < aux->nsyms; ++i, ++sym) + { + if (ELF_ST_TYPE (sym->st_info) == STT_FUNC + && sym->st_name != 0 + && (addr.section == SHN_UNDEF || addr.section == sym->st_shndx) + && addr.offset >= sym->st_value + && addr.offset - sym->st_value < dist) + { + best = sym; + dist = addr.offset - sym->st_value; + if (!dist) + break; + } + } + if (best) + { + *symname = (best->st_name >= aux->strtab_size + ? "" : aux->strtab + best->st_name); + *offset = dist; + return; + } + *symname = NULL; + *offset = addr.offset; +} + +static void +dump_ia64_unwind (aux) + struct unw_aux_info *aux; +{ + bfd_vma addr_size; + struct unw_table_entry * tp; + int in_body; + + addr_size = is_32bit_elf ? 4 : 8; + + for (tp = aux->table; tp < aux->table + aux->table_len; ++tp) + { + bfd_vma stamp; + bfd_vma offset; + const unsigned char * dp; + const unsigned char * head; + const char * procname; + + find_symbol_for_address (aux, tp->start, &procname, &offset); + + fputs ("\n<", stdout); + + if (procname) + { + fputs (procname, stdout); + + if (offset) + printf ("+%lx", (unsigned long) offset); + } + + fputs (">: [", stdout); + print_vma (tp->start.offset, PREFIX_HEX); + fputc ('-', stdout); + print_vma (tp->end.offset, PREFIX_HEX); + printf ("), info at +0x%lx\n", + (unsigned long) (tp->info.offset - aux->seg_base)); + + head = aux->info + (tp->info.offset - aux->info_addr); + stamp = BYTE_GET8 ((unsigned char *) head); + + printf (" v%u, flags=0x%lx (%s%s ), len=%lu bytes\n", + (unsigned) UNW_VER (stamp), + (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32), + UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "", + UNW_FLAG_UHANDLER (stamp) ? " uhandler" : "", + (unsigned long) (addr_size * UNW_LENGTH (stamp))); + + if (UNW_VER (stamp) != 1) + { + printf ("\tUnknown version.\n"); + continue; + } + + in_body = 0; + for (dp = head + 8; dp < head + 8 + addr_size * UNW_LENGTH (stamp);) + dp = unw_decode (dp, in_body, & in_body); + } +} + +static int +slurp_ia64_unwind_table (file, aux, sec) + FILE *file; + struct unw_aux_info *aux; + Elf32_Internal_Shdr *sec; +{ + unsigned long size, addr_size, nrelas, i; + Elf_Internal_Phdr *prog_hdrs, *seg; + struct unw_table_entry *tep; + Elf32_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; + + /* First, find the starting address of the segment that includes + this section: */ + + 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); + return 0; + } + + for (seg = prog_hdrs; seg < prog_hdrs + elf_header.e_phnum; ++seg) + { + if (seg->p_type != PT_LOAD) + continue; + + if (sec->sh_addr >= seg->p_vaddr + && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz)) + { + aux->seg_base = seg->p_vaddr; + 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")); + 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) + { + tep->start.section = SHN_UNDEF; + tep->end.section = SHN_UNDEF; + tep->info.section = SHN_UNDEF; + if (is_32bit_elf) + { + tep->start.offset = byte_get ((unsigned char *) tp + 0, 4); + tep->end.offset = byte_get ((unsigned char *) tp + 4, 4); + tep->info.offset = byte_get ((unsigned char *) tp + 8, 4); + } + else + { + tep->start.offset = BYTE_GET8 ((unsigned char *) tp + 0); + tep->end.offset = BYTE_GET8 ((unsigned char *) tp + 8); + tep->info.offset = BYTE_GET8 ((unsigned char *) tp + 16); + } + tep->start.offset += aux->seg_base; + tep->end.offset += aux->seg_base; + tep->info.offset += aux->seg_base; + } + free (table); + + /* Third, apply any relocations to the unwind table: */ + + for (relsec = section_headers; + relsec < section_headers + elf_header.e_shnum; + ++relsec) + { + if (relsec->sh_type != SHT_RELA + || section_headers + relsec->sh_info != sec) + continue; + + if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size, + & rela, & nrelas)) + return 0; + + for (rp = rela; rp < rela + nrelas; ++rp) + { + if (is_32bit_elf) + { + relname = elf_ia64_reloc_type (ELF32_R_TYPE (rp->r_info)); + sym = aux->symtab + ELF32_R_SYM (rp->r_info); + + if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION) + { + warn (_("Skipping unexpected symbol type %u"), + ELF32_ST_TYPE (sym->st_info)); + continue; + } + } + else + { + relname = elf_ia64_reloc_type (ELF64_R_TYPE (rp->r_info)); + sym = aux->symtab + ELF64_R_SYM (rp->r_info); + + if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION) + { + warn (_("Skipping unexpected symbol type %u"), + ELF64_ST_TYPE (sym->st_info)); + continue; + } + } + + if (strncmp (relname, "R_IA64_SEGREL", 13) != 0) + { + warn (_("Skipping unexpected relocation type %s"), relname); + continue; + } + + i = rp->r_offset / (3 * addr_size); + + switch (rp->r_offset/addr_size % 3) + { + case 0: + aux->table[i].start.section = sym->st_shndx; + aux->table[i].start.offset += rp->r_addend; + break; + case 1: + aux->table[i].end.section = sym->st_shndx; + aux->table[i].end.offset += rp->r_addend; + break; + case 2: + aux->table[i].info.section = sym->st_shndx; + aux->table[i].info.offset += rp->r_addend; + break; + default: + break; + } + } + + free (rela); + } + + aux->table_len = size / (3 * addr_size); + return 1; +} + +static int +process_unwind (file) + FILE * file; +{ + Elf32_Internal_Shdr *sec, *unwsec = NULL, *strsec; + unsigned long i, addr_size, unwcount = 0, unwstart = 0; + struct unw_aux_info aux; + + if (!do_unwind) + return 1; + + if (elf_header.e_machine != EM_IA_64) + { + printf (_("\nThere are no unwind sections in this file.\n")); + return 1; + } + + memset (& aux, 0, sizeof (aux)); + + addr_size = is_32bit_elf ? 4 : 8; + + for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec) + { + if (sec->sh_type == SHT_SYMTAB) + { + aux.nsyms = sec->sh_size / sec->sh_entsize; + aux.symtab = GET_ELF_SYMBOLS (file, sec->sh_offset, aux.nsyms); + + strsec = section_headers + sec->sh_link; + aux.strtab_size = strsec->sh_size; + aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset, + aux.strtab_size, _("string table")); + } + else if (sec->sh_type == SHT_IA_64_UNWIND) + unwcount++; + } + + if (!unwcount) + printf (_("\nThere are no unwind sections in this file.\n")); + + while (unwcount-- > 0) + { + char *suffix; + size_t len, len2; + + for (i = unwstart, sec = section_headers + unwstart; + i < elf_header.e_shnum; ++i, ++sec) + if (sec->sh_type == SHT_IA_64_UNWIND) + { + unwsec = sec; + break; + } + + unwstart = i + 1; + len = sizeof (ELF_STRING_ia64_unwind_once) - 1; + + if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once, + len) == 0) + { + /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO */ + len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1; + suffix = SECTION_NAME (unwsec) + len; + for (i = 0, sec = section_headers; i < elf_header.e_shnum; + ++i, ++sec) + if (strncmp (SECTION_NAME (sec), + ELF_STRING_ia64_unwind_info_once, len2) == 0 + && strcmp (SECTION_NAME (sec) + len2, suffix) == 0) + break; + } + else + { + /* .IA_64.unwindFOO -> .IA_64.unwind_infoFOO + .IA_64.unwind or BAR -> .IA_64.unwind_info */ + len = sizeof (ELF_STRING_ia64_unwind) - 1; + len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1; + suffix = ""; + if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind, + len) == 0) + suffix = SECTION_NAME (unwsec) + len; + for (i = 0, sec = section_headers; i < elf_header.e_shnum; + ++i, ++sec) + if (strncmp (SECTION_NAME (sec), + ELF_STRING_ia64_unwind_info, len2) == 0 + && strcmp (SECTION_NAME (sec) + len2, suffix) == 0) + break; + } + + if (i == elf_header.e_shnum) + { + printf (_("\nCould not find unwind info section for ")); + + if (string_table == NULL) + printf ("%d", unwsec->sh_name); + else + printf ("'%s'", SECTION_NAME (unwsec)); + } + else + { + 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")); + + printf (_("\nUnwind section ")); + + if (string_table == NULL) + printf ("%d", unwsec->sh_name); + else + printf ("'%s'", SECTION_NAME (unwsec)); + + printf (_(" at offset 0x%lx contains %lu entries:\n"), + unwsec->sh_offset, + (unsigned long) (unwsec->sh_size / (3 * addr_size))); + + (void) slurp_ia64_unwind_table (file, & aux, unwsec); + + if (aux.table_len > 0) + dump_ia64_unwind (& aux); + + if (aux.table) + free ((char *) aux.table); + if (aux.info) + free ((char *) aux.info); + aux.table = NULL; + aux.info = NULL; + } + } + + if (aux.symtab) + free (aux.symtab); + if (aux.strtab) + free ((char *) aux.strtab); + + return 1; +} static void dynamic_segment_mips_val (entry) @@ -3004,7 +3714,7 @@ dynamic_segment_parisc_val (entry) first = 0; val ^= flags[cnt].bit; } - + if (val != 0 || first) { if (! first) @@ -3013,7 +3723,7 @@ dynamic_segment_parisc_val (entry) } } break; - + default: print_vma (entry->d_un.d_ptr, PREFIX_HEX); break; @@ -3028,8 +3738,10 @@ get_32bit_dynamic_segment (file) Elf_Internal_Dyn * entry; bfd_size_type i; - GET_DATA_ALLOC (dynamic_addr, dynamic_size, - edyn, Elf32_External_Dyn *, "dynamic segment"); + edyn = (Elf32_External_Dyn *) get_data (NULL, file, dynamic_addr, + dynamic_size, _("dynamic segment")); + if (!edyn) + return 0; /* SGI's ELF has more than one section in the DYNAMIC segment. Determine how large this .dynamic is now. We can do this even before the byte @@ -3069,8 +3781,10 @@ get_64bit_dynamic_segment (file) Elf_Internal_Dyn * entry; bfd_size_type i; - GET_DATA_ALLOC (dynamic_addr, dynamic_size, - edyn, Elf64_External_Dyn *, "dynamic segment"); + edyn = (Elf64_External_Dyn *) get_data (NULL, file, dynamic_addr, + dynamic_size, _("dynamic segment")); + if (!edyn) + return 0; /* SGI's ELF has more than one section in the DYNAMIC segment. Determine how large this .dynamic is now. We can do this even before the byte @@ -3220,8 +3934,8 @@ process_dynamic_segment (file) continue; } - GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *, - "dynamic string table"); + dynamic_strings = (char *) get_data (NULL, file, offset, str_tab_len, + _("dynamic string table")); break; } @@ -3254,8 +3968,11 @@ process_dynamic_segment (file) Elf_Internal_Syminfo * syminfo; /* There is a syminfo section. Read the data. */ - GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo, - Elf_External_Syminfo *, "symbol information"); + extsyminfo = ((Elf_External_Syminfo *) + get_data (NULL, file, dynamic_syminfo_offset, + syminsz, _("symbol information"))); + if (!extsyminfo) + return 0; dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz); if (dynamic_syminfo == NULL) @@ -3305,15 +4022,36 @@ process_dynamic_segment (file) if (do_dynamic) printf ("%s", get_dynamic_flags (entry->d_un.d_val)); break; - + case DT_AUXILIARY: case DT_FILTER: + case DT_CONFIG: + case DT_DEPAUDIT: + case DT_AUDIT: if (do_dynamic) { - if (entry->d_tag == DT_AUXILIARY) - printf (_("Auxiliary library")); - else - printf (_("Filter library")); + switch (entry->d_tag) + { + case DT_AUXILIARY: + printf (_("Auxiliary library")); + break; + + case DT_FILTER: + printf (_("Filter library")); + break; + + case DT_CONFIG: + printf (_("Configuration file")); + break; + + case DT_DEPAUDIT: + printf (_("Dependency audit library")); + break; + + case DT_AUDIT: + printf (_("Audit library")); + break; + } if (dynamic_strings) printf (": [%s]\n", dynamic_strings + entry->d_un.d_val); @@ -3326,7 +4064,7 @@ process_dynamic_segment (file) } break; - case DT_FEATURE_1: + case DT_FEATURE: if (do_dynamic) { printf (_("Flags:")); @@ -3340,6 +4078,11 @@ process_dynamic_segment (file) printf (" PARINIT"); val ^= DTF_1_PARINIT; } + if (val & DTF_1_CONFEXP) + { + printf (" CONFEXP"); + val ^= DTF_1_CONFEXP; + } if (val != 0) printf (" %lx", val); puts (""); @@ -3437,6 +4180,21 @@ process_dynamic_segment (file) printf (" INTERPOSE"); val ^= DF_1_INTERPOSE; } + if (val & DF_1_NODEFLIB) + { + printf (" NODEFLIB"); + val ^= DF_1_NODEFLIB; + } + if (val & DF_1_NODUMP) + { + printf (" NODUMP"); + val ^= DF_1_NODUMP; + } + if (val & DF_1_CONLFAT) + { + printf (" CONLFAT"); + val ^= DF_1_CONLFAT; + } if (val != 0) printf (" %lx", val); puts (""); @@ -3465,6 +4223,7 @@ process_dynamic_segment (file) case DT_DEBUG : case DT_TEXTREL : case DT_JMPREL : + case DT_RUNPATH : dynamic_info[entry->d_tag] = entry->d_un.d_val; if (do_dynamic) @@ -3495,6 +4254,10 @@ process_dynamic_segment (file) printf (_("Library rpath: [%s]"), name); break; + case DT_RUNPATH: + printf (_("Library runpath: [%s]"), name); + break; + default: print_vma (entry->d_un.d_val, PREFIX_HEX); break; @@ -3577,7 +4340,7 @@ process_dynamic_segment (file) switch (elf_header.e_machine) { case EM_MIPS: - case EM_MIPS_RS4_BE: + case EM_MIPS_RS3_LE: dynamic_segment_mips_val (entry); break; case EM_PARISC: @@ -3659,9 +4422,12 @@ process_version_sections (file) (unsigned long) section->sh_offset, section->sh_link, SECTION_NAME (section_headers + section->sh_link)); - GET_DATA_ALLOC (section->sh_offset, section->sh_size, - edefs, Elf_External_Verdef *, - "version definition section"); + edefs = ((Elf_External_Verdef *) + 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) { @@ -3747,9 +4513,11 @@ process_version_sections (file) (unsigned long) section->sh_offset, section->sh_link, SECTION_NAME (section_headers + section->sh_link)); - GET_DATA_ALLOC (section->sh_offset, section->sh_size, - eneed, Elf_External_Verneed *, - "version need section"); + eneed = ((Elf_External_Verneed *) + 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) { @@ -3817,12 +4585,12 @@ 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; + int total; + int cnt; + unsigned char * edata; + unsigned short * data; + char * strtab; + Elf_Internal_Sym * symbols; Elf32_Internal_Shdr * string_sec; link_section = section_headers + section->sh_link; @@ -3835,8 +4603,11 @@ process_version_sections (file) string_sec = section_headers + link_section->sh_link; - GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size, - strtab, char *, "version string table"); + strtab = (char *) get_data (NULL, file, string_sec->sh_offset, + string_sec->sh_size, + _("version string table")); + if (!strtab) + break; printf (_("\nVersion symbols section '%s' contains %d entries:\n"), SECTION_NAME (section), total); @@ -3847,10 +4618,16 @@ process_version_sections (file) (unsigned long) section->sh_offset, section->sh_link, SECTION_NAME (link_section)); - GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)] - - loadaddr, - total * sizeof (short), edata, - unsigned char *, "version symbol data"); + edata = + ((unsigned char *) + get_data (NULL, file, + version_info[DT_VERSIONTAGIDX (DT_VERSYM)] - loadaddr, + total * sizeof (short), _("version symbol data"))); + if (!edata) + { + free (strtab); + break; + } data = (unsigned short *) malloc (total * sizeof (short)); @@ -3863,6 +4640,7 @@ process_version_sections (file) for (cnt = 0; cnt < total; cnt += 4) { int j, nn; + int check_def, check_need; char * name; printf (" %03x:", cnt); @@ -3882,40 +4660,51 @@ process_version_sections (file) nn = printf ("%4x%c", data [cnt + j] & 0x7fff, data [cnt + j] & 0x8000 ? 'h' : ' '); - if (symbols [cnt + j].st_shndx < SHN_LORESERVE - && section_headers[symbols [cnt + j].st_shndx].sh_type - == SHT_NOBITS) + check_def = 1; + check_need = 1; + if (symbols [cnt + j].st_shndx >= SHN_LORESERVE + || section_headers[symbols [cnt + j].st_shndx].sh_type + != SHT_NOBITS) + { + if (symbols [cnt + j].st_shndx == SHN_UNDEF) + check_def = 0; + else + check_need = 0; + } + + if (check_need + && version_info [DT_VERSIONTAGIDX (DT_VERNEED)]) { - /* We must test both. */ Elf_Internal_Verneed ivn; unsigned long offset; offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr; - do + do { + Elf_Internal_Vernaux ivna; Elf_External_Verneed evn; Elf_External_Vernaux evna; - Elf_Internal_Vernaux ivna; - unsigned long vna_off; + unsigned long a_off; - GET_DATA (offset, evn, "version need"); + get_data (&evn, file, offset, sizeof (evn), + _("version need")); ivn.vn_aux = BYTE_GET (evn.vn_aux); ivn.vn_next = BYTE_GET (evn.vn_next); - vna_off = offset + ivn.vn_aux; + a_off = offset + ivn.vn_aux; do { - GET_DATA (vna_off, evna, - "version need aux (1)"); + get_data (&evna, file, a_off, sizeof (evna), + _("version need aux (2)")); ivna.vna_next = BYTE_GET (evna.vna_next); ivna.vna_other = BYTE_GET (evna.vna_other); - vna_off += ivna.vna_next; + a_off += ivna.vna_next; } while (ivna.vna_other != data [cnt + j] && ivna.vna_next != 0); @@ -3929,129 +4718,32 @@ process_version_sections (file) name, 12 - (int) strlen (name), ")"); + check_def = 0; break; } - else if (ivn.vn_next == 0) - { - if (data [cnt + j] != 0x8001) - { - Elf_Internal_Verdef ivd; - Elf_External_Verdef evd; - - offset = version_info - [DT_VERSIONTAGIDX (DT_VERDEF)] - - loadaddr; - - do - { - GET_DATA (offset, evd, - "version definition"); - - ivd.vd_next = BYTE_GET (evd.vd_next); - ivd.vd_ndx = BYTE_GET (evd.vd_ndx); - - offset += ivd.vd_next; - } - while (ivd.vd_ndx - != (data [cnt + j] & 0x7fff) - && ivd.vd_next != 0); - - if (ivd.vd_ndx - == (data [cnt + j] & 0x7fff)) - { - Elf_External_Verdaux evda; - Elf_Internal_Verdaux ivda; - - ivd.vd_aux = BYTE_GET (evd.vd_aux); - - GET_DATA (offset + ivd.vd_aux, evda, - "version definition aux"); - - ivda.vda_name = - BYTE_GET (evda.vda_name); - - name = strtab + ivda.vda_name; - nn += - printf ("(%s%-*s", - name, - 12 - (int) strlen (name), - ")"); - } - } - break; - } - else - offset += ivn.vn_next; + offset += ivn.vn_next; } while (ivn.vn_next); } - else if (symbols [cnt + j].st_shndx == SHN_UNDEF) + + if (check_def && data [cnt + j] != 0x8001 + && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) { - Elf_Internal_Verneed ivn; - unsigned long offset; + Elf_Internal_Verdef ivd; + Elf_External_Verdef evd; + unsigned long offset; - offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)] - - loadaddr; + offset = version_info + [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr; - do + do { - Elf_Internal_Vernaux ivna; - Elf_External_Verneed evn; - Elf_External_Vernaux evna; - unsigned long a_off; + get_data (&evd, file, offset, sizeof (evd), + _("version def")); - GET_DATA (offset, evn, "version need"); - - ivn.vn_aux = BYTE_GET (evn.vn_aux); - ivn.vn_next = BYTE_GET (evn.vn_next); - - a_off = offset + ivn.vn_aux; - - do - { - GET_DATA (a_off, evna, - "version need aux (2)"); - - ivna.vna_next = BYTE_GET (evna.vna_next); - ivna.vna_other = BYTE_GET (evna.vna_other); - - a_off += ivna.vna_next; - } - while (ivna.vna_other != data [cnt + j] - && ivna.vna_next != 0); - - if (ivna.vna_other == data [cnt + j]) - { - ivna.vna_name = BYTE_GET (evna.vna_name); - - name = strtab + ivna.vna_name; - nn += printf ("(%s%-*s", - name, - 12 - (int) strlen (name), - ")"); - break; - } - - offset += ivn.vn_next; - } - while (ivn.vn_next); - } - else if (data [cnt + j] != 0x8001) - { - Elf_Internal_Verdef ivd; - Elf_External_Verdef evd; - unsigned long offset; - - offset = version_info - [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr; - - do - { - GET_DATA (offset, evd, "version def"); - - ivd.vd_next = BYTE_GET (evd.vd_next); - ivd.vd_ndx = BYTE_GET (evd.vd_ndx); + ivd.vd_next = BYTE_GET (evd.vd_next); + ivd.vd_ndx = BYTE_GET (evd.vd_ndx); offset += ivd.vd_next; } @@ -4065,8 +4757,9 @@ process_version_sections (file) ivd.vd_aux = BYTE_GET (evd.vd_aux); - GET_DATA (offset - ivd.vd_next + ivd.vd_aux, - evda, "version def aux"); + get_data (&evda, file, + offset - ivd.vd_next + ivd.vd_aux, + sizeof (evda), _("version def aux")); ivda.vda_name = BYTE_GET (evda.vda_name); @@ -4215,10 +4908,10 @@ get_dynamic_data (file, number) FILE * file; unsigned int number; { - char * e_data; + unsigned char * e_data; int * i_data; - e_data = (char *) malloc (number * 4); + e_data = (unsigned char *) malloc (number * 4); if (e_data == NULL) { @@ -4255,8 +4948,8 @@ process_symbol_table (file) FILE * file; { Elf32_Internal_Shdr * section; - char nb [4]; - char nc [4]; + unsigned char nb [4]; + unsigned char nc [4]; int nbuckets = 0; int nchains = 0; int * buckets = NULL; @@ -4323,7 +5016,7 @@ process_symbol_table (file) print_vma (psym->st_value, LONG_HEX); putchar (' ' ); print_vma (psym->st_size, DEC_5); - + printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info))); printf (" %6s", get_symbol_binding (ELF_ST_BIND (psym->st_info))); printf (" %3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other))); @@ -4371,8 +5064,9 @@ process_symbol_table (file) string_sec = section_headers + section->sh_link; - GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size, - strtab, char *, "string table"); + strtab = (char *) get_data (NULL, file, string_sec->sh_offset, + string_sec->sh_size, + _("string table")); } for (si = 0, psym = symtab; @@ -4401,8 +5095,8 @@ process_symbol_table (file) offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)] - loadaddr; - GET_DATA (offset + si * sizeof (vers_data), data, - "version data"); + get_data (&data, file, offset + si * sizeof (vers_data), + sizeof (data), _("version data")); vers_data = byte_get (data, 2); @@ -4414,7 +5108,8 @@ process_symbol_table (file) if ((vers_data & 0x8000) || vers_data > 1) { - if (is_nobits || ! check_def) + if (version_info [DT_VERSIONTAGIDX (DT_VERNEED)] + && (is_nobits || ! check_def)) { Elf_External_Verneed evn; Elf_Internal_Verneed ivn; @@ -4428,7 +5123,8 @@ process_symbol_table (file) { unsigned long vna_off; - GET_DATA (offset, evn, "version need"); + get_data (&evn, file, offset, sizeof (evn), + _("version need")); ivn.vn_aux = BYTE_GET (evn.vn_aux); ivn.vn_next = BYTE_GET (evn.vn_next); @@ -4439,8 +5135,9 @@ process_symbol_table (file) { Elf_External_Vernaux evna; - GET_DATA (vna_off, evna, - "version need aux (3)"); + get_data (&evna, file, vna_off, + sizeof (evna), + _("version need aux (3)")); ivna.vna_other = BYTE_GET (evna.vna_other); ivna.vna_next = BYTE_GET (evna.vna_next); @@ -4472,7 +5169,8 @@ process_symbol_table (file) if (check_def) { - if (vers_data != 0x8001) + if (vers_data != 0x8001 + && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) { Elf_Internal_Verdef ivd; Elf_Internal_Verdaux ivda; @@ -4487,7 +5185,8 @@ process_symbol_table (file) { Elf_External_Verdef evd; - GET_DATA (offset, evd, "version def"); + 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); @@ -4501,7 +5200,8 @@ process_symbol_table (file) offset -= ivd.vd_next; offset += ivd.vd_aux; - GET_DATA (offset, evda, "version def aux"); + get_data (&evda, file, offset, sizeof (evda), + _("version def aux")); ivda.vda_name = BYTE_GET (evda.vda_name); @@ -4528,13 +5228,13 @@ 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); @@ -4694,8 +5394,10 @@ dump_section (section, file) addr = section->sh_addr; - GET_DATA_ALLOC (section->sh_offset, bytes, start, unsigned char *, - "section data"); + start = (unsigned char *) get_data (NULL, file, section->sh_offset, bytes, + _("section data")); + if (!start) + return 0; data = start; @@ -4870,7 +5572,7 @@ process_extended_line_op (data, is_stmt, pointer_size) printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); name = data; - data += strlen (data) + 1; + data += strlen ((char *) data) + 1; printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); data += bytes_read; printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); @@ -4915,7 +5617,7 @@ display_debug_lines (section, start, file) /* Check the length of the block. */ info.li_length = BYTE_GET (external->li_length); - if (info.li_length > section->sh_size) + if (info.li_length + sizeof (external->li_length) > section->sh_size) { warn (_("The line info appears to be corrupt - the section is too small\n")); @@ -4943,14 +5645,14 @@ display_debug_lines (section, start, file) printf (_(" Length: %ld\n"), info.li_length); printf (_(" DWARF Version: %d\n"), info.li_version); - printf (_(" Prolgue Length: %d\n"), info.li_prologue_length); + printf (_(" Prologue Length: %d\n"), info.li_prologue_length); printf (_(" Minimum Instruction Length: %d\n"), info.li_min_insn_length); printf (_(" Initial value of 'is_stmt': %d\n"), info.li_default_is_stmt); printf (_(" Line Base: %d\n"), info.li_line_base); printf (_(" Line Range: %d\n"), info.li_line_range); printf (_(" Opcode Base: %d\n"), info.li_opcode_base); - end_of_sequence = data + info.li_length + sizeof (info.li_length); + end_of_sequence = data + info.li_length + sizeof (external->li_length); reset_state_machine (info.li_default_is_stmt); @@ -4975,7 +5677,7 @@ display_debug_lines (section, start, file) { printf (_(" %s\n"), data); - data += strlen (data) + 1; + data += strlen ((char *) data) + 1; } } @@ -4992,13 +5694,13 @@ display_debug_lines (section, start, file) while (* data != 0) { - char * name; + unsigned char * name; int bytes_read; printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); name = data; - data += strlen (data) + 1; + data += strlen ((char *) data) + 1; printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); data += bytes_read; @@ -5145,7 +5847,14 @@ display_debug_pubnames (section, start, file) if (pubnames.pn_version != 2) { - warn (_("Only DWARF 2 pubnames are currently supported")); + static int warned = 0; + + if (! warned) + { + warn (_("Only DWARF 2 pubnames are currently supported\n")); + warned = 1; + } + continue; } @@ -5168,7 +5877,7 @@ display_debug_pubnames (section, start, file) { data += 4; printf (" %ld\t\t%s\n", offset, data); - data += strlen (data) + 1; + data += strlen ((char *) data) + 1; } } while (offset != 0); @@ -5184,58 +5893,67 @@ get_TAG_name (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"; default: { static char buffer [100]; @@ -5252,85 +5970,100 @@ get_AT_name (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_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_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_MIPS_fde: return "DW_AT_MIPS_fde"; - case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; + /* 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"; + /* 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_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_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_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"; default: { static char buffer [100]; @@ -5347,27 +6080,27 @@ get_FORM_name (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_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_indirect: return "DW_FORM_indirect"; default: { static char buffer [100]; @@ -5539,13 +6272,87 @@ process_abbrev_section (start, end) } +static int +display_debug_macinfo (section, start, file) + Elf32_Internal_Shdr * section; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + unsigned char * end = start + section->sh_size; + unsigned char * curr = start; + unsigned int bytes_read; + enum dwarf_macinfo_record_type op; + + printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); + + while (curr < end) + { + unsigned int lineno; + const char * string; + + op = * curr; + curr ++; + + switch (op) + { + case DW_MACINFO_start_file: + { + unsigned int filenum; + + lineno = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + filenum = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + + printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"), lineno, filenum); + } + break; + + case DW_MACINFO_end_file: + printf (_(" DW_MACINFO_end_file\n")); + break; + + case DW_MACINFO_define: + lineno = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + string = curr; + curr += strlen (string) + 1; + printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"), lineno, string); + break; + + case DW_MACINFO_undef: + lineno = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + string = curr; + curr += strlen (string) + 1; + printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"), lineno, string); + break; + + case DW_MACINFO_vendor_ext: + { + unsigned int constant; + + constant = read_leb128 (curr, & bytes_read, 0); + curr += bytes_read; + string = curr; + curr += strlen (string) + 1; + printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"), constant, string); + } + break; + } + } + + return 1; +} + + static int display_debug_abbrev (section, start, file) Elf32_Internal_Shdr * section; unsigned char * start; FILE * file ATTRIBUTE_UNUSED; { - abbrev_entry * entry; + abbrev_entry * entry; unsigned char * end = start + section->sh_size; printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); @@ -5598,12 +6405,12 @@ static void decode_location_expression (data, pointer_size, length) unsigned char * data; unsigned int pointer_size; - unsigned long length; + 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) { @@ -5890,6 +6697,22 @@ decode_location_expression (data, pointer_size, length) printf ("DW_OP_nop"); break; + /* DWARF 2.1 extensions. */ + case DW_OP_push_object_address: + printf ("DW_OP_push_object_address"); + break; + case DW_OP_call2: + printf ("DW_OP_call2: <%lx>", (long) byte_get (data, 2)); + data += 2; + break; + case DW_OP_call4: + printf ("DW_OP_call4: <%lx>", (long) byte_get (data, 4)); + data += 4; + break; + case DW_OP_calli: + printf ("DW_OP_calli"); + break; + default: if (op >= DW_OP_lo_user && op <= DW_OP_hi_user) @@ -5899,6 +6722,9 @@ decode_location_expression (data, pointer_size, length) /* No way to tell where the next op is, so just bail. */ return; } + + /* Separate the ops. */ + printf ("; "); } } @@ -5919,6 +6745,9 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size) switch (form) { + default: + break; + case DW_FORM_ref_addr: case DW_FORM_addr: uvalue = byte_get (data, pointer_size); @@ -5960,7 +6789,7 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size) case DW_FORM_ref_addr: printf (" <#%lx>", uvalue); break; - + case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: @@ -5990,7 +6819,7 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size) case DW_FORM_string: printf (" %s", data); - data += strlen (data) + 1; + data += strlen ((char *) data) + 1; break; case DW_FORM_block: @@ -6057,6 +6886,11 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size) 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; } @@ -6074,6 +6908,8 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size) 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; default: if (uvalue >= DW_ATE_lo_user && uvalue <= DW_ATE_hi_user) @@ -6140,10 +6976,25 @@ read_and_display_attr (attribute, form, data, cu_offset, pointer_size) } break; + case DW_AT_ordering: + switch (uvalue) + { + case -1: printf ("(undefined)"); break; + case 0: printf ("(row major)"); break; + case 1: printf ("(column major)"); break; + } + break; + case DW_AT_frame_base: case DW_AT_location: case DW_AT_data_member_location: case DW_AT_vtable_elem_location: + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_stride: + case DW_AT_upper_bound: + case DW_AT_lower_bound: if (block_start) { printf ("("); @@ -6191,18 +7042,18 @@ display_debug_info (section, start, file) cu_offset = start - section_begin; start += compunit.cu_length + sizeof (external->cu_length); + printf (_(" Compilation Unit @ %lx:\n"), cu_offset); + printf (_(" Length: %ld\n"), compunit.cu_length); + printf (_(" Version: %d\n"), compunit.cu_version); + printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset); + printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size); + if (compunit.cu_version != 2) { warn (_("Only version 2 DWARF debug information is currently supported.\n")); continue; } - printf (_(" Compilation Unit:\n")); - printf (_(" Length: %ld\n"), compunit.cu_length); - printf (_(" Version: %d\n"), compunit.cu_version); - printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset); - printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size); - if (first_abbrev != NULL) free_abbrevs (); @@ -6225,8 +7076,11 @@ display_debug_info (section, start, file) return 0; } - GET_DATA_ALLOC (sec->sh_offset, sec->sh_size, begin, unsigned char *, - "debug_abbrev section data"); + begin = ((unsigned char *) + get_data (NULL, file, sec->sh_offset, sec->sh_size, + _("debug_abbrev section data"))); + if (!begin) + return 0; process_abbrev_section (begin + compunit.cu_abbrev_offset, begin + sec->sh_size); @@ -6314,6 +7168,12 @@ display_debug_aranges (section, start, file) arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size); arange.ar_segment_size = BYTE_GET (external->ar_segment_size); + if (arange.ar_version != 2) + { + warn (_("Only DWARF 2 aranges are currently supported.\n")); + break; + } + printf (_(" Length: %ld\n"), arange.ar_length); printf (_(" Version: %d\n"), arange.ar_version); printf (_(" Offset into .debug_info: %lx\n"), arange.ar_info_offset); @@ -6325,7 +7185,7 @@ display_debug_aranges (section, start, file) ranges = start + sizeof (* external); /* Must pad to an alignment boundary that is twice the pointer size. */ - excess = sizeof (*external) % (2 * arange.ar_pointer_size); + excess = sizeof (* external) % (2 * arange.ar_pointer_size); if (excess) ranges += (2 * arange.ar_pointer_size) - excess; @@ -6354,6 +7214,671 @@ display_debug_aranges (section, start, file) return 1; } +typedef struct Frame_Chunk +{ + 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; +} +Frame_Chunk; + +/* A marker for a col_type that means this column was never referenced + in the frame info. */ +#define DW_CFA_unreferenced (-1) + +static void +frame_need_space (fc, reg) + Frame_Chunk * fc; + int reg; +{ + int prev = fc->ncols; + + if (reg < fc->ncols) + 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)); + + while (prev < fc->ncols) + { + fc->col_type[prev] = DW_CFA_unreferenced; + fc->col_offset[prev] = 0; + prev++; + } +} + +static void +frame_display_row (fc, need_col_headers, max_regs) + 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 (* need_col_headers) + { + * need_col_headers = 0; + + printf (" LOC CFA "); + + for (r = 0; r < * max_regs; r++) + if (fc->col_type[r] != DW_CFA_unreferenced) + { + if (r == fc->ra) + printf ("ra "); + else + printf ("r%-4d", r); + } + + printf ("\n"); + } + + printf ("%08lx ", fc->pc_begin); + sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset); + printf ("%-8s ", tmp); + + for (r = 0; r < fc->ncols; r++) + { + if (fc->col_type[r] != DW_CFA_unreferenced) + { + switch (fc->col_type[r]) + { + case DW_CFA_undefined: + strcpy (tmp, "u"); + break; + case DW_CFA_same_value: + strcpy (tmp, "s"); + break; + case DW_CFA_offset: + sprintf (tmp, "c%+d", fc->col_offset[r]); + break; + case DW_CFA_register: + sprintf (tmp, "r%d", fc->col_offset[r]); + break; + default: + strcpy (tmp, "n/a"); + break; + } + printf ("%-5s", tmp); + } + } + printf ("\n"); +} + +static int +size_of_encoded_value (encoding) + int encoding; +{ + switch (encoding & 0x7) + { + default: /* ??? */ + case 0: return is_32bit_elf ? 4 : 8; + case 2: return 2; + case 3: return 4; + case 4: return 8; + } +} + +#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; + + 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; + + saved_start = start; + length = byte_get (start, 4); start += 4; + + if (length == 0) + return 1; + + block_end = saved_start + length + 4; + cie_id = byte_get (start, 4); start += 4; + + if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID)) + { + int version; + + fc = (Frame_Chunk *) 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)); + frame_need_space (fc, max_regs-1); + + version = *start++; + + fc->augmentation = start; + start = strchr (start, '\0') + 1; + + if (fc->augmentation[0] == 'z') + { + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + fc->ra = byte_get (start, 1); start += 1; + augmentation_data_len = LEB (); + augmentation_data = start; + start += augmentation_data_len; + } + else if (strcmp (fc->augmentation, "eh") == 0) + { + start += addr_size; + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + fc->ra = byte_get (start, 1); start += 1; + } + else + { + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + fc->ra = byte_get (start, 1); start += 1; + } + cie = fc; + + if (do_debug_frames_interp) + printf ("\n%08lx %08lx %08lx CIE \"%s\" cf=%d df=%d ra=%d\n", + (unsigned long)(saved_start - section_start), length, cie_id, + fc->augmentation, fc->code_factor, fc->data_factor, + fc->ra); + else + { + printf ("\n%08lx %08lx %08lx CIE\n", + (unsigned long)(saved_start - section_start), length, cie_id); + printf (" Version: %d\n", version); + printf (" Augmentation: \"%s\"\n", fc->augmentation); + printf (" Code alignment factor: %u\n", fc->code_factor); + printf (" Data alignment factor: %d\n", fc->data_factor); + printf (" Return address column: %d\n", fc->ra); + + if (augmentation_data_len) + { + unsigned long i; + printf (" Augmentation data: "); + for (i = 0; i < augmentation_data_len; ++i) + printf (" %02x", augmentation_data[i]); + putchar ('\n'); + } + putchar ('\n'); + } + + if (augmentation_data_len) + { + unsigned char *p, *q; + p = fc->augmentation + 1; + q = augmentation_data; + + while (1) + { + if (*p == 'L') + q++; + else if (*p == 'P') + q += 1 + size_of_encoded_value (*q); + else if (*p == 'R') + fc->fde_encoding = *q++; + else + break; + p++; + } + + if (fc->fde_encoding) + encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); + } + + frame_need_space (fc, fc->ra); + } + else + { + unsigned char * look_for; + static Frame_Chunk fde_fc; + + fc = & fde_fc; + memset (fc, 0, sizeof (Frame_Chunk)); + + look_for = is_eh ? start - 4 - cie_id : section_start + cie_id; + + for (cie=chunks; cie ; cie = cie->next) + if (cie->chunk_start == look_for) + break; + + if (!cie) + { + warn ("Invalid CIE pointer %08lx in FDE at %08lx\n", + 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)); + frame_need_space (fc, max_regs - 1); + cie = fc; + fc->augmentation = ""; + fc->fde_encoding = 0; + } + 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)); + 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; + fc->code_factor = cie->code_factor; + fc->data_factor = cie->data_factor; + fc->cfa_reg = cie->cfa_reg; + fc->cfa_offset = cie->cfa_offset; + fc->ra = cie->ra; + frame_need_space (fc, max_regs-1); + fc->fde_encoding = cie->fde_encoding; + } + + if (fc->fde_encoding) + encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); + + fc->pc_begin = byte_get (start, encoded_ptr_size); + start += encoded_ptr_size; + fc->pc_range = byte_get (start, encoded_ptr_size); + start += encoded_ptr_size; + + if (cie->augmentation[0] == 'z') + { + augmentation_data_len = LEB (); + augmentation_data = start; + start += augmentation_data_len; + } + + printf ("\n%08lx %08lx %08lx FDE cie=%08x pc=%08lx..%08lx\n", + (unsigned long)(saved_start - section_start), length, cie_id, + cie->chunk_start - section_start, fc->pc_begin, + fc->pc_begin + fc->pc_range); + if (! do_debug_frames_interp && augmentation_data_len) + { + unsigned long i; + printf (" Augmentation data: "); + for (i = 0; i < augmentation_data_len; ++i) + printf (" %02x", augmentation_data[i]); + putchar ('\n'); + putchar ('\n'); + } + } + + /* 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) + { + /* Start by making a pass over the chunk, allocating storage + and taking note of what registers are used. */ + unsigned char * tmp = start; + + while (start < block_end) + { + unsigned op, opa; + unsigned long reg; + + op = * start ++; + opa = op & 0x3f; + if (op & 0xc0) + op &= 0xc0; + + /* Warning: if you add any more cases to this switch, be + sure to add them to the corresponding switch below. */ + switch (op) + { + case DW_CFA_advance_loc: + break; + case DW_CFA_offset: + LEB (); + frame_need_space (fc, opa); + fc->col_type[opa] = DW_CFA_undefined; + break; + case DW_CFA_restore: + frame_need_space (fc, opa); + fc->col_type[opa] = DW_CFA_undefined; + break; + case DW_CFA_set_loc: + start += encoded_ptr_size; + break; + case DW_CFA_advance_loc1: + start += 1; + break; + case DW_CFA_advance_loc2: + start += 2; + break; + case DW_CFA_advance_loc4: + start += 4; + break; + case DW_CFA_offset_extended: + reg = LEB (); LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_restore_extended: + reg = LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_undefined: + reg = LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_same_value: + reg = LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_register: + reg = LEB (); LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + break; + case DW_CFA_def_cfa: + LEB (); LEB (); + break; + case DW_CFA_def_cfa_register: + LEB (); + break; + case DW_CFA_def_cfa_offset: + LEB (); + break; +#ifndef DW_CFA_GNU_args_size +#define DW_CFA_GNU_args_size 0x2e +#endif + case DW_CFA_GNU_args_size: + LEB (); + break; +#ifndef DW_CFA_GNU_negative_offset_extended +#define DW_CFA_GNU_negative_offset_extended 0x2f +#endif + case DW_CFA_GNU_negative_offset_extended: + reg = LEB (); LEB (); + frame_need_space (fc, reg); + fc->col_type[reg] = DW_CFA_undefined; + + default: + break; + } + } + start = tmp; + } + + /* Now we know what registers are used, make a second pass over + the chunk, this time actually printing out the info. */ + + while (start < block_end) + { + unsigned op, opa; + unsigned long ul, reg, roffs; + long l, ofs; + bfd_vma vma; + + op = * start ++; + opa = op & 0x3f; + if (op & 0xc0) + op &= 0xc0; + + /* Warning: if you add any more cases to this switch, be + sure to add them to the corresponding switch above. */ + switch (op) + { + case DW_CFA_advance_loc: + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_advance_loc: %d to %08lx\n", + opa * fc->code_factor, + fc->pc_begin + opa * fc->code_factor); + fc->pc_begin += opa * fc->code_factor; + break; + + case DW_CFA_offset: + roffs = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_offset: r%d at cfa%+ld\n", + opa, roffs * fc->data_factor); + fc->col_type[opa] = DW_CFA_offset; + fc->col_offset[opa] = roffs * fc->data_factor; + break; + + case DW_CFA_restore: + if (! do_debug_frames_interp) + printf (" DW_CFA_restore: r%d\n", opa); + fc->col_type[opa] = cie->col_type[opa]; + fc->col_offset[opa] = cie->col_offset[opa]; + break; + + case DW_CFA_set_loc: + vma = byte_get (start, encoded_ptr_size); + start += encoded_ptr_size; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_set_loc: %08lx\n", (unsigned long)vma); + fc->pc_begin = vma; + break; + + case DW_CFA_advance_loc1: + ofs = byte_get (start, 1); start += 1; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_advance_loc1: %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_advance_loc2: + ofs = byte_get (start, 2); start += 2; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_advance_loc2: %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_advance_loc4: + ofs = byte_get (start, 4); start += 4; + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + else + printf (" DW_CFA_advance_loc4: %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_offset_extended: + reg = LEB (); + roffs = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_offset_extended: r%ld at cfa%+ld\n", + reg, roffs * fc->data_factor); + fc->col_type[reg] = DW_CFA_offset; + fc->col_offset[reg] = roffs * fc->data_factor; + break; + + case DW_CFA_restore_extended: + reg = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_restore_extended: r%ld\n", reg); + fc->col_type[reg] = cie->col_type[reg]; + fc->col_offset[reg] = cie->col_offset[reg]; + break; + + case DW_CFA_undefined: + reg = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_undefined: r%ld\n", reg); + fc->col_type[reg] = DW_CFA_undefined; + fc->col_offset[reg] = 0; + break; + + case DW_CFA_same_value: + reg = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_same_value: r%ld\n", reg); + fc->col_type[reg] = DW_CFA_same_value; + fc->col_offset[reg] = 0; + break; + + case DW_CFA_register: + reg = LEB (); + roffs = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_register: r%ld\n", reg); + fc->col_type[reg] = DW_CFA_register; + fc->col_offset[reg] = roffs; + break; + + case DW_CFA_remember_state: + if (! do_debug_frames_interp) + printf (" DW_CFA_remember_state\n"); + rs = (Frame_Chunk *) 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)); + memcpy (rs->col_type, fc->col_type, rs->ncols); + memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int)); + rs->next = remembered_state; + remembered_state = rs; + break; + + case DW_CFA_restore_state: + if (! do_debug_frames_interp) + printf (" DW_CFA_restore_state\n"); + rs = remembered_state; + remembered_state = rs->next; + frame_need_space (fc, rs->ncols-1); + memcpy (fc->col_type, rs->col_type, rs->ncols); + memcpy (fc->col_offset, rs->col_offset, rs->ncols * sizeof (int)); + free (rs->col_type); + free (rs->col_offset); + free (rs); + break; + + case DW_CFA_def_cfa: + fc->cfa_reg = LEB (); + fc->cfa_offset = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_def_cfa: r%d ofs %d\n", + fc->cfa_reg, fc->cfa_offset); + break; + + case DW_CFA_def_cfa_register: + fc->cfa_reg = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg); + break; + + case DW_CFA_def_cfa_offset: + fc->cfa_offset = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset); + break; + + case DW_CFA_nop: + if (! do_debug_frames_interp) + printf (" DW_CFA_nop\n"); + break; + +#ifndef DW_CFA_GNU_window_save +#define DW_CFA_GNU_window_save 0x2d +#endif + case DW_CFA_GNU_window_save: + if (! do_debug_frames_interp) + printf (" DW_CFA_GNU_window_save\n"); + break; + + case DW_CFA_GNU_args_size: + ul = LEB (); + if (! do_debug_frames_interp) + printf (" DW_CFA_GNU_args_size: %ld\n", ul); + break; + + case DW_CFA_GNU_negative_offset_extended: + reg = LEB (); + l = - LEB (); + frame_need_space (fc, reg); + if (! do_debug_frames_interp) + printf (" DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n", + reg, l * fc->data_factor); + fc->col_type[reg] = DW_CFA_offset; + fc->col_offset[reg] = l * fc->data_factor; + break; + + default: + fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op); + start = block_end; + } + } + + if (do_debug_frames_interp) + frame_display_row (fc, &need_col_headers, &max_regs); + + start = block_end; + } + + printf ("\n"); + + return 1; +} + +#undef GET +#undef LEB +#undef SLEB static int display_debug_not_supported (section, start, file) @@ -6401,8 +7926,9 @@ debug_displays[] = { ".debug_line", display_debug_lines, NULL }, { ".debug_aranges", display_debug_aranges, NULL }, { ".debug_pubnames", display_debug_pubnames, NULL }, - { ".debug_macinfo", display_debug_not_supported, NULL }, - { ".debug_frame", display_debug_not_supported, NULL }, + { ".debug_frame", display_debug_frames, NULL }, + { ".eh_frame", display_debug_frames, NULL }, + { ".debug_macinfo", display_debug_macinfo, NULL }, { ".debug_str", display_debug_not_supported, NULL }, { ".debug_static_func", display_debug_not_supported, NULL }, { ".debug_static_vars", display_debug_not_supported, NULL }, @@ -6427,10 +7953,15 @@ display_debug_section (section, file) return 0; } - GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *, - "debug section data"); + start = (unsigned char *) get_data (NULL, file, section->sh_offset, length, + _("debug section data")); + if (!start) + return 0; /* See if we know how to display the contents of this section. */ + if (strncmp (name, ".gnu.linkonce.wi.", 17) == 0) + name = ".debug_info"; + for (i = NUM_ELEM (debug_displays); i--;) if (strcmp (debug_displays[i].name, name) == 0) { @@ -6456,7 +7987,7 @@ process_section_contents (file) FILE * file; { Elf32_Internal_Shdr * section; - unsigned int i; + unsigned int i; if (! do_dump) return 1; @@ -6484,8 +8015,11 @@ process_section_contents (file) unsigned char * start; length = section->sh_size; - GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *, - "debug section data"); + start = ((unsigned char *) + get_data (NULL, file, section->sh_offset, length, + _("debug section data"))); + if (!start) + return 0; debug_displays[j].prescan (section, start, file); free (start); @@ -6581,73 +8115,77 @@ process_mips_specific (file) Elf32_External_Lib * elib; size_t cnt; - GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib), - elib, Elf32_External_Lib *, "liblist"); - - printf ("\nSection '.liblist' contains %lu entries:\n", - (unsigned long) liblistno); - fputs (" Library Time Stamp Checksum Version Flags\n", - stdout); - - for (cnt = 0; cnt < liblistno; ++cnt) + elib = ((Elf32_External_Lib *) + get_data (NULL, file, liblist_offset, + liblistno * sizeof (Elf32_External_Lib), + _("liblist"))); + if (elib) { - Elf32_Lib liblist; - time_t time; - char timebuf[20]; - struct tm * tmp; - - liblist.l_name = BYTE_GET (elib[cnt].l_name); - time = BYTE_GET (elib[cnt].l_time_stamp); - liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum); - liblist.l_version = BYTE_GET (elib[cnt].l_version); - liblist.l_flags = BYTE_GET (elib[cnt].l_flags); - - tmp = gmtime (&time); - sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u", - tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - - printf ("%3lu: %-20s %s %#10lx %-7ld", (unsigned long) cnt, - dynamic_strings + liblist.l_name, timebuf, - liblist.l_checksum, liblist.l_version); - - if (liblist.l_flags == 0) - puts (" NONE"); - else + printf ("\nSection '.liblist' contains %lu entries:\n", + (unsigned long) liblistno); + fputs (" Library Time Stamp Checksum Version Flags\n", + stdout); + + for (cnt = 0; cnt < liblistno; ++cnt) { - static const struct - { - const char * name; - int bit; - } - l_flags_vals[] = - { - { " EXACT_MATCH", LL_EXACT_MATCH }, - { " IGNORE_INT_VER", LL_IGNORE_INT_VER }, - { " REQUIRE_MINOR", LL_REQUIRE_MINOR }, - { " EXPORTS", LL_EXPORTS }, - { " DELAY_LOAD", LL_DELAY_LOAD }, - { " DELTA", LL_DELTA } - }; - int flags = liblist.l_flags; - size_t fcnt; - - for (fcnt = 0; - fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]); - ++fcnt) - if ((flags & l_flags_vals[fcnt].bit) != 0) + Elf32_Lib liblist; + time_t time; + char timebuf[20]; + struct tm * tmp; + + liblist.l_name = BYTE_GET (elib[cnt].l_name); + time = BYTE_GET (elib[cnt].l_time_stamp); + liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum); + liblist.l_version = BYTE_GET (elib[cnt].l_version); + liblist.l_flags = BYTE_GET (elib[cnt].l_flags); + + tmp = gmtime (&time); + sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + printf ("%3lu: %-20s %s %#10lx %-7ld", (unsigned long) cnt, + dynamic_strings + liblist.l_name, timebuf, + liblist.l_checksum, liblist.l_version); + + if (liblist.l_flags == 0) + puts (" NONE"); + else + { + static const struct { - fputs (l_flags_vals[fcnt].name, stdout); - flags ^= l_flags_vals[fcnt].bit; + const char * name; + int bit; } - if (flags != 0) - printf (" %#x", (unsigned int) flags); + l_flags_vals[] = + { + { " EXACT_MATCH", LL_EXACT_MATCH }, + { " IGNORE_INT_VER", LL_IGNORE_INT_VER }, + { " REQUIRE_MINOR", LL_REQUIRE_MINOR }, + { " EXPORTS", LL_EXPORTS }, + { " DELAY_LOAD", LL_DELAY_LOAD }, + { " DELTA", LL_DELTA } + }; + int flags = liblist.l_flags; + size_t fcnt; + + for (fcnt = 0; + fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]); + ++fcnt) + if ((flags & l_flags_vals[fcnt].bit) != 0) + { + fputs (l_flags_vals[fcnt].name, stdout); + flags ^= l_flags_vals[fcnt].bit; + } + if (flags != 0) + printf (" %#x", (unsigned int) flags); - puts (""); + puts (""); + } } - } - free (elib); + free (elib); + } } if (options_offset != 0) @@ -6663,194 +8201,194 @@ process_mips_specific (file) while (sect->sh_type != SHT_MIPS_OPTIONS) ++ sect; - GET_DATA_ALLOC (options_offset, sect->sh_size, eopt, - Elf_External_Options *, "options"); - - iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt)) - * sizeof (*iopt)); - if (iopt == NULL) + eopt = (Elf_External_Options *) get_data (NULL, file, options_offset, + sect->sh_size, _("options")); + if (eopt) { - error (_("Out of memory")); - return 0; - } + iopt = ((Elf_Internal_Options *) + malloc ((sect->sh_size / sizeof (eopt)) * sizeof (* iopt))); + if (iopt == NULL) + { + error (_("Out of memory")); + return 0; + } - offset = cnt = 0; - option = iopt; - - while (offset < sect->sh_size) - { - Elf_External_Options * eoption; + offset = cnt = 0; + option = iopt; - eoption = (Elf_External_Options *) ((char *) eopt + offset); + while (offset < sect->sh_size) + { + Elf_External_Options * eoption; - option->kind = BYTE_GET (eoption->kind); - option->size = BYTE_GET (eoption->size); - option->section = BYTE_GET (eoption->section); - option->info = BYTE_GET (eoption->info); + eoption = (Elf_External_Options *) ((char *) eopt + offset); - offset += option->size; - - ++option; - ++cnt; - } + option->kind = BYTE_GET (eoption->kind); + option->size = BYTE_GET (eoption->size); + option->section = BYTE_GET (eoption->section); + option->info = BYTE_GET (eoption->info); - printf (_("\nSection '%s' contains %d entries:\n"), - string_table + sect->sh_name, cnt); + offset += option->size; - option = iopt; - - while (cnt-- > 0) - { - size_t len; + ++option; + ++cnt; + } + + printf (_("\nSection '%s' contains %d entries:\n"), + SECTION_NAME (sect), cnt); - switch (option->kind) + option = iopt; + + while (cnt-- > 0) { - case ODK_NULL: - /* This shouldn't happen. */ - printf (" NULL %d %lx", option->section, option->info); - break; - case ODK_REGINFO: - printf (" REGINFO "); - if (elf_header.e_machine == EM_MIPS) - { - /* 32bit form. */ - Elf32_External_RegInfo *ereg; - Elf32_RegInfo reginfo; - - ereg = (Elf32_External_RegInfo *) (option + 1); - reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); - reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); - reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); - reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); - reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); - reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value); - - printf ("GPR %08lx GP 0x%lx\n", - reginfo.ri_gprmask, - (unsigned long) reginfo.ri_gp_value); - printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", - reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], - reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); - } - else + size_t len; + + switch (option->kind) { - /* 64 bit form. */ - Elf64_External_RegInfo * ereg; - Elf64_Internal_RegInfo reginfo; - - ereg = (Elf64_External_RegInfo *) (option + 1); - reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); - reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); - reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); - reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); - reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); - reginfo.ri_gp_value = BYTE_GET8 (ereg->ri_gp_value); - - printf ("GPR %08lx GP 0x", - reginfo.ri_gprmask); - printf_vma (reginfo.ri_gp_value); - printf ("\n"); - - printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", - reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], - reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); + case ODK_NULL: + /* This shouldn't happen. */ + printf (" NULL %d %lx", option->section, option->info); + break; + case ODK_REGINFO: + printf (" REGINFO "); + if (elf_header.e_machine == EM_MIPS) + { + /* 32bit form. */ + Elf32_External_RegInfo * ereg; + Elf32_RegInfo reginfo; + + ereg = (Elf32_External_RegInfo *) (option + 1); + reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); + reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); + reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); + reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); + reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); + reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value); + + printf ("GPR %08lx GP 0x%lx\n", + reginfo.ri_gprmask, + (unsigned long) reginfo.ri_gp_value); + printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", + reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], + reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); + } + else + { + /* 64 bit form. */ + Elf64_External_RegInfo * ereg; + Elf64_Internal_RegInfo reginfo; + + ereg = (Elf64_External_RegInfo *) (option + 1); + reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); + reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); + reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); + reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); + reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); + reginfo.ri_gp_value = BYTE_GET8 (ereg->ri_gp_value); + + printf ("GPR %08lx GP 0x", + reginfo.ri_gprmask); + printf_vma (reginfo.ri_gp_value); + printf ("\n"); + + printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", + reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], + reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); + } + ++option; + continue; + case ODK_EXCEPTIONS: + fputs (" EXCEPTIONS fpe_min(", stdout); + process_mips_fpe_exception (option->info & OEX_FPU_MIN); + fputs (") fpe_max(", stdout); + process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8); + fputs (")", stdout); + + if (option->info & OEX_PAGE0) + fputs (" PAGE0", stdout); + if (option->info & OEX_SMM) + fputs (" SMM", stdout); + if (option->info & OEX_FPDBUG) + fputs (" FPDBUG", stdout); + if (option->info & OEX_DISMISS) + fputs (" DISMISS", stdout); + break; + case ODK_PAD: + fputs (" PAD ", stdout); + if (option->info & OPAD_PREFIX) + fputs (" PREFIX", stdout); + if (option->info & OPAD_POSTFIX) + fputs (" POSTFIX", stdout); + if (option->info & OPAD_SYMBOL) + fputs (" SYMBOL", stdout); + break; + case ODK_HWPATCH: + fputs (" HWPATCH ", stdout); + if (option->info & OHW_R4KEOP) + fputs (" R4KEOP", stdout); + if (option->info & OHW_R8KPFETCH) + fputs (" R8KPFETCH", stdout); + if (option->info & OHW_R5KEOP) + fputs (" R5KEOP", stdout); + if (option->info & OHW_R5KCVTL) + fputs (" R5KCVTL", stdout); + break; + case ODK_FILL: + fputs (" FILL ", stdout); + /* XXX Print content of info word? */ + break; + case ODK_TAGS: + fputs (" TAGS ", stdout); + /* XXX Print content of info word? */ + break; + case ODK_HWAND: + fputs (" HWAND ", stdout); + if (option->info & OHWA0_R4KEOP_CHECKED) + fputs (" R4KEOP_CHECKED", stdout); + if (option->info & OHWA0_R4KEOP_CLEAN) + fputs (" R4KEOP_CLEAN", stdout); + break; + case ODK_HWOR: + fputs (" HWOR ", stdout); + if (option->info & OHWA0_R4KEOP_CHECKED) + fputs (" R4KEOP_CHECKED", stdout); + if (option->info & OHWA0_R4KEOP_CLEAN) + fputs (" R4KEOP_CLEAN", stdout); + break; + case ODK_GP_GROUP: + printf (" GP_GROUP %#06lx self-contained %#06lx", + option->info & OGP_GROUP, + (option->info & OGP_SELF) >> 16); + break; + case ODK_IDENT: + printf (" IDENT %#06lx self-contained %#06lx", + option->info & OGP_GROUP, + (option->info & OGP_SELF) >> 16); + break; + default: + /* This shouldn't happen. */ + printf (" %3d ??? %d %lx", + option->kind, option->section, option->info); + break; } + + len = sizeof (* eopt); + while (len < option->size) + if (((char *) option)[len] >= ' ' + && ((char *) option)[len] < 0x7f) + printf ("%c", ((char *) option)[len++]); + else + printf ("\\%03o", ((char *) option)[len++]); + + fputs ("\n", stdout); ++option; - continue; - case ODK_EXCEPTIONS: - fputs (" EXCEPTIONS fpe_min(", stdout); - process_mips_fpe_exception (option->info & OEX_FPU_MIN); - fputs (") fpe_max(", stdout); - process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8); - fputs (")", stdout); - - if (option->info & OEX_PAGE0) - fputs (" PAGE0", stdout); - if (option->info & OEX_SMM) - fputs (" SMM", stdout); - if (option->info & OEX_FPDBUG) - fputs (" FPDBUG", stdout); - if (option->info & OEX_DISMISS) - fputs (" DISMISS", stdout); - break; - case ODK_PAD: - fputs (" PAD ", stdout); - if (option->info & OPAD_PREFIX) - fputs (" PREFIX", stdout); - if (option->info & OPAD_POSTFIX) - fputs (" POSTFIX", stdout); - if (option->info & OPAD_SYMBOL) - fputs (" SYMBOL", stdout); - break; - case ODK_HWPATCH: - fputs (" HWPATCH ", stdout); - if (option->info & OHW_R4KEOP) - fputs (" R4KEOP", stdout); - if (option->info & OHW_R8KPFETCH) - fputs (" R8KPFETCH", stdout); - if (option->info & OHW_R5KEOP) - fputs (" R5KEOP", stdout); - if (option->info & OHW_R5KCVTL) - fputs (" R5KCVTL", stdout); - break; - case ODK_FILL: - fputs (" FILL ", stdout); - /* XXX Print content of info word? */ - break; - case ODK_TAGS: - fputs (" TAGS ", stdout); - /* XXX Print content of info word? */ - break; - case ODK_HWAND: - fputs (" HWAND ", stdout); - if (option->info & OHWA0_R4KEOP_CHECKED) - fputs (" R4KEOP_CHECKED", stdout); - if (option->info & OHWA0_R4KEOP_CLEAN) - fputs (" R4KEOP_CLEAN", stdout); - break; - case ODK_HWOR: - fputs (" HWOR ", stdout); - if (option->info & OHWA0_R4KEOP_CHECKED) - fputs (" R4KEOP_CHECKED", stdout); - if (option->info & OHWA0_R4KEOP_CLEAN) - fputs (" R4KEOP_CLEAN", stdout); - break; - case ODK_GP_GROUP: - printf (" GP_GROUP %#06lx self-contained %#06lx", - option->info & OGP_GROUP, - (option->info & OGP_SELF) >> 16); - break; - case ODK_IDENT: - printf (" IDENT %#06lx self-contained %#06lx", - option->info & OGP_GROUP, - (option->info & OGP_SELF) >> 16); - break; - default: - /* This shouldn't happen. */ - printf (" %3d ??? %d %lx", - option->kind, option->section, option->info); - break; } - len = sizeof (*eopt); - while (len < option->size) - if (((char *) option)[len] >= ' ' - && ((char *) option)[len] < 0x7f) - printf ("%c", ((char *) option)[len++]); - else - printf ("\\%03o", ((char *) option)[len++]); - - fputs ("\n", stdout); - ++option; + free (eopt); } - - free (eopt); } if (conflicts_offset != 0 && conflictsno != 0) { - Elf32_External_Conflict * econf32; - Elf64_External_Conflict * econf64; Elf32_Conflict * iconf; size_t cnt; @@ -6860,7 +8398,7 @@ process_mips_specific (file) return 0; } - iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (*iconf)); + iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (* iconf)); if (iconf == NULL) { error (_("Out of memory")); @@ -6869,19 +8407,35 @@ process_mips_specific (file) if (is_32bit_elf) { - GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf32), - econf32, Elf32_External_Conflict *, "conflict"); + Elf32_External_Conflict * econf32; + + econf32 = ((Elf32_External_Conflict *) + get_data (NULL, file, conflicts_offset, + conflictsno * sizeof (* econf32), + _("conflict"))); + if (!econf32) + return 0; for (cnt = 0; cnt < conflictsno; ++cnt) iconf[cnt] = BYTE_GET (econf32[cnt]); + + free (econf32); } else { - GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf64), - econf64, Elf64_External_Conflict *, "conflict"); + Elf64_External_Conflict * econf64; + + econf64 = ((Elf64_External_Conflict *) + get_data (NULL, file, conflicts_offset, + conflictsno * sizeof (* econf64), + _("conflict"))); + if (!econf64) + return 0; for (cnt = 0; cnt < conflictsno; ++cnt) iconf[cnt] = BYTE_GET (econf64[cnt]); + + free (econf64); } printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno); @@ -6938,7 +8492,7 @@ process_note (pnote) { printf (" %s\t\t0x%08lx\t%s\n", pnote->namesz ? pnote->namedata : "(NONE)", - pnote->descsz, get_note_type (pnote->type)); + pnote->descsz, get_note_type (pnote->type)); return 1; } @@ -6956,7 +8510,10 @@ process_corefile_note_segment (file, offset, length) if (length <= 0) return 0; - GET_DATA_ALLOC (offset, length, pnotes, Elf_External_Note *, "notes"); + pnotes = (Elf_External_Note *) get_data (NULL, file, offset, length, + _("notes")); + if (!pnotes) + return 0; external = pnotes; @@ -6975,7 +8532,7 @@ process_corefile_note_segment (file, offset, length) inote.descsz = BYTE_GET (external->descsz); inote.descdata = inote.namedata + align_power (inote.namesz, 2); inote.descpos = offset + (inote.descdata - (char *) pnotes); - + external = (Elf_External_Note *)(inote.descdata + align_power (inote.descsz, 2)); /* Verify that name is null terminated. It appears that at least @@ -6985,17 +8542,17 @@ process_corefile_note_segment (file, offset, length) if (inote.namedata[inote.namesz] != '\0') { temp = malloc (inote.namesz + 1); - + if (temp == NULL) { error (_("Out of memory\n")); res = 0; break; } - + strncpy (temp, inote.namedata, inote.namesz); temp[inote.namesz] = 0; - + /* warn (_("'%s' NOTE name not properly null terminated\n"), temp); */ inote.namedata = temp; } @@ -7090,7 +8647,7 @@ process_arch_specific (file) switch (elf_header.e_machine) { case EM_MIPS: - case EM_MIPS_RS4_BE: + case EM_MIPS_RS3_LE: return process_mips_specific (file); break; default: @@ -7230,6 +8787,8 @@ process_file (file_name) process_relocs (file); + process_unwind (file); + process_symbol_table (file); process_syminfo (file); @@ -7254,6 +8813,7 @@ process_file (file_name) { free (string_table); string_table = NULL; + string_table_length = 0; } if (dynamic_strings)