X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=504c51bd7fa6f10fd93e23518857b98122804b8f;hb=800eeca487f145ccc5481a03bfff2b871a2fd361;hp=3c613a6fa4c6ed5ef37f6b339c9328f4ce61ebe6;hpb=a952a37550523872520cc6bd73a1e8aae92128a5;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index 3c613a6fa4..504c51bd7f 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1,5 +1,5 @@ /* readelf.c -- display contents of an ELF format file - Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Copyright (C) 1998, 99, 2000 Free Software Foundation, Inc. Originally developed by Eric Youngdale Modifications by Nick Clifton @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -67,16 +68,13 @@ #include "elf/fr30.h" #include "elf/mcore.h" #include "elf/i960.h" +#include "elf/pj.h" +#include "elf/avr.h" +#include "elf/ia64.h" #include "bucomm.h" #include "getopt.h" -#ifdef ANSI_PROTOTYPES -#include -#else -#include -#endif - char * program_name = "readelf"; unsigned int dynamic_addr; bfd_size_type dynamic_size; @@ -114,6 +112,7 @@ int do_debug_lines; int do_debug_pubnames; int do_debug_aranges; int do_arch; +int do_notes; int is_32bit_elf; /* A dynamic array of flags indicating which sections require dumping. */ @@ -124,28 +123,51 @@ unsigned int num_dump_sects = 0; #define DISASS_DUMP (1 << 1) #define DEBUG_DUMP (1 << 2) +/* How to rpint a vma value. */ +typedef enum print_mode +{ + HEX, + DEC, + DEC_5, + UNSIGNED, + PREFIX_HEX, + FULL_HEX, + LONG_HEX +} +print_mode; + /* Forward declarations for dumb compilers. */ +static void print_vma PARAMS ((bfd_vma, print_mode)); static bfd_vma (* byte_get) PARAMS ((unsigned char *, int)); static bfd_vma byte_get_little_endian PARAMS ((unsigned char *, int)); static bfd_vma byte_get_big_endian PARAMS ((unsigned char *, int)); static const char * get_mips_dynamic_type PARAMS ((unsigned long)); +static const char * get_sparc64_dynamic_type PARAMS ((unsigned long)); +static const char * get_parisc_dynamic_type PARAMS ((unsigned long)); 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)); 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_section_type_name PARAMS ((unsigned int)); -static char * get_symbol_binding PARAMS ((unsigned int)); -static char * get_symbol_type PARAMS ((unsigned int)); +static const char * get_symbol_binding PARAMS ((unsigned int)); +static const char * get_symbol_type PARAMS ((unsigned int)); +static const char * get_symbol_visibility PARAMS ((unsigned int)); +static const char * get_symbol_index_type PARAMS ((unsigned int)); +static const char * get_dynamic_flags PARAMS ((bfd_vma)); static void usage PARAMS ((void)); static void parse_args PARAMS ((int, char **)); static int process_file_header PARAMS ((void)); static int process_program_headers PARAMS ((FILE *)); static int process_section_headers PARAMS ((FILE *)); static void dynamic_segment_mips_val PARAMS ((Elf_Internal_Dyn *)); +static void dynamic_segment_parisc_val PARAMS ((Elf_Internal_Dyn *)); static int process_dynamic_segment PARAMS ((FILE *)); static int process_symbol_table PARAMS ((FILE *)); static int process_section_contents PARAMS ((FILE *)); @@ -153,7 +175,6 @@ static void process_file PARAMS ((char *)); static int process_relocs PARAMS ((FILE *)); static int process_version_sections PARAMS ((FILE *)); static char * get_ver_flags PARAMS ((unsigned int)); -static char * get_symbol_index_type PARAMS ((unsigned int)); static int get_32bit_section_headers PARAMS ((FILE *)); static int get_64bit_section_headers PARAMS ((FILE *)); static int get_32bit_program_headers PARAMS ((FILE *, Elf_Internal_Phdr *)); @@ -176,7 +197,7 @@ static int display_debug_abbrev PARAMS ((Elf32_Internal_Sh static int display_debug_aranges 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)); +static int process_extended_line_op PARAMS ((unsigned char *, int, int)); static void reset_state_machine PARAMS ((int)); static char * get_TAG_name PARAMS ((unsigned long)); static char * get_AT_name PARAMS ((unsigned long)); @@ -184,14 +205,19 @@ 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)); 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 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 *)); typedef int Elf32_Word; @@ -366,6 +392,95 @@ byte_get_little_endian (field, size) } } +/* Print a VMA value. */ +static void +print_vma (vma, mode) + bfd_vma vma; + print_mode mode; +{ +#ifdef BFD64 + if (is_32bit_elf) +#endif + { + switch (mode) + { + case FULL_HEX: printf ("0x"); /* drop through */ + case LONG_HEX: printf ("%8.8lx", (unsigned long) vma); break; + case PREFIX_HEX: printf ("0x"); /* drop through */ + case HEX: printf ("%lx", (unsigned long) vma); break; + case DEC: printf ("%ld", (unsigned long) vma); break; + case DEC_5: printf ("%5ld", (long) vma); break; + case UNSIGNED: printf ("%lu", (unsigned long) vma); break; + } + } +#ifdef BFD64 + else + { + switch (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); +#else + if (_bfd_int64_high (vma)) + printf ("%lx%lx", _bfd_int64_high (vma), _bfd_int64_low (vma)); + else + printf ("%lx", _bfd_int64_low (vma)); +#endif + break; + + case DEC: +#if BFD_HOST_64BIT_LONG + printf ("%ld", vma); +#else + if (_bfd_int64_high (vma)) + /* ugg */ + printf ("++%ld", _bfd_int64_low (vma)); + else + printf ("%ld", _bfd_int64_low (vma)); +#endif + break; + + case DEC_5: +#if BFD_HOST_64BIT_LONG + printf ("%5ld", vma); +#else + if (_bfd_int64_high (vma)) + /* ugg */ + printf ("++%ld", _bfd_int64_low (vma)); + else + printf ("%5ld", _bfd_int64_low (vma)); +#endif + break; + + case UNSIGNED: +#if BFD_HOST_64BIT_LONG + printf ("%lu", vma); +#else + if (_bfd_int64_high (vma)) + /* ugg */ + printf ("++%lu", _bfd_int64_low (vma)); + else + printf ("%lu", _bfd_int64_low (vma)); +#endif + break; + } + } +#endif +} + static bfd_vma byte_get_big_endian (field, size) unsigned char * field; @@ -408,7 +523,7 @@ byte_get_big_endian (field, size) | (((bfd_vma) (field [1])) << 48) | (((bfd_vma) (field [0])) << 56); #endif - + default: error (_("Unhandled data length: %d\n"), size); abort (); @@ -433,7 +548,7 @@ guess_is_rela (e_machine) case EM_MIPS: case EM_MIPS_RS4_BE: return FALSE; - + /* Targets that use RELA relocations. */ case EM_68K: case EM_SPARC32PLUS: @@ -448,8 +563,27 @@ guess_is_rela (e_machine) case EM_SH: case EM_ALPHA: case EM_MCORE: + case EM_IA_64: return TRUE; - + + case EM_MMA: + case EM_PCP: + case EM_NCPU: + case EM_NDR1: + case EM_STARCORE: + case EM_ME16: + case EM_ST100: + case EM_TINYJ: + case EM_FX66: + case EM_ST9PLUS: + case EM_ST7: + case EM_68HC16: + case EM_68HC11: + case EM_68HC08: + case EM_68HC05: + case EM_SVX: + case EM_ST19: + case EM_VAX: default: warn (_("Don't know about relocations on this machine architecture\n")); return FALSE; @@ -471,7 +605,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) Elf_Internal_Rel * rels; Elf_Internal_Rela * relas; - + if (is_rela == UNKNOWN) is_rela = guess_is_rela (elf_header.e_machine); @@ -480,59 +614,59 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) if (is_32bit_elf) { Elf32_External_Rela * erelas; - + GET_DATA_ALLOC (rel_offset, rel_size, erelas, Elf32_External_Rela *, "relocs"); - + rel_size = rel_size / sizeof (Elf32_External_Rela); - + relas = (Elf_Internal_Rela *) malloc (rel_size * sizeof (Elf_Internal_Rela)); - + if (relas == NULL) { error(_("out of memory parsing relocs")); return 0; } - + 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); } - + free (erelas); - + rels = (Elf_Internal_Rel *) relas; } else { Elf64_External_Rela * erelas; - + GET_DATA_ALLOC (rel_offset, rel_size, erelas, Elf64_External_Rela *, "relocs"); - + rel_size = rel_size / sizeof (Elf64_External_Rela); - + relas = (Elf_Internal_Rela *) malloc (rel_size * sizeof (Elf_Internal_Rela)); - + if (relas == NULL) { error(_("out of memory parsing relocs")); return 0; } - + 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); } - + free (erelas); - + rels = (Elf_Internal_Rel *) relas; } } @@ -544,26 +678,26 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) GET_DATA_ALLOC (rel_offset, rel_size, erels, Elf32_External_Rel *, "relocs"); - + 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; } - + 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); } - + free (erels); - + relas = (Elf_Internal_Rela *) rels; } else @@ -572,26 +706,26 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) GET_DATA_ALLOC (rel_offset, rel_size, erels, Elf64_External_Rel *, "relocs"); - + rel_size = rel_size / sizeof (Elf64_External_Rel); - + rels = (Elf_Internal_Rel *) malloc (rel_size * sizeof (Elf_Internal_Rel)); - + if (rels == NULL) { error(_("out of memory parsing relocs")); return 0; } - + 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); - + relas = (Elf_Internal_Rela *) rels; } } @@ -610,7 +744,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) bfd_vma info; bfd_vma symtab_index; bfd_vma type; - + if (is_rela) { offset = relas [i].r_offset; @@ -621,7 +755,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) offset = rels [i].r_offset; info = rels [i].r_info; } - + if (is_32bit_elf) { type = ELF32_R_TYPE (info); @@ -636,7 +770,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) /* The #ifdef BFD64 below is to prevent a compile time warning. We know that if we do not have a 64 bit data type that we will never execute this code anyway. */ -#ifdef BFD64 +#ifdef BFD64 symtab_index = ELF64_R_SYM (info); #endif } @@ -646,7 +780,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) #else printf (" %8.8lx %5.5lx ", offset, info); #endif - + switch (elf_header.e_machine) { default: @@ -670,6 +804,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) rtype = elf_i960_reloc_type (type); break; + case EM_AVR: + rtype = elf_avr_reloc_type (type); + break; + case EM_OLD_SPARCV9: case EM_SPARC32PLUS: case EM_SPARCV9: @@ -733,10 +871,17 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) case EM_PARISC: rtype = elf_hppa_reloc_type (type); break; + + case EM_PJ: + rtype = elf_pj_reloc_type (type); + break; + case EM_IA_64: + rtype = elf_ia64_reloc_type (type); + break; } if (rtype == NULL) -#ifdef _bfd_int64_low +#ifdef _bfd_int64_low printf (_("unrecognised: %-7lx"), _bfd_int64_low (type)); #else printf (_("unrecognised: %-7lx"), type); @@ -755,9 +900,11 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) Elf_Internal_Sym * psym; psym = symtab + symtab_index; - - printf (" %08lx ", (unsigned long) psym->st_value); - + + printf (" "); + print_vma (psym->st_value, LONG_HEX); + printf (" "); + if (psym->st_name == 0) printf ("%-25.25s", SECTION_NAME (section_headers + psym->st_shndx)); @@ -765,14 +912,17 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) printf (_(""), psym->st_name); else printf ("%-25.25s", strtab + psym->st_name); - + if (is_rela) printf (" + %lx", (unsigned long) relas [i].r_addend); } } } else if (is_rela) - printf ("%34c%lx", ' ', (unsigned long) relas[i].r_addend); + { + printf ("%*c", is_32bit_elf ? 34 : 26, ' '); + print_vma (relas[i].r_addend, LONG_HEX); + } if (elf_header.e_machine == EM_SPARCV9 && !strcmp (rtype, "R_SPARC_OLO10")) @@ -840,6 +990,42 @@ get_mips_dynamic_type (type) } } +static const char * +get_sparc64_dynamic_type (type) + unsigned long type; +{ + switch (type) + { + case DT_SPARC_REGISTER: return "SPARC_REGISTER"; + default: + return NULL; + } +} + +static const char * +get_parisc_dynamic_type (type) + unsigned long type; +{ + switch (type) + { + case DT_HP_LOAD_MAP: return "HP_LOAD_MAP"; + case DT_HP_DLD_FLAGS: return "HP_DLD_FLAGS"; + case DT_HP_DLD_HOOK: return "HP_DLD_HOOK"; + case DT_HP_UX10_INIT: return "HP_UX10_INIT"; + case DT_HP_UX10_INITSZ: return "HP_UX10_INITSZ"; + case DT_HP_PREINIT: return "HP_PREINIT"; + case DT_HP_PREINITSZ: return "HP_PREINITSZ"; + case DT_HP_NEEDED: return "HP_NEEDED"; + case DT_HP_TIME_STAMP: return "HP_TIME_STAMP"; + case DT_HP_CHECKSUM: return "HP_CHECKSUM"; + case DT_HP_GST_SIZE: return "HP_GST_SIZE"; + case DT_HP_GST_VERSION: return "HP_GST_VERSION"; + case DT_HP_GST_HASHVAL: return "HP_GST_HASHVAL"; + default: + return NULL; + } +} + static const char * get_dynamic_type (type) unsigned long type; @@ -877,7 +1063,12 @@ get_dynamic_type (type) case DT_FINI_ARRAY: return "FINI_ARRAY"; case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ"; case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ"; - + case DT_RUNPATH: return "RUNPATH"; + case DT_FLAGS: return "FLAGS"; + + case DT_PREINIT_ARRAY: return "PREINIT_ARRAY"; + case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; + case DT_PLTPADSZ: return "PLTPADSZ"; case DT_MOVEENT: return "MOVEENT"; case DT_MOVESZ: return "MOVESZ"; @@ -885,12 +1076,12 @@ get_dynamic_type (type) 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_SYMINFO: return "SYMINFO"; /* aka ADDRRNGHI */ - + case DT_VERSYM: return "VERSYM"; - + case DT_RELACOUNT: return "RELACOUNT"; case DT_RELCOUNT: return "RELCOUNT"; case DT_FLAGS_1: return "FLAGS_1"; @@ -898,22 +1089,25 @@ get_dynamic_type (type) case DT_VERDEFNUM: return "VERDEFNUM"; case DT_VERNEED: return "VERNEED"; case DT_VERNEEDNUM: return "VERNEEDNUM"; - + case DT_AUXILIARY: return "AUXILARY"; case DT_USED: return "USED"; case DT_FILTER: return "FILTER"; - + default: if ((type >= DT_LOPROC) && (type <= DT_HIPROC)) { const char * result; - + switch (elf_header.e_machine) { case EM_MIPS: case EM_MIPS_RS4_BE: result = get_mips_dynamic_type (type); break; + case EM_SPARCV9: + result = get_sparc64_dynamic_type (type); + break; default: result = NULL; break; @@ -925,10 +1119,27 @@ get_dynamic_type (type) sprintf (buff, _("Processor Specific: %lx"), type); } else if ((type >= DT_LOOS) && (type <= DT_HIOS)) - sprintf (buff, _("Operating System specific: %lx"), type); + { + const char * result; + + switch (elf_header.e_machine) + { + case EM_PARISC: + result = get_parisc_dynamic_type (type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, _("Operating System specific: %lx"), type); + } else sprintf (buff, _(": %lx"), type); - + return buff; } } @@ -962,7 +1173,7 @@ static char * get_machine_name (e_machine) unsigned e_machine; { - static char buff [32]; + static char buff [64]; /* XXX */ switch (e_machine) { @@ -974,8 +1185,8 @@ get_machine_name (e_machine) case EM_88K: return "MC88000"; case EM_486: return "Intel 80486"; case EM_860: return "Intel 80860"; - case EM_MIPS: return "MIPS R3000 big-endian"; - case EM_S370: return "Amdahl"; + 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_OLD_SPARCV9: return "Sparc v9 (old)"; case EM_PARISC: return "HPPA"; @@ -997,7 +1208,7 @@ get_machine_name (e_machine) case EM_H8_300H: return "Hitachi H8/300H"; case EM_H8S: return "Hitachi H8S"; case EM_H8_500: return "Hitachi H8/500"; - case EM_IA_64: return "Intel Merced"; + case EM_IA_64: return "Intel IA-64"; case EM_MIPS_X: return "Stanford MIPS-X"; case EM_COLDFIRE: return "Motorola Coldfire"; case EM_68HC12: return "Motorola M68HC12"; @@ -1010,13 +1221,141 @@ get_machine_name (e_machine) 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"; default: sprintf (buff, _(": %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, ", "); + 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,", "); +} + static char * get_machine_flags (e_flags, e_machine) unsigned e_flags; @@ -1025,6 +1364,7 @@ get_machine_flags (e_flags, e_machine) static char buf [1024]; buf[0] = '\0'; + if (e_flags) { switch (e_machine) @@ -1032,6 +1372,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"); @@ -1104,7 +1448,10 @@ get_machine_flags (e_flags, e_machine) strcat (buf, ", v8+"); if (e_flags & EF_SPARC_SUN_US1) - strcat (buf, ", ultrasparc"); + strcat (buf, ", ultrasparcI"); + + if (e_flags & EF_SPARC_SUN_US3) + strcat (buf, ", ultrasparcIII"); if (e_flags & EF_SPARC_HAL_R1) strcat (buf, ", halr1"); @@ -1121,6 +1468,43 @@ get_machine_flags (e_flags, e_machine) if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_RMO) strcat (buf, ", rmo"); break; + + case EM_PARISC: + switch (e_flags & EF_PARISC_ARCH) + { + case EFA_PARISC_1_0: + strcpy (buf, ", PA-RISC 1.0"); + break; + case EFA_PARISC_1_1: + strcpy (buf, ", PA-RISC 1.1"); + break; + case EFA_PARISC_2_0: + strcpy (buf, ", PA-RISC 2.0"); + break; + default: + break; + } + if (e_flags & EF_PARISC_TRAPNIL) + strcat (buf, ", trapnil"); + if (e_flags & EF_PARISC_EXT) + strcat (buf, ", ext"); + if (e_flags & EF_PARISC_LSB) + strcat (buf, ", lsb"); + if (e_flags & EF_PARISC_WIDE) + strcat (buf, ", wide"); + if (e_flags & EF_PARISC_NO_KABP) + strcat (buf, ", no kabp"); + 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"); + + if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS) + strcat (buf, ", gnu calling convention"); + break; } } @@ -1147,8 +1531,35 @@ get_mips_segment_type (type) } static const char * -get_segment_type (p_type) - unsigned long p_type; +get_parisc_segment_type (type) + unsigned long type; +{ + switch (type) + { + case PT_HP_TLS: return "HP_TLS"; + case PT_HP_CORE_NONE: return "HP_CORE_NONE"; + case PT_HP_CORE_VERSION: return "HP_CORE_VERSION"; + case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL"; + case PT_HP_CORE_COMM: return "HP_CORE_COMM"; + case PT_HP_CORE_PROC: return "HP_CORE_PROC"; + case PT_HP_CORE_LOADABLE: return "HP_CORE_LOADABLE"; + case PT_HP_CORE_STACK: return "HP_CORE_STACK"; + case PT_HP_CORE_SHM: return "HP_CORE_SHM"; + case PT_HP_CORE_MMF: return "HP_CORE_MMF"; + case PT_HP_PARALLEL: return "HP_PARALLEL"; + case PT_HP_FASTBIND: return "HP_FASTBIND"; + case PT_PARISC_ARCHEXT: return "PARISC_ARCHEXT"; + case PT_PARISC_UNWIND: return "PARISC_UNWIND"; + default: + break; + } + + return NULL; +} + +static const char * +get_segment_type (p_type) + unsigned long p_type; { static char buff [32]; @@ -1166,25 +1577,45 @@ get_segment_type (p_type) if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) { const char * result; - + switch (elf_header.e_machine) { case EM_MIPS: case EM_MIPS_RS4_BE: result = get_mips_segment_type (p_type); break; + case EM_PARISC: + result = get_parisc_segment_type (p_type); + break; default: result = NULL; break; } - + if (result != NULL) return result; - + sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC); } else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS)) - sprintf (buff, "LOOS+%lx", p_type - PT_LOOS); + { + const char * result; + + switch (elf_header.e_machine) + { + case EM_PARISC: + result = get_parisc_segment_type (p_type); + break; + default: + result = NULL; + break; + } + + if (result != NULL) + return result; + + sprintf (buff, "LOOS+%lx", p_type - PT_LOOS); + } else sprintf (buff, _(": %lx"), p_type); @@ -1243,6 +1674,21 @@ get_mips_section_type_name (sh_type) return NULL; } +static const char * +get_parisc_section_type_name (sh_type) + unsigned int sh_type; +{ + switch (sh_type) + { + case SHT_PARISC_EXT: return "PARISC_EXT"; + case SHT_PARISC_UNWIND: return "PARISC_UNWIND"; + case SHT_PARISC_DOC: return "PARISC_DOC"; + default: + break; + } + return NULL; +} + static const char * get_section_type_name (sh_type) unsigned int sh_type; @@ -1263,6 +1709,9 @@ get_section_type_name (sh_type) case SHT_REL: return "REL"; case SHT_SHLIB: return "SHLIB"; case SHT_DYNSYM: return "DYNSYM"; + case SHT_INIT_ARRAY: return "INIT_ARRAY"; + case SHT_FINI_ARRAY: return "FINI_ARRAY"; + case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY"; case SHT_GNU_verdef: return "VERDEF"; case SHT_GNU_verneed: return "VERNEED"; case SHT_GNU_versym: return "VERSYM"; @@ -1282,6 +1731,9 @@ get_section_type_name (sh_type) case EM_MIPS_RS4_BE: result = get_mips_section_type_name (sh_type); break; + case EM_PARISC: + result = get_parisc_section_type_name (sh_type); + break; default: result = NULL; break; @@ -1298,7 +1750,7 @@ get_section_type_name (sh_type) sprintf (buff, "SHT_LOUSER+%x", sh_type - SHT_LOUSER); else sprintf (buff, _(": %x"), sh_type); - + return buff; } } @@ -1316,6 +1768,7 @@ struct option options [] = {"symbols", no_argument, 0, 's'}, {"syms", no_argument, 0, 's'}, {"relocs", no_argument, 0, 'r'}, + {"notes", no_argument, 0, 'n'}, {"dynamic", no_argument, 0, 'd'}, {"arch-specific", no_argument, 0, 'A'}, {"version-info", no_argument, 0, 'V'}, @@ -1344,6 +1797,7 @@ usage () fprintf (stdout, _(" Display the sections' header\n")); fprintf (stdout, _(" -e or --headers Equivalent to: -h -l -S\n")); 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, _(" -d or --dynamic Display the dynamic segment (if present)\n")); fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n")); @@ -1360,7 +1814,7 @@ usage () fprintf (stdout, _(" -I or --histogram Display histogram of bucket list lengths\n")); fprintf (stdout, _(" -v or --version Display the version number of readelf\n")); fprintf (stdout, _(" -H or --help Display this information\n")); - fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n")); + fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO); exit (0); } @@ -1407,7 +1861,7 @@ parse_args (argc, argv) usage (); while ((c = getopt_long - (argc, argv, "ersahldSDAIw::x:i:vV", options, NULL)) != EOF) + (argc, argv, "ersahnldSDAIw::x:i:vV", options, NULL)) != EOF) { char * cp; int section; @@ -1431,6 +1885,7 @@ parse_args (argc, argv) do_version ++; do_histogram ++; do_arch ++; + do_notes ++; break; case 'e': do_header ++; @@ -1464,6 +1919,9 @@ parse_args (argc, argv) case 'I': do_histogram ++; break; + case 'n': + do_notes ++; + break; case 'x': do_dump ++; section = strtoul (optarg, & cp, 0); @@ -1542,7 +2000,7 @@ parse_args (argc, argv) if (!do_dynamic && !do_syms && !do_reloc && !do_sections && !do_segments && !do_header && !do_dump && !do_version - && !do_histogram && !do_debugging && !do_arch) + && !do_histogram && !do_debugging && !do_arch && !do_notes) usage (); else if (argc < 3) { @@ -1556,7 +2014,7 @@ get_elf_class (elf_class) unsigned char elf_class; { static char buff [32]; - + switch (elf_class) { case ELFCLASSNONE: return _("none"); @@ -1573,13 +2031,13 @@ get_data_encoding (encoding) unsigned char encoding; { static char buff [32]; - + switch (encoding) { case ELFDATANONE: return _("none"); case ELFDATA2LSB: return _("2's complement, little endian"); case ELFDATA2MSB: return _("2's complement, big endian"); - default: + default: sprintf (buff, _(""), encoding); return buff; } @@ -1590,12 +2048,14 @@ get_osabi_name (osabi) unsigned char osabi; { static char buff [32]; - + switch (osabi) { case ELFOSABI_SYSV: return _("UNIX - System V"); case ELFOSABI_HPUX: return _("UNIX - HP-UX"); + case ELFOSABI_LINUX: return _("UNIX - Linux"); case ELFOSABI_STANDALONE: return _("Standalone App"); + case ELFOSABI_ARM: return _("ARM"); default: sprintf (buff, _(""), osabi); return buff; @@ -1646,12 +2106,15 @@ 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: 0x%lx\n"), - (unsigned long) elf_header.e_entry); - printf (_(" Start of program headers: %ld (bytes into file)\n"), - (long) elf_header.e_phoff); - printf (_(" Start of section headers: %ld (bytes into file)\n"), - (long) elf_header.e_shoff); + + printf (_(" Entry point address: ")); + print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX); + printf (_("\n Start of program headers: ")); + print_vma ((bfd_vma) elf_header.e_phoff, DEC); + 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)); @@ -1668,7 +2131,7 @@ process_file_header () printf (_(" Section header string table index: %ld\n"), (long) elf_header.e_shstrndx); } - + return 1; } @@ -1682,7 +2145,7 @@ get_32bit_program_headers (file, program_headers) Elf32_External_Phdr * external; 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"); @@ -1715,7 +2178,7 @@ get_64bit_program_headers (file, program_headers) Elf64_External_Phdr * external; 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"); @@ -1756,10 +2219,13 @@ process_program_headers (file) if (do_segments && !do_header) { - printf (_("\nElf file is %s\n"), get_file_type (elf_header.e_type)); - printf (_("Entry point 0x%lx\n"), (unsigned long) elf_header.e_entry); - printf (_("There are %d program headers, starting at offset %lx:\n"), - elf_header.e_phnum, (unsigned long) elf_header.e_phoff); + printf (_("\nElf file type is %s\n"), get_file_type (elf_header.e_type)); + printf (_("Entry point ")); + print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX); + printf (_("\nThere are %d program headers, starting at offset "), + elf_header.e_phnum); + print_vma ((bfd_vma) elf_header.e_phoff, DEC); + printf ("\n"); } program_headers = (Elf_Internal_Phdr *) malloc @@ -1781,13 +2247,22 @@ process_program_headers (file) free (program_headers); return 0; } - + if (do_segments) { printf (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : ""); - printf - (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n")); + + if (is_32bit_elf) + printf + (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n")); + else + { + printf + (_(" Type Offset VirtAddr PhysAddr\n")); + printf + (_(" FileSiz MemSiz Flags Align\n")); + } } loadaddr = -1; @@ -1800,17 +2275,38 @@ process_program_headers (file) { if (do_segments) { - printf (" %-11.11s ", get_segment_type (segment->p_type)); - printf ("0x%6.6lx ", (unsigned long) segment->p_offset); - printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr); - printf ("0x%8.8lx ", (unsigned long) segment->p_paddr); - printf ("0x%5.5lx ", (unsigned long) segment->p_filesz); - printf ("0x%5.5lx ", (unsigned long) segment->p_memsz); - printf ("%c%c%c ", - (segment->p_flags & PF_R ? 'R' : ' '), - (segment->p_flags & PF_W ? 'W' : ' '), - (segment->p_flags & PF_X ? 'E' : ' ')); - printf ("%#lx", (unsigned long) segment->p_align); + printf (" %-14.14s ", get_segment_type (segment->p_type)); + + if (is_32bit_elf) + { + printf ("0x%6.6lx ", (unsigned long) segment->p_offset); + printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr); + printf ("0x%8.8lx ", (unsigned long) segment->p_paddr); + printf ("0x%5.5lx ", (unsigned long) segment->p_filesz); + printf ("0x%5.5lx ", (unsigned long) segment->p_memsz); + printf ("%c%c%c ", + (segment->p_flags & PF_R ? 'R' : ' '), + (segment->p_flags & PF_W ? 'W' : ' '), + (segment->p_flags & PF_X ? 'E' : ' ')); + printf ("%#lx", (unsigned long) segment->p_align); + } + else + { + print_vma (segment->p_offset, FULL_HEX); + putchar (' '); + print_vma (segment->p_vaddr, FULL_HEX); + putchar (' '); + print_vma (segment->p_paddr, FULL_HEX); + printf ("\n "); + print_vma (segment->p_filesz, FULL_HEX); + putchar (' '); + print_vma (segment->p_memsz, FULL_HEX); + printf (" %c%c%c ", + (segment->p_flags & PF_R ? 'R' : ' '), + (segment->p_flags & PF_W ? 'W' : ' '), + (segment->p_flags & PF_X ? 'E' : ' ')); + print_vma (segment->p_align, HEX); + } } switch (segment->p_type) @@ -1830,7 +2326,7 @@ process_program_headers (file) break; case PT_INTERP: - if (fseek (file, segment->p_offset, SEEK_SET)) + if (fseek (file, (long) segment->p_offset, SEEK_SET)) error (_("Unable to find program interpreter name\n")); else { @@ -1880,7 +2376,7 @@ process_program_headers (file) ? (section->sh_addr >= segment->p_vaddr && section->sh_addr + section->sh_size <= segment->p_vaddr + segment->p_memsz) - : (section->sh_offset >= segment->p_offset + : ((bfd_vma) section->sh_offset >= segment->p_offset && (section->sh_offset + section->sh_size <= segment->p_offset + segment->p_filesz)))) printf ("%s ", SECTION_NAME (section)); @@ -2062,6 +2558,52 @@ get_64bit_elf_symbols (file, offset, number) return isyms; } +static const char * +get_elf_section_flags (sh_flags) + bfd_vma 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; + case SHF_ALLOC: strcat (buff, "A"); break; + case SHF_EXECINSTR: strcat (buff, "X"); break; + case SHF_MERGE: strcat (buff, "M"); break; + case SHF_STRINGS: strcat (buff, "S"); break; + case SHF_INFO_LINK: strcat (buff, "I"); break; + case SHF_LINK_ORDER: strcat (buff, "L"); break; + case SHF_OS_NONCONFORMING: strcat (buff, "O"); break; + + default: + if (flag & SHF_MASKOS) + { + strcat (buff, "o"); + sh_flags &= ~ SHF_MASKOS; + } + else if (flag & SHF_MASKPROC) + { + strcat (buff, "p"); + sh_flags &= ~ SHF_MASKPROC; + } + else + strcat (buff, "x"); + break; + } + } + + return buff; +} + static int process_section_headers (file) FILE * file; @@ -2109,7 +2651,7 @@ process_section_headers (file) dynamic_symbols = NULL; dynamic_strings = NULL; dynamic_syminfo = NULL; - + for (i = 0, section = section_headers; i < elf_header.e_shnum; i ++, section ++) @@ -2161,8 +2703,15 @@ process_section_headers (file) return 1; printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : ""); - printf - (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n")); + + if (is_32bit_elf) + printf + (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n")); + else + { + printf (_(" [Nr] Name Type Address Offset\n")); + printf (_(" Size EntSize Flags Link Info Align\n")); + } for (i = 0, section = section_headers; i < elf_header.e_shnum; @@ -2173,21 +2722,45 @@ process_section_headers (file) SECTION_NAME (section), get_section_type_name (section->sh_type)); - printf ( "%8.8lx %6.6lx %6.6lx %2.2lx", - (unsigned long) section->sh_addr, - (unsigned long) section->sh_offset, - (unsigned long) section->sh_size, - (unsigned long) section->sh_entsize); + 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 (" %c%c%c %2ld %3lx %ld\n", - (section->sh_flags & SHF_WRITE ? 'W' : ' '), - (section->sh_flags & SHF_ALLOC ? 'A' : ' '), - (section->sh_flags & SHF_EXECINSTR ? 'X' : ' '), - (unsigned long) section->sh_link, - (unsigned long) section->sh_info, - (unsigned long) section->sh_addralign); + printf (" %3s ", get_elf_section_flags (section->sh_flags)); + + printf (" %2ld %3lx %ld\n", + (unsigned long) section->sh_link, + (unsigned long) section->sh_info, + (unsigned long) section->sh_addralign); + } + else + { + putchar (' '); + print_vma (section->sh_addr, LONG_HEX); + printf (" %8.8lx", section->sh_offset); + printf ("\n "); + 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, + (unsigned long) section->sh_addralign); + } } + 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")); + return 1; } @@ -2205,7 +2778,7 @@ process_relocs (file) if (do_using_dynamic) { - int is_rela; + int is_rela = FALSE; rel_size = 0; rel_offset = 0; @@ -2226,7 +2799,7 @@ process_relocs (file) { rel_offset = dynamic_info[DT_JMPREL]; rel_size = dynamic_info[DT_PLTRELSZ]; - + switch (dynamic_info[DT_PLTREL]) { case DT_REL: @@ -2278,7 +2851,7 @@ process_relocs (file) char * strtab; int is_rela; unsigned long nsyms; - + printf (_("\nRelocation section ")); if (string_table == NULL) @@ -2301,7 +2874,7 @@ process_relocs (file) GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab, char *, "string table"); - + is_rela = section->sh_type == SHT_RELA; dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela); @@ -2351,7 +2924,7 @@ dynamic_segment_mips_val (entry) puts (""); } break; - + case DT_MIPS_IVERSION: if (dynamic_strings != NULL) printf ("Interface Version: %s\n", @@ -2359,16 +2932,21 @@ dynamic_segment_mips_val (entry) else printf ("%ld\n", (long) entry->d_un.d_ptr); break; - + case DT_MIPS_TIME_STAMP: { char timebuf[20]; + struct tm * tmp; + time_t time = entry->d_un.d_val; - strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time)); + 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 ("Time Stamp: %s\n", timebuf); } break; - + case DT_MIPS_RLD_VERSION: case DT_MIPS_LOCAL_GOTNO: case DT_MIPS_CONFLICTNO: @@ -2384,12 +2962,69 @@ dynamic_segment_mips_val (entry) case DT_MIPS_COMPACT_SIZE: printf ("%ld\n", (long) entry->d_un.d_ptr); break; - + default: printf ("%#lx\n", (long) entry->d_un.d_ptr); } } + +static void +dynamic_segment_parisc_val (entry) + Elf_Internal_Dyn * entry; +{ + switch (entry->d_tag) + { + case DT_HP_DLD_FLAGS: + { + static struct + { + long int bit; + const char * str; + } + flags[] = + { + { DT_HP_DEBUG_PRIVATE, "HP_DEBUG_PRIVATE" }, + { DT_HP_DEBUG_CALLBACK, "HP_DEBUG_CALLBACK" }, + { DT_HP_DEBUG_CALLBACK_BOR, "HP_DEBUG_CALLBACK_BOR" }, + { DT_HP_NO_ENVVAR, "HP_NO_ENVVAR" }, + { DT_HP_BIND_NOW, "HP_BIND_NOW" }, + { DT_HP_BIND_NONFATAL, "HP_BIND_NONFATAL" }, + { DT_HP_BIND_VERBOSE, "HP_BIND_VERBOSE" }, + { DT_HP_BIND_RESTRICTED, "HP_BIND_RESTRICTED" }, + { DT_HP_BIND_SYMBOLIC, "HP_BIND_SYMBOLIC" }, + { DT_HP_RPATH_FIRST, "HP_RPATH_FIRST" }, + { DT_HP_BIND_DEPTH_FIRST, "HP_BIND_DEPTH_FIRST" } + }; + int first = 1; + size_t cnt; + bfd_vma val = entry->d_un.d_val; + + for (cnt = 0; cnt < sizeof (flags) / sizeof (flags[0]); ++cnt) + if (val & flags[cnt].bit) + { + if (! first) + putchar (' '); + fputs (flags[cnt].str, stdout); + first = 0; + val ^= flags[cnt].bit; + } + + if (val != 0 || first) + { + if (! first) + putchar (' '); + print_vma (val, HEX); + } + } + break; + + default: + print_vma (entry->d_un.d_ptr, PREFIX_HEX); + break; + } +} + static int get_32bit_dynamic_segment (file) FILE * file; @@ -2397,10 +3032,10 @@ get_32bit_dynamic_segment (file) Elf32_External_Dyn * edyn; Elf_Internal_Dyn * entry; bfd_size_type i; - + GET_DATA_ALLOC (dynamic_addr, dynamic_size, edyn, Elf32_External_Dyn *, "dynamic segment"); - + /* 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 swapping since the DT_NULL tag is recognizable. */ @@ -2438,10 +3073,10 @@ get_64bit_dynamic_segment (file) Elf64_External_Dyn * edyn; Elf_Internal_Dyn * entry; bfd_size_type i; - + GET_DATA_ALLOC (dynamic_addr, dynamic_size, edyn, Elf64_External_Dyn *, "dynamic segment"); - + /* 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 swapping since the DT_NULL tag is recognizable. */ @@ -2472,6 +3107,30 @@ get_64bit_dynamic_segment (file) return 1; } +static const char * +get_dynamic_flags (flags) + bfd_vma flags; +{ + static char buff [64]; + while (flags) + { + bfd_vma flag; + + flag = flags & - flags; + flags &= ~ flag; + + switch (flag) + { + case DF_ORIGIN: strcat (buff, "ORIGIN "); break; + case DF_SYMBOLIC: strcat (buff, "SYMBOLIC "); break; + case DF_TEXTREL: strcat (buff, "TEXTREL "); break; + case DF_BIND_NOW: strcat (buff, "BIND_NOW "); break; + default: strcat (buff, "unknown "); break; + } + } + return buff; +} + /* Parse and display the contents of the dynamic segment. */ static int process_dynamic_segment (file) @@ -2633,14 +3292,25 @@ process_dynamic_segment (file) i++, entry ++) { if (do_dynamic) - printf (_(" 0x%-8.8lx (%s)%*s"), - (unsigned long) entry->d_tag, - get_dynamic_type (entry->d_tag), - 27 - strlen (get_dynamic_type (entry->d_tag)), - " "); + { + const char * dtype; + + putchar (' '); + print_vma (entry->d_tag, FULL_HEX); + dtype = get_dynamic_type (entry->d_tag); + printf (" (%s)%*s", dtype, + ((is_32bit_elf ? 27 : 19) + - (int) strlen (dtype)), + " "); + } switch (entry->d_tag) { + case DT_FLAGS: + if (do_dynamic) + printf ("%s", get_dynamic_flags (entry->d_un.d_val)); + break; + case DT_AUXILIARY: case DT_FILTER: if (do_dynamic) @@ -2653,7 +3323,11 @@ process_dynamic_segment (file) if (dynamic_strings) printf (": [%s]\n", dynamic_strings + entry->d_un.d_val); else - printf (": %#lx\n", (long) entry->d_un.d_val); + { + printf (": "); + print_vma (entry->d_un.d_val, PREFIX_HEX); + putchar ('\n'); + } } break; @@ -2814,26 +3488,27 @@ process_dynamic_segment (file) case DT_NEEDED: printf (_("Shared library: [%s]"), name); - if (strcmp (name, program_interpreter)) - printf ("\n"); - else - printf (_(" program interpreter\n")); + if (strcmp (name, program_interpreter) == 0) + printf (_(" program interpreter")); break; case DT_SONAME: - printf (_("Library soname: [%s]\n"), name); + printf (_("Library soname: [%s]"), name); break; case DT_RPATH: - printf (_("Library rpath: [%s]\n"), name); + printf (_("Library rpath: [%s]"), name); break; default: - printf ("%#lx\n", (long) entry->d_un.d_val); + print_vma (entry->d_un.d_val, PREFIX_HEX); + break; } } else - printf ("%#lx\n", (long) entry->d_un.d_val); + print_vma (entry->d_un.d_val, PREFIX_HEX); + + putchar ('\n'); } break; @@ -2850,7 +3525,10 @@ process_dynamic_segment (file) case DT_INIT_ARRAYSZ: case DT_FINI_ARRAYSZ: if (do_dynamic) - printf ("%lu (bytes)\n", (unsigned long) entry->d_un.d_val); + { + print_vma (entry->d_un.d_val, UNSIGNED); + printf (" (bytes)\n"); + } break; case DT_VERDEFNUM: @@ -2858,7 +3536,10 @@ process_dynamic_segment (file) case DT_RELACOUNT: case DT_RELCOUNT: if (do_dynamic) - printf ("%lu\n", (unsigned long) entry->d_un.d_val); + { + print_vma (entry->d_un.d_val, UNSIGNED); + putchar ('\n'); + } break; case DT_SYMINSZ: @@ -2881,15 +3562,16 @@ process_dynamic_segment (file) break; } } - - printf ("%#lx\n", (long) entry->d_un.d_val); + + print_vma (entry->d_un.d_val, PREFIX_HEX); + putchar ('\n'); } break; case DT_BIND_NOW: /* The value of this entry is ignored. */ break; - + default: if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM)) version_info [DT_VERSIONTAGIDX (entry->d_tag)] = @@ -2903,8 +3585,12 @@ process_dynamic_segment (file) case EM_MIPS_RS4_BE: dynamic_segment_mips_val (entry); break; + case EM_PARISC: + dynamic_segment_parisc_val (entry); + break; default: - printf ("%#lx\n", (long) entry->d_un.d_ptr); + print_vma (entry->d_un.d_val, PREFIX_HEX); + putchar ('\n'); } } break; @@ -2991,7 +3677,7 @@ process_version_sections (file) Elf_Internal_Verdaux aux; int j; int isum; - + vstart = ((char *) edefs) + idx; edef = (Elf_External_Verdef *) vstart; @@ -3048,7 +3734,7 @@ process_version_sections (file) free (edefs); } break; - + case SHT_GNU_verneed: { Elf_External_Verneed * eneed; @@ -3128,7 +3814,7 @@ process_version_sections (file) idx += ent.vn_next; } - + free (eneed); } break; @@ -3182,6 +3868,7 @@ process_version_sections (file) for (cnt = 0; cnt < total; cnt += 4) { int j, nn; + char * name; printf (" %03x:", cnt); @@ -3215,8 +3902,8 @@ process_version_sections (file) { Elf_External_Verneed evn; Elf_External_Vernaux evna; - Elf_Internal_Vernaux ivna; - unsigned long vna_off; + Elf_Internal_Vernaux ivna; + unsigned long vna_off; GET_DATA (offset, evn, "version need"); @@ -3242,10 +3929,10 @@ process_version_sections (file) { ivna.vna_name = BYTE_GET (evna.vna_name); + name = strtab + ivna.vna_name; nn += printf ("(%s%-*s", - strtab + ivna.vna_name, - 12 - strlen (strtab - + ivna.vna_name), + name, + 12 - (int) strlen (name), ")"); break; } @@ -3288,12 +3975,11 @@ process_version_sections (file) ivda.vda_name = BYTE_GET (evda.vda_name); + name = strtab + ivda.vda_name; nn += printf ("(%s%-*s", - strtab + ivda.vda_name, - 12 - - strlen (strtab - + ivda.vda_name), + name, + 12 - (int) strlen (name), ")"); } } @@ -3315,10 +4001,10 @@ process_version_sections (file) do { - Elf_Internal_Vernaux ivna; + Elf_Internal_Vernaux ivna; Elf_External_Verneed evn; Elf_External_Vernaux evna; - unsigned long a_off; + unsigned long a_off; GET_DATA (offset, evn, "version need"); @@ -3344,10 +4030,10 @@ process_version_sections (file) { ivna.vna_name = BYTE_GET (evna.vna_name); + name = strtab + ivna.vna_name; nn += printf ("(%s%-*s", - strtab + ivna.vna_name, - 12 - strlen (strtab - + ivna.vna_name), + name, + 12 - (int) strlen (name), ")"); break; } @@ -3389,10 +4075,10 @@ process_version_sections (file) ivda.vda_name = BYTE_GET (evda.vda_name); + name = strtab + ivda.vda_name; nn += printf ("(%s%-*s", - strtab + ivda.vda_name, - 12 - strlen (strtab - + ivda.vda_name), + name, + 12 - (int) strlen (name), ")"); } } @@ -3409,7 +4095,7 @@ process_version_sections (file) free (symbols); } break; - + default: break; } @@ -3421,7 +4107,7 @@ process_version_sections (file) return 1; } -static char * +static const char * get_symbol_binding (binding) unsigned int binding; { @@ -3429,9 +4115,9 @@ get_symbol_binding (binding) switch (binding) { - case STB_LOCAL: return _("LOCAL"); - case STB_GLOBAL: return _("GLOBAL"); - case STB_WEAK: return _("WEAK"); + case STB_LOCAL: return "LOCAL"; + case STB_GLOBAL: return "GLOBAL"; + case STB_WEAK: return "WEAK"; default: if (binding >= STB_LOPROC && binding <= STB_HIPROC) sprintf (buff, _(": %d"), binding); @@ -3443,7 +4129,7 @@ get_symbol_binding (binding) } } -static char * +static const char * get_symbol_type (type) unsigned int type; { @@ -3451,31 +4137,59 @@ get_symbol_type (type) switch (type) { - case STT_NOTYPE: return _("NOTYPE"); - case STT_OBJECT: return _("OBJECT"); - case STT_FUNC: return _("FUNC"); - case STT_SECTION: return _("SECTION"); - case STT_FILE: return _("FILE"); + case STT_NOTYPE: return "NOTYPE"; + case STT_OBJECT: return "OBJECT"; + case STT_FUNC: return "FUNC"; + case STT_SECTION: return "SECTION"; + case STT_FILE: return "FILE"; + case STT_COMMON: return "COMMON"; default: if (type >= STT_LOPROC && type <= STT_HIPROC) { if (elf_header.e_machine == EM_ARM && type == STT_ARM_TFUNC) - return _("THUMB_FUNC"); - + return "THUMB_FUNC"; + if (elf_header.e_machine == EM_SPARCV9 && type == STT_REGISTER) - return _("REGISTER"); - + return "REGISTER"; + + if (elf_header.e_machine == EM_PARISC && type == STT_PARISC_MILLI) + return "PARISC_MILLI"; + sprintf (buff, _(": %d"), type); } else if (type >= STT_LOOS && type <= STT_HIOS) - sprintf (buff, _(": %d"), type); + { + if (elf_header.e_machine == EM_PARISC) + { + if (type == STT_HP_OPAQUE) + return "HP_OPAQUE"; + if (type == STT_HP_STUB) + return "HP_STUB"; + } + + sprintf (buff, _(": %d"), type); + } else sprintf (buff, _(": %d"), type); return buff; } } -static char * +static const char * +get_symbol_visibility (visibility) + unsigned int visibility; +{ + switch (visibility) + { + case STV_DEFAULT: return "DEFAULT"; + case STV_INTERNAL: return "INTERNAL"; + case STV_HIDDEN: return "HIDDEN"; + case STV_PROTECTED: return "PROTECTED"; + default: abort (); + } +} + +static const char * get_symbol_index_type (type) unsigned int type; { @@ -3501,7 +4215,6 @@ get_symbol_index_type (type) } } - static int * get_dynamic_data (file, number) FILE * file; @@ -3549,8 +4262,8 @@ process_symbol_table (file) Elf32_Internal_Shdr * section; char nb [4]; char nc [4]; - int nbuckets; - int nchains; + int nbuckets = 0; + int nchains = 0; int * buckets = NULL; int * chains = NULL; @@ -3595,29 +4308,31 @@ process_symbol_table (file) int si; printf (_("\nSymbol table for image:\n")); - printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\n")); + if (is_32bit_elf) + printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); + else + printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); for (hn = 0; hn < nbuckets; hn++) { if (! buckets [hn]) continue; - for (si = buckets [hn]; si; si = chains [si]) + for (si = buckets [hn]; si < nchains && si > 0; si = chains [si]) { Elf_Internal_Sym * psym; psym = dynamic_symbols + si; - printf (" %3d %3d: %8lx %5ld %6s %6s %2d ", - si, hn, - (unsigned long) psym->st_value, - (unsigned long) psym->st_size, - get_symbol_type (ELF_ST_TYPE (psym->st_info)), - get_symbol_binding (ELF_ST_BIND (psym->st_info)), - psym->st_other); - - printf ("%3.3s", get_symbol_index_type (psym->st_shndx)); - + printf (" %3d %3d: ", si, hn); + 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))); + printf (" %3.3s", get_symbol_index_type (psym->st_shndx)); printf (" %s\n", dynamic_strings + psym->st_name); } } @@ -3643,8 +4358,10 @@ process_symbol_table (file) printf (_("\nSymbol table '%s' contains %lu entries:\n"), SECTION_NAME (section), (unsigned long) (section->sh_size / section->sh_entsize)); - fputs (_(" Num: Value Size Type Bind Ot Ndx Name\n"), - stdout); + if (is_32bit_elf) + printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); + else + printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); symtab = GET_ELF_SYMBOLS (file, section->sh_offset, section->sh_size / section->sh_entsize); @@ -3667,16 +4384,14 @@ process_symbol_table (file) si < section->sh_size / section->sh_entsize; si ++, psym ++) { - printf (" %3d: %8lx %5ld %-7s %-6s %2d ", - si, - (unsigned long) psym->st_value, - (unsigned long) psym->st_size, - get_symbol_type (ELF_ST_TYPE (psym->st_info)), - get_symbol_binding (ELF_ST_BIND (psym->st_info)), - psym->st_other); - - printf ("%4s", get_symbol_index_type (psym->st_shndx)); - + printf ("%6d: ", si); + print_vma (psym->st_value, LONG_HEX); + putchar (' '); + print_vma (psym->st_size, DEC_5); + printf (" %-7s", 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))); + printf (" %4s", get_symbol_index_type (psym->st_shndx)); printf (" %s", strtab + psym->st_name); if (section->sh_type == SHT_DYNSYM && @@ -3714,15 +4429,15 @@ process_symbol_table (file) offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr; - GET_DATA (offset, evn, "version need"); - - ivn.vn_aux = BYTE_GET (evn.vn_aux); - ivn.vn_next = BYTE_GET (evn.vn_next); - do { 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 @@ -3841,11 +4556,11 @@ process_symbol_table (file) if (! buckets [hn]) continue; - for (si = buckets[hn]; si; si = chains[si]) + for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si]) { - ++nsyms; + ++ nsyms; if (maxlength < ++lengths[hn]) - ++maxlength; + ++ maxlength; } } @@ -3859,14 +4574,17 @@ process_symbol_table (file) for (hn = 0; hn < nbuckets; ++hn) ++ counts [lengths [hn]]; - printf (" 0 %-10d (%5.1f%%)\n", - counts[0], (counts[0] * 100.0) / nbuckets); - for (si = 1; si <= maxlength; ++si) + if (nbuckets > 0) { - nzero_counts += counts[si] * si; - printf ("%7d %-10d (%5.1f%%) %5.1f%%\n", - si, counts[si], (counts[si] * 100.0) / nbuckets, - (nzero_counts * 100.0) / nsyms); + printf (" 0 %-10d (%5.1f%%)\n", + counts[0], (counts[0] * 100.0) / nbuckets); + for (si = 1; si <= maxlength; ++si) + { + nzero_counts += counts[si] * si; + printf ("%7d %-10d (%5.1f%%) %5.1f%%\n", + si, counts[si], (counts[si] * 100.0) / nbuckets, + (nzero_counts * 100.0) / nsyms); + } } free (counts); @@ -3884,9 +4602,9 @@ process_symbol_table (file) static int process_syminfo (file) - FILE * file; + FILE * file ATTRIBUTE_UNUSED; { - int i; + unsigned int i; if (dynamic_syminfo == NULL || !do_dynamic) @@ -4113,16 +4831,17 @@ reset_state_machine (is_stmt) /* Handled an extend line op. Returns true if this is the end of sequence. */ static int -process_extended_line_op (data, is_stmt) +process_extended_line_op (data, is_stmt, pointer_size) unsigned char * data; int is_stmt; + int pointer_size; { unsigned char op_code; int bytes_read; unsigned int len; unsigned char * name; unsigned long adr; - + len = read_leb128 (data, & bytes_read, 0); data += bytes_read; @@ -4136,7 +4855,7 @@ process_extended_line_op (data, is_stmt) op_code = * data ++; printf (_(" Extended opcode %d: "), op_code); - + switch (op_code) { case DW_LNE_end_sequence: @@ -4145,8 +4864,7 @@ process_extended_line_op (data, is_stmt) break; case DW_LNE_set_address: - /* XXX - assumption here that address size is 4! */ - adr = byte_get (data, 4); + adr = byte_get (data, pointer_size); printf (_("set Address to 0x%lx\n"), adr); state_machine_regs.address = adr; break; @@ -4154,7 +4872,7 @@ process_extended_line_op (data, is_stmt) case DW_LNE_define_file: printf (_(" define new File Table entry\n")); printf (_(" Entry\tDir\tTime\tSize\tName\n")); - + printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); name = data; data += strlen (data) + 1; @@ -4174,12 +4892,16 @@ process_extended_line_op (data, is_stmt) return len; } +/* Size of pointers in the .debug_line section. This information is not + really present in that section. It's obtained before dumping the debug + sections by doing some pre-scan of the .debug_info section. */ +static int debug_line_pointer_size = 4; static int display_debug_lines (section, start, file) Elf32_Internal_Shdr * section; unsigned char * start; - FILE * file; + FILE * file ATTRIBUTE_UNUSED; { DWARF2_External_LineInfo * external; DWARF2_Internal_LineInfo info; @@ -4204,7 +4926,7 @@ display_debug_lines (section, start, file) (_("The line info appears to be corrupt - the section is too small\n")); return 0; } - + /* Check its version number. */ info.li_version = BYTE_GET (external->li_version); if (info.li_version != 2) @@ -4212,18 +4934,18 @@ display_debug_lines (section, start, file) warn (_("Only DWARF version 2 line info is currently supported.\n")); return 0; } - + info.li_prologue_length = BYTE_GET (external->li_prologue_length); info.li_min_insn_length = BYTE_GET (external->li_min_insn_length); info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt); info.li_line_base = BYTE_GET (external->li_line_base); info.li_line_range = BYTE_GET (external->li_line_range); info.li_opcode_base = BYTE_GET (external->li_opcode_base); - + /* Sign extend the line base field. */ info.li_line_base <<= 24; info.li_line_base >>= 24; - + printf (_(" Length: %ld\n"), info.li_length); printf (_(" DWARF Version: %d\n"), info.li_version); printf (_(" Prolgue Length: %d\n"), info.li_prologue_length); @@ -4236,35 +4958,35 @@ display_debug_lines (section, start, file) end_of_sequence = data + info.li_length + sizeof (info.li_length); reset_state_machine (info.li_default_is_stmt); - + /* Display the contents of the Opcodes table. */ standard_opcodes = data + sizeof (* external); - + printf (_("\n Opcodes:\n")); - + for (i = 1; i < info.li_opcode_base; i++) - printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i]); - + printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i - 1]); + /* Display the contents of the Directory table. */ data = standard_opcodes + info.li_opcode_base - 1; - + if (* data == 0) printf (_("\n The Directory Table is empty.\n")); else { printf (_("\n The Directory Table:\n")); - + while (* data != 0) { printf (_(" %s\n"), data); - + data += strlen (data) + 1; } } - + /* Skip the NUL at the end of the table. */ data ++; - + /* Display the contents of the File Name table. */ if (* data == 0) printf (_("\n The File Name Table is empty.\n")); @@ -4272,17 +4994,17 @@ display_debug_lines (section, start, file) { printf (_("\n The File Name Table:\n")); printf (_(" Entry\tDir\tTime\tSize\tName\n")); - + while (* data != 0) { char * name; int bytes_read; - + printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); name = data; - + data += strlen (data) + 1; - + printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); data += bytes_read; printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); @@ -4292,32 +5014,33 @@ display_debug_lines (section, start, file) printf (_("%s\n"), name); } } - + /* Skip the NUL at the end of the table. */ data ++; - + /* Now display the statements. */ printf (_("\n Line Number Statements:\n")); - - + + while (data < end_of_sequence) { unsigned char op_code; int adv; int bytes_read; - + op_code = * data ++; - + switch (op_code) { case DW_LNS_extended_op: - data += process_extended_line_op (data, info.li_default_is_stmt); + data += process_extended_line_op (data, info.li_default_is_stmt, + debug_line_pointer_size); break; - + case DW_LNS_copy: printf (_(" Copy\n")); break; - + case DW_LNS_advance_pc: adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0); data += bytes_read; @@ -4325,7 +5048,7 @@ display_debug_lines (section, start, file) printf (_(" Advance PC by %d to %lx\n"), adv, state_machine_regs.address); break; - + case DW_LNS_advance_line: adv = read_leb128 (data, & bytes_read, 1); data += bytes_read; @@ -4333,7 +5056,7 @@ display_debug_lines (section, start, file) printf (_(" Advance Line by %d to %d\n"), adv, state_machine_regs.line); break; - + case DW_LNS_set_file: adv = read_leb128 (data, & bytes_read, 0); data += bytes_read; @@ -4341,33 +5064,34 @@ display_debug_lines (section, start, file) adv); state_machine_regs.file = adv; break; - + case DW_LNS_set_column: adv = read_leb128 (data, & bytes_read, 0); data += bytes_read; printf (_(" Set column to %d\n"), adv); state_machine_regs.column = adv; break; - + case DW_LNS_negate_stmt: adv = state_machine_regs.is_stmt; adv = ! adv; printf (_(" Set is_stmt to %d\n"), adv); state_machine_regs.is_stmt = adv; break; - + case DW_LNS_set_basic_block: printf (_(" Set basic block\n")); state_machine_regs.basic_block = 1; break; - + case DW_LNS_const_add_pc: - adv = (255 - info.li_opcode_base) / info.li_line_range; + adv = (((255 - info.li_opcode_base) / info.li_line_range) + * info.li_min_insn_length); state_machine_regs.address += adv; printf (_(" Advance PC by constant %d to 0x%lx\n"), adv, state_machine_regs.address); break; - + case DW_LNS_fixed_advance_pc: adv = byte_get (data, 2); data += 2; @@ -4375,14 +5099,14 @@ display_debug_lines (section, start, file) printf (_(" Advance PC by fixed size amount %d to 0x%lx\n"), adv, state_machine_regs.address); break; - + default: op_code -= info.li_opcode_base; adv = (op_code / info.li_line_range) * info.li_min_insn_length; state_machine_regs.address += adv; printf (_(" Special opcode %d: advance Address by %d to 0x%lx"), op_code, adv, state_machine_regs.address); - adv += (op_code % info.li_line_range) + info.li_line_base; + adv = (op_code % info.li_line_range) + info.li_line_base; state_machine_regs.line += adv; printf (_(" and Line by %d to %d\n"), adv, state_machine_regs.line); @@ -4391,7 +5115,7 @@ display_debug_lines (section, start, file) } printf ("\n"); } - + return 1; } @@ -4399,7 +5123,7 @@ static int display_debug_pubnames (section, start, file) Elf32_Internal_Shdr * section; unsigned char * start; - FILE * file; + FILE * file ATTRIBUTE_UNUSED; { DWARF2_External_PubNames * external; DWARF2_Internal_PubNames pubnames; @@ -4787,8 +5511,11 @@ process_abbrev_section (start, end) entry = read_leb128 (start, & bytes_read, 0); start += bytes_read; + /* A single zero is supposed to end the section according + to the standard. If there's more, then signal that to + the caller. */ if (entry == 0) - return start; + return start == end ? NULL : start; tag = read_leb128 (start, & bytes_read, 0); start += bytes_read; @@ -4821,7 +5548,7 @@ static int display_debug_abbrev (section, start, file) Elf32_Internal_Shdr * section; unsigned char * start; - FILE * file; + FILE * file ATTRIBUTE_UNUSED; { abbrev_entry * entry; unsigned char * end = start + section->sh_size; @@ -4873,500 +5600,333 @@ 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; + unsigned op; int bytes_read; unsigned long uvalue; + unsigned char *end = data + length; - op = * data ++; - - 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; - unsigned char * block_start; + 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; - } - switch (form) { case DW_FORM_ref_addr: case DW_FORM_addr: uvalue = byte_get (data, pointer_size); - printf (is_ref ? " <%x>" : " %#x", uvalue); data += pointer_size; break; @@ -5374,21 +5934,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 ? " <%x>" : " %d", uvalue); break; case DW_FORM_ref2: case DW_FORM_data2: uvalue = byte_get (data, 2); data += 2; - printf (is_ref ? " <%x>" : " %d", uvalue); break; case DW_FORM_ref4: case DW_FORM_data4: uvalue = byte_get (data, 4); data += 4; - printf (is_ref ? " <%x>" : " %d", 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: @@ -5404,45 +5998,28 @@ read_and_display_attr (attribute, form, data, pointer_size) 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); - 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: @@ -5472,11 +6049,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) { @@ -5573,12 +6145,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: @@ -5607,6 +6183,7 @@ display_debug_info (section, start, file) unsigned char * tags; int i; int level; + unsigned long cu_offset; external = (DWARF2_External_CompUnit *) start; @@ -5616,6 +6193,7 @@ 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); if (compunit.cu_version != 2) @@ -5665,7 +6243,7 @@ display_debug_info (section, start, file) while (tags < start) { int bytes_read; - int abbrev_number; + unsigned long abbrev_number; abbrev_entry * entry; abbrev_attr * attr; @@ -5688,12 +6266,12 @@ display_debug_info (section, start, file) if (entry == NULL) { - warn (_("Unable to locate entry %d in the abbreviation table\n"), + warn (_("Unable to locate entry %lu in the abbreviation table\n"), abbrev_number); return 0; } - printf (_(" <%d><%x>: Abbrev Number: %d (%s)\n"), + printf (_(" <%d><%x>: Abbrev Number: %lu (%s)\n"), level, tags - section_begin - bytes_read, abbrev_number, get_TAG_name (entry->tag)); @@ -5701,7 +6279,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) @@ -5718,7 +6296,7 @@ static int display_debug_aranges (section, start, file) Elf32_Internal_Shdr * section; unsigned char * start; - FILE * file; + FILE * file ATTRIBUTE_UNUSED; { unsigned char * end = start + section->sh_size; @@ -5731,6 +6309,7 @@ display_debug_aranges (section, start, file) unsigned char * ranges; unsigned long length; unsigned long address; + int excess; external = (DWARF2_External_ARange *) start; @@ -5750,19 +6329,25 @@ 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); + if (excess) + ranges += (2 * arange.ar_pointer_size) - excess; + for (;;) { address = byte_get (ranges, arange.ar_pointer_size); - if (address == 0) - break; - ranges += arange.ar_pointer_size; length = byte_get (ranges, arange.ar_pointer_size); ranges += arange.ar_pointer_size; + /* A pair of zeros marks the end of the list. */ + if (address == 0 && length == 0) + break; + printf (" %8.8lx %lu\n", address, length); } @@ -5778,8 +6363,8 @@ display_debug_aranges (section, start, file) static int display_debug_not_supported (section, start, file) Elf32_Internal_Shdr * section; - unsigned char * start; - FILE * file; + unsigned char * start ATTRIBUTE_UNUSED; + FILE * file ATTRIBUTE_UNUSED; { printf (_("Displaying the debug contents of section %s is not yet supported.\n"), SECTION_NAME (section)); @@ -5787,27 +6372,47 @@ display_debug_not_supported (section, start, file) return 1; } +/* Pre-scan the .debug_info section to record the size of address. + When dumping the .debug_line, we use that size information, assuming + that all compilation units have the same address size. */ +static int +prescan_debug_info (section, start, file) + Elf32_Internal_Shdr * section ATTRIBUTE_UNUSED; + unsigned char * start; + FILE * file ATTRIBUTE_UNUSED; +{ + DWARF2_External_CompUnit * external; + + external = (DWARF2_External_CompUnit *) start; + + debug_line_pointer_size = BYTE_GET (external->cu_pointer_size); + return 0; +} + /* A structure containing the name of a debug section and a pointer - to a function that can decode it. */ + to a function that can decode it. The third field is a prescan + function to be run over the section before displaying any of the + sections. */ struct { char * name; - int (* display) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *)); + int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); + int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); } debug_displays[] = { - { ".debug_info", display_debug_info }, - { ".debug_abbrev", display_debug_abbrev }, - { ".debug_line", display_debug_lines }, - { ".debug_aranges", display_debug_aranges }, - { ".debug_pubnames", display_debug_pubnames }, - { ".debug_macinfo", display_debug_not_supported }, - { ".debug_frame", display_debug_not_supported }, - { ".debug_str", display_debug_not_supported }, - { ".debug_static_func", display_debug_not_supported }, - { ".debug_static_vars", display_debug_not_supported }, - { ".debug_types", display_debug_not_supported }, - { ".debug_weaknames", display_debug_not_supported } + { ".debug_info", display_debug_info, prescan_debug_info }, + { ".debug_abbrev", display_debug_abbrev, NULL }, + { ".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_str", display_debug_not_supported, NULL }, + { ".debug_static_func", display_debug_not_supported, NULL }, + { ".debug_static_vars", display_debug_not_supported, NULL }, + { ".debug_types", display_debug_not_supported, NULL }, + { ".debug_weaknames", display_debug_not_supported, NULL } }; static int @@ -5855,15 +6460,48 @@ static int process_section_contents (file) FILE * file; { - Elf32_Internal_Shdr * section; - unsigned int i; + Elf32_Internal_Shdr * section; + unsigned int i; if (! do_dump) return 1; + /* Pre-scan the debug sections to find some debug information not + present in some of them. For the .debug_line, we must find out the + size of address (specified in .debug_info and .debug_aranges). */ + for (i = 0, section = section_headers; + i < elf_header.e_shnum && i < num_dump_sects; + i ++, section ++) + { + char * name = SECTION_NAME (section); + int j; + + if (section->sh_size == 0) + continue; + + /* See if there is some pre-scan operation for this section. */ + for (j = NUM_ELEM (debug_displays); j--;) + if (strcmp (debug_displays[j].name, name) == 0) + { + if (debug_displays[j].prescan != NULL) + { + bfd_size_type length; + unsigned char * start; + + length = section->sh_size; + GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *, + "debug section data"); + + debug_displays[j].prescan (section, start, file); + free (start); + } + + break; + } + } + for (i = 0, section = section_headers; - i < elf_header.e_shnum - && i < num_dump_sects; + i < elf_header.e_shnum && i < num_dump_sects; i ++, section ++) { #ifdef SUPPORT_DISASSEMBLY @@ -5951,7 +6589,8 @@ process_mips_specific (file) GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib), elib, Elf32_External_Lib *, "liblist"); - printf ("\nSection '.liblist' contains %d entries:\n", liblistno); + printf ("\nSection '.liblist' contains %lu entries:\n", + (unsigned long) liblistno); fputs (" Library Time Stamp Checksum Version Flags\n", stdout); @@ -5960,6 +6599,7 @@ process_mips_specific (file) 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); @@ -5967,9 +6607,12 @@ process_mips_specific (file) liblist.l_version = BYTE_GET (elib[cnt].l_version); liblist.l_flags = BYTE_GET (elib[cnt].l_flags); - strftime (timebuf, 20, "%Y-%m-%dT%H:%M:%S", gmtime (&time)); + 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 ("%3d: %-20s %s %#10lx %-7ld", cnt, + printf ("%3lu: %-20s %s %#10lx %-7ld", (unsigned long) cnt, dynamic_strings + liblist.l_name, timebuf, liblist.l_checksum, liblist.l_version); @@ -5979,19 +6622,20 @@ process_mips_specific (file) { static const struct { - const char *name; + 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 } - }; + } + 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; - int fcnt; + size_t fcnt; for (fcnt = 0; fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]); @@ -6014,7 +6658,7 @@ process_mips_specific (file) if (options_offset != 0) { Elf_External_Options * eopt; - Elf_Internal_Shdr * sect = section_headers; + Elf_Internal_Shdr * sect = section_headers; Elf_Internal_Options * iopt; Elf_Internal_Options * option; size_t offset; @@ -6022,7 +6666,7 @@ process_mips_specific (file) /* Find the section header so that we get the size. */ while (sect->sh_type != SHT_MIPS_OPTIONS) - ++sect; + ++ sect; GET_DATA_ALLOC (options_offset, sect->sh_size, eopt, Elf_External_Options *, "options"); @@ -6037,6 +6681,7 @@ process_mips_specific (file) offset = cnt = 0; option = iopt; + while (offset < sect->sh_size) { Elf_External_Options * eoption; @@ -6049,6 +6694,7 @@ process_mips_specific (file) option->info = BYTE_GET (eoption->info); offset += option->size; + ++option; ++cnt; } @@ -6057,6 +6703,7 @@ process_mips_specific (file) string_table + sect->sh_name, cnt); option = iopt; + while (cnt-- > 0) { size_t len; @@ -6249,18 +6896,195 @@ process_mips_specific (file) { Elf_Internal_Sym * psym = &dynamic_symbols[iconf[cnt]]; - printf ("%5u: %8lu %#10lx %s\n", - cnt, iconf[cnt], (unsigned long) psym->st_value, - dynamic_strings + psym->st_name); + printf ("%5lu: %8lu ", (unsigned long) cnt, iconf[cnt]); + print_vma (psym->st_value, FULL_HEX); + printf (" %s\n", dynamic_strings + psym->st_name); } - free (iconf); } return 1; } +static char * +get_note_type (e_type) + unsigned e_type; +{ + static char buff[64]; + + switch (e_type) + { + case NT_PRSTATUS: return _("NT_PRSTATUS (prstatus structure)"); + case NT_FPREGSET: return _("NT_FPREGSET (floating point registers)"); + case NT_PRPSINFO: return _("NT_PRPSINFO (prpsinfo structure)"); + case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)"); + case NT_PRXFPREG: return _("NT_PRXFPREG (user_xfpregs structure)"); + case NT_PSTATUS: return _("NT_PSTATUS (pstatus structure)"); + case NT_FPREGS: return _("NT_FPREGS (floating point registers)"); + case NT_PSINFO: return _("NT_PSINFO (psinfo structure)"); + case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)"); + case NT_LWPSINFO: return _("NT_LWPSINFO (lwpsinfo_t structure)"); + case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus strcuture)"); + default: + sprintf (buff, _("Unknown note type: (0x%08x)"), e_type); + return buff; + } +} + +/* Note that by the ELF standard, the name field is already null byte + terminated, and namesz includes the terminating null byte. + I.E. the value of namesz for the name "FSF" is 4. + + If the value of namesz is zero, there is no name present. */ +static int +process_note (pnote) + Elf32_Internal_Note * pnote; +{ + printf (" %s\t\t0x%08lx\t%s\n", + pnote->namesz ? pnote->namedata : "(NONE)", + pnote->descsz, get_note_type (pnote->type)); + return 1; +} + + +static int +process_corefile_note_segment (file, offset, length) + FILE * file; + bfd_vma offset; + bfd_vma length; +{ + Elf_External_Note * pnotes; + Elf_External_Note * external; + int res = 1; + + if (length <= 0) + return 0; + + GET_DATA_ALLOC (offset, length, pnotes, Elf_External_Note *, "notes"); + + external = pnotes; + + printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"), + (unsigned long) offset, (unsigned long) length); + printf (_(" Owner\t\tData size\tDescription\n")); + + while (external < (Elf_External_Note *)((char *) pnotes + length)) + { + Elf32_Internal_Note inote; + char * temp = NULL; + + inote.type = BYTE_GET (external->type); + inote.namesz = BYTE_GET (external->namesz); + inote.namedata = external->name; + 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 + one version of Linux (RedHat 6.0) generates corefiles that don't + comply with the ELF spec by failing to include the null byte in + namesz. */ + 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; + } + + res &= process_note (& inote); + + if (temp != NULL) + { + free (temp); + temp = NULL; + } + } + + free (pnotes); + + return res; +} + +static int +process_corefile_note_segments (file) + FILE * file; +{ + Elf_Internal_Phdr * program_headers; + Elf_Internal_Phdr * segment; + unsigned int i; + int res = 1; + + program_headers = (Elf_Internal_Phdr *) malloc + (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); + + if (program_headers == NULL) + { + error (_("Out of memory\n")); + return 0; + } + + if (is_32bit_elf) + i = get_32bit_program_headers (file, program_headers); + else + i = get_64bit_program_headers (file, program_headers); + + if (i == 0) + { + free (program_headers); + return 0; + } + + for (i = 0, segment = program_headers; + i < elf_header.e_phnum; + i ++, segment ++) + { + if (segment->p_type == PT_NOTE) + res &= process_corefile_note_segment (file, + (bfd_vma) segment->p_offset, + (bfd_vma) segment->p_filesz); + } + + free (program_headers); + + return res; +} + +static int +process_corefile_contents (file) + FILE * file; +{ + /* If we have not been asked to display the notes then do nothing. */ + if (! do_notes) + return 1; + + /* If file is not a core file then exit. */ + if (elf_header.e_type != ET_CORE) + return 1; + + /* No program headers means no NOTE segment. */ + if (elf_header.e_phnum == 0) + { + printf (_("No note segments present in the core file.\n")); + return 1; + } + + return process_corefile_note_segments (file); +} + static int process_arch_specific (file) FILE * file; @@ -6307,7 +7131,7 @@ get_file_header (file) if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT, 1, file) != 1) return 0; - + elf_header.e_type = BYTE_GET (ehdr32.e_type); elf_header.e_machine = BYTE_GET (ehdr32.e_machine); elf_header.e_version = BYTE_GET (ehdr32.e_version); @@ -6336,10 +7160,10 @@ get_file_header (file) error (_("64 bit data type and so it cannot read 64 bit ELF files.\n")); return 0; } - + if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 1, file) != 1) return 0; - + elf_header.e_type = BYTE_GET (ehdr64.e_type); elf_header.e_machine = BYTE_GET (ehdr64.e_machine); elf_header.e_version = BYTE_GET (ehdr64.e_version); @@ -6419,6 +7243,8 @@ process_file (file_name) process_section_contents (file); + process_corefile_contents (file); + process_arch_specific (file); fclose (file);