diff options
Diffstat (limited to 'contrib/binutils/binutils/readelf.c')
-rw-r--r-- | contrib/binutils/binutils/readelf.c | 1940 |
1 files changed, 1249 insertions, 691 deletions
diff --git a/contrib/binutils/binutils/readelf.c b/contrib/binutils/binutils/readelf.c index 8858d57..d506925 100644 --- a/contrib/binutils/binutils/readelf.c +++ b/contrib/binutils/binutils/readelf.c @@ -1,5 +1,5 @@ /* readelf.c -- display contents of an ELF format file - Copyright (C) 1998, 99, 2000 Free Software Foundation, Inc. + Copyright (C) 1998, 99, 2000, 2001 Free Software Foundation, Inc. Originally developed by Eric Youngdale <eric@andante.jic.com> Modifications by Nick Clifton <nickc@cygnus.com> @@ -70,6 +70,10 @@ #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 "bucomm.h" #include "getopt.h" @@ -81,6 +85,7 @@ unsigned int rela_addr; unsigned int rela_size; char * dynamic_strings; char * string_table; +unsigned long string_table_length; unsigned long num_dynamic_syms; Elf_Internal_Sym * dynamic_symbols; Elf_Internal_Syminfo * dynamic_syminfo; @@ -110,6 +115,7 @@ int do_debug_abbrevs; int do_debug_lines; int do_debug_pubnames; int do_debug_aranges; +int do_debug_frames; int do_arch; int do_notes; int is_32bit_elf; @@ -147,6 +153,7 @@ static const char * get_dynamic_type PARAMS ((unsigned long)); static int dump_relocations PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, unsigned long, char *, int)); static char * get_file_type PARAMS ((unsigned)); static char * get_machine_name PARAMS ((unsigned)); +static void decode_ARM_machine_flags PARAMS ((unsigned, char [])); static char * get_machine_flags PARAMS ((unsigned, unsigned)); static const char * get_mips_segment_type PARAMS ((unsigned long)); static const char * get_parisc_segment_type PARAMS ((unsigned long)); @@ -193,6 +200,7 @@ static int display_debug_not_supported PARAMS ((Elf32_Internal_Sh 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 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)); @@ -203,9 +211,9 @@ static char * get_FORM_name PARAMS ((unsigned long)); static void free_abbrevs PARAMS ((void)); static void add_abbrev PARAMS ((unsigned long, unsigned long, int)); static void add_abbrev_attr PARAMS ((unsigned long, unsigned long)); -static unsigned char * read_and_display_attr PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long)); +static unsigned char * read_and_display_attr PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, unsigned long)); static unsigned char * display_block PARAMS ((unsigned char *, unsigned long)); -static void decode_location_expression PARAMS ((unsigned char *, unsigned int)); +static void decode_location_expression PARAMS ((unsigned char *, unsigned int, unsigned long)); static void request_dump PARAMS ((unsigned int, char)); static const char * get_elf_class PARAMS ((unsigned char)); static const char * get_data_encoding PARAMS ((unsigned char)); @@ -225,7 +233,9 @@ typedef int Elf32_Word; #endif #define UNKNOWN -1 -#define SECTION_NAME(X) (string_table + (X)->sh_name) +#define SECTION_NAME(X) ((X) == NULL ? "<none>" : \ + ((X)->sh_name >= string_table_length \ + ? "<corrupt>" : string_table + (X)->sh_name)) #define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ @@ -419,15 +429,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); @@ -448,7 +458,7 @@ print_vma (vma, mode) printf ("++%ld", _bfd_int64_low (vma)); else printf ("%ld", _bfd_int64_low (vma)); -#endif +#endif break; case DEC_5: @@ -460,13 +470,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)); @@ -528,8 +538,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; @@ -561,6 +571,11 @@ 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: return TRUE; case EM_MMA: @@ -862,6 +877,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; @@ -872,6 +888,21 @@ 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; } if (rtype == NULL) @@ -1203,7 +1234,7 @@ get_machine_name (e_machine) 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_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"; @@ -1215,7 +1246,7 @@ get_machine_name (e_machine) 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"; @@ -1240,12 +1271,130 @@ get_machine_name (e_machine) 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"; default: sprintf (buff, _("<unknown>: %x"), e_machine); return buff; } } +static void +decode_ARM_machine_flags (e_flags, buf) + unsigned e_flags; + char buf[]; +{ + unsigned eabi; + int unknown = 0; + + eabi = EF_ARM_EABI_VERSION (e_flags); + e_flags &= ~ EF_ARM_EABIMASK; + + /* Handle "generic" ARM flags. */ + if (e_flags & EF_ARM_RELEXEC) + { + 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, ", <unknown EABI>"); + if (e_flags) + unknown = 1; + break; + + case EF_ARM_EABI_VER1: + 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. */ + strcat (buf, ", sorted symbol tables"); + break; + + default: + unknown = 1; + break; + } + } + break; + + case EF_ARM_EABI_UNKNOWN: + 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: + strcat (buf, ", interworking enabled"); + break; + + case EF_APCS_26: + strcat (buf, ", uses APCS/26"); + break; + + case EF_APCS_FLOAT: + strcat (buf, ", uses APCS/float"); + break; + + case EF_PIC: + strcat (buf, ", position independent"); + break; + + case EF_ALIGN8: + strcat (buf, ", 8 bit structure alignment"); + break; + + case EF_NEW_ABI: + strcat (buf, ", uses new ABI"); + break; + + case EF_OLD_ABI: + strcat (buf, ", uses old ABI"); + break; + + case EF_SOFT_FLOAT: + strcat (buf, ", software FP"); + break; + + default: + unknown = 1; + break; + } + } + } + + if (unknown) + strcat (buf,", <unknown>"); +} + static char * get_machine_flags (e_flags, e_machine) unsigned e_flags; @@ -1254,7 +1403,7 @@ get_machine_flags (e_flags, e_machine) static char buf [1024]; buf[0] = '\0'; - + if (e_flags) { switch (e_machine) @@ -1262,6 +1411,10 @@ get_machine_flags (e_flags, e_machine) default: break; + case EM_ARM: + decode_ARM_machine_flags (e_flags, buf); + break; + case EM_68K: if (e_flags & EF_CPU32) strcat (buf, ", cpu32"); @@ -1327,6 +1480,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: @@ -1383,7 +1557,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"); @@ -1598,6 +1772,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"; @@ -1691,7 +1867,7 @@ usage () fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n")); fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n")); fprintf (stdout, _(" Dump the contents of section <number>\n")); - fprintf (stdout, _(" -w[liapr] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges]\n")); + fprintf (stdout, _(" -w[liaprf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=frames]\n")); fprintf (stdout, _(" Display the contents of DWARF2 debug sections\n")); #ifdef SUPPORT_DISASSEMBLY fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n")); @@ -1851,6 +2027,11 @@ parse_args (argc, argv) do_debug_aranges = 1; break; + case 'f': + case 'F': + do_debug_frames = 1; + break; + default: warn (_("Unrecognised debug option '%s'\n"), optarg); break; @@ -1943,7 +2124,7 @@ get_osabi_name (osabi) case ELFOSABI_LINUX: return _("UNIX - Linux"); case ELFOSABI_HURD: return _("GNU/Hurd"); case ELFOSABI_SOLARIS: return _("UNIX - Solaris"); - case ELFOSABI_MONTEREY: return _("UNIX - Monterey"); + case ELFOSABI_AIX: return _("UNIX - AIX"); case ELFOSABI_IRIX: return _("UNIX - IRIX"); case ELFOSABI_FREEBSD: return _("UNIX - FreeBSD"); case ELFOSABI_TRU64: return _("UNIX - TRU64"); @@ -2001,7 +2182,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: ")); @@ -2009,7 +2190,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)); @@ -2147,7 +2328,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")); @@ -2460,14 +2641,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; @@ -2478,7 +2659,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) { @@ -2495,7 +2677,7 @@ get_elf_section_flags (sh_flags) break; } } - + return buff; } @@ -2533,12 +2715,10 @@ process_section_headers (file) if (section->sh_size != 0) { - unsigned long string_table_offset; - - string_table_offset = section->sh_offset; - 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 @@ -2578,7 +2758,7 @@ process_section_headers (file) dynamic_strings, char *, "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) && strncmp (name, ".debug_", 7) == 0) { name += 7; @@ -2589,16 +2769,23 @@ 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)) ) 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")); @@ -2620,15 +2807,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); @@ -2642,9 +2829,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, @@ -2652,9 +2839,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; } @@ -2904,7 +3092,7 @@ dynamic_segment_parisc_val (entry) first = 0; val ^= flags[cnt].bit; } - + if (val != 0 || first) { if (! first) @@ -2913,7 +3101,7 @@ dynamic_segment_parisc_val (entry) } } break; - + default: print_vma (entry->d_un.d_ptr, PREFIX_HEX); break; @@ -3188,7 +3376,7 @@ process_dynamic_segment (file) { if (do_dynamic) { - const char *dtype; + const char * dtype; putchar (' '); print_vma (entry->d_tag, FULL_HEX); @@ -3205,7 +3393,7 @@ 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: @@ -3809,7 +3997,8 @@ process_version_sections (file) for (cnt = 0; cnt < total; cnt += 4) { int j, nn; - char *name; + int check_def, check_need; + char * name; printf (" %03x:", cnt); @@ -3828,111 +4017,20 @@ 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) { - /* We must test both. */ - Elf_Internal_Verneed ivn; - unsigned long offset; - - offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)] - - loadaddr; - - do - { - Elf_External_Verneed evn; - Elf_External_Vernaux evna; - Elf_Internal_Vernaux ivna; - unsigned long vna_off; - - GET_DATA (offset, 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; - - do - { - GET_DATA (vna_off, evna, - "version need aux (1)"); - - ivna.vna_next = BYTE_GET (evna.vna_next); - ivna.vna_other = BYTE_GET (evna.vna_other); - - vna_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; - } - 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; - } - while (ivn.vn_next); + if (symbols [cnt + j].st_shndx == SHN_UNDEF) + check_def = 0; + else + check_need = 0; } - else if (symbols [cnt + j].st_shndx == SHN_UNDEF) + + if (check_need + && version_info [DT_VERSIONTAGIDX (DT_VERNEED)]) { Elf_Internal_Verneed ivn; unsigned long offset; @@ -3976,6 +4074,7 @@ process_version_sections (file) name, 12 - (int) strlen (name), ")"); + check_def = 0; break; } @@ -3983,7 +4082,9 @@ process_version_sections (file) } while (ivn.vn_next); } - else if (data [cnt + j] != 0x8001) + + if (check_def && data [cnt + j] != 0x8001 + && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) { Elf_Internal_Verdef ivd; Elf_External_Verdef evd; @@ -4161,10 +4262,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) { @@ -4201,8 +4302,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; @@ -4269,7 +4370,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))); @@ -4360,7 +4461,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; @@ -4418,7 +4520,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; @@ -4474,13 +4577,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); @@ -4816,7 +4919,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)); @@ -4861,7 +4964,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")); @@ -4896,7 +4999,7 @@ display_debug_lines (section, start, file) printf (_(" Line Range: %d\n"), info.li_line_range); printf (_(" Opcode Base: %d\n"), info.li_opcode_base); - end_of_sequence = data + info.li_length + sizeof (info.li_length); + end_of_sequence = data + info.li_length + sizeof (external->li_length); reset_state_machine (info.li_default_is_stmt); @@ -4921,7 +5024,7 @@ display_debug_lines (section, start, file) { printf (_(" %s\n"), data); - data += strlen (data) + 1; + data += strlen ((char *) data) + 1; } } @@ -4938,13 +5041,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; @@ -5098,7 +5201,7 @@ display_debug_pubnames (section, start, file) warn (_("Only DWARF 2 pubnames are currently supported\n")); warned = 1; } - + continue; } @@ -5121,7 +5224,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); @@ -5498,7 +5601,7 @@ display_debug_abbrev (section, start, file) 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)); @@ -5548,500 +5651,336 @@ display_block (data, length) } static void -decode_location_expression (data, pointer_size) +decode_location_expression (data, pointer_size, length) unsigned char * data; unsigned int pointer_size; + unsigned long length; { - unsigned char op; - int bytes_read; - unsigned long uvalue; - - op = * data ++; + unsigned op; + int bytes_read; + unsigned long uvalue; + unsigned char * end = data + length; - switch (op) + while (data < end) { - case DW_OP_addr: - printf ("DW_OP_addr: %lx", (unsigned long) byte_get (data, pointer_size)); - break; - case DW_OP_deref: - printf ("DW_OP_deref"); - break; - case DW_OP_const1u: - printf ("DW_OP_const1u: %lu", (unsigned long) byte_get (data, 1)); - break; - case DW_OP_const1s: - printf ("DW_OP_const1s: %ld", (long) byte_get (data, 1)); - break; - case DW_OP_const2u: - printf ("DW_OP_const2u: %lu", (unsigned long) byte_get (data, 2)); - break; - case DW_OP_const2s: - printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2)); - break; - case DW_OP_const4u: - printf ("DW_OP_const4u: %lu", (unsigned long) byte_get (data, 4)); - break; - case DW_OP_const4s: - printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4)); - break; - case DW_OP_const8u: - printf ("DW_OP_const8u: %lu %lu", (unsigned long) byte_get (data, 4), - (unsigned long) byte_get (data + 4, 4)); - break; - case DW_OP_const8s: - printf ("DW_OP_const8s: %ld %ld", (long) byte_get (data, 4), - (long) byte_get (data + 4, 4)); - break; - case DW_OP_constu: - printf ("DW_OP_constu: %lu", read_leb128 (data, NULL, 0)); - break; - case DW_OP_consts: - printf ("DW_OP_consts: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_dup: - printf ("DW_OP_dup"); - break; - case DW_OP_drop: - printf ("DW_OP_drop"); - break; - case DW_OP_over: - printf ("DW_OP_over"); - break; - case DW_OP_pick: - printf ("DW_OP_pick: %ld", (unsigned long) byte_get (data, 1)); - break; - case DW_OP_swap: - printf ("DW_OP_swap"); - break; - case DW_OP_rot: - printf ("DW_OP_rot"); - break; - case DW_OP_xderef: - printf ("DW_OP_xderef"); - break; - case DW_OP_abs: - printf ("DW_OP_abs"); - break; - case DW_OP_and: - printf ("DW_OP_and"); - break; - case DW_OP_div: - printf ("DW_OP_div"); - break; - case DW_OP_minus: - printf ("DW_OP_minus"); - break; - case DW_OP_mod: - printf ("DW_OP_mod"); - break; - case DW_OP_mul: - printf ("DW_OP_mul"); - break; - case DW_OP_neg: - printf ("DW_OP_neg"); - break; - case DW_OP_not: - printf ("DW_OP_not"); - break; - case DW_OP_or: - printf ("DW_OP_or"); - break; - case DW_OP_plus: - printf ("DW_OP_plus"); - break; - case DW_OP_plus_uconst: - printf ("DW_OP_plus_uconst: %lu", read_leb128 (data, NULL, 0)); - break; - case DW_OP_shl: - printf ("DW_OP_shl"); - break; - case DW_OP_shr: - printf ("DW_OP_shr"); - break; - case DW_OP_shra: - printf ("DW_OP_shra"); - break; - case DW_OP_xor: - printf ("DW_OP_xor"); - break; - case DW_OP_bra: - printf ("DW_OP_bra: %ld", (long) byte_get (data, 2)); - break; - case DW_OP_eq: - printf ("DW_OP_eq"); - break; - case DW_OP_ge: - printf ("DW_OP_ge"); - break; - case DW_OP_gt: - printf ("DW_OP_gt"); - break; - case DW_OP_le: - printf ("DW_OP_le"); - break; - case DW_OP_lt: - printf ("DW_OP_lt"); - break; - case DW_OP_ne: - printf ("DW_OP_ne"); - break; - case DW_OP_skip: - printf ("DW_OP_skip: %ld", (long) byte_get (data, 2)); - break; - case DW_OP_lit0: - printf ("DW_OP_lit0"); - break; - case DW_OP_lit1: - printf ("DW_OP_lit1"); - break; - case DW_OP_lit2: - printf ("DW_OP_lit2"); - break; - case DW_OP_lit3: - printf ("DW_OP_lit3"); - break; - case DW_OP_lit4: - printf ("DW_OP_lit4"); - break; - case DW_OP_lit5: - printf ("DW_OP_lit5"); - break; - case DW_OP_lit6: - printf ("DW_OP_lit6"); - break; - case DW_OP_lit7: - printf ("DW_OP_lit7"); - break; - case DW_OP_lit8: - printf ("DW_OP_lit8"); - break; - case DW_OP_lit9: - printf ("DW_OP_lit9"); - break; - case DW_OP_lit10: - printf ("DW_OP_lit10"); - break; - case DW_OP_lit11: - printf ("DW_OP_lit11"); - break; - case DW_OP_lit12: - printf ("DW_OP_lit12"); - break; - case DW_OP_lit13: - printf ("DW_OP_lit13"); - break; - case DW_OP_lit14: - printf ("DW_OP_lit14"); - break; - case DW_OP_lit15: - printf ("DW_OP_lit15"); - break; - case DW_OP_lit16: - printf ("DW_OP_lit16"); - break; - case DW_OP_lit17: - printf ("DW_OP_lit17"); - break; - case DW_OP_lit18: - printf ("DW_OP_lit18"); - break; - case DW_OP_lit19: - printf ("DW_OP_lit19"); - break; - case DW_OP_lit20: - printf ("DW_OP_lit20"); - break; - case DW_OP_lit21: - printf ("DW_OP_lit21"); - break; - case DW_OP_lit22: - printf ("DW_OP_lit22"); - break; - case DW_OP_lit23: - printf ("DW_OP_lit23"); - break; - case DW_OP_lit24: - printf ("DW_OP_lit24"); - break; - case DW_OP_lit25: - printf ("DW_OP_lit25"); - break; - case DW_OP_lit26: - printf ("DW_OP_lit26"); - break; - case DW_OP_lit27: - printf ("DW_OP_lit27"); - break; - case DW_OP_lit28: - printf ("DW_OP_lit28"); - break; - case DW_OP_lit29: - printf ("DW_OP_lit29"); - break; - case DW_OP_lit30: - printf ("DW_OP_lit30"); - break; - case DW_OP_lit31: - printf ("DW_OP_lit31"); - break; - case DW_OP_reg0: - printf ("DW_OP_reg0"); - break; - case DW_OP_reg1: - printf ("DW_OP_reg1"); - break; - case DW_OP_reg2: - printf ("DW_OP_reg2"); - break; - case DW_OP_reg3: - printf ("DW_OP_reg3"); - break; - case DW_OP_reg4: - printf ("DW_OP_reg4"); - break; - case DW_OP_reg5: - printf ("DW_OP_reg5"); - break; - case DW_OP_reg6: - printf ("DW_OP_reg6"); - break; - case DW_OP_reg7: - printf ("DW_OP_reg7"); - break; - case DW_OP_reg8: - printf ("DW_OP_reg8"); - break; - case DW_OP_reg9: - printf ("DW_OP_reg9"); - break; - case DW_OP_reg10: - printf ("DW_OP_reg10"); - break; - case DW_OP_reg11: - printf ("DW_OP_reg11"); - break; - case DW_OP_reg12: - printf ("DW_OP_reg12"); - break; - case DW_OP_reg13: - printf ("DW_OP_reg13"); - break; - case DW_OP_reg14: - printf ("DW_OP_reg14"); - break; - case DW_OP_reg15: - printf ("DW_OP_reg15"); - break; - case DW_OP_reg16: - printf ("DW_OP_reg16"); - break; - case DW_OP_reg17: - printf ("DW_OP_reg17"); - break; - case DW_OP_reg18: - printf ("DW_OP_reg18"); - break; - case DW_OP_reg19: - printf ("DW_OP_reg19"); - break; - case DW_OP_reg20: - printf ("DW_OP_reg20"); - break; - case DW_OP_reg21: - printf ("DW_OP_reg21"); - break; - case DW_OP_reg22: - printf ("DW_OP_reg22"); - break; - case DW_OP_reg23: - printf ("DW_OP_reg23"); - break; - case DW_OP_reg24: - printf ("DW_OP_reg24"); - break; - case DW_OP_reg25: - printf ("DW_OP_reg25"); - break; - case DW_OP_reg26: - printf ("DW_OP_reg26"); - break; - case DW_OP_reg27: - printf ("DW_OP_reg27"); - break; - case DW_OP_reg28: - printf ("DW_OP_reg28"); - break; - case DW_OP_reg29: - printf ("DW_OP_reg29"); - break; - case DW_OP_reg30: - printf ("DW_OP_reg30"); - break; - case DW_OP_reg31: - printf ("DW_OP_reg31"); - break; - case DW_OP_breg0: - printf ("DW_OP_breg0: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg1: - printf ("DW_OP_breg1: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg2: - printf ("DW_OP_breg2: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg3: - printf ("DW_OP_breg3: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg4: - printf ("DW_OP_breg4: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg5: - printf ("DW_OP_breg5: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg6: - printf ("DW_OP_breg6: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg7: - printf ("DW_OP_breg7: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg8: - printf ("DW_OP_breg8: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg9: - printf ("DW_OP_breg9: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg10: - printf ("DW_OP_breg10: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg11: - printf ("DW_OP_breg11: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg12: - printf ("DW_OP_breg12: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg13: - printf ("DW_OP_breg13: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg14: - printf ("DW_OP_breg14: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg15: - printf ("DW_OP_breg15: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg16: - printf ("DW_OP_breg16: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg17: - printf ("DW_OP_breg17: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg18: - printf ("DW_OP_breg18: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg19: - printf ("DW_OP_breg19: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg20: - printf ("DW_OP_breg20: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg21: - printf ("DW_OP_breg21: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg22: - printf ("DW_OP_breg22: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg23: - printf ("DW_OP_breg23: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg24: - printf ("DW_OP_breg24: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg25: - printf ("DW_OP_breg25: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg26: - printf ("DW_OP_breg26: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg27: - printf ("DW_OP_breg27: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg28: - printf ("DW_OP_breg28: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg29: - printf ("DW_OP_breg29: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg30: - printf ("DW_OP_breg30: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_breg31: - printf ("DW_OP_breg31: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_regx: - printf ("DW_OP_regx: %lu", read_leb128 (data, NULL, 0)); - break; - case DW_OP_fbreg: - printf ("DW_OP_fbreg: %ld", read_leb128 (data, NULL, 1)); - break; - case DW_OP_bregx: - uvalue = read_leb128 (data, &bytes_read, 0); - printf ("DW_OP_bregx: %lu %ld", uvalue, - read_leb128 (data + bytes_read, NULL, 1)); - break; - case DW_OP_piece: - printf ("DW_OP_piece: %lu", read_leb128 (data, NULL, 0)); - break; - case DW_OP_deref_size: - printf ("DW_OP_deref_size: %ld", (long) byte_get (data, 1)); - break; - case DW_OP_xderef_size: - printf ("DW_OP_xderef_size: %ld", (long) byte_get (data, 1)); - break; - case DW_OP_nop: - printf ("DW_OP_nop"); - break; + op = * data ++; - default: - if (op >= DW_OP_lo_user - && op <= DW_OP_hi_user) - printf (_("(User defined location op)")); - else - printf (_("(Unknown location op)")); - break; + switch (op) + { + case DW_OP_addr: + printf ("DW_OP_addr: %lx", + (unsigned long) byte_get (data, pointer_size)); + data += pointer_size; + break; + case DW_OP_deref: + printf ("DW_OP_deref"); + break; + case DW_OP_const1u: + printf ("DW_OP_const1u: %lu", (unsigned long) byte_get (data++, 1)); + break; + case DW_OP_const1s: + printf ("DW_OP_const1s: %ld", (long) byte_get (data++, 1)); + break; + case DW_OP_const2u: + printf ("DW_OP_const2u: %lu", (unsigned long) byte_get (data, 2)); + data += 2; + break; + case DW_OP_const2s: + printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2)); + data += 2; + break; + case DW_OP_const4u: + printf ("DW_OP_const4u: %lu", (unsigned long) byte_get (data, 4)); + data += 4; + break; + case DW_OP_const4s: + printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4)); + data += 4; + break; + case DW_OP_const8u: + printf ("DW_OP_const8u: %lu %lu", (unsigned long) byte_get (data, 4), + (unsigned long) byte_get (data + 4, 4)); + data += 8; + break; + case DW_OP_const8s: + printf ("DW_OP_const8s: %ld %ld", (long) byte_get (data, 4), + (long) byte_get (data + 4, 4)); + data += 8; + break; + case DW_OP_constu: + printf ("DW_OP_constu: %lu", read_leb128 (data, &bytes_read, 0)); + data += bytes_read; + break; + case DW_OP_consts: + printf ("DW_OP_consts: %ld", read_leb128 (data, &bytes_read, 1)); + data += bytes_read; + break; + case DW_OP_dup: + printf ("DW_OP_dup"); + break; + case DW_OP_drop: + printf ("DW_OP_drop"); + break; + case DW_OP_over: + printf ("DW_OP_over"); + break; + case DW_OP_pick: + printf ("DW_OP_pick: %ld", (unsigned long) byte_get (data++, 1)); + break; + case DW_OP_swap: + printf ("DW_OP_swap"); + break; + case DW_OP_rot: + printf ("DW_OP_rot"); + break; + case DW_OP_xderef: + printf ("DW_OP_xderef"); + break; + case DW_OP_abs: + printf ("DW_OP_abs"); + break; + case DW_OP_and: + printf ("DW_OP_and"); + break; + case DW_OP_div: + printf ("DW_OP_div"); + break; + case DW_OP_minus: + printf ("DW_OP_minus"); + break; + case DW_OP_mod: + printf ("DW_OP_mod"); + break; + case DW_OP_mul: + printf ("DW_OP_mul"); + break; + case DW_OP_neg: + printf ("DW_OP_neg"); + break; + case DW_OP_not: + printf ("DW_OP_not"); + break; + case DW_OP_or: + printf ("DW_OP_or"); + break; + case DW_OP_plus: + printf ("DW_OP_plus"); + break; + case DW_OP_plus_uconst: + printf ("DW_OP_plus_uconst: %lu", + read_leb128 (data, &bytes_read, 0)); + data += bytes_read; + break; + case DW_OP_shl: + printf ("DW_OP_shl"); + break; + case DW_OP_shr: + printf ("DW_OP_shr"); + break; + case DW_OP_shra: + printf ("DW_OP_shra"); + break; + case DW_OP_xor: + printf ("DW_OP_xor"); + break; + case DW_OP_bra: + printf ("DW_OP_bra: %ld", (long) byte_get (data, 2)); + data += 2; + break; + case DW_OP_eq: + printf ("DW_OP_eq"); + break; + case DW_OP_ge: + printf ("DW_OP_ge"); + break; + case DW_OP_gt: + printf ("DW_OP_gt"); + break; + case DW_OP_le: + printf ("DW_OP_le"); + break; + case DW_OP_lt: + printf ("DW_OP_lt"); + break; + case DW_OP_ne: + printf ("DW_OP_ne"); + break; + case DW_OP_skip: + printf ("DW_OP_skip: %ld", (long) byte_get (data, 2)); + data += 2; + break; + + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + printf ("DW_OP_lit%d", op - DW_OP_lit0); + break; + + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + printf ("DW_OP_reg%d", op - DW_OP_reg0); + break; + + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + printf ("DW_OP_breg%d: %ld", op - DW_OP_breg0, + read_leb128 (data, &bytes_read, 1)); + data += bytes_read; + break; + + case DW_OP_regx: + printf ("DW_OP_regx: %lu", read_leb128 (data, &bytes_read, 0)); + data += bytes_read; + break; + case DW_OP_fbreg: + printf ("DW_OP_fbreg: %ld", read_leb128 (data, &bytes_read, 1)); + data += bytes_read; + break; + case DW_OP_bregx: + uvalue = read_leb128 (data, &bytes_read, 0); + data += bytes_read; + printf ("DW_OP_bregx: %lu %ld", uvalue, + read_leb128 (data, &bytes_read, 1)); + data += bytes_read; + break; + case DW_OP_piece: + printf ("DW_OP_piece: %lu", read_leb128 (data, &bytes_read, 0)); + data += bytes_read; + break; + case DW_OP_deref_size: + printf ("DW_OP_deref_size: %ld", (long) byte_get (data++, 1)); + break; + case DW_OP_xderef_size: + printf ("DW_OP_xderef_size: %ld", (long) byte_get (data++, 1)); + break; + case DW_OP_nop: + printf ("DW_OP_nop"); + break; + + default: + if (op >= DW_OP_lo_user + && op <= DW_OP_hi_user) + printf (_("(User defined location op)")); + else + printf (_("(Unknown location op)")); + /* No way to tell where the next op is, so just bail. */ + return; + } } } static unsigned char * -read_and_display_attr (attribute, form, data, pointer_size) +read_and_display_attr (attribute, form, data, cu_offset, pointer_size) unsigned long attribute; unsigned long form; unsigned char * data; + unsigned long cu_offset; unsigned long pointer_size; { unsigned long uvalue = 0; unsigned char * block_start = NULL; int bytes_read; - int is_ref = 0; printf (" %-18s:", get_AT_name (attribute)); switch (form) { - case DW_FORM_ref_addr: - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: - is_ref = 1; - } + default: + break; - switch (form) - { case DW_FORM_ref_addr: case DW_FORM_addr: uvalue = byte_get (data, pointer_size); - printf (is_ref ? " <%lx>" : " %#lx", uvalue); data += pointer_size; break; @@ -6049,21 +5988,55 @@ read_and_display_attr (attribute, form, data, pointer_size) case DW_FORM_flag: case DW_FORM_data1: uvalue = byte_get (data ++, 1); - printf (is_ref ? " <%lx>" : " %ld", uvalue); break; case DW_FORM_ref2: case DW_FORM_data2: uvalue = byte_get (data, 2); data += 2; - printf (is_ref ? " <%lx>" : " %ld", uvalue); break; case DW_FORM_ref4: case DW_FORM_data4: uvalue = byte_get (data, 4); data += 4; - printf (is_ref ? " <%lx>" : " %ld", uvalue); + break; + + case DW_FORM_sdata: + uvalue = read_leb128 (data, & bytes_read, 1); + data += bytes_read; + break; + + case DW_FORM_ref_udata: + case DW_FORM_udata: + uvalue = read_leb128 (data, & bytes_read, 0); + data += bytes_read; + break; + } + + switch (form) + { + case DW_FORM_ref_addr: + printf (" <#%lx>", uvalue); + break; + + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref_udata: + printf (" <%lx>", uvalue + cu_offset); + break; + + case DW_FORM_addr: + printf (" %#lx", uvalue); + + case DW_FORM_flag: + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_sdata: + case DW_FORM_udata: + printf (" %ld", uvalue); break; case DW_FORM_ref8: @@ -6076,48 +6049,31 @@ read_and_display_attr (attribute, form, data, pointer_size) case DW_FORM_string: printf (" %s", data); - data += strlen (data) + 1; - break; - - case DW_FORM_sdata: - uvalue = read_leb128 (data, & bytes_read, 1); - data += bytes_read; - printf (" %ld", (long) uvalue); - break; - - case DW_FORM_ref_udata: - case DW_FORM_udata: - uvalue = read_leb128 (data, & bytes_read, 0); - data += bytes_read; - printf (is_ref ? " <%lx>" : " %ld", uvalue); + data += strlen ((char *) data) + 1; break; case DW_FORM_block: uvalue = read_leb128 (data, & bytes_read, 0); block_start = data + bytes_read; data = display_block (block_start, uvalue); - uvalue = * block_start; break; case DW_FORM_block1: uvalue = byte_get (data, 1); block_start = data + 1; data = display_block (block_start, uvalue); - uvalue = * block_start; break; case DW_FORM_block2: uvalue = byte_get (data, 2); block_start = data + 2; data = display_block (block_start, uvalue); - uvalue = * block_start; break; case DW_FORM_block4: uvalue = byte_get (data, 4); block_start = data + 4; data = display_block (block_start, uvalue); - uvalue = * block_start; break; case DW_FORM_strp: @@ -6147,11 +6103,6 @@ read_and_display_attr (attribute, form, data, pointer_size) } break; - case DW_AT_frame_base: - if (uvalue >= DW_OP_reg0 && uvalue <= DW_OP_reg31) - printf ("(reg %ld)", uvalue - DW_OP_reg0); - break; - case DW_AT_language: switch (uvalue) { @@ -6248,12 +6199,16 @@ read_and_display_attr (attribute, form, data, pointer_size) } break; + case DW_AT_frame_base: case DW_AT_location: case DW_AT_data_member_location: case DW_AT_vtable_elem_location: - printf ("("); - decode_location_expression (block_start, pointer_size); - printf (")"); + if (block_start) + { + printf ("("); + decode_location_expression (block_start, pointer_size, uvalue); + printf (")"); + } break; default: @@ -6282,6 +6237,7 @@ display_debug_info (section, start, file) unsigned char * tags; int i; int level; + unsigned long cu_offset; external = (DWARF2_External_CompUnit *) start; @@ -6291,20 +6247,21 @@ display_debug_info (section, start, file) compunit.cu_pointer_size = BYTE_GET (external->cu_pointer_size); tags = start + sizeof (* external); + 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 (); @@ -6376,7 +6333,7 @@ display_debug_info (section, start, file) for (attr = entry->first_attr; attr; attr = attr->next) tags = read_and_display_attr (attr->attribute, attr->form, - tags, + tags, cu_offset, compunit.cu_pointer_size); if (entry->children) @@ -6433,7 +6390,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; @@ -6462,6 +6419,602 @@ 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; + unsigned int data_factor; + unsigned long pc_begin; + unsigned long pc_range; + int cfa_reg; + int cfa_offset; + int ra; +} +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 ("%08x ", (unsigned int) 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"); +} + +#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; + + 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; + + 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; + + printf ("\n%08x %08lx %08lx ", saved_start - section_start, length, cie_id); + + if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID)) + { + 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); + + start ++; /* version */ + fc->augmentation = start; + + while (* start) + start++; + + start++; /* skip past NUL */ + + if (fc->augmentation[0] == 'z') + { + int xtra; + fc->code_factor = LEB (); + fc->data_factor = SLEB (); + fc->ra = byte_get (start, 1); start += 1; + xtra = LEB (); + printf ("skipping %d extra bytes\n", xtra); + start += xtra; + } + else if (strcmp (fc->augmentation, "eh") == 0) + { + start += 4; + 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; + printf ("CIE \"%s\" cf=%d df=%d ra=%d\n", + fc->augmentation, fc->code_factor, fc->data_factor, fc->ra); + + 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 : (unsigned char *) cie_id; + + fc->pc_begin = byte_get (start, 4); start += 4; + fc->pc_range = byte_get (start, 4); start += 4; + + for (cie=chunks; cie && (cie->chunk_start != look_for); cie = cie->next); + if (!cie) + { + warn ("Invalid CIE pointer %08x in FDE at %08x\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 = ""; + } + 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); + } + + if (cie->augmentation[0] == 'z') + { + unsigned long l = LEB (); + start += l; + } + + printf ("FDE cie=%08x pc=%08lx..%08lx\n", + cie->chunk_start-section_start, fc->pc_begin, + fc->pc_begin + fc->pc_range); + } + + /* At this point, fc is the current chunk, cie (if any) is set, and we're + about to interpret instructions for the chunk. */ + + /* This exists for readelf maintainers. */ +#define FDEBUG 0 + + { + /* 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; + 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 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 += sizeof (vma); + 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: + frame_display_row (fc, &need_col_headers, &max_regs); +#if FDEBUG + printf (" DW_CFA_advance_loc: %08x = %08x + %d*%d\n", + fc->pc_begin + opa * fc->code_factor, fc->pc_begin, opa, fc->code_factor); +#endif + fc->pc_begin += opa * fc->code_factor; + break; + + case DW_CFA_offset: + roffs = LEB (); +#if FDEBUG + printf (" DW_CFA_offset: r%d = cfa[%d*%d]\n", opa, roffs, fc->data_factor); +#endif + fc->col_type[opa] = DW_CFA_offset; + fc->col_offset[opa] = roffs * fc->data_factor; + break; + + case DW_CFA_restore: +#if FDEBUG + printf (" DW_CFA_restore: r%d\n", opa); +#endif + fc->col_type[opa] = cie->col_type[opa]; + fc->col_offset[opa] = cie->col_offset[opa]; + break; + + case DW_CFA_set_loc: + frame_display_row (fc, &need_col_headers, &max_regs); + vma = byte_get (start, sizeof (vma)); start += sizeof (vma); +#if FDEBUG + printf (" DW_CFA_set_loc: %08x\n", vma); +#endif + fc->pc_begin = vma; + break; + + case DW_CFA_advance_loc1: + frame_display_row (fc, &need_col_headers, &max_regs); + ofs = byte_get (start, 1); start += 1; +#if FDEBUG + printf (" DW_CFA_advance_loc1: %08x = %08x + %d*%d\n", + fc->pc_begin + ofs * fc->code_factor, fc->pc_begin, ofs, fc->code_factor); +#endif + fc->pc_begin += ofs * fc->code_factor; + break; + + case DW_CFA_advance_loc2: + frame_display_row (fc, &need_col_headers, &max_regs); + ofs = byte_get (start, 2); start += 2; +#if FDEBUG + printf (" DW_CFA_advance_loc2: %08x = %08x + %d*%d\n", + fc->pc_begin + ofs * fc->code_factor, fc->pc_begin, ofs, fc->code_factor); +#endif + fc->pc_begin += ofs * fc->code_factor; + break; + + case DW_CFA_advance_loc4: + frame_display_row (fc, &need_col_headers, &max_regs); + ofs = byte_get (start, 4); start += 4; +#if FDEBUG + printf (" DW_CFA_advance_loc4: %08x = %08x + %d*%d\n", + fc->pc_begin + ofs * fc->code_factor, fc->pc_begin, ofs, fc->code_factor); +#endif + fc->pc_begin += ofs * fc->code_factor; + break; + + case DW_CFA_offset_extended: + reg = LEB (); + roffs = LEB (); +#if FDEBUG + printf (" DW_CFA_offset_extended: r%d = cfa[%d*%d]\n", reg, roffs, fc->data_factor); +#endif + fc->col_type[reg] = DW_CFA_offset; + fc->col_offset[reg] = roffs * fc->data_factor; + break; + + case DW_CFA_restore_extended: + reg = LEB (); +#if FDEBUG + printf (" DW_CFA_restore_extended: r%d\n", reg); +#endif + fc->col_type[reg] = cie->col_type[reg]; + fc->col_offset[reg] = cie->col_offset[reg]; + break; + + case DW_CFA_undefined: + reg = LEB (); +#if FDEBUG + printf (" DW_CFA_undefined: r%d\n", reg); +#endif + fc->col_type[reg] = DW_CFA_undefined; + fc->col_offset[reg] = 0; + break; + + case DW_CFA_same_value: + reg = LEB (); +#if FDEBUG + printf (" DW_CFA_same_value: r%d\n", reg); +#endif + fc->col_type[reg] = DW_CFA_same_value; + fc->col_offset[reg] = 0; + break; + + case DW_CFA_register: + reg = LEB (); + roffs = LEB (); +#if FDEBUG + printf (" DW_CFA_register: r%d\n", reg); +#endif + fc->col_type[reg] = DW_CFA_register; + fc->col_offset[reg] = roffs; + break; + + case DW_CFA_remember_state: +#if FDEBUG + printf (" DW_CFA_remember_state\n"); +#endif + 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 FDEBUG + printf (" DW_CFA_restore_state\n"); +#endif + 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 FDEBUG + printf (" DW_CFA_def_cfa: reg %d ofs %d\n", fc->cfa_reg, fc->cfa_offset); +#endif + break; + + case DW_CFA_def_cfa_register: + fc->cfa_reg = LEB (); +#if FDEBUG + printf (" DW_CFA_def_cfa_reg: %d\n", fc->cfa_reg); +#endif + break; + + case DW_CFA_def_cfa_offset: + fc->cfa_offset = LEB (); +#if FDEBUG + printf (" DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset); +#endif + break; + + case DW_CFA_nop: +#if FDEBUG + printf (" DW_CFA_nop\n"); +#endif + break; + +#ifndef DW_CFA_GNU_window_save +#define DW_CFA_GNU_window_save 0x2d +#endif + case DW_CFA_GNU_window_save: +#if FDEBUG + printf (" DW_CFA_GNU_window_save\n"); +#endif + break; + +#ifndef DW_CFA_GNU_args_size +#define DW_CFA_GNU_args_size 0x2e +#endif + case DW_CFA_GNU_args_size: + ul = LEB (); +#if FDEBUG + printf (" DW_CFA_GNU_args_size: %d\n", ul); +#endif + 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 (); + l = - LEB (); + frame_need_space (fc, reg); +#if FDEBUG + printf (" DW_CFA_GNU_negative_offset_extended: r%d = cfa[%d*%d]\n", reg, l, fc->data_factor); +#endif + 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; + } + } + + 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) @@ -6509,6 +7062,8 @@ debug_displays[] = { ".debug_line", display_debug_lines, NULL }, { ".debug_aranges", display_debug_aranges, NULL }, { ".debug_pubnames", display_debug_pubnames, NULL }, + { ".debug_frame", display_debug_frames, NULL }, + { ".eh_frame", display_debug_frames, NULL }, { ".debug_macinfo", display_debug_not_supported, NULL }, { ".debug_frame", display_debug_not_supported, NULL }, { ".debug_str", display_debug_not_supported, NULL }, @@ -6539,6 +7094,9 @@ display_debug_section (section, file) "debug section data"); /* 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) { @@ -6775,7 +7333,7 @@ process_mips_specific (file) Elf_External_Options *, "options"); iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt)) - * sizeof (*iopt)); + * sizeof (* iopt)); if (iopt == NULL) { error (_("Out of memory")); @@ -6784,7 +7342,7 @@ process_mips_specific (file) offset = cnt = 0; option = iopt; - + while (offset < sect->sh_size) { Elf_External_Options * eoption; @@ -6797,16 +7355,16 @@ process_mips_specific (file) option->info = BYTE_GET (eoption->info); offset += option->size; - + ++option; ++cnt; } printf (_("\nSection '%s' contains %d entries:\n"), - string_table + sect->sh_name, cnt); + SECTION_NAME (sect), cnt); option = iopt; - + while (cnt-- > 0) { size_t len; @@ -6822,8 +7380,8 @@ process_mips_specific (file) if (elf_header.e_machine == EM_MIPS) { /* 32bit form. */ - Elf32_External_RegInfo *ereg; - Elf32_RegInfo reginfo; + Elf32_External_RegInfo * ereg; + Elf32_RegInfo reginfo; ereg = (Elf32_External_RegInfo *) (option + 1); reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); @@ -6940,7 +7498,7 @@ process_mips_specific (file) break; } - len = sizeof (*eopt); + len = sizeof (* eopt); while (len < option->size) if (((char *) option)[len] >= ' ' && ((char *) option)[len] < 0x7f) @@ -6968,7 +7526,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")); @@ -6977,7 +7535,7 @@ process_mips_specific (file) if (is_32bit_elf) { - GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf32), + GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (* econf32), econf32, Elf32_External_Conflict *, "conflict"); for (cnt = 0; cnt < conflictsno; ++cnt) @@ -6985,7 +7543,7 @@ process_mips_specific (file) } else { - GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (*econf64), + GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (* econf64), econf64, Elf64_External_Conflict *, "conflict"); for (cnt = 0; cnt < conflictsno; ++cnt) @@ -7069,8 +7627,7 @@ process_corefile_note_segment (file, offset, length) external = pnotes; printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"), - (unsigned long) offset, - (unsigned long) length); + (unsigned long) offset, (unsigned long) length); printf (_(" Owner\t\tData size\tDescription\n")); while (external < (Elf_External_Note *)((char *) pnotes + length)) @@ -7084,7 +7641,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 @@ -7094,17 +7651,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; } @@ -7363,6 +7920,7 @@ process_file (file_name) { free (string_table); string_table = NULL; + string_table_length = 0; } if (dynamic_strings) |