readelf.c revision 78828
160484Sobrien/* readelf.c -- display contents of an ELF format file 278828Sobrien Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. 360484Sobrien 460484Sobrien Originally developed by Eric Youngdale <eric@andante.jic.com> 560484Sobrien Modifications by Nick Clifton <nickc@cygnus.com> 660484Sobrien 760484Sobrien This file is part of GNU Binutils. 860484Sobrien 960484Sobrien This program is free software; you can redistribute it and/or modify 1060484Sobrien it under the terms of the GNU General Public License as published by 1160484Sobrien the Free Software Foundation; either version 2 of the License, or 1260484Sobrien (at your option) any later version. 1360484Sobrien 1460484Sobrien This program is distributed in the hope that it will be useful, 1560484Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1660484Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1760484Sobrien GNU General Public License for more details. 1860484Sobrien 1960484Sobrien You should have received a copy of the GNU General Public License 2060484Sobrien along with this program; if not, write to the Free Software 2160484Sobrien Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 2260484Sobrien 02111-1307, USA. */ 2360484Sobrien 2460484Sobrien 2560484Sobrien#include <assert.h> 2660484Sobrien#include <sys/types.h> 2760484Sobrien#include <sys/stat.h> 2860484Sobrien#include <stdio.h> 2960484Sobrien#include <time.h> 3060484Sobrien 3160484Sobrien#if __GNUC__ >= 2 3260484Sobrien/* Define BFD64 here, even if our default architecture is 32 bit ELF 3360484Sobrien as this will allow us to read in and parse 64bit and 32bit ELF files. 3460484Sobrien Only do this if we belive that the compiler can support a 64 bit 3560484Sobrien data type. For now we only rely on GCC being able to do this. */ 3660484Sobrien#define BFD64 3760484Sobrien#endif 3860484Sobrien 3960484Sobrien#include "bfd.h" 4060484Sobrien 4160484Sobrien#include "elf/common.h" 4260484Sobrien#include "elf/external.h" 4360484Sobrien#include "elf/internal.h" 4460484Sobrien#include "elf/dwarf2.h" 4560484Sobrien 4660484Sobrien/* The following headers use the elf/reloc-macros.h file to 4760484Sobrien automatically generate relocation recognition functions 4860484Sobrien such as elf_mips_reloc_type() */ 4960484Sobrien 5060484Sobrien#define RELOC_MACROS_GEN_FUNC 5160484Sobrien 5260484Sobrien#include "elf/i386.h" 5360484Sobrien#include "elf/v850.h" 5460484Sobrien#include "elf/ppc.h" 5560484Sobrien#include "elf/mips.h" 5660484Sobrien#include "elf/alpha.h" 5760484Sobrien#include "elf/arm.h" 5860484Sobrien#include "elf/m68k.h" 5960484Sobrien#include "elf/sparc.h" 6060484Sobrien#include "elf/m32r.h" 6160484Sobrien#include "elf/d10v.h" 6260484Sobrien#include "elf/d30v.h" 6360484Sobrien#include "elf/sh.h" 6460484Sobrien#include "elf/mn10200.h" 6560484Sobrien#include "elf/mn10300.h" 6660484Sobrien#include "elf/hppa.h" 6760484Sobrien#include "elf/arc.h" 6860484Sobrien#include "elf/fr30.h" 6960484Sobrien#include "elf/mcore.h" 7060484Sobrien#include "elf/i960.h" 7160484Sobrien#include "elf/pj.h" 7260484Sobrien#include "elf/avr.h" 7377298Sobrien#include "elf/ia64.h" 7477298Sobrien#include "elf/cris.h" 7577298Sobrien#include "elf/i860.h" 7677298Sobrien#include "elf/x86-64.h" 7760484Sobrien 7860484Sobrien#include "bucomm.h" 7960484Sobrien#include "getopt.h" 8060484Sobrien 8178828Sobrienchar * program_name = "readelf"; 8278828Sobrienunsigned int dynamic_addr; 8378828Sobrienbfd_size_type dynamic_size; 8478828Sobrienunsigned int rela_addr; 8578828Sobrienunsigned int rela_size; 8678828Sobrienchar * dynamic_strings; 8760484Sobrienchar * string_table; 8877298Sobrienunsigned long string_table_length; 8960484Sobrienunsigned long num_dynamic_syms; 9078828SobrienElf_Internal_Sym * dynamic_symbols; 9160484SobrienElf_Internal_Syminfo * dynamic_syminfo; 9278828Sobrienunsigned long dynamic_syminfo_offset; 9360484Sobrienunsigned int dynamic_syminfo_nent; 9478828Sobrienchar program_interpreter [64]; 9578828Sobrienint dynamic_info[DT_JMPREL + 1]; 9678828Sobrienint version_info[16]; 9778828Sobrienint loadaddr = 0; 9860484SobrienElf_Internal_Ehdr elf_header; 9960484SobrienElf_Internal_Shdr * section_headers; 10060484SobrienElf_Internal_Dyn * dynamic_segment; 10178828Sobrienint show_name; 10278828Sobrienint do_dynamic; 10378828Sobrienint do_syms; 10478828Sobrienint do_reloc; 10578828Sobrienint do_sections; 10678828Sobrienint do_segments; 10778828Sobrienint do_unwind; 10878828Sobrienint do_using_dynamic; 10978828Sobrienint do_header; 11078828Sobrienint do_dump; 11178828Sobrienint do_version; 11260484Sobrienint do_histogram; 11360484Sobrienint do_debugging; 11460484Sobrienint do_debug_info; 11560484Sobrienint do_debug_abbrevs; 11660484Sobrienint do_debug_lines; 11760484Sobrienint do_debug_pubnames; 11860484Sobrienint do_debug_aranges; 11977298Sobrienint do_debug_frames; 12078828Sobrienint do_debug_frames_interp; 12160484Sobrienint do_arch; 12260484Sobrienint do_notes; 12360484Sobrienint is_32bit_elf; 12460484Sobrien 12560484Sobrien/* A dynamic array of flags indicating which sections require dumping. */ 12660484Sobrienchar * dump_sects = NULL; 12760484Sobrienunsigned int num_dump_sects = 0; 12860484Sobrien 12960484Sobrien#define HEX_DUMP (1 << 0) 13060484Sobrien#define DISASS_DUMP (1 << 1) 13160484Sobrien#define DEBUG_DUMP (1 << 2) 13260484Sobrien 13360484Sobrien/* How to rpint a vma value. */ 13460484Sobrientypedef enum print_mode 13560484Sobrien{ 13660484Sobrien HEX, 13760484Sobrien DEC, 13860484Sobrien DEC_5, 13960484Sobrien UNSIGNED, 14060484Sobrien PREFIX_HEX, 14160484Sobrien FULL_HEX, 14260484Sobrien LONG_HEX 14360484Sobrien} 14460484Sobrienprint_mode; 14560484Sobrien 14660484Sobrien/* Forward declarations for dumb compilers. */ 14760484Sobrienstatic void print_vma PARAMS ((bfd_vma, print_mode)); 14860484Sobrienstatic bfd_vma (* byte_get) PARAMS ((unsigned char *, int)); 14960484Sobrienstatic bfd_vma byte_get_little_endian PARAMS ((unsigned char *, int)); 15060484Sobrienstatic bfd_vma byte_get_big_endian PARAMS ((unsigned char *, int)); 15160484Sobrienstatic const char * get_mips_dynamic_type PARAMS ((unsigned long)); 15260484Sobrienstatic const char * get_sparc64_dynamic_type PARAMS ((unsigned long)); 15360484Sobrienstatic const char * get_parisc_dynamic_type PARAMS ((unsigned long)); 15460484Sobrienstatic const char * get_dynamic_type PARAMS ((unsigned long)); 15578828Sobrienstatic int slurp_rela_relocs PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **, unsigned long *)); 15678828Sobrienstatic int slurp_rel_relocs PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rel **, unsigned long *)); 15760484Sobrienstatic int dump_relocations PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, unsigned long, char *, int)); 15860484Sobrienstatic char * get_file_type PARAMS ((unsigned)); 15960484Sobrienstatic char * get_machine_name PARAMS ((unsigned)); 16077298Sobrienstatic void decode_ARM_machine_flags PARAMS ((unsigned, char [])); 16160484Sobrienstatic char * get_machine_flags PARAMS ((unsigned, unsigned)); 16260484Sobrienstatic const char * get_mips_segment_type PARAMS ((unsigned long)); 16360484Sobrienstatic const char * get_parisc_segment_type PARAMS ((unsigned long)); 16478828Sobrienstatic const char * get_ia64_segment_type PARAMS ((unsigned long)); 16560484Sobrienstatic const char * get_segment_type PARAMS ((unsigned long)); 16660484Sobrienstatic const char * get_mips_section_type_name PARAMS ((unsigned int)); 16760484Sobrienstatic const char * get_parisc_section_type_name PARAMS ((unsigned int)); 16878828Sobrienstatic const char * get_ia64_section_type_name PARAMS ((unsigned int)); 16960484Sobrienstatic const char * get_section_type_name PARAMS ((unsigned int)); 17060484Sobrienstatic const char * get_symbol_binding PARAMS ((unsigned int)); 17160484Sobrienstatic const char * get_symbol_type PARAMS ((unsigned int)); 17260484Sobrienstatic const char * get_symbol_visibility PARAMS ((unsigned int)); 17360484Sobrienstatic const char * get_symbol_index_type PARAMS ((unsigned int)); 17478828Sobrienstatic const char * get_dynamic_flags PARAMS ((bfd_vma)); 17560484Sobrienstatic void usage PARAMS ((void)); 17660484Sobrienstatic void parse_args PARAMS ((int, char **)); 17760484Sobrienstatic int process_file_header PARAMS ((void)); 17860484Sobrienstatic int process_program_headers PARAMS ((FILE *)); 17960484Sobrienstatic int process_section_headers PARAMS ((FILE *)); 18078828Sobrienstatic int process_unwind PARAMS ((FILE *)); 18160484Sobrienstatic void dynamic_segment_mips_val PARAMS ((Elf_Internal_Dyn *)); 18260484Sobrienstatic void dynamic_segment_parisc_val PARAMS ((Elf_Internal_Dyn *)); 18360484Sobrienstatic int process_dynamic_segment PARAMS ((FILE *)); 18460484Sobrienstatic int process_symbol_table PARAMS ((FILE *)); 18560484Sobrienstatic int process_section_contents PARAMS ((FILE *)); 18660484Sobrienstatic void process_file PARAMS ((char *)); 18760484Sobrienstatic int process_relocs PARAMS ((FILE *)); 18860484Sobrienstatic int process_version_sections PARAMS ((FILE *)); 18960484Sobrienstatic char * get_ver_flags PARAMS ((unsigned int)); 19060484Sobrienstatic int get_32bit_section_headers PARAMS ((FILE *)); 19160484Sobrienstatic int get_64bit_section_headers PARAMS ((FILE *)); 19260484Sobrienstatic int get_32bit_program_headers PARAMS ((FILE *, Elf_Internal_Phdr *)); 19360484Sobrienstatic int get_64bit_program_headers PARAMS ((FILE *, Elf_Internal_Phdr *)); 19460484Sobrienstatic int get_file_header PARAMS ((FILE *)); 19560484Sobrienstatic Elf_Internal_Sym * get_32bit_elf_symbols PARAMS ((FILE *, unsigned long, unsigned long)); 19660484Sobrienstatic Elf_Internal_Sym * get_64bit_elf_symbols PARAMS ((FILE *, unsigned long, unsigned long)); 19778828Sobrienstatic const char * get_elf_section_flags PARAMS ((bfd_vma)); 19860484Sobrienstatic int * get_dynamic_data PARAMS ((FILE *, unsigned int)); 19960484Sobrienstatic int get_32bit_dynamic_segment PARAMS ((FILE *)); 20060484Sobrienstatic int get_64bit_dynamic_segment PARAMS ((FILE *)); 20160484Sobrien#ifdef SUPPORT_DISASSEMBLY 20278828Sobrienstatic int disassemble_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); 20360484Sobrien#endif 20478828Sobrienstatic int dump_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); 20578828Sobrienstatic int display_debug_section PARAMS ((Elf32_Internal_Shdr *, FILE *)); 20660484Sobrienstatic int display_debug_info PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); 20760484Sobrienstatic int display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); 20860484Sobrienstatic int display_debug_lines PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); 20960484Sobrienstatic int display_debug_abbrev PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); 21060484Sobrienstatic int display_debug_aranges PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); 21177298Sobrienstatic int display_debug_frames PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); 21260484Sobrienstatic unsigned char * process_abbrev_section PARAMS ((unsigned char *, unsigned char *)); 21360484Sobrienstatic unsigned long read_leb128 PARAMS ((unsigned char *, int *, int)); 21460484Sobrienstatic int process_extended_line_op PARAMS ((unsigned char *, int, int)); 21560484Sobrienstatic void reset_state_machine PARAMS ((int)); 21660484Sobrienstatic char * get_TAG_name PARAMS ((unsigned long)); 21760484Sobrienstatic char * get_AT_name PARAMS ((unsigned long)); 21860484Sobrienstatic char * get_FORM_name PARAMS ((unsigned long)); 21960484Sobrienstatic void free_abbrevs PARAMS ((void)); 22060484Sobrienstatic void add_abbrev PARAMS ((unsigned long, unsigned long, int)); 22160484Sobrienstatic void add_abbrev_attr PARAMS ((unsigned long, unsigned long)); 22277298Sobrienstatic unsigned char * read_and_display_attr PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long, unsigned long)); 22360484Sobrienstatic unsigned char * display_block PARAMS ((unsigned char *, unsigned long)); 22477298Sobrienstatic void decode_location_expression PARAMS ((unsigned char *, unsigned int, unsigned long)); 22560484Sobrienstatic void request_dump PARAMS ((unsigned int, char)); 22660484Sobrienstatic const char * get_elf_class PARAMS ((unsigned char)); 22760484Sobrienstatic const char * get_data_encoding PARAMS ((unsigned char)); 22860484Sobrienstatic const char * get_osabi_name PARAMS ((unsigned char)); 22960484Sobrienstatic int guess_is_rela PARAMS ((unsigned long)); 23078828Sobrienstatic char * get_note_type PARAMS ((unsigned int)); 23160484Sobrienstatic int process_note PARAMS ((Elf32_Internal_Note *)); 23260484Sobrienstatic int process_corefile_note_segment PARAMS ((FILE *, bfd_vma, bfd_vma)); 23360484Sobrienstatic int process_corefile_note_segments PARAMS ((FILE *)); 23478828Sobrienstatic int process_corefile_contents PARAMS ((FILE *)); 23560484Sobrien 23660484Sobrientypedef int Elf32_Word; 23760484Sobrien 23860484Sobrien#ifndef TRUE 23960484Sobrien#define TRUE 1 24060484Sobrien#define FALSE 0 24160484Sobrien#endif 24260484Sobrien#define UNKNOWN -1 24360484Sobrien 24478828Sobrien#define SECTION_NAME(X) ((X) == NULL ? "<none>" : \ 24577298Sobrien ((X)->sh_name >= string_table_length \ 24677298Sobrien ? "<corrupt>" : string_table + (X)->sh_name)) 24760484Sobrien 24860484Sobrien#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ 24960484Sobrien 25078828Sobrien#define BYTE_GET(field) byte_get (field, sizeof (field)) 25160484Sobrien 25260484Sobrien/* If we can support a 64 bit data type then BFD64 should be defined 25360484Sobrien and sizeof (bfd_vma) == 8. In this case when translating from an 25460484Sobrien external 8 byte field to an internal field, we can assume that the 25578828Sobrien internal field is also 8 bytes wide and so we can extract all the data. 25660484Sobrien If, however, BFD64 is not defined, then we must assume that the 25760484Sobrien internal data structure only has 4 byte wide fields that are the 25860484Sobrien equivalent of the 8 byte wide external counterparts, and so we must 25960484Sobrien truncate the data. */ 26060484Sobrien#ifdef BFD64 26178828Sobrien#define BYTE_GET8(field) byte_get (field, -8) 26260484Sobrien#else 26378828Sobrien#define BYTE_GET8(field) byte_get (field, 8) 26460484Sobrien#endif 26560484Sobrien 26678828Sobrien#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0])) 26760484Sobrien 26860484Sobrien#define GET_DATA_ALLOC(offset, size, var, type, reason) \ 26960484Sobrien if (fseek (file, offset, SEEK_SET)) \ 27060484Sobrien { \ 27160484Sobrien error (_("Unable to seek to start of %s at %x\n"), reason, offset); \ 27260484Sobrien return 0; \ 27360484Sobrien } \ 27460484Sobrien \ 27560484Sobrien var = (type) malloc (size); \ 27660484Sobrien \ 27760484Sobrien if (var == NULL) \ 27860484Sobrien { \ 27960484Sobrien error (_("Out of memory allocating %d bytes for %s\n"), size, reason); \ 28060484Sobrien return 0; \ 28178828Sobrien } \ 28278828Sobrien \ 28378828Sobrien if (fread (var, size, 1, file) != 1) \ 28478828Sobrien { \ 28578828Sobrien error (_("Unable to read in %d bytes of %s\n"), size, reason); \ 28678828Sobrien free (var); \ 28760484Sobrien var = NULL; \ 28878828Sobrien return 0; \ 28960484Sobrien } 29060484Sobrien 29160484Sobrien 29278828Sobrien#define GET_DATA(offset, var, reason) \ 29360484Sobrien if (fseek (file, offset, SEEK_SET)) \ 29478828Sobrien { \ 29560484Sobrien error (_("Unable to seek to %x for %s\n"), offset, reason); \ 29660484Sobrien return 0; \ 29760484Sobrien } \ 29860484Sobrien else if (fread (& var, sizeof (var), 1, file) != 1) \ 29960484Sobrien { \ 30060484Sobrien error (_("Unable to read data at %x for %s\n"), offset, reason); \ 30160484Sobrien return 0; \ 30260484Sobrien } 30360484Sobrien 30460484Sobrien#define GET_ELF_SYMBOLS(file, offset, size) \ 30560484Sobrien (is_32bit_elf ? get_32bit_elf_symbols (file, offset, size) \ 30660484Sobrien : get_64bit_elf_symbols (file, offset, size)) 30760484Sobrien 30860484Sobrien 30960484Sobrien#ifdef ANSI_PROTOTYPES 31060484Sobrienstatic void 31160484Sobrienerror (const char * message, ...) 31260484Sobrien{ 31360484Sobrien va_list args; 31460484Sobrien 31560484Sobrien fprintf (stderr, _("%s: Error: "), program_name); 31660484Sobrien va_start (args, message); 31760484Sobrien vfprintf (stderr, message, args); 31860484Sobrien va_end (args); 31960484Sobrien return; 32060484Sobrien} 32160484Sobrien 32260484Sobrienstatic void 32360484Sobrienwarn (const char * message, ...) 32460484Sobrien{ 32560484Sobrien va_list args; 32660484Sobrien 32760484Sobrien fprintf (stderr, _("%s: Warning: "), program_name); 32860484Sobrien va_start (args, message); 32960484Sobrien vfprintf (stderr, message, args); 33060484Sobrien va_end (args); 33160484Sobrien return; 33260484Sobrien} 33360484Sobrien#else 33460484Sobrienstatic void 33560484Sobrienerror (va_alist) 33660484Sobrien va_dcl 33760484Sobrien{ 33860484Sobrien char * message; 33960484Sobrien va_list args; 34060484Sobrien 34160484Sobrien fprintf (stderr, _("%s: Error: "), program_name); 34260484Sobrien va_start (args); 34360484Sobrien message = va_arg (args, char *); 34460484Sobrien vfprintf (stderr, message, args); 34560484Sobrien va_end (args); 34660484Sobrien return; 34760484Sobrien} 34860484Sobrien 34960484Sobrienstatic void 35060484Sobrienwarn (va_alist) 35160484Sobrien va_dcl 35260484Sobrien{ 35360484Sobrien char * message; 35460484Sobrien va_list args; 35560484Sobrien 35660484Sobrien fprintf (stderr, _("%s: Warning: "), program_name); 35760484Sobrien va_start (args); 35860484Sobrien message = va_arg (args, char *); 35960484Sobrien vfprintf (stderr, message, args); 36060484Sobrien va_end (args); 36160484Sobrien return; 36260484Sobrien} 36360484Sobrien#endif 36460484Sobrien 36560484Sobrienstatic bfd_vma 36660484Sobrienbyte_get_little_endian (field, size) 36760484Sobrien unsigned char * field; 36860484Sobrien int size; 36960484Sobrien{ 37060484Sobrien switch (size) 37160484Sobrien { 37260484Sobrien case 1: 37360484Sobrien return * field; 37460484Sobrien 37560484Sobrien case 2: 37660484Sobrien return ((unsigned int) (field [0])) 37760484Sobrien | (((unsigned int) (field [1])) << 8); 37860484Sobrien 37978828Sobrien#ifndef BFD64 38060484Sobrien case 8: 38160484Sobrien /* We want to extract data from an 8 byte wide field and 38260484Sobrien place it into a 4 byte wide field. Since this is a little 38360484Sobrien endian source we can juts use the 4 byte extraction code. */ 38460484Sobrien /* Fall through. */ 38578828Sobrien#endif 38660484Sobrien case 4: 38760484Sobrien return ((unsigned long) (field [0])) 38860484Sobrien | (((unsigned long) (field [1])) << 8) 38960484Sobrien | (((unsigned long) (field [2])) << 16) 39060484Sobrien | (((unsigned long) (field [3])) << 24); 39160484Sobrien 39260484Sobrien#ifdef BFD64 39378828Sobrien case 8: 39460484Sobrien case -8: 39560484Sobrien /* This is a special case, generated by the BYTE_GET8 macro. 39660484Sobrien It means that we are loading an 8 byte value from a field 39760484Sobrien in an external structure into an 8 byte value in a field 39860484Sobrien in an internal strcuture. */ 39960484Sobrien return ((bfd_vma) (field [0])) 40060484Sobrien | (((bfd_vma) (field [1])) << 8) 40160484Sobrien | (((bfd_vma) (field [2])) << 16) 40260484Sobrien | (((bfd_vma) (field [3])) << 24) 40360484Sobrien | (((bfd_vma) (field [4])) << 32) 40460484Sobrien | (((bfd_vma) (field [5])) << 40) 40560484Sobrien | (((bfd_vma) (field [6])) << 48) 40660484Sobrien | (((bfd_vma) (field [7])) << 56); 40760484Sobrien#endif 40860484Sobrien default: 40960484Sobrien error (_("Unhandled data length: %d\n"), size); 41060484Sobrien abort (); 41160484Sobrien } 41260484Sobrien} 41360484Sobrien 41460484Sobrien/* Print a VMA value. */ 41560484Sobrienstatic void 41660484Sobrienprint_vma (vma, mode) 41760484Sobrien bfd_vma vma; 41860484Sobrien print_mode mode; 41960484Sobrien{ 42060484Sobrien#ifdef BFD64 42160484Sobrien if (is_32bit_elf) 42260484Sobrien#endif 42360484Sobrien { 42460484Sobrien switch (mode) 42560484Sobrien { 42660484Sobrien case FULL_HEX: printf ("0x"); /* drop through */ 42760484Sobrien case LONG_HEX: printf ("%8.8lx", (unsigned long) vma); break; 42860484Sobrien case PREFIX_HEX: printf ("0x"); /* drop through */ 42960484Sobrien case HEX: printf ("%lx", (unsigned long) vma); break; 43060484Sobrien case DEC: printf ("%ld", (unsigned long) vma); break; 43160484Sobrien case DEC_5: printf ("%5ld", (long) vma); break; 43260484Sobrien case UNSIGNED: printf ("%lu", (unsigned long) vma); break; 43360484Sobrien } 43460484Sobrien } 43560484Sobrien#ifdef BFD64 43660484Sobrien else 43760484Sobrien { 43860484Sobrien switch (mode) 43960484Sobrien { 44060484Sobrien case FULL_HEX: 44160484Sobrien printf ("0x"); 44260484Sobrien /* drop through */ 44377298Sobrien 44460484Sobrien case LONG_HEX: 44560484Sobrien printf_vma (vma); 44660484Sobrien break; 44777298Sobrien 44860484Sobrien case PREFIX_HEX: 44960484Sobrien printf ("0x"); 45060484Sobrien /* drop through */ 45177298Sobrien 45260484Sobrien case HEX: 45360484Sobrien#if BFD_HOST_64BIT_LONG 45460484Sobrien printf ("%lx", vma); 45560484Sobrien#else 45660484Sobrien if (_bfd_int64_high (vma)) 45760484Sobrien printf ("%lx%lx", _bfd_int64_high (vma), _bfd_int64_low (vma)); 45860484Sobrien else 45960484Sobrien printf ("%lx", _bfd_int64_low (vma)); 46060484Sobrien#endif 46160484Sobrien break; 46260484Sobrien 46360484Sobrien case DEC: 46460484Sobrien#if BFD_HOST_64BIT_LONG 46560484Sobrien printf ("%ld", vma); 46660484Sobrien#else 46760484Sobrien if (_bfd_int64_high (vma)) 46860484Sobrien /* ugg */ 46960484Sobrien printf ("++%ld", _bfd_int64_low (vma)); 47060484Sobrien else 47160484Sobrien printf ("%ld", _bfd_int64_low (vma)); 47277298Sobrien#endif 47360484Sobrien break; 47460484Sobrien 47560484Sobrien case DEC_5: 47660484Sobrien#if BFD_HOST_64BIT_LONG 47760484Sobrien printf ("%5ld", vma); 47860484Sobrien#else 47960484Sobrien if (_bfd_int64_high (vma)) 48060484Sobrien /* ugg */ 48160484Sobrien printf ("++%ld", _bfd_int64_low (vma)); 48260484Sobrien else 48360484Sobrien printf ("%5ld", _bfd_int64_low (vma)); 48477298Sobrien#endif 48560484Sobrien break; 48677298Sobrien 48760484Sobrien case UNSIGNED: 48860484Sobrien#if BFD_HOST_64BIT_LONG 48960484Sobrien printf ("%lu", vma); 49077298Sobrien#else 49160484Sobrien if (_bfd_int64_high (vma)) 49260484Sobrien /* ugg */ 49360484Sobrien printf ("++%lu", _bfd_int64_low (vma)); 49460484Sobrien else 49560484Sobrien printf ("%lu", _bfd_int64_low (vma)); 49660484Sobrien#endif 49760484Sobrien break; 49860484Sobrien } 49960484Sobrien } 50060484Sobrien#endif 50160484Sobrien} 50260484Sobrien 50360484Sobrienstatic bfd_vma 50460484Sobrienbyte_get_big_endian (field, size) 50560484Sobrien unsigned char * field; 50660484Sobrien int size; 50760484Sobrien{ 50860484Sobrien switch (size) 50960484Sobrien { 51060484Sobrien case 1: 51160484Sobrien return * field; 51260484Sobrien 51360484Sobrien case 2: 51460484Sobrien return ((unsigned int) (field [1])) | (((int) (field [0])) << 8); 51560484Sobrien 51660484Sobrien case 4: 51760484Sobrien return ((unsigned long) (field [3])) 51860484Sobrien | (((unsigned long) (field [2])) << 8) 51960484Sobrien | (((unsigned long) (field [1])) << 16) 52060484Sobrien | (((unsigned long) (field [0])) << 24); 52160484Sobrien 52278828Sobrien#ifndef BFD64 52360484Sobrien case 8: 52460484Sobrien /* Although we are extracing data from an 8 byte wide field, we 52560484Sobrien are returning only 4 bytes of data. */ 52660484Sobrien return ((unsigned long) (field [7])) 52760484Sobrien | (((unsigned long) (field [6])) << 8) 52860484Sobrien | (((unsigned long) (field [5])) << 16) 52960484Sobrien | (((unsigned long) (field [4])) << 24); 53078828Sobrien#else 53178828Sobrien case 8: 53260484Sobrien case -8: 53360484Sobrien /* This is a special case, generated by the BYTE_GET8 macro. 53460484Sobrien It means that we are loading an 8 byte value from a field 53560484Sobrien in an external structure into an 8 byte value in a field 53660484Sobrien in an internal strcuture. */ 53760484Sobrien return ((bfd_vma) (field [7])) 53860484Sobrien | (((bfd_vma) (field [6])) << 8) 53960484Sobrien | (((bfd_vma) (field [5])) << 16) 54060484Sobrien | (((bfd_vma) (field [4])) << 24) 54160484Sobrien | (((bfd_vma) (field [3])) << 32) 54260484Sobrien | (((bfd_vma) (field [2])) << 40) 54360484Sobrien | (((bfd_vma) (field [1])) << 48) 54460484Sobrien | (((bfd_vma) (field [0])) << 56); 54560484Sobrien#endif 54660484Sobrien 54760484Sobrien default: 54860484Sobrien error (_("Unhandled data length: %d\n"), size); 54960484Sobrien abort (); 55060484Sobrien } 55160484Sobrien} 55260484Sobrien 55377298Sobrien/* Guess the relocation size commonly used by the specific machines. */ 55460484Sobrien 55560484Sobrienstatic int 55660484Sobrienguess_is_rela (e_machine) 55760484Sobrien unsigned long e_machine; 55860484Sobrien{ 55960484Sobrien switch (e_machine) 56060484Sobrien { 56160484Sobrien /* Targets that use REL relocations. */ 56260484Sobrien case EM_ARM: 56360484Sobrien case EM_386: 56460484Sobrien case EM_486: 56560484Sobrien case EM_960: 56660484Sobrien case EM_CYGNUS_M32R: 56760484Sobrien case EM_CYGNUS_D10V: 56860484Sobrien case EM_MIPS: 56978828Sobrien case EM_MIPS_RS3_LE: 57060484Sobrien return FALSE; 57160484Sobrien 57260484Sobrien /* Targets that use RELA relocations. */ 57360484Sobrien case EM_68K: 57460484Sobrien case EM_SPARC32PLUS: 57560484Sobrien case EM_SPARCV9: 57660484Sobrien case EM_SPARC: 57760484Sobrien case EM_PPC: 57860484Sobrien case EM_CYGNUS_V850: 57960484Sobrien case EM_CYGNUS_D30V: 58060484Sobrien case EM_CYGNUS_MN10200: 58160484Sobrien case EM_CYGNUS_MN10300: 58260484Sobrien case EM_CYGNUS_FR30: 58360484Sobrien case EM_SH: 58460484Sobrien case EM_ALPHA: 58560484Sobrien case EM_MCORE: 58677298Sobrien case EM_IA_64: 58777298Sobrien case EM_AVR: 58877298Sobrien case EM_CRIS: 58977298Sobrien case EM_860: 59077298Sobrien case EM_X86_64: 59160484Sobrien return TRUE; 59260484Sobrien 59360484Sobrien case EM_MMA: 59460484Sobrien case EM_PCP: 59560484Sobrien case EM_NCPU: 59660484Sobrien case EM_NDR1: 59760484Sobrien case EM_STARCORE: 59860484Sobrien case EM_ME16: 59960484Sobrien case EM_ST100: 60060484Sobrien case EM_TINYJ: 60160484Sobrien case EM_FX66: 60260484Sobrien case EM_ST9PLUS: 60360484Sobrien case EM_ST7: 60460484Sobrien case EM_68HC16: 60560484Sobrien case EM_68HC11: 60660484Sobrien case EM_68HC08: 60760484Sobrien case EM_68HC05: 60860484Sobrien case EM_SVX: 60960484Sobrien case EM_ST19: 61060484Sobrien case EM_VAX: 61160484Sobrien default: 61260484Sobrien warn (_("Don't know about relocations on this machine architecture\n")); 61360484Sobrien return FALSE; 61460484Sobrien } 61560484Sobrien} 61660484Sobrien 61760484Sobrienstatic int 61878828Sobrienslurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp) 61978828Sobrien FILE *file; 62078828Sobrien unsigned long rel_offset; 62178828Sobrien unsigned long rel_size; 62278828Sobrien Elf_Internal_Rela **relasp; 62378828Sobrien unsigned long *nrelasp; 62460484Sobrien{ 62578828Sobrien Elf_Internal_Rela *relas; 62678828Sobrien unsigned long nrelas; 62778828Sobrien unsigned int i; 62860484Sobrien 62978828Sobrien if (is_32bit_elf) 63078828Sobrien { 63178828Sobrien Elf32_External_Rela * erelas; 63260484Sobrien 63378828Sobrien GET_DATA_ALLOC (rel_offset, rel_size, erelas, 63478828Sobrien Elf32_External_Rela *, "relocs"); 63560484Sobrien 63678828Sobrien nrelas = rel_size / sizeof (Elf32_External_Rela); 63778828Sobrien 63878828Sobrien relas = (Elf_Internal_Rela *) 63978828Sobrien malloc (nrelas * sizeof (Elf_Internal_Rela)); 64078828Sobrien 64178828Sobrien if (relas == NULL) 64260484Sobrien { 64378828Sobrien error(_("out of memory parsing relocs")); 64478828Sobrien return 0; 64578828Sobrien } 64660484Sobrien 64778828Sobrien for (i = 0; i < nrelas; i++) 64878828Sobrien { 64978828Sobrien relas[i].r_offset = BYTE_GET (erelas[i].r_offset); 65078828Sobrien relas[i].r_info = BYTE_GET (erelas[i].r_info); 65178828Sobrien relas[i].r_addend = BYTE_GET (erelas[i].r_addend); 65278828Sobrien } 65360484Sobrien 65478828Sobrien free (erelas); 65578828Sobrien } 65678828Sobrien else 65778828Sobrien { 65878828Sobrien Elf64_External_Rela * erelas; 65960484Sobrien 66078828Sobrien GET_DATA_ALLOC (rel_offset, rel_size, erelas, 66178828Sobrien Elf64_External_Rela *, "relocs"); 66260484Sobrien 66378828Sobrien nrelas = rel_size / sizeof (Elf64_External_Rela); 66460484Sobrien 66578828Sobrien relas = (Elf_Internal_Rela *) 66678828Sobrien malloc (nrelas * sizeof (Elf_Internal_Rela)); 66760484Sobrien 66878828Sobrien if (relas == NULL) 66978828Sobrien { 67078828Sobrien error(_("out of memory parsing relocs")); 67178828Sobrien return 0; 67278828Sobrien } 67360484Sobrien 67478828Sobrien for (i = 0; i < nrelas; i++) 67578828Sobrien { 67678828Sobrien relas[i].r_offset = BYTE_GET8 (erelas[i].r_offset); 67778828Sobrien relas[i].r_info = BYTE_GET8 (erelas[i].r_info); 67878828Sobrien relas[i].r_addend = BYTE_GET8 (erelas[i].r_addend); 67960484Sobrien } 68060484Sobrien 68178828Sobrien free (erelas); 68278828Sobrien } 68378828Sobrien *relasp = relas; 68478828Sobrien *nrelasp = nrelas; 68578828Sobrien return 1; 68678828Sobrien} 68760484Sobrien 68878828Sobrienstatic int 68978828Sobrienslurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp) 69078828Sobrien FILE *file; 69178828Sobrien unsigned long rel_offset; 69278828Sobrien unsigned long rel_size; 69378828Sobrien Elf_Internal_Rel **relsp; 69478828Sobrien unsigned long *nrelsp; 69578828Sobrien{ 69678828Sobrien Elf_Internal_Rel *rels; 69778828Sobrien unsigned long nrels; 69878828Sobrien unsigned int i; 69960484Sobrien 70078828Sobrien if (is_32bit_elf) 70178828Sobrien { 70278828Sobrien Elf32_External_Rel * erels; 70360484Sobrien 70478828Sobrien GET_DATA_ALLOC (rel_offset, rel_size, erels, 70578828Sobrien Elf32_External_Rel *, "relocs"); 70660484Sobrien 70778828Sobrien nrels = rel_size / sizeof (Elf32_External_Rel); 70860484Sobrien 70978828Sobrien rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel)); 71060484Sobrien 71178828Sobrien if (rels == NULL) 71278828Sobrien { 71378828Sobrien error(_("out of memory parsing relocs")); 71478828Sobrien return 0; 71560484Sobrien } 71678828Sobrien 71778828Sobrien for (i = 0; i < nrels; i++) 71878828Sobrien { 71978828Sobrien rels[i].r_offset = BYTE_GET (erels[i].r_offset); 72078828Sobrien rels[i].r_info = BYTE_GET (erels[i].r_info); 72178828Sobrien } 72278828Sobrien 72378828Sobrien free (erels); 72460484Sobrien } 72560484Sobrien else 72660484Sobrien { 72778828Sobrien Elf64_External_Rel * erels; 72860484Sobrien 72978828Sobrien GET_DATA_ALLOC (rel_offset, rel_size, erels, 73078828Sobrien Elf64_External_Rel *, "relocs"); 73160484Sobrien 73278828Sobrien nrels = rel_size / sizeof (Elf64_External_Rel); 73360484Sobrien 73478828Sobrien rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel)); 73560484Sobrien 73678828Sobrien if (rels == NULL) 73778828Sobrien { 73878828Sobrien error(_("out of memory parsing relocs")); 73978828Sobrien return 0; 74078828Sobrien } 74160484Sobrien 74278828Sobrien for (i = 0; i < nrels; i++) 74378828Sobrien { 74478828Sobrien rels[i].r_offset = BYTE_GET8 (erels[i].r_offset); 74578828Sobrien rels[i].r_info = BYTE_GET8 (erels[i].r_info); 74660484Sobrien } 74760484Sobrien 74878828Sobrien free (erels); 74978828Sobrien } 75078828Sobrien *relsp = rels; 75178828Sobrien *nrelsp = nrels; 75278828Sobrien return 1; 75378828Sobrien} 75460484Sobrien 75578828Sobrien/* Display the contents of the relocation data found at the specified offset. */ 75678828Sobrienstatic int 75778828Sobriendump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela) 75878828Sobrien FILE * file; 75978828Sobrien unsigned long rel_offset; 76078828Sobrien unsigned long rel_size; 76178828Sobrien Elf_Internal_Sym * symtab; 76278828Sobrien unsigned long nsyms; 76378828Sobrien char * strtab; 76478828Sobrien int is_rela; 76578828Sobrien{ 76678828Sobrien unsigned int i; 76778828Sobrien Elf_Internal_Rel * rels; 76878828Sobrien Elf_Internal_Rela * relas; 76960484Sobrien 77060484Sobrien 77178828Sobrien if (is_rela == UNKNOWN) 77278828Sobrien is_rela = guess_is_rela (elf_header.e_machine); 77360484Sobrien 77478828Sobrien if (is_rela) 77578828Sobrien { 77678828Sobrien if (!slurp_rela_relocs (file, rel_offset, rel_size, &relas, &rel_size)) 77778828Sobrien return 0; 77860484Sobrien } 77978828Sobrien else 78078828Sobrien { 78178828Sobrien if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size)) 78278828Sobrien return 0; 78378828Sobrien } 78460484Sobrien 78560484Sobrien if (is_rela) 78660484Sobrien printf 78760484Sobrien (_(" Offset Info Type Symbol's Value Symbol's Name Addend\n")); 78860484Sobrien else 78960484Sobrien printf 79060484Sobrien (_(" Offset Info Type Symbol's Value Symbol's Name\n")); 79160484Sobrien 79260484Sobrien for (i = 0; i < rel_size; i++) 79360484Sobrien { 79460484Sobrien const char * rtype; 79560484Sobrien bfd_vma offset; 79660484Sobrien bfd_vma info; 79760484Sobrien bfd_vma symtab_index; 79860484Sobrien bfd_vma type; 79960484Sobrien 80060484Sobrien if (is_rela) 80160484Sobrien { 80260484Sobrien offset = relas [i].r_offset; 80360484Sobrien info = relas [i].r_info; 80460484Sobrien } 80560484Sobrien else 80660484Sobrien { 80760484Sobrien offset = rels [i].r_offset; 80860484Sobrien info = rels [i].r_info; 80960484Sobrien } 81060484Sobrien 81160484Sobrien if (is_32bit_elf) 81260484Sobrien { 81360484Sobrien type = ELF32_R_TYPE (info); 81460484Sobrien symtab_index = ELF32_R_SYM (info); 81560484Sobrien } 81660484Sobrien else 81760484Sobrien { 81860484Sobrien if (elf_header.e_machine == EM_SPARCV9) 81960484Sobrien type = ELF64_R_TYPE_ID (info); 82060484Sobrien else 82160484Sobrien type = ELF64_R_TYPE (info); 82260484Sobrien /* The #ifdef BFD64 below is to prevent a compile time warning. 82360484Sobrien We know that if we do not have a 64 bit data type that we 82460484Sobrien will never execute this code anyway. */ 82560484Sobrien#ifdef BFD64 82660484Sobrien symtab_index = ELF64_R_SYM (info); 82760484Sobrien#endif 82860484Sobrien } 82960484Sobrien 83060484Sobrien#ifdef _bfd_int64_low 83160484Sobrien printf (" %8.8lx %5.5lx ", _bfd_int64_low (offset), _bfd_int64_low (info)); 83260484Sobrien#else 83360484Sobrien printf (" %8.8lx %5.5lx ", offset, info); 83460484Sobrien#endif 83560484Sobrien 83660484Sobrien switch (elf_header.e_machine) 83760484Sobrien { 83860484Sobrien default: 83960484Sobrien rtype = NULL; 84060484Sobrien break; 84160484Sobrien 84260484Sobrien case EM_CYGNUS_M32R: 84360484Sobrien rtype = elf_m32r_reloc_type (type); 84460484Sobrien break; 84560484Sobrien 84660484Sobrien case EM_386: 84760484Sobrien case EM_486: 84860484Sobrien rtype = elf_i386_reloc_type (type); 84960484Sobrien break; 85060484Sobrien 85160484Sobrien case EM_68K: 85260484Sobrien rtype = elf_m68k_reloc_type (type); 85360484Sobrien break; 85460484Sobrien 85560484Sobrien case EM_960: 85660484Sobrien rtype = elf_i960_reloc_type (type); 85760484Sobrien break; 85860484Sobrien 85960484Sobrien case EM_AVR: 86060484Sobrien rtype = elf_avr_reloc_type (type); 86160484Sobrien break; 86260484Sobrien 86360484Sobrien case EM_OLD_SPARCV9: 86460484Sobrien case EM_SPARC32PLUS: 86560484Sobrien case EM_SPARCV9: 86660484Sobrien case EM_SPARC: 86760484Sobrien rtype = elf_sparc_reloc_type (type); 86860484Sobrien break; 86960484Sobrien 87060484Sobrien case EM_CYGNUS_V850: 87160484Sobrien rtype = v850_reloc_type (type); 87260484Sobrien break; 87360484Sobrien 87460484Sobrien case EM_CYGNUS_D10V: 87560484Sobrien rtype = elf_d10v_reloc_type (type); 87660484Sobrien break; 87760484Sobrien 87860484Sobrien case EM_CYGNUS_D30V: 87960484Sobrien rtype = elf_d30v_reloc_type (type); 88060484Sobrien break; 88160484Sobrien 88260484Sobrien case EM_SH: 88360484Sobrien rtype = elf_sh_reloc_type (type); 88460484Sobrien break; 88560484Sobrien 88660484Sobrien case EM_CYGNUS_MN10300: 88760484Sobrien rtype = elf_mn10300_reloc_type (type); 88860484Sobrien break; 88960484Sobrien 89060484Sobrien case EM_CYGNUS_MN10200: 89160484Sobrien rtype = elf_mn10200_reloc_type (type); 89260484Sobrien break; 89360484Sobrien 89460484Sobrien case EM_CYGNUS_FR30: 89560484Sobrien rtype = elf_fr30_reloc_type (type); 89660484Sobrien break; 89760484Sobrien 89860484Sobrien case EM_MCORE: 89960484Sobrien rtype = elf_mcore_reloc_type (type); 90060484Sobrien break; 90160484Sobrien 90260484Sobrien case EM_PPC: 90360484Sobrien rtype = elf_ppc_reloc_type (type); 90460484Sobrien break; 90560484Sobrien 90660484Sobrien case EM_MIPS: 90778828Sobrien case EM_MIPS_RS3_LE: 90860484Sobrien rtype = elf_mips_reloc_type (type); 90960484Sobrien break; 91060484Sobrien 91160484Sobrien case EM_ALPHA: 91260484Sobrien rtype = elf_alpha_reloc_type (type); 91360484Sobrien break; 91460484Sobrien 91560484Sobrien case EM_ARM: 91660484Sobrien rtype = elf_arm_reloc_type (type); 91760484Sobrien break; 91860484Sobrien 91960484Sobrien case EM_CYGNUS_ARC: 92077298Sobrien case EM_ARC: 92160484Sobrien rtype = elf_arc_reloc_type (type); 92260484Sobrien break; 92360484Sobrien 92460484Sobrien case EM_PARISC: 92560484Sobrien rtype = elf_hppa_reloc_type (type); 92660484Sobrien break; 92760484Sobrien 92860484Sobrien case EM_PJ: 92960484Sobrien rtype = elf_pj_reloc_type (type); 93060484Sobrien break; 93177298Sobrien case EM_IA_64: 93277298Sobrien rtype = elf_ia64_reloc_type (type); 93377298Sobrien break; 93477298Sobrien 93577298Sobrien case EM_CRIS: 93677298Sobrien rtype = elf_cris_reloc_type (type); 93777298Sobrien break; 93877298Sobrien 93977298Sobrien case EM_860: 94077298Sobrien rtype = elf_i860_reloc_type (type); 94177298Sobrien break; 94277298Sobrien 94377298Sobrien case EM_X86_64: 94477298Sobrien rtype = elf_x86_64_reloc_type (type); 94577298Sobrien break; 94660484Sobrien } 94760484Sobrien 94860484Sobrien if (rtype == NULL) 94960484Sobrien#ifdef _bfd_int64_low 95060484Sobrien printf (_("unrecognised: %-7lx"), _bfd_int64_low (type)); 95160484Sobrien#else 95260484Sobrien printf (_("unrecognised: %-7lx"), type); 95360484Sobrien#endif 95460484Sobrien else 95560484Sobrien printf ("%-21.21s", rtype); 95660484Sobrien 95760484Sobrien if (symtab_index) 95860484Sobrien { 95960484Sobrien if (symtab != NULL) 96060484Sobrien { 96160484Sobrien if (symtab_index >= nsyms) 96260484Sobrien printf (" bad symbol index: %08lx", (unsigned long) symtab_index); 96360484Sobrien else 96460484Sobrien { 96560484Sobrien Elf_Internal_Sym * psym; 96660484Sobrien 96760484Sobrien psym = symtab + symtab_index; 96860484Sobrien 96960484Sobrien printf (" "); 97060484Sobrien print_vma (psym->st_value, LONG_HEX); 97160484Sobrien printf (" "); 97260484Sobrien 97360484Sobrien if (psym->st_name == 0) 97460484Sobrien printf ("%-25.25s", 97560484Sobrien SECTION_NAME (section_headers + psym->st_shndx)); 97660484Sobrien else if (strtab == NULL) 97760484Sobrien printf (_("<string table index %3ld>"), psym->st_name); 97860484Sobrien else 97960484Sobrien printf ("%-25.25s", strtab + psym->st_name); 98060484Sobrien 98160484Sobrien if (is_rela) 98260484Sobrien printf (" + %lx", (unsigned long) relas [i].r_addend); 98360484Sobrien } 98460484Sobrien } 98560484Sobrien } 98660484Sobrien else if (is_rela) 98760484Sobrien { 98860484Sobrien printf ("%*c", is_32bit_elf ? 34 : 26, ' '); 98960484Sobrien print_vma (relas[i].r_addend, LONG_HEX); 99060484Sobrien } 99160484Sobrien 99260484Sobrien if (elf_header.e_machine == EM_SPARCV9 99360484Sobrien && !strcmp (rtype, "R_SPARC_OLO10")) 99460484Sobrien printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info)); 99560484Sobrien 99660484Sobrien putchar ('\n'); 99760484Sobrien } 99860484Sobrien 99978828Sobrien if (is_rela) 100078828Sobrien free (relas); 100178828Sobrien else 100278828Sobrien free (rels); 100360484Sobrien 100460484Sobrien return 1; 100560484Sobrien} 100660484Sobrien 100760484Sobrienstatic const char * 100860484Sobrienget_mips_dynamic_type (type) 100960484Sobrien unsigned long type; 101060484Sobrien{ 101160484Sobrien switch (type) 101260484Sobrien { 101360484Sobrien case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION"; 101460484Sobrien case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP"; 101560484Sobrien case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM"; 101660484Sobrien case DT_MIPS_IVERSION: return "MIPS_IVERSION"; 101760484Sobrien case DT_MIPS_FLAGS: return "MIPS_FLAGS"; 101860484Sobrien case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS"; 101960484Sobrien case DT_MIPS_MSYM: return "MIPS_MSYM"; 102060484Sobrien case DT_MIPS_CONFLICT: return "MIPS_CONFLICT"; 102160484Sobrien case DT_MIPS_LIBLIST: return "MIPS_LIBLIST"; 102260484Sobrien case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO"; 102360484Sobrien case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO"; 102460484Sobrien case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO"; 102560484Sobrien case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO"; 102660484Sobrien case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO"; 102760484Sobrien case DT_MIPS_GOTSYM: return "MIPS_GOTSYM"; 102860484Sobrien case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO"; 102960484Sobrien case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP"; 103060484Sobrien case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS"; 103160484Sobrien case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO"; 103260484Sobrien case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE"; 103360484Sobrien case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO"; 103460484Sobrien case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC"; 103560484Sobrien case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO"; 103660484Sobrien case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM"; 103760484Sobrien case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO"; 103860484Sobrien case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM"; 103960484Sobrien case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO"; 104060484Sobrien case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS"; 104160484Sobrien case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT"; 104260484Sobrien case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; 104360484Sobrien case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX"; 104460484Sobrien case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX"; 104560484Sobrien case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX"; 104660484Sobrien case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX"; 104760484Sobrien case DT_MIPS_OPTIONS: return "MIPS_OPTIONS"; 104860484Sobrien case DT_MIPS_INTERFACE: return "MIPS_INTERFACE"; 104960484Sobrien case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN"; 105060484Sobrien case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE"; 105160484Sobrien case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR"; 105260484Sobrien case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX"; 105360484Sobrien case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE"; 105460484Sobrien case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE"; 105560484Sobrien case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC"; 105660484Sobrien default: 105760484Sobrien return NULL; 105860484Sobrien } 105960484Sobrien} 106060484Sobrien 106160484Sobrienstatic const char * 106260484Sobrienget_sparc64_dynamic_type (type) 106360484Sobrien unsigned long type; 106460484Sobrien{ 106560484Sobrien switch (type) 106660484Sobrien { 106760484Sobrien case DT_SPARC_REGISTER: return "SPARC_REGISTER"; 106860484Sobrien default: 106960484Sobrien return NULL; 107060484Sobrien } 107160484Sobrien} 107260484Sobrien 107360484Sobrienstatic const char * 107460484Sobrienget_parisc_dynamic_type (type) 107560484Sobrien unsigned long type; 107660484Sobrien{ 107760484Sobrien switch (type) 107860484Sobrien { 107960484Sobrien case DT_HP_LOAD_MAP: return "HP_LOAD_MAP"; 108060484Sobrien case DT_HP_DLD_FLAGS: return "HP_DLD_FLAGS"; 108160484Sobrien case DT_HP_DLD_HOOK: return "HP_DLD_HOOK"; 108260484Sobrien case DT_HP_UX10_INIT: return "HP_UX10_INIT"; 108360484Sobrien case DT_HP_UX10_INITSZ: return "HP_UX10_INITSZ"; 108460484Sobrien case DT_HP_PREINIT: return "HP_PREINIT"; 108560484Sobrien case DT_HP_PREINITSZ: return "HP_PREINITSZ"; 108660484Sobrien case DT_HP_NEEDED: return "HP_NEEDED"; 108760484Sobrien case DT_HP_TIME_STAMP: return "HP_TIME_STAMP"; 108860484Sobrien case DT_HP_CHECKSUM: return "HP_CHECKSUM"; 108960484Sobrien case DT_HP_GST_SIZE: return "HP_GST_SIZE"; 109060484Sobrien case DT_HP_GST_VERSION: return "HP_GST_VERSION"; 109160484Sobrien case DT_HP_GST_HASHVAL: return "HP_GST_HASHVAL"; 109260484Sobrien default: 109360484Sobrien return NULL; 109460484Sobrien } 109560484Sobrien} 109660484Sobrien 109760484Sobrienstatic const char * 109860484Sobrienget_dynamic_type (type) 109960484Sobrien unsigned long type; 110060484Sobrien{ 110160484Sobrien static char buff [32]; 110260484Sobrien 110360484Sobrien switch (type) 110460484Sobrien { 110560484Sobrien case DT_NULL: return "NULL"; 110660484Sobrien case DT_NEEDED: return "NEEDED"; 110760484Sobrien case DT_PLTRELSZ: return "PLTRELSZ"; 110860484Sobrien case DT_PLTGOT: return "PLTGOT"; 110960484Sobrien case DT_HASH: return "HASH"; 111060484Sobrien case DT_STRTAB: return "STRTAB"; 111160484Sobrien case DT_SYMTAB: return "SYMTAB"; 111260484Sobrien case DT_RELA: return "RELA"; 111360484Sobrien case DT_RELASZ: return "RELASZ"; 111460484Sobrien case DT_RELAENT: return "RELAENT"; 111560484Sobrien case DT_STRSZ: return "STRSZ"; 111660484Sobrien case DT_SYMENT: return "SYMENT"; 111760484Sobrien case DT_INIT: return "INIT"; 111860484Sobrien case DT_FINI: return "FINI"; 111960484Sobrien case DT_SONAME: return "SONAME"; 112060484Sobrien case DT_RPATH: return "RPATH"; 112160484Sobrien case DT_SYMBOLIC: return "SYMBOLIC"; 112260484Sobrien case DT_REL: return "REL"; 112360484Sobrien case DT_RELSZ: return "RELSZ"; 112460484Sobrien case DT_RELENT: return "RELENT"; 112560484Sobrien case DT_PLTREL: return "PLTREL"; 112660484Sobrien case DT_DEBUG: return "DEBUG"; 112760484Sobrien case DT_TEXTREL: return "TEXTREL"; 112860484Sobrien case DT_JMPREL: return "JMPREL"; 112960484Sobrien case DT_BIND_NOW: return "BIND_NOW"; 113060484Sobrien case DT_INIT_ARRAY: return "INIT_ARRAY"; 113160484Sobrien case DT_FINI_ARRAY: return "FINI_ARRAY"; 113260484Sobrien case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ"; 113360484Sobrien case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ"; 113460484Sobrien case DT_RUNPATH: return "RUNPATH"; 113560484Sobrien case DT_FLAGS: return "FLAGS"; 113660484Sobrien 113760484Sobrien case DT_PREINIT_ARRAY: return "PREINIT_ARRAY"; 113860484Sobrien case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; 113960484Sobrien 114068765Sobrien case DT_CHECKSUM: return "CHECKSUM"; 114160484Sobrien case DT_PLTPADSZ: return "PLTPADSZ"; 114260484Sobrien case DT_MOVEENT: return "MOVEENT"; 114360484Sobrien case DT_MOVESZ: return "MOVESZ"; 114468765Sobrien case DT_FEATURE: return "FEATURE"; 114560484Sobrien case DT_POSFLAG_1: return "POSFLAG_1"; 114660484Sobrien case DT_SYMINSZ: return "SYMINSZ"; 114760484Sobrien case DT_SYMINENT: return "SYMINENT"; /* aka VALRNGHI */ 114860484Sobrien 114960484Sobrien case DT_ADDRRNGLO: return "ADDRRNGLO"; 115068765Sobrien case DT_CONFIG: return "CONFIG"; 115168765Sobrien case DT_DEPAUDIT: return "DEPAUDIT"; 115268765Sobrien case DT_AUDIT: return "AUDIT"; 115368765Sobrien case DT_PLTPAD: return "PLTPAD"; 115468765Sobrien case DT_MOVETAB: return "MOVETAB"; 115560484Sobrien case DT_SYMINFO: return "SYMINFO"; /* aka ADDRRNGHI */ 115660484Sobrien 115760484Sobrien case DT_VERSYM: return "VERSYM"; 115860484Sobrien 115960484Sobrien case DT_RELACOUNT: return "RELACOUNT"; 116060484Sobrien case DT_RELCOUNT: return "RELCOUNT"; 116160484Sobrien case DT_FLAGS_1: return "FLAGS_1"; 116260484Sobrien case DT_VERDEF: return "VERDEF"; 116360484Sobrien case DT_VERDEFNUM: return "VERDEFNUM"; 116460484Sobrien case DT_VERNEED: return "VERNEED"; 116560484Sobrien case DT_VERNEEDNUM: return "VERNEEDNUM"; 116660484Sobrien 116768765Sobrien case DT_AUXILIARY: return "AUXILIARY"; 116860484Sobrien case DT_USED: return "USED"; 116960484Sobrien case DT_FILTER: return "FILTER"; 117060484Sobrien 117160484Sobrien default: 117260484Sobrien if ((type >= DT_LOPROC) && (type <= DT_HIPROC)) 117360484Sobrien { 117460484Sobrien const char * result; 117560484Sobrien 117660484Sobrien switch (elf_header.e_machine) 117760484Sobrien { 117860484Sobrien case EM_MIPS: 117978828Sobrien case EM_MIPS_RS3_LE: 118060484Sobrien result = get_mips_dynamic_type (type); 118160484Sobrien break; 118260484Sobrien case EM_SPARCV9: 118360484Sobrien result = get_sparc64_dynamic_type (type); 118460484Sobrien break; 118560484Sobrien default: 118660484Sobrien result = NULL; 118760484Sobrien break; 118860484Sobrien } 118960484Sobrien 119060484Sobrien if (result != NULL) 119160484Sobrien return result; 119260484Sobrien 119360484Sobrien sprintf (buff, _("Processor Specific: %lx"), type); 119460484Sobrien } 119560484Sobrien else if ((type >= DT_LOOS) && (type <= DT_HIOS)) 119660484Sobrien { 119760484Sobrien const char * result; 119860484Sobrien 119960484Sobrien switch (elf_header.e_machine) 120060484Sobrien { 120160484Sobrien case EM_PARISC: 120260484Sobrien result = get_parisc_dynamic_type (type); 120360484Sobrien break; 120460484Sobrien default: 120560484Sobrien result = NULL; 120660484Sobrien break; 120760484Sobrien } 120860484Sobrien 120960484Sobrien if (result != NULL) 121060484Sobrien return result; 121160484Sobrien 121260484Sobrien sprintf (buff, _("Operating System specific: %lx"), type); 121360484Sobrien } 121460484Sobrien else 121560484Sobrien sprintf (buff, _("<unknown>: %lx"), type); 121660484Sobrien 121760484Sobrien return buff; 121860484Sobrien } 121960484Sobrien} 122060484Sobrien 122160484Sobrienstatic char * 122260484Sobrienget_file_type (e_type) 122360484Sobrien unsigned e_type; 122460484Sobrien{ 122560484Sobrien static char buff [32]; 122660484Sobrien 122760484Sobrien switch (e_type) 122860484Sobrien { 122960484Sobrien case ET_NONE: return _("NONE (None)"); 123060484Sobrien case ET_REL: return _("REL (Relocatable file)"); 123160484Sobrien case ET_EXEC: return _("EXEC (Executable file)"); 123260484Sobrien case ET_DYN: return _("DYN (Shared object file)"); 123360484Sobrien case ET_CORE: return _("CORE (Core file)"); 123460484Sobrien 123560484Sobrien default: 123660484Sobrien if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC)) 123760484Sobrien sprintf (buff, _("Processor Specific: (%x)"), e_type); 123860484Sobrien else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS)) 123960484Sobrien sprintf (buff, _("OS Specific: (%x)"), e_type); 124060484Sobrien else 124160484Sobrien sprintf (buff, _("<unknown>: %x"), e_type); 124260484Sobrien return buff; 124360484Sobrien } 124460484Sobrien} 124560484Sobrien 124660484Sobrienstatic char * 124760484Sobrienget_machine_name (e_machine) 124860484Sobrien unsigned e_machine; 124960484Sobrien{ 125060484Sobrien static char buff [64]; /* XXX */ 125160484Sobrien 125260484Sobrien switch (e_machine) 125360484Sobrien { 125478828Sobrien case EM_NONE: return _("None"); 125578828Sobrien case EM_M32: return "WE32100"; 125678828Sobrien case EM_SPARC: return "Sparc"; 125778828Sobrien case EM_386: return "Intel 80386"; 125878828Sobrien case EM_68K: return "MC68000"; 125978828Sobrien case EM_88K: return "MC88000"; 126078828Sobrien case EM_486: return "Intel 80486"; 126178828Sobrien case EM_860: return "Intel 80860"; 126278828Sobrien case EM_MIPS: return "MIPS R3000"; 126378828Sobrien case EM_S370: return "IBM System/370"; 126478828Sobrien case EM_MIPS_RS3_LE: return "MIPS R4000 big-endian"; 126560484Sobrien case EM_OLD_SPARCV9: return "Sparc v9 (old)"; 126678828Sobrien case EM_PARISC: return "HPPA"; 126760484Sobrien case EM_PPC_OLD: return "Power PC (old)"; 126878828Sobrien case EM_SPARC32PLUS: return "Sparc v8+" ; 126978828Sobrien case EM_960: return "Intel 90860"; 127078828Sobrien case EM_PPC: return "PowerPC"; 127178828Sobrien case EM_V800: return "NEC V800"; 127278828Sobrien case EM_FR20: return "Fujitsu FR20"; 127378828Sobrien case EM_RH32: return "TRW RH32"; 127460484Sobrien case EM_MCORE: return "MCORE"; 127578828Sobrien case EM_ARM: return "ARM"; 127678828Sobrien case EM_OLD_ALPHA: return "Digital Alpha (old)"; 127778828Sobrien case EM_SH: return "Hitachi SH"; 127878828Sobrien case EM_SPARCV9: return "Sparc v9"; 127978828Sobrien case EM_TRICORE: return "Siemens Tricore"; 128077298Sobrien case EM_ARC: return "ARC"; 128160484Sobrien case EM_H8_300: return "Hitachi H8/300"; 128260484Sobrien case EM_H8_300H: return "Hitachi H8/300H"; 128360484Sobrien case EM_H8S: return "Hitachi H8S"; 128460484Sobrien case EM_H8_500: return "Hitachi H8/500"; 128560484Sobrien case EM_IA_64: return "Intel IA-64"; 128660484Sobrien case EM_MIPS_X: return "Stanford MIPS-X"; 128760484Sobrien case EM_COLDFIRE: return "Motorola Coldfire"; 128860484Sobrien case EM_68HC12: return "Motorola M68HC12"; 128978828Sobrien case EM_ALPHA: return "Alpha"; 129060484Sobrien case EM_CYGNUS_D10V: return "d10v"; 129160484Sobrien case EM_CYGNUS_D30V: return "d30v"; 129277298Sobrien case EM_CYGNUS_ARC: return "ARC"; 129360484Sobrien case EM_CYGNUS_M32R: return "Mitsubishi M32r"; 129460484Sobrien case EM_CYGNUS_V850: return "NEC v850"; 129560484Sobrien case EM_CYGNUS_MN10300: return "mn10300"; 129660484Sobrien case EM_CYGNUS_MN10200: return "mn10200"; 129760484Sobrien case EM_CYGNUS_FR30: return "Fujitsu FR30"; 129860484Sobrien case EM_PJ: return "picoJava"; 129978828Sobrien case EM_MMA: return "Fujitsu Multimedia Accelerator"; 130078828Sobrien case EM_PCP: return "Siemens PCP"; 130178828Sobrien case EM_NCPU: return "Sony nCPU embedded RISC processor"; 130278828Sobrien case EM_NDR1: return "Denso NDR1 microprocesspr"; 130378828Sobrien case EM_STARCORE: return "Motorola Star*Core processor"; 130478828Sobrien case EM_ME16: return "Toyota ME16 processor"; 130578828Sobrien case EM_ST100: return "STMicroelectronics ST100 processor"; 130678828Sobrien case EM_TINYJ: return "Advanced Logic Corp. TinyJ embedded processor"; 130778828Sobrien case EM_FX66: return "Siemens FX66 microcontroller"; 130878828Sobrien case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 bit microcontroller"; 130978828Sobrien case EM_ST7: return "STMicroelectronics ST7 8-bit microcontroller"; 131078828Sobrien case EM_68HC16: return "Motorola MC68HC16 Microcontroller"; 131178828Sobrien case EM_68HC11: return "Motorola MC68HC11 Microcontroller"; 131278828Sobrien case EM_68HC08: return "Motorola MC68HC08 Microcontroller"; 131378828Sobrien case EM_68HC05: return "Motorola MC68HC05 Microcontroller"; 131478828Sobrien case EM_SVX: return "Silicon Graphics SVx"; 131578828Sobrien case EM_ST19: return "STMicroelectronics ST19 8-bit microcontroller"; 131678828Sobrien case EM_VAX: return "Digital VAX"; 131777298Sobrien case EM_AVR: return "Atmel AVR 8-bit microcontroller"; 131877298Sobrien case EM_CRIS: return "Axis Communications 32-bit embedded processor"; 131978828Sobrien case EM_JAVELIN: return "Infineon Technologies 32-bit embedded cpu"; 132078828Sobrien case EM_FIREPATH: return "Element 14 64-bit DSP processor"; 132178828Sobrien case EM_ZSP: return "LSI Logic's 16-bit DSP processor"; 132277298Sobrien case EM_MMIX: return "Donald Knuth's educational 64-bit processor"; 132378828Sobrien case EM_HUANY: return "Harvard Universitys's machine-independent object format"; 132478828Sobrien case EM_PRISM: return "SiTera Prism"; 132577298Sobrien case EM_X86_64: return "Advanced Micro Devices X86-64"; 132660484Sobrien default: 132760484Sobrien sprintf (buff, _("<unknown>: %x"), e_machine); 132860484Sobrien return buff; 132960484Sobrien } 133060484Sobrien} 133160484Sobrien 133277298Sobrienstatic void 133377298Sobriendecode_ARM_machine_flags (e_flags, buf) 133477298Sobrien unsigned e_flags; 133577298Sobrien char buf[]; 133677298Sobrien{ 133777298Sobrien unsigned eabi; 133877298Sobrien int unknown = 0; 133977298Sobrien 134077298Sobrien eabi = EF_ARM_EABI_VERSION (e_flags); 134177298Sobrien e_flags &= ~ EF_ARM_EABIMASK; 134277298Sobrien 134377298Sobrien /* Handle "generic" ARM flags. */ 134477298Sobrien if (e_flags & EF_ARM_RELEXEC) 134577298Sobrien { 134677298Sobrien strcat (buf, ", relocatable executable"); 134777298Sobrien e_flags &= ~ EF_ARM_RELEXEC; 134877298Sobrien } 134977298Sobrien 135077298Sobrien if (e_flags & EF_ARM_HASENTRY) 135177298Sobrien { 135277298Sobrien strcat (buf, ", has entry point"); 135377298Sobrien e_flags &= ~ EF_ARM_HASENTRY; 135477298Sobrien } 135577298Sobrien 135677298Sobrien /* Now handle EABI specific flags. */ 135777298Sobrien switch (eabi) 135877298Sobrien { 135977298Sobrien default: 136077298Sobrien strcat (buf, ", <unknown EABI>"); 136177298Sobrien if (e_flags) 136277298Sobrien unknown = 1; 136377298Sobrien break; 136477298Sobrien 136577298Sobrien case EF_ARM_EABI_VER1: 136677298Sobrien while (e_flags) 136777298Sobrien { 136877298Sobrien unsigned flag; 136977298Sobrien 137077298Sobrien /* Process flags one bit at a time. */ 137177298Sobrien flag = e_flags & - e_flags; 137277298Sobrien e_flags &= ~ flag; 137377298Sobrien 137477298Sobrien switch (flag) 137577298Sobrien { 137677298Sobrien case EF_ARM_SYMSARESORTED: /* Conflicts with EF_INTERWORK. */ 137777298Sobrien strcat (buf, ", sorted symbol tables"); 137877298Sobrien break; 137977298Sobrien 138077298Sobrien default: 138177298Sobrien unknown = 1; 138277298Sobrien break; 138377298Sobrien } 138477298Sobrien } 138577298Sobrien break; 138677298Sobrien 138777298Sobrien case EF_ARM_EABI_UNKNOWN: 138877298Sobrien while (e_flags) 138977298Sobrien { 139077298Sobrien unsigned flag; 139177298Sobrien 139277298Sobrien /* Process flags one bit at a time. */ 139377298Sobrien flag = e_flags & - e_flags; 139477298Sobrien e_flags &= ~ flag; 139577298Sobrien 139677298Sobrien switch (flag) 139777298Sobrien { 139877298Sobrien case EF_INTERWORK: 139977298Sobrien strcat (buf, ", interworking enabled"); 140077298Sobrien break; 140177298Sobrien 140277298Sobrien case EF_APCS_26: 140377298Sobrien strcat (buf, ", uses APCS/26"); 140477298Sobrien break; 140577298Sobrien 140677298Sobrien case EF_APCS_FLOAT: 140777298Sobrien strcat (buf, ", uses APCS/float"); 140877298Sobrien break; 140977298Sobrien 141077298Sobrien case EF_PIC: 141177298Sobrien strcat (buf, ", position independent"); 141277298Sobrien break; 141377298Sobrien 141477298Sobrien case EF_ALIGN8: 141577298Sobrien strcat (buf, ", 8 bit structure alignment"); 141677298Sobrien break; 141777298Sobrien 141877298Sobrien case EF_NEW_ABI: 141977298Sobrien strcat (buf, ", uses new ABI"); 142077298Sobrien break; 142177298Sobrien 142277298Sobrien case EF_OLD_ABI: 142377298Sobrien strcat (buf, ", uses old ABI"); 142477298Sobrien break; 142577298Sobrien 142677298Sobrien case EF_SOFT_FLOAT: 142777298Sobrien strcat (buf, ", software FP"); 142877298Sobrien break; 142977298Sobrien 143077298Sobrien default: 143177298Sobrien unknown = 1; 143277298Sobrien break; 143377298Sobrien } 143477298Sobrien } 143577298Sobrien } 143677298Sobrien 143777298Sobrien if (unknown) 143877298Sobrien strcat (buf,", <unknown>"); 143977298Sobrien} 144077298Sobrien 144160484Sobrienstatic char * 144260484Sobrienget_machine_flags (e_flags, e_machine) 144360484Sobrien unsigned e_flags; 144460484Sobrien unsigned e_machine; 144560484Sobrien{ 144660484Sobrien static char buf [1024]; 144760484Sobrien 144860484Sobrien buf[0] = '\0'; 144977298Sobrien 145060484Sobrien if (e_flags) 145160484Sobrien { 145260484Sobrien switch (e_machine) 145360484Sobrien { 145460484Sobrien default: 145560484Sobrien break; 145660484Sobrien 145777298Sobrien case EM_ARM: 145877298Sobrien decode_ARM_machine_flags (e_flags, buf); 145977298Sobrien break; 146077298Sobrien 146160484Sobrien case EM_68K: 146260484Sobrien if (e_flags & EF_CPU32) 146360484Sobrien strcat (buf, ", cpu32"); 146460484Sobrien break; 146560484Sobrien 146660484Sobrien case EM_PPC: 146760484Sobrien if (e_flags & EF_PPC_EMB) 146860484Sobrien strcat (buf, ", emb"); 146960484Sobrien 147060484Sobrien if (e_flags & EF_PPC_RELOCATABLE) 147160484Sobrien strcat (buf, ", relocatable"); 147260484Sobrien 147360484Sobrien if (e_flags & EF_PPC_RELOCATABLE_LIB) 147460484Sobrien strcat (buf, ", relocatable-lib"); 147560484Sobrien break; 147660484Sobrien 147760484Sobrien case EM_CYGNUS_V850: 147860484Sobrien switch (e_flags & EF_V850_ARCH) 147960484Sobrien { 148060484Sobrien case E_V850E_ARCH: 148160484Sobrien strcat (buf, ", v850e"); 148260484Sobrien break; 148360484Sobrien case E_V850EA_ARCH: 148460484Sobrien strcat (buf, ", v850ea"); 148560484Sobrien break; 148660484Sobrien case E_V850_ARCH: 148760484Sobrien strcat (buf, ", v850"); 148860484Sobrien break; 148960484Sobrien default: 149060484Sobrien strcat (buf, ", unknown v850 architecture variant"); 149160484Sobrien break; 149260484Sobrien } 149360484Sobrien break; 149460484Sobrien 149560484Sobrien case EM_CYGNUS_M32R: 149660484Sobrien if ((e_flags & EF_M32R_ARCH) == E_M32R_ARCH) 149760484Sobrien strcat (buf, ", m32r"); 149860484Sobrien 149960484Sobrien break; 150060484Sobrien 150160484Sobrien case EM_MIPS: 150278828Sobrien case EM_MIPS_RS3_LE: 150360484Sobrien if (e_flags & EF_MIPS_NOREORDER) 150460484Sobrien strcat (buf, ", noreorder"); 150560484Sobrien 150660484Sobrien if (e_flags & EF_MIPS_PIC) 150760484Sobrien strcat (buf, ", pic"); 150860484Sobrien 150960484Sobrien if (e_flags & EF_MIPS_CPIC) 151060484Sobrien strcat (buf, ", cpic"); 151160484Sobrien 151260484Sobrien if (e_flags & EF_MIPS_ABI2) 151360484Sobrien strcat (buf, ", abi2"); 151460484Sobrien 151560484Sobrien if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1) 151660484Sobrien strcat (buf, ", mips1"); 151760484Sobrien 151860484Sobrien if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2) 151960484Sobrien strcat (buf, ", mips2"); 152060484Sobrien 152160484Sobrien if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_3) 152260484Sobrien strcat (buf, ", mips3"); 152360484Sobrien 152460484Sobrien if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_4) 152560484Sobrien strcat (buf, ", mips4"); 152677298Sobrien 152777298Sobrien if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_5) 152877298Sobrien strcat (buf, ", mips5"); 152977298Sobrien 153077298Sobrien if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32) 153177298Sobrien strcat (buf, ", mips32"); 153277298Sobrien 153377298Sobrien if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64) 153477298Sobrien strcat (buf, ", mips64"); 153577298Sobrien 153677298Sobrien switch ((e_flags & EF_MIPS_MACH)) 153777298Sobrien { 153877298Sobrien case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break; 153977298Sobrien case E_MIPS_MACH_4010: strcat (buf, ", 4010"); break; 154077298Sobrien case E_MIPS_MACH_4100: strcat (buf, ", 4100"); break; 154177298Sobrien case E_MIPS_MACH_4650: strcat (buf, ", 4650"); break; 154277298Sobrien case E_MIPS_MACH_4111: strcat (buf, ", 4111"); break; 154377298Sobrien case E_MIPS_MACH_MIPS32_4K: strcat (buf, ", mips32-4k"); break; 154477298Sobrien case E_MIPS_MACH_SB1: strcat (buf, ", sb1"); break; 154577298Sobrien default: strcat (buf, " UNKNOWN"); break; 154677298Sobrien } 154760484Sobrien break; 154860484Sobrien 154960484Sobrien case EM_SPARCV9: 155060484Sobrien if (e_flags & EF_SPARC_32PLUS) 155160484Sobrien strcat (buf, ", v8+"); 155260484Sobrien 155360484Sobrien if (e_flags & EF_SPARC_SUN_US1) 155460484Sobrien strcat (buf, ", ultrasparcI"); 155560484Sobrien 155660484Sobrien if (e_flags & EF_SPARC_SUN_US3) 155760484Sobrien strcat (buf, ", ultrasparcIII"); 155860484Sobrien 155960484Sobrien if (e_flags & EF_SPARC_HAL_R1) 156060484Sobrien strcat (buf, ", halr1"); 156160484Sobrien 156260484Sobrien if (e_flags & EF_SPARC_LEDATA) 156360484Sobrien strcat (buf, ", ledata"); 156460484Sobrien 156560484Sobrien if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_TSO) 156660484Sobrien strcat (buf, ", tso"); 156760484Sobrien 156860484Sobrien if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_PSO) 156960484Sobrien strcat (buf, ", pso"); 157060484Sobrien 157160484Sobrien if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_RMO) 157260484Sobrien strcat (buf, ", rmo"); 157360484Sobrien break; 157460484Sobrien 157560484Sobrien case EM_PARISC: 157660484Sobrien switch (e_flags & EF_PARISC_ARCH) 157760484Sobrien { 157860484Sobrien case EFA_PARISC_1_0: 157960484Sobrien strcpy (buf, ", PA-RISC 1.0"); 158060484Sobrien break; 158160484Sobrien case EFA_PARISC_1_1: 158260484Sobrien strcpy (buf, ", PA-RISC 1.1"); 158360484Sobrien break; 158460484Sobrien case EFA_PARISC_2_0: 158560484Sobrien strcpy (buf, ", PA-RISC 2.0"); 158660484Sobrien break; 158760484Sobrien default: 158860484Sobrien break; 158960484Sobrien } 159060484Sobrien if (e_flags & EF_PARISC_TRAPNIL) 159160484Sobrien strcat (buf, ", trapnil"); 159260484Sobrien if (e_flags & EF_PARISC_EXT) 159360484Sobrien strcat (buf, ", ext"); 159460484Sobrien if (e_flags & EF_PARISC_LSB) 159560484Sobrien strcat (buf, ", lsb"); 159660484Sobrien if (e_flags & EF_PARISC_WIDE) 159760484Sobrien strcat (buf, ", wide"); 159860484Sobrien if (e_flags & EF_PARISC_NO_KABP) 159960484Sobrien strcat (buf, ", no kabp"); 160060484Sobrien if (e_flags & EF_PARISC_LAZYSWAP) 160160484Sobrien strcat (buf, ", lazyswap"); 160260484Sobrien break; 160377298Sobrien 160460484Sobrien case EM_PJ: 160560484Sobrien if ((e_flags & EF_PICOJAVA_NEWCALLS) == EF_PICOJAVA_NEWCALLS) 160660484Sobrien strcat (buf, ", new calling convention"); 160760484Sobrien 160860484Sobrien if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS) 160960484Sobrien strcat (buf, ", gnu calling convention"); 161060484Sobrien break; 161178828Sobrien 161278828Sobrien case EM_IA_64: 161378828Sobrien if ((e_flags & EF_IA_64_ABI64)) 161478828Sobrien strcat (buf, ", 64-bit"); 161578828Sobrien else 161678828Sobrien strcat (buf, ", 32-bit"); 161778828Sobrien if ((e_flags & EF_IA_64_REDUCEDFP)) 161878828Sobrien strcat (buf, ", reduced fp model"); 161978828Sobrien if ((e_flags & EF_IA_64_NOFUNCDESC_CONS_GP)) 162078828Sobrien strcat (buf, ", no function descriptors, constant gp"); 162178828Sobrien else if ((e_flags & EF_IA_64_CONS_GP)) 162278828Sobrien strcat (buf, ", constant gp"); 162378828Sobrien if ((e_flags & EF_IA_64_ABSOLUTE)) 162478828Sobrien strcat (buf, ", absolute"); 162578828Sobrien break; 162660484Sobrien } 162760484Sobrien } 162860484Sobrien 162960484Sobrien return buf; 163060484Sobrien} 163160484Sobrien 163260484Sobrienstatic const char * 163360484Sobrienget_mips_segment_type (type) 163460484Sobrien unsigned long type; 163560484Sobrien{ 163660484Sobrien switch (type) 163760484Sobrien { 163860484Sobrien case PT_MIPS_REGINFO: 163960484Sobrien return "REGINFO"; 164060484Sobrien case PT_MIPS_RTPROC: 164160484Sobrien return "RTPROC"; 164260484Sobrien case PT_MIPS_OPTIONS: 164360484Sobrien return "OPTIONS"; 164460484Sobrien default: 164560484Sobrien break; 164660484Sobrien } 164760484Sobrien 164860484Sobrien return NULL; 164960484Sobrien} 165060484Sobrien 165160484Sobrienstatic const char * 165260484Sobrienget_parisc_segment_type (type) 165360484Sobrien unsigned long type; 165460484Sobrien{ 165560484Sobrien switch (type) 165660484Sobrien { 165760484Sobrien case PT_HP_TLS: return "HP_TLS"; 165860484Sobrien case PT_HP_CORE_NONE: return "HP_CORE_NONE"; 165960484Sobrien case PT_HP_CORE_VERSION: return "HP_CORE_VERSION"; 166060484Sobrien case PT_HP_CORE_KERNEL: return "HP_CORE_KERNEL"; 166160484Sobrien case PT_HP_CORE_COMM: return "HP_CORE_COMM"; 166260484Sobrien case PT_HP_CORE_PROC: return "HP_CORE_PROC"; 166360484Sobrien case PT_HP_CORE_LOADABLE: return "HP_CORE_LOADABLE"; 166460484Sobrien case PT_HP_CORE_STACK: return "HP_CORE_STACK"; 166560484Sobrien case PT_HP_CORE_SHM: return "HP_CORE_SHM"; 166660484Sobrien case PT_HP_CORE_MMF: return "HP_CORE_MMF"; 166760484Sobrien case PT_HP_PARALLEL: return "HP_PARALLEL"; 166860484Sobrien case PT_HP_FASTBIND: return "HP_FASTBIND"; 166960484Sobrien case PT_PARISC_ARCHEXT: return "PARISC_ARCHEXT"; 167060484Sobrien case PT_PARISC_UNWIND: return "PARISC_UNWIND"; 167160484Sobrien default: 167260484Sobrien break; 167360484Sobrien } 167460484Sobrien 167560484Sobrien return NULL; 167660484Sobrien} 167760484Sobrien 167860484Sobrienstatic const char * 167978828Sobrienget_ia64_segment_type (type) 168078828Sobrien unsigned long type; 168178828Sobrien{ 168278828Sobrien switch (type) 168378828Sobrien { 168478828Sobrien case PT_IA_64_ARCHEXT: return "IA_64_ARCHEXT"; 168578828Sobrien case PT_IA_64_UNWIND: return "IA_64_UNWIND"; 168678828Sobrien default: 168778828Sobrien break; 168878828Sobrien } 168978828Sobrien 169078828Sobrien return NULL; 169178828Sobrien} 169278828Sobrien 169378828Sobrienstatic const char * 169460484Sobrienget_segment_type (p_type) 169560484Sobrien unsigned long p_type; 169660484Sobrien{ 169760484Sobrien static char buff [32]; 169860484Sobrien 169960484Sobrien switch (p_type) 170060484Sobrien { 170160484Sobrien case PT_NULL: return "NULL"; 170260484Sobrien case PT_LOAD: return "LOAD"; 170360484Sobrien case PT_DYNAMIC: return "DYNAMIC"; 170460484Sobrien case PT_INTERP: return "INTERP"; 170560484Sobrien case PT_NOTE: return "NOTE"; 170660484Sobrien case PT_SHLIB: return "SHLIB"; 170760484Sobrien case PT_PHDR: return "PHDR"; 170860484Sobrien 170960484Sobrien default: 171060484Sobrien if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC)) 171160484Sobrien { 171260484Sobrien const char * result; 171360484Sobrien 171460484Sobrien switch (elf_header.e_machine) 171560484Sobrien { 171660484Sobrien case EM_MIPS: 171778828Sobrien case EM_MIPS_RS3_LE: 171860484Sobrien result = get_mips_segment_type (p_type); 171960484Sobrien break; 172060484Sobrien case EM_PARISC: 172160484Sobrien result = get_parisc_segment_type (p_type); 172260484Sobrien break; 172378828Sobrien case EM_IA_64: 172478828Sobrien result = get_ia64_segment_type (p_type); 172578828Sobrien break; 172660484Sobrien default: 172760484Sobrien result = NULL; 172860484Sobrien break; 172960484Sobrien } 173060484Sobrien 173160484Sobrien if (result != NULL) 173260484Sobrien return result; 173360484Sobrien 173460484Sobrien sprintf (buff, "LOPROC+%lx", p_type - PT_LOPROC); 173560484Sobrien } 173660484Sobrien else if ((p_type >= PT_LOOS) && (p_type <= PT_HIOS)) 173760484Sobrien { 173860484Sobrien const char * result; 173960484Sobrien 174060484Sobrien switch (elf_header.e_machine) 174160484Sobrien { 174260484Sobrien case EM_PARISC: 174360484Sobrien result = get_parisc_segment_type (p_type); 174460484Sobrien break; 174560484Sobrien default: 174660484Sobrien result = NULL; 174760484Sobrien break; 174860484Sobrien } 174960484Sobrien 175060484Sobrien if (result != NULL) 175160484Sobrien return result; 175260484Sobrien 175360484Sobrien sprintf (buff, "LOOS+%lx", p_type - PT_LOOS); 175460484Sobrien } 175560484Sobrien else 175660484Sobrien sprintf (buff, _("<unknown>: %lx"), p_type); 175760484Sobrien 175860484Sobrien return buff; 175960484Sobrien } 176060484Sobrien} 176160484Sobrien 176260484Sobrienstatic const char * 176360484Sobrienget_mips_section_type_name (sh_type) 176460484Sobrien unsigned int sh_type; 176560484Sobrien{ 176660484Sobrien switch (sh_type) 176760484Sobrien { 176860484Sobrien case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST"; 176960484Sobrien case SHT_MIPS_MSYM: return "MIPS_MSYM"; 177060484Sobrien case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT"; 177160484Sobrien case SHT_MIPS_GPTAB: return "MIPS_GPTAB"; 177260484Sobrien case SHT_MIPS_UCODE: return "MIPS_UCODE"; 177360484Sobrien case SHT_MIPS_DEBUG: return "MIPS_DEBUG"; 177460484Sobrien case SHT_MIPS_REGINFO: return "MIPS_REGINFO"; 177560484Sobrien case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE"; 177660484Sobrien case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM"; 177760484Sobrien case SHT_MIPS_RELD: return "MIPS_RELD"; 177860484Sobrien case SHT_MIPS_IFACE: return "MIPS_IFACE"; 177960484Sobrien case SHT_MIPS_CONTENT: return "MIPS_CONTENT"; 178060484Sobrien case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS"; 178160484Sobrien case SHT_MIPS_SHDR: return "MIPS_SHDR"; 178260484Sobrien case SHT_MIPS_FDESC: return "MIPS_FDESC"; 178360484Sobrien case SHT_MIPS_EXTSYM: return "MIPS_EXTSYM"; 178460484Sobrien case SHT_MIPS_DENSE: return "MIPS_DENSE"; 178560484Sobrien case SHT_MIPS_PDESC: return "MIPS_PDESC"; 178660484Sobrien case SHT_MIPS_LOCSYM: return "MIPS_LOCSYM"; 178760484Sobrien case SHT_MIPS_AUXSYM: return "MIPS_AUXSYM"; 178860484Sobrien case SHT_MIPS_OPTSYM: return "MIPS_OPTSYM"; 178960484Sobrien case SHT_MIPS_LOCSTR: return "MIPS_LOCSTR"; 179060484Sobrien case SHT_MIPS_LINE: return "MIPS_LINE"; 179160484Sobrien case SHT_MIPS_RFDESC: return "MIPS_RFDESC"; 179260484Sobrien case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM"; 179360484Sobrien case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST"; 179460484Sobrien case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS"; 179560484Sobrien case SHT_MIPS_DWARF: return "MIPS_DWARF"; 179660484Sobrien case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL"; 179760484Sobrien case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; 179860484Sobrien case SHT_MIPS_EVENTS: return "MIPS_EVENTS"; 179960484Sobrien case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE"; 180060484Sobrien case SHT_MIPS_PIXIE: return "MIPS_PIXIE"; 180160484Sobrien case SHT_MIPS_XLATE: return "MIPS_XLATE"; 180260484Sobrien case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG"; 180360484Sobrien case SHT_MIPS_WHIRL: return "MIPS_WHIRL"; 180460484Sobrien case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION"; 180560484Sobrien case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; 180660484Sobrien case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION"; 180760484Sobrien default: 180860484Sobrien break; 180960484Sobrien } 181060484Sobrien return NULL; 181160484Sobrien} 181260484Sobrien 181360484Sobrienstatic const char * 181460484Sobrienget_parisc_section_type_name (sh_type) 181560484Sobrien unsigned int sh_type; 181660484Sobrien{ 181760484Sobrien switch (sh_type) 181860484Sobrien { 181960484Sobrien case SHT_PARISC_EXT: return "PARISC_EXT"; 182060484Sobrien case SHT_PARISC_UNWIND: return "PARISC_UNWIND"; 182160484Sobrien case SHT_PARISC_DOC: return "PARISC_DOC"; 182260484Sobrien default: 182360484Sobrien break; 182460484Sobrien } 182560484Sobrien return NULL; 182660484Sobrien} 182760484Sobrien 182860484Sobrienstatic const char * 182978828Sobrienget_ia64_section_type_name (sh_type) 183078828Sobrien unsigned int sh_type; 183178828Sobrien{ 183278828Sobrien switch (sh_type) 183378828Sobrien { 183478828Sobrien case SHT_IA_64_EXT: return "IA_64_EXT"; 183578828Sobrien case SHT_IA_64_UNWIND: return "IA_64_UNWIND"; 183678828Sobrien default: 183778828Sobrien break; 183878828Sobrien } 183978828Sobrien return NULL; 184078828Sobrien} 184178828Sobrien 184278828Sobrienstatic const char * 184360484Sobrienget_section_type_name (sh_type) 184460484Sobrien unsigned int sh_type; 184560484Sobrien{ 184660484Sobrien static char buff [32]; 184760484Sobrien 184860484Sobrien switch (sh_type) 184960484Sobrien { 185060484Sobrien case SHT_NULL: return "NULL"; 185160484Sobrien case SHT_PROGBITS: return "PROGBITS"; 185260484Sobrien case SHT_SYMTAB: return "SYMTAB"; 185360484Sobrien case SHT_STRTAB: return "STRTAB"; 185460484Sobrien case SHT_RELA: return "RELA"; 185560484Sobrien case SHT_HASH: return "HASH"; 185660484Sobrien case SHT_DYNAMIC: return "DYNAMIC"; 185760484Sobrien case SHT_NOTE: return "NOTE"; 185860484Sobrien case SHT_NOBITS: return "NOBITS"; 185960484Sobrien case SHT_REL: return "REL"; 186060484Sobrien case SHT_SHLIB: return "SHLIB"; 186160484Sobrien case SHT_DYNSYM: return "DYNSYM"; 186260484Sobrien case SHT_INIT_ARRAY: return "INIT_ARRAY"; 186360484Sobrien case SHT_FINI_ARRAY: return "FINI_ARRAY"; 186460484Sobrien case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY"; 186577298Sobrien case SHT_GROUP: return "GROUP"; 186677298Sobrien case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICIES"; 186760484Sobrien case SHT_GNU_verdef: return "VERDEF"; 186860484Sobrien case SHT_GNU_verneed: return "VERNEED"; 186960484Sobrien case SHT_GNU_versym: return "VERSYM"; 187060484Sobrien case 0x6ffffff0: return "VERSYM"; 187160484Sobrien case 0x6ffffffc: return "VERDEF"; 187260484Sobrien case 0x7ffffffd: return "AUXILIARY"; 187360484Sobrien case 0x7fffffff: return "FILTER"; 187460484Sobrien 187560484Sobrien default: 187660484Sobrien if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC)) 187760484Sobrien { 187860484Sobrien const char * result; 187960484Sobrien 188060484Sobrien switch (elf_header.e_machine) 188160484Sobrien { 188260484Sobrien case EM_MIPS: 188378828Sobrien case EM_MIPS_RS3_LE: 188460484Sobrien result = get_mips_section_type_name (sh_type); 188560484Sobrien break; 188660484Sobrien case EM_PARISC: 188760484Sobrien result = get_parisc_section_type_name (sh_type); 188860484Sobrien break; 188978828Sobrien case EM_IA_64: 189078828Sobrien result = get_ia64_section_type_name (sh_type); 189178828Sobrien break; 189260484Sobrien default: 189360484Sobrien result = NULL; 189460484Sobrien break; 189560484Sobrien } 189660484Sobrien 189760484Sobrien if (result != NULL) 189860484Sobrien return result; 189960484Sobrien 190060484Sobrien sprintf (buff, "SHT_LOPROC+%x", sh_type - SHT_LOPROC); 190160484Sobrien } 190260484Sobrien else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS)) 190360484Sobrien sprintf (buff, "SHT_LOOS+%x", sh_type - SHT_LOOS); 190460484Sobrien else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER)) 190560484Sobrien sprintf (buff, "SHT_LOUSER+%x", sh_type - SHT_LOUSER); 190660484Sobrien else 190760484Sobrien sprintf (buff, _("<unknown>: %x"), sh_type); 190860484Sobrien 190960484Sobrien return buff; 191060484Sobrien } 191160484Sobrien} 191260484Sobrien 191360484Sobrienstruct option options [] = 191460484Sobrien{ 191560484Sobrien {"all", no_argument, 0, 'a'}, 191660484Sobrien {"file-header", no_argument, 0, 'h'}, 191760484Sobrien {"program-headers", no_argument, 0, 'l'}, 191860484Sobrien {"headers", no_argument, 0, 'e'}, 191960484Sobrien {"histogram", no_argument, 0, 'I'}, 192060484Sobrien {"segments", no_argument, 0, 'l'}, 192160484Sobrien {"sections", no_argument, 0, 'S'}, 192260484Sobrien {"section-headers", no_argument, 0, 'S'}, 192360484Sobrien {"symbols", no_argument, 0, 's'}, 192460484Sobrien {"syms", no_argument, 0, 's'}, 192560484Sobrien {"relocs", no_argument, 0, 'r'}, 192660484Sobrien {"notes", no_argument, 0, 'n'}, 192760484Sobrien {"dynamic", no_argument, 0, 'd'}, 192860484Sobrien {"arch-specific", no_argument, 0, 'A'}, 192960484Sobrien {"version-info", no_argument, 0, 'V'}, 193060484Sobrien {"use-dynamic", no_argument, 0, 'D'}, 193160484Sobrien {"hex-dump", required_argument, 0, 'x'}, 193260484Sobrien {"debug-dump", optional_argument, 0, 'w'}, 193378828Sobrien {"unwind", no_argument, 0, 'u'}, 193460484Sobrien#ifdef SUPPORT_DISASSEMBLY 193560484Sobrien {"instruction-dump", required_argument, 0, 'i'}, 193660484Sobrien#endif 193760484Sobrien 193860484Sobrien {"version", no_argument, 0, 'v'}, 193960484Sobrien {"help", no_argument, 0, 'H'}, 194060484Sobrien {0, no_argument, 0, 0} 194160484Sobrien}; 194260484Sobrien 194360484Sobrienstatic void 194460484Sobrienusage () 194560484Sobrien{ 194660484Sobrien fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n")); 194760484Sobrien fprintf (stdout, _(" Options are:\n")); 194860484Sobrien fprintf (stdout, _(" -a or --all Equivalent to: -h -l -S -s -r -d -V -A -I\n")); 194960484Sobrien fprintf (stdout, _(" -h or --file-header Display the ELF file header\n")); 195060484Sobrien fprintf (stdout, _(" -l or --program-headers or --segments\n")); 195160484Sobrien fprintf (stdout, _(" Display the program headers\n")); 195260484Sobrien fprintf (stdout, _(" -S or --section-headers or --sections\n")); 195360484Sobrien fprintf (stdout, _(" Display the sections' header\n")); 195460484Sobrien fprintf (stdout, _(" -e or --headers Equivalent to: -h -l -S\n")); 195560484Sobrien fprintf (stdout, _(" -s or --syms or --symbols Display the symbol table\n")); 195660484Sobrien fprintf (stdout, _(" -n or --notes Display the core notes (if present)\n")); 195760484Sobrien fprintf (stdout, _(" -r or --relocs Display the relocations (if present)\n")); 195878828Sobrien fprintf (stdout, _(" -u or --unwind Display the unwind info (if present)\n")); 195960484Sobrien fprintf (stdout, _(" -d or --dynamic Display the dynamic segment (if present)\n")); 196060484Sobrien fprintf (stdout, _(" -V or --version-info Display the version sections (if present)\n")); 196160484Sobrien fprintf (stdout, _(" -A or --arch-specific Display architecture specific information (if any).\n")); 196260484Sobrien fprintf (stdout, _(" -D or --use-dynamic Use the dynamic section info when displaying symbols\n")); 196360484Sobrien fprintf (stdout, _(" -x <number> or --hex-dump=<number>\n")); 196460484Sobrien fprintf (stdout, _(" Dump the contents of section <number>\n")); 196577298Sobrien fprintf (stdout, _(" -w[liaprf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=frames]\n")); 196660484Sobrien fprintf (stdout, _(" Display the contents of DWARF2 debug sections\n")); 196760484Sobrien#ifdef SUPPORT_DISASSEMBLY 196860484Sobrien fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n")); 196960484Sobrien fprintf (stdout, _(" Disassemble the contents of section <number>\n")); 197060484Sobrien#endif 197160484Sobrien fprintf (stdout, _(" -I or --histogram Display histogram of bucket list lengths\n")); 197260484Sobrien fprintf (stdout, _(" -v or --version Display the version number of readelf\n")); 197360484Sobrien fprintf (stdout, _(" -H or --help Display this information\n")); 197460484Sobrien fprintf (stdout, _("Report bugs to %s\n"), REPORT_BUGS_TO); 197560484Sobrien 197660484Sobrien exit (0); 197760484Sobrien} 197860484Sobrien 197960484Sobrienstatic void 198060484Sobrienrequest_dump (section, type) 198160484Sobrien unsigned int section; 198260484Sobrien char type; 198360484Sobrien{ 198460484Sobrien if (section >= num_dump_sects) 198560484Sobrien { 198660484Sobrien char * new_dump_sects; 198760484Sobrien 198860484Sobrien new_dump_sects = (char *) calloc (section + 1, 1); 198960484Sobrien 199060484Sobrien if (new_dump_sects == NULL) 199160484Sobrien error (_("Out of memory allocating dump request table.")); 199260484Sobrien else 199360484Sobrien { 199460484Sobrien /* Copy current flag settings. */ 199560484Sobrien memcpy (new_dump_sects, dump_sects, num_dump_sects); 199660484Sobrien 199760484Sobrien free (dump_sects); 199860484Sobrien 199960484Sobrien dump_sects = new_dump_sects; 200060484Sobrien num_dump_sects = section + 1; 200160484Sobrien } 200260484Sobrien } 200360484Sobrien 200460484Sobrien if (dump_sects) 200560484Sobrien dump_sects [section] |= type; 200660484Sobrien 200760484Sobrien return; 200860484Sobrien} 200960484Sobrien 201060484Sobrienstatic void 201160484Sobrienparse_args (argc, argv) 201260484Sobrien int argc; 201360484Sobrien char ** argv; 201460484Sobrien{ 201560484Sobrien int c; 201660484Sobrien 201760484Sobrien if (argc < 2) 201860484Sobrien usage (); 201960484Sobrien 202060484Sobrien while ((c = getopt_long 202178828Sobrien (argc, argv, "ersuahnldSDAIw::x:i:vV", options, NULL)) != EOF) 202260484Sobrien { 202360484Sobrien char * cp; 202460484Sobrien int section; 202560484Sobrien 202660484Sobrien switch (c) 202760484Sobrien { 202860484Sobrien case 0: 202960484Sobrien /* Long options. */ 203060484Sobrien break; 203160484Sobrien case 'H': 203260484Sobrien usage (); 203360484Sobrien break; 203460484Sobrien 203560484Sobrien case 'a': 203660484Sobrien do_syms ++; 203760484Sobrien do_reloc ++; 203878828Sobrien do_unwind ++; 203960484Sobrien do_dynamic ++; 204060484Sobrien do_header ++; 204160484Sobrien do_sections ++; 204260484Sobrien do_segments ++; 204360484Sobrien do_version ++; 204460484Sobrien do_histogram ++; 204560484Sobrien do_arch ++; 204660484Sobrien do_notes ++; 204760484Sobrien break; 204860484Sobrien case 'e': 204960484Sobrien do_header ++; 205060484Sobrien do_sections ++; 205160484Sobrien do_segments ++; 205260484Sobrien break; 205360484Sobrien case 'A': 205460484Sobrien do_arch ++; 205560484Sobrien break; 205660484Sobrien case 'D': 205760484Sobrien do_using_dynamic ++; 205860484Sobrien break; 205960484Sobrien case 'r': 206060484Sobrien do_reloc ++; 206160484Sobrien break; 206278828Sobrien case 'u': 206378828Sobrien do_unwind ++; 206478828Sobrien break; 206560484Sobrien case 'h': 206660484Sobrien do_header ++; 206760484Sobrien break; 206860484Sobrien case 'l': 206960484Sobrien do_segments ++; 207060484Sobrien break; 207160484Sobrien case 's': 207260484Sobrien do_syms ++; 207360484Sobrien break; 207460484Sobrien case 'S': 207560484Sobrien do_sections ++; 207660484Sobrien break; 207760484Sobrien case 'd': 207860484Sobrien do_dynamic ++; 207960484Sobrien break; 208060484Sobrien case 'I': 208160484Sobrien do_histogram ++; 208260484Sobrien break; 208360484Sobrien case 'n': 208460484Sobrien do_notes ++; 208560484Sobrien break; 208660484Sobrien case 'x': 208760484Sobrien do_dump ++; 208860484Sobrien section = strtoul (optarg, & cp, 0); 208960484Sobrien if (! * cp && section >= 0) 209060484Sobrien { 209160484Sobrien request_dump (section, HEX_DUMP); 209260484Sobrien break; 209360484Sobrien } 209460484Sobrien goto oops; 209560484Sobrien case 'w': 209660484Sobrien do_dump ++; 209760484Sobrien if (optarg == 0) 209860484Sobrien do_debugging = 1; 209960484Sobrien else 210060484Sobrien { 210160484Sobrien do_debugging = 0; 210260484Sobrien switch (optarg[0]) 210360484Sobrien { 210460484Sobrien case 'i': 210560484Sobrien case 'I': 210660484Sobrien do_debug_info = 1; 210760484Sobrien break; 210860484Sobrien 210960484Sobrien case 'a': 211060484Sobrien case 'A': 211160484Sobrien do_debug_abbrevs = 1; 211260484Sobrien break; 211360484Sobrien 211460484Sobrien case 'l': 211560484Sobrien case 'L': 211660484Sobrien do_debug_lines = 1; 211760484Sobrien break; 211860484Sobrien 211960484Sobrien case 'p': 212060484Sobrien case 'P': 212160484Sobrien do_debug_pubnames = 1; 212260484Sobrien break; 212360484Sobrien 212460484Sobrien case 'r': 212560484Sobrien case 'R': 212660484Sobrien do_debug_aranges = 1; 212760484Sobrien break; 212860484Sobrien 212978828Sobrien case 'F': 213078828Sobrien do_debug_frames_interp = 1; 213177298Sobrien case 'f': 213277298Sobrien do_debug_frames = 1; 213377298Sobrien break; 213477298Sobrien 213560484Sobrien default: 213660484Sobrien warn (_("Unrecognised debug option '%s'\n"), optarg); 213760484Sobrien break; 213860484Sobrien } 213960484Sobrien } 214060484Sobrien break; 214160484Sobrien#ifdef SUPPORT_DISASSEMBLY 214260484Sobrien case 'i': 214360484Sobrien do_dump ++; 214460484Sobrien section = strtoul (optarg, & cp, 0); 214560484Sobrien if (! * cp && section >= 0) 214660484Sobrien { 214760484Sobrien request_dump (section, DISASS_DUMP); 214860484Sobrien break; 214960484Sobrien } 215060484Sobrien goto oops; 215160484Sobrien#endif 215260484Sobrien case 'v': 215360484Sobrien print_version (program_name); 215460484Sobrien break; 215560484Sobrien case 'V': 215660484Sobrien do_version ++; 215760484Sobrien break; 215860484Sobrien default: 215960484Sobrien oops: 216060484Sobrien /* xgettext:c-format */ 216160484Sobrien error (_("Invalid option '-%c'\n"), c); 216260484Sobrien /* Drop through. */ 216360484Sobrien case '?': 216460484Sobrien usage (); 216560484Sobrien } 216660484Sobrien } 216760484Sobrien 216878828Sobrien if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections 216960484Sobrien && !do_segments && !do_header && !do_dump && !do_version 217060484Sobrien && !do_histogram && !do_debugging && !do_arch && !do_notes) 217160484Sobrien usage (); 217260484Sobrien else if (argc < 3) 217360484Sobrien { 217460484Sobrien warn (_("Nothing to do.\n")); 217560484Sobrien usage(); 217660484Sobrien } 217760484Sobrien} 217860484Sobrien 217960484Sobrienstatic const char * 218060484Sobrienget_elf_class (elf_class) 218160484Sobrien unsigned char elf_class; 218260484Sobrien{ 218360484Sobrien static char buff [32]; 218460484Sobrien 218560484Sobrien switch (elf_class) 218660484Sobrien { 218760484Sobrien case ELFCLASSNONE: return _("none"); 218860484Sobrien case ELFCLASS32: return _("ELF32"); 218960484Sobrien case ELFCLASS64: return _("ELF64"); 219060484Sobrien default: 219160484Sobrien sprintf (buff, _("<unknown: %x>"), elf_class); 219260484Sobrien return buff; 219360484Sobrien } 219460484Sobrien} 219560484Sobrien 219660484Sobrienstatic const char * 219760484Sobrienget_data_encoding (encoding) 219860484Sobrien unsigned char encoding; 219960484Sobrien{ 220060484Sobrien static char buff [32]; 220160484Sobrien 220260484Sobrien switch (encoding) 220360484Sobrien { 220460484Sobrien case ELFDATANONE: return _("none"); 220560484Sobrien case ELFDATA2LSB: return _("2's complement, little endian"); 220660484Sobrien case ELFDATA2MSB: return _("2's complement, big endian"); 220760484Sobrien default: 220860484Sobrien sprintf (buff, _("<unknown: %x>"), encoding); 220960484Sobrien return buff; 221060484Sobrien } 221160484Sobrien} 221260484Sobrien 221360484Sobrienstatic const char * 221460484Sobrienget_osabi_name (osabi) 221560484Sobrien unsigned char osabi; 221660484Sobrien{ 221760484Sobrien static char buff [32]; 221860484Sobrien 221960484Sobrien switch (osabi) 222060484Sobrien { 222161843Sobrien case ELFOSABI_NONE: return _("UNIX - System V"); 222260484Sobrien case ELFOSABI_HPUX: return _("UNIX - HP-UX"); 222361843Sobrien case ELFOSABI_NETBSD: return _("UNIX - NetBSD"); 222460484Sobrien case ELFOSABI_LINUX: return _("UNIX - Linux"); 222561843Sobrien case ELFOSABI_HURD: return _("GNU/Hurd"); 222661843Sobrien case ELFOSABI_SOLARIS: return _("UNIX - Solaris"); 222777298Sobrien case ELFOSABI_AIX: return _("UNIX - AIX"); 222861843Sobrien case ELFOSABI_IRIX: return _("UNIX - IRIX"); 222961843Sobrien case ELFOSABI_FREEBSD: return _("UNIX - FreeBSD"); 223061843Sobrien case ELFOSABI_TRU64: return _("UNIX - TRU64"); 223161843Sobrien case ELFOSABI_MODESTO: return _("Novell - Modesto"); 223261843Sobrien case ELFOSABI_OPENBSD: return _("UNIX - OpenBSD"); 223360484Sobrien case ELFOSABI_STANDALONE: return _("Standalone App"); 223460484Sobrien case ELFOSABI_ARM: return _("ARM"); 223560484Sobrien default: 223660484Sobrien sprintf (buff, _("<unknown: %x>"), osabi); 223760484Sobrien return buff; 223860484Sobrien } 223960484Sobrien} 224060484Sobrien 224160484Sobrien/* Decode the data held in 'elf_header'. */ 224260484Sobrienstatic int 224360484Sobrienprocess_file_header () 224460484Sobrien{ 224560484Sobrien if ( elf_header.e_ident [EI_MAG0] != ELFMAG0 224660484Sobrien || elf_header.e_ident [EI_MAG1] != ELFMAG1 224760484Sobrien || elf_header.e_ident [EI_MAG2] != ELFMAG2 224860484Sobrien || elf_header.e_ident [EI_MAG3] != ELFMAG3) 224960484Sobrien { 225060484Sobrien error 225160484Sobrien (_("Not an ELF file - it has the wrong magic bytes at the start\n")); 225260484Sobrien return 0; 225360484Sobrien } 225460484Sobrien 225560484Sobrien if (do_header) 225660484Sobrien { 225760484Sobrien int i; 225860484Sobrien 225960484Sobrien printf (_("ELF Header:\n")); 226060484Sobrien printf (_(" Magic: ")); 226160484Sobrien for (i = 0; i < EI_NIDENT; i ++) 226260484Sobrien printf ("%2.2x ", elf_header.e_ident [i]); 226360484Sobrien printf ("\n"); 226460484Sobrien printf (_(" Class: %s\n"), 226560484Sobrien get_elf_class (elf_header.e_ident [EI_CLASS])); 226660484Sobrien printf (_(" Data: %s\n"), 226760484Sobrien get_data_encoding (elf_header.e_ident [EI_DATA])); 226860484Sobrien printf (_(" Version: %d %s\n"), 226960484Sobrien elf_header.e_ident [EI_VERSION], 227060484Sobrien (elf_header.e_ident [EI_VERSION] == EV_CURRENT 227160484Sobrien ? "(current)" 227260484Sobrien : (elf_header.e_ident [EI_VERSION] != EV_NONE 227360484Sobrien ? "<unknown: %lx>" 227460484Sobrien : ""))); 227560484Sobrien printf (_(" OS/ABI: %s\n"), 227660484Sobrien get_osabi_name (elf_header.e_ident [EI_OSABI])); 227760484Sobrien printf (_(" ABI Version: %d\n"), 227860484Sobrien elf_header.e_ident [EI_ABIVERSION]); 227960484Sobrien printf (_(" Type: %s\n"), 228060484Sobrien get_file_type (elf_header.e_type)); 228160484Sobrien printf (_(" Machine: %s\n"), 228260484Sobrien get_machine_name (elf_header.e_machine)); 228360484Sobrien printf (_(" Version: 0x%lx\n"), 228460484Sobrien (unsigned long) elf_header.e_version); 228577298Sobrien 228660484Sobrien printf (_(" Entry point address: ")); 228760484Sobrien print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX); 228860484Sobrien printf (_("\n Start of program headers: ")); 228960484Sobrien print_vma ((bfd_vma) elf_header.e_phoff, DEC); 229060484Sobrien printf (_(" (bytes into file)\n Start of section headers: ")); 229160484Sobrien print_vma ((bfd_vma) elf_header.e_shoff, DEC); 229260484Sobrien printf (_(" (bytes into file)\n")); 229377298Sobrien 229460484Sobrien printf (_(" Flags: 0x%lx%s\n"), 229560484Sobrien (unsigned long) elf_header.e_flags, 229660484Sobrien get_machine_flags (elf_header.e_flags, elf_header.e_machine)); 229760484Sobrien printf (_(" Size of this header: %ld (bytes)\n"), 229860484Sobrien (long) elf_header.e_ehsize); 229960484Sobrien printf (_(" Size of program headers: %ld (bytes)\n"), 230060484Sobrien (long) elf_header.e_phentsize); 230160484Sobrien printf (_(" Number of program headers: %ld\n"), 230260484Sobrien (long) elf_header.e_phnum); 230360484Sobrien printf (_(" Size of section headers: %ld (bytes)\n"), 230460484Sobrien (long) elf_header.e_shentsize); 230560484Sobrien printf (_(" Number of section headers: %ld\n"), 230660484Sobrien (long) elf_header.e_shnum); 230760484Sobrien printf (_(" Section header string table index: %ld\n"), 230860484Sobrien (long) elf_header.e_shstrndx); 230960484Sobrien } 231060484Sobrien 231160484Sobrien return 1; 231260484Sobrien} 231360484Sobrien 231460484Sobrien 231560484Sobrienstatic int 231660484Sobrienget_32bit_program_headers (file, program_headers) 231760484Sobrien FILE * file; 231860484Sobrien Elf_Internal_Phdr * program_headers; 231960484Sobrien{ 232060484Sobrien Elf32_External_Phdr * phdrs; 232160484Sobrien Elf32_External_Phdr * external; 232260484Sobrien Elf32_Internal_Phdr * internal; 232360484Sobrien unsigned int i; 232460484Sobrien 232560484Sobrien GET_DATA_ALLOC (elf_header.e_phoff, 232660484Sobrien elf_header.e_phentsize * elf_header.e_phnum, 232760484Sobrien phdrs, Elf32_External_Phdr *, "program headers"); 232860484Sobrien 232960484Sobrien for (i = 0, internal = program_headers, external = phdrs; 233060484Sobrien i < elf_header.e_phnum; 233160484Sobrien i ++, internal ++, external ++) 233260484Sobrien { 233360484Sobrien internal->p_type = BYTE_GET (external->p_type); 233460484Sobrien internal->p_offset = BYTE_GET (external->p_offset); 233560484Sobrien internal->p_vaddr = BYTE_GET (external->p_vaddr); 233660484Sobrien internal->p_paddr = BYTE_GET (external->p_paddr); 233760484Sobrien internal->p_filesz = BYTE_GET (external->p_filesz); 233860484Sobrien internal->p_memsz = BYTE_GET (external->p_memsz); 233960484Sobrien internal->p_flags = BYTE_GET (external->p_flags); 234060484Sobrien internal->p_align = BYTE_GET (external->p_align); 234160484Sobrien } 234260484Sobrien 234360484Sobrien free (phdrs); 234460484Sobrien 234560484Sobrien return 1; 234660484Sobrien} 234760484Sobrien 234860484Sobrienstatic int 234960484Sobrienget_64bit_program_headers (file, program_headers) 235060484Sobrien FILE * file; 235160484Sobrien Elf_Internal_Phdr * program_headers; 235260484Sobrien{ 235360484Sobrien Elf64_External_Phdr * phdrs; 235460484Sobrien Elf64_External_Phdr * external; 235560484Sobrien Elf64_Internal_Phdr * internal; 235660484Sobrien unsigned int i; 235760484Sobrien 235860484Sobrien GET_DATA_ALLOC (elf_header.e_phoff, 235960484Sobrien elf_header.e_phentsize * elf_header.e_phnum, 236060484Sobrien phdrs, Elf64_External_Phdr *, "program headers"); 236160484Sobrien 236260484Sobrien for (i = 0, internal = program_headers, external = phdrs; 236360484Sobrien i < elf_header.e_phnum; 236460484Sobrien i ++, internal ++, external ++) 236560484Sobrien { 236660484Sobrien internal->p_type = BYTE_GET (external->p_type); 236760484Sobrien internal->p_flags = BYTE_GET (external->p_flags); 236860484Sobrien internal->p_offset = BYTE_GET8 (external->p_offset); 236960484Sobrien internal->p_vaddr = BYTE_GET8 (external->p_vaddr); 237060484Sobrien internal->p_paddr = BYTE_GET8 (external->p_paddr); 237160484Sobrien internal->p_filesz = BYTE_GET8 (external->p_filesz); 237260484Sobrien internal->p_memsz = BYTE_GET8 (external->p_memsz); 237360484Sobrien internal->p_align = BYTE_GET8 (external->p_align); 237460484Sobrien } 237560484Sobrien 237660484Sobrien free (phdrs); 237760484Sobrien 237860484Sobrien return 1; 237960484Sobrien} 238060484Sobrien 238160484Sobrienstatic int 238260484Sobrienprocess_program_headers (file) 238360484Sobrien FILE * file; 238460484Sobrien{ 238560484Sobrien Elf_Internal_Phdr * program_headers; 238660484Sobrien Elf_Internal_Phdr * segment; 238760484Sobrien unsigned int i; 238860484Sobrien 238960484Sobrien if (elf_header.e_phnum == 0) 239060484Sobrien { 239160484Sobrien if (do_segments) 239260484Sobrien printf (_("\nThere are no program headers in this file.\n")); 239360484Sobrien return 1; 239460484Sobrien } 239560484Sobrien 239660484Sobrien if (do_segments && !do_header) 239760484Sobrien { 239860484Sobrien printf (_("\nElf file type is %s\n"), get_file_type (elf_header.e_type)); 239960484Sobrien printf (_("Entry point ")); 240060484Sobrien print_vma ((bfd_vma) elf_header.e_entry, PREFIX_HEX); 240160484Sobrien printf (_("\nThere are %d program headers, starting at offset "), 240260484Sobrien elf_header.e_phnum); 240360484Sobrien print_vma ((bfd_vma) elf_header.e_phoff, DEC); 240460484Sobrien printf ("\n"); 240560484Sobrien } 240660484Sobrien 240760484Sobrien program_headers = (Elf_Internal_Phdr *) malloc 240860484Sobrien (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); 240960484Sobrien 241060484Sobrien if (program_headers == NULL) 241160484Sobrien { 241260484Sobrien error (_("Out of memory\n")); 241360484Sobrien return 0; 241460484Sobrien } 241560484Sobrien 241660484Sobrien if (is_32bit_elf) 241760484Sobrien i = get_32bit_program_headers (file, program_headers); 241860484Sobrien else 241960484Sobrien i = get_64bit_program_headers (file, program_headers); 242060484Sobrien 242160484Sobrien if (i == 0) 242260484Sobrien { 242360484Sobrien free (program_headers); 242460484Sobrien return 0; 242560484Sobrien } 242660484Sobrien 242760484Sobrien if (do_segments) 242860484Sobrien { 242960484Sobrien printf 243060484Sobrien (_("\nProgram Header%s:\n"), elf_header.e_phnum > 1 ? "s" : ""); 243177298Sobrien 243260484Sobrien if (is_32bit_elf) 243360484Sobrien printf 243460484Sobrien (_(" Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align\n")); 243560484Sobrien else 243660484Sobrien { 243760484Sobrien printf 243860484Sobrien (_(" Type Offset VirtAddr PhysAddr\n")); 243960484Sobrien printf 244060484Sobrien (_(" FileSiz MemSiz Flags Align\n")); 244160484Sobrien } 244260484Sobrien } 244360484Sobrien 244460484Sobrien loadaddr = -1; 244560484Sobrien dynamic_addr = 0; 244660484Sobrien dynamic_size = 0; 244760484Sobrien 244860484Sobrien for (i = 0, segment = program_headers; 244960484Sobrien i < elf_header.e_phnum; 245060484Sobrien i ++, segment ++) 245160484Sobrien { 245260484Sobrien if (do_segments) 245360484Sobrien { 245460484Sobrien printf (" %-14.14s ", get_segment_type (segment->p_type)); 245560484Sobrien 245660484Sobrien if (is_32bit_elf) 245760484Sobrien { 245860484Sobrien printf ("0x%6.6lx ", (unsigned long) segment->p_offset); 245960484Sobrien printf ("0x%8.8lx ", (unsigned long) segment->p_vaddr); 246060484Sobrien printf ("0x%8.8lx ", (unsigned long) segment->p_paddr); 246160484Sobrien printf ("0x%5.5lx ", (unsigned long) segment->p_filesz); 246260484Sobrien printf ("0x%5.5lx ", (unsigned long) segment->p_memsz); 246360484Sobrien printf ("%c%c%c ", 246460484Sobrien (segment->p_flags & PF_R ? 'R' : ' '), 246560484Sobrien (segment->p_flags & PF_W ? 'W' : ' '), 246660484Sobrien (segment->p_flags & PF_X ? 'E' : ' ')); 246760484Sobrien printf ("%#lx", (unsigned long) segment->p_align); 246860484Sobrien } 246960484Sobrien else 247060484Sobrien { 247160484Sobrien print_vma (segment->p_offset, FULL_HEX); 247260484Sobrien putchar (' '); 247360484Sobrien print_vma (segment->p_vaddr, FULL_HEX); 247460484Sobrien putchar (' '); 247560484Sobrien print_vma (segment->p_paddr, FULL_HEX); 247660484Sobrien printf ("\n "); 247760484Sobrien print_vma (segment->p_filesz, FULL_HEX); 247860484Sobrien putchar (' '); 247960484Sobrien print_vma (segment->p_memsz, FULL_HEX); 248060484Sobrien printf (" %c%c%c ", 248160484Sobrien (segment->p_flags & PF_R ? 'R' : ' '), 248260484Sobrien (segment->p_flags & PF_W ? 'W' : ' '), 248360484Sobrien (segment->p_flags & PF_X ? 'E' : ' ')); 248460484Sobrien print_vma (segment->p_align, HEX); 248560484Sobrien } 248660484Sobrien } 248760484Sobrien 248860484Sobrien switch (segment->p_type) 248960484Sobrien { 249060484Sobrien case PT_LOAD: 249160484Sobrien if (loadaddr == -1) 249260484Sobrien loadaddr = (segment->p_vaddr & 0xfffff000) 249360484Sobrien - (segment->p_offset & 0xfffff000); 249460484Sobrien break; 249560484Sobrien 249660484Sobrien case PT_DYNAMIC: 249760484Sobrien if (dynamic_addr) 249860484Sobrien error (_("more than one dynamic segment\n")); 249960484Sobrien 250060484Sobrien dynamic_addr = segment->p_offset; 250160484Sobrien dynamic_size = segment->p_filesz; 250260484Sobrien break; 250360484Sobrien 250460484Sobrien case PT_INTERP: 250560484Sobrien if (fseek (file, (long) segment->p_offset, SEEK_SET)) 250660484Sobrien error (_("Unable to find program interpreter name\n")); 250760484Sobrien else 250860484Sobrien { 250960484Sobrien program_interpreter[0] = 0; 251060484Sobrien fscanf (file, "%63s", program_interpreter); 251160484Sobrien 251260484Sobrien if (do_segments) 251360484Sobrien printf (_("\n [Requesting program interpreter: %s]"), 251460484Sobrien program_interpreter); 251560484Sobrien } 251660484Sobrien break; 251760484Sobrien } 251860484Sobrien 251960484Sobrien if (do_segments) 252060484Sobrien putc ('\n', stdout); 252160484Sobrien } 252260484Sobrien 252360484Sobrien if (loadaddr == -1) 252460484Sobrien { 252560484Sobrien /* Very strange. */ 252660484Sobrien loadaddr = 0; 252760484Sobrien } 252860484Sobrien 252960484Sobrien if (do_segments && section_headers != NULL) 253060484Sobrien { 253160484Sobrien printf (_("\n Section to Segment mapping:\n")); 253260484Sobrien printf (_(" Segment Sections...\n")); 253360484Sobrien 253460484Sobrien assert (string_table != NULL); 253560484Sobrien 253660484Sobrien for (i = 0; i < elf_header.e_phnum; i++) 253760484Sobrien { 253860484Sobrien int j; 253960484Sobrien Elf_Internal_Shdr * section; 254060484Sobrien 254160484Sobrien segment = program_headers + i; 254260484Sobrien section = section_headers; 254360484Sobrien 254460484Sobrien printf (" %2.2d ", i); 254560484Sobrien 254660484Sobrien for (j = 0; j < elf_header.e_shnum; j++, section ++) 254760484Sobrien { 254860484Sobrien if (section->sh_size > 0 254960484Sobrien /* Compare allocated sections by VMA, unallocated 255060484Sobrien sections by file offset. */ 255160484Sobrien && (section->sh_flags & SHF_ALLOC 255260484Sobrien ? (section->sh_addr >= segment->p_vaddr 255360484Sobrien && section->sh_addr + section->sh_size 255460484Sobrien <= segment->p_vaddr + segment->p_memsz) 255560484Sobrien : ((bfd_vma) section->sh_offset >= segment->p_offset 255660484Sobrien && (section->sh_offset + section->sh_size 255760484Sobrien <= segment->p_offset + segment->p_filesz)))) 255860484Sobrien printf ("%s ", SECTION_NAME (section)); 255960484Sobrien } 256060484Sobrien 256160484Sobrien putc ('\n',stdout); 256260484Sobrien } 256360484Sobrien } 256460484Sobrien 256560484Sobrien free (program_headers); 256660484Sobrien 256760484Sobrien return 1; 256860484Sobrien} 256960484Sobrien 257060484Sobrien 257160484Sobrienstatic int 257260484Sobrienget_32bit_section_headers (file) 257360484Sobrien FILE * file; 257460484Sobrien{ 257560484Sobrien Elf32_External_Shdr * shdrs; 257660484Sobrien Elf32_Internal_Shdr * internal; 257760484Sobrien unsigned int i; 257860484Sobrien 257960484Sobrien GET_DATA_ALLOC (elf_header.e_shoff, 258060484Sobrien elf_header.e_shentsize * elf_header.e_shnum, 258160484Sobrien shdrs, Elf32_External_Shdr *, "section headers"); 258260484Sobrien 258360484Sobrien section_headers = (Elf_Internal_Shdr *) malloc 258460484Sobrien (elf_header.e_shnum * sizeof (Elf_Internal_Shdr)); 258560484Sobrien 258660484Sobrien if (section_headers == NULL) 258760484Sobrien { 258860484Sobrien error (_("Out of memory\n")); 258960484Sobrien return 0; 259060484Sobrien } 259160484Sobrien 259260484Sobrien for (i = 0, internal = section_headers; 259360484Sobrien i < elf_header.e_shnum; 259460484Sobrien i ++, internal ++) 259560484Sobrien { 259660484Sobrien internal->sh_name = BYTE_GET (shdrs[i].sh_name); 259760484Sobrien internal->sh_type = BYTE_GET (shdrs[i].sh_type); 259860484Sobrien internal->sh_flags = BYTE_GET (shdrs[i].sh_flags); 259960484Sobrien internal->sh_addr = BYTE_GET (shdrs[i].sh_addr); 260060484Sobrien internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); 260160484Sobrien internal->sh_size = BYTE_GET (shdrs[i].sh_size); 260260484Sobrien internal->sh_link = BYTE_GET (shdrs[i].sh_link); 260360484Sobrien internal->sh_info = BYTE_GET (shdrs[i].sh_info); 260460484Sobrien internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); 260560484Sobrien internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize); 260660484Sobrien } 260760484Sobrien 260860484Sobrien free (shdrs); 260960484Sobrien 261060484Sobrien return 1; 261160484Sobrien} 261260484Sobrien 261360484Sobrienstatic int 261460484Sobrienget_64bit_section_headers (file) 261560484Sobrien FILE * file; 261660484Sobrien{ 261760484Sobrien Elf64_External_Shdr * shdrs; 261860484Sobrien Elf64_Internal_Shdr * internal; 261960484Sobrien unsigned int i; 262060484Sobrien 262160484Sobrien GET_DATA_ALLOC (elf_header.e_shoff, 262260484Sobrien elf_header.e_shentsize * elf_header.e_shnum, 262360484Sobrien shdrs, Elf64_External_Shdr *, "section headers"); 262460484Sobrien 262560484Sobrien section_headers = (Elf_Internal_Shdr *) malloc 262660484Sobrien (elf_header.e_shnum * sizeof (Elf_Internal_Shdr)); 262760484Sobrien 262860484Sobrien if (section_headers == NULL) 262960484Sobrien { 263060484Sobrien error (_("Out of memory\n")); 263160484Sobrien return 0; 263260484Sobrien } 263360484Sobrien 263460484Sobrien for (i = 0, internal = section_headers; 263560484Sobrien i < elf_header.e_shnum; 263660484Sobrien i ++, internal ++) 263760484Sobrien { 263860484Sobrien internal->sh_name = BYTE_GET (shdrs[i].sh_name); 263960484Sobrien internal->sh_type = BYTE_GET (shdrs[i].sh_type); 264060484Sobrien internal->sh_flags = BYTE_GET8 (shdrs[i].sh_flags); 264160484Sobrien internal->sh_addr = BYTE_GET8 (shdrs[i].sh_addr); 264260484Sobrien internal->sh_size = BYTE_GET8 (shdrs[i].sh_size); 264360484Sobrien internal->sh_entsize = BYTE_GET8 (shdrs[i].sh_entsize); 264460484Sobrien internal->sh_link = BYTE_GET (shdrs[i].sh_link); 264560484Sobrien internal->sh_info = BYTE_GET (shdrs[i].sh_info); 264660484Sobrien internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); 264760484Sobrien internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); 264860484Sobrien } 264960484Sobrien 265060484Sobrien free (shdrs); 265160484Sobrien 265260484Sobrien return 1; 265360484Sobrien} 265460484Sobrien 265560484Sobrienstatic Elf_Internal_Sym * 265660484Sobrienget_32bit_elf_symbols (file, offset, number) 265760484Sobrien FILE * file; 265860484Sobrien unsigned long offset; 265960484Sobrien unsigned long number; 266060484Sobrien{ 266160484Sobrien Elf32_External_Sym * esyms; 266260484Sobrien Elf_Internal_Sym * isyms; 266360484Sobrien Elf_Internal_Sym * psym; 266460484Sobrien unsigned int j; 266560484Sobrien 266660484Sobrien GET_DATA_ALLOC (offset, number * sizeof (Elf32_External_Sym), 266760484Sobrien esyms, Elf32_External_Sym *, "symbols"); 266860484Sobrien 266960484Sobrien isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); 267060484Sobrien 267160484Sobrien if (isyms == NULL) 267260484Sobrien { 267360484Sobrien error (_("Out of memory\n")); 267460484Sobrien free (esyms); 267560484Sobrien 267660484Sobrien return NULL; 267760484Sobrien } 267860484Sobrien 267960484Sobrien for (j = 0, psym = isyms; 268060484Sobrien j < number; 268160484Sobrien j ++, psym ++) 268260484Sobrien { 268360484Sobrien psym->st_name = BYTE_GET (esyms[j].st_name); 268460484Sobrien psym->st_value = BYTE_GET (esyms[j].st_value); 268560484Sobrien psym->st_size = BYTE_GET (esyms[j].st_size); 268660484Sobrien psym->st_shndx = BYTE_GET (esyms[j].st_shndx); 268760484Sobrien psym->st_info = BYTE_GET (esyms[j].st_info); 268860484Sobrien psym->st_other = BYTE_GET (esyms[j].st_other); 268960484Sobrien } 269060484Sobrien 269160484Sobrien free (esyms); 269260484Sobrien 269360484Sobrien return isyms; 269460484Sobrien} 269560484Sobrien 269660484Sobrienstatic Elf_Internal_Sym * 269760484Sobrienget_64bit_elf_symbols (file, offset, number) 269860484Sobrien FILE * file; 269960484Sobrien unsigned long offset; 270060484Sobrien unsigned long number; 270160484Sobrien{ 270260484Sobrien Elf64_External_Sym * esyms; 270360484Sobrien Elf_Internal_Sym * isyms; 270460484Sobrien Elf_Internal_Sym * psym; 270560484Sobrien unsigned int j; 270660484Sobrien 270760484Sobrien GET_DATA_ALLOC (offset, number * sizeof (Elf64_External_Sym), 270860484Sobrien esyms, Elf64_External_Sym *, "symbols"); 270960484Sobrien 271060484Sobrien isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym)); 271160484Sobrien 271260484Sobrien if (isyms == NULL) 271360484Sobrien { 271460484Sobrien error (_("Out of memory\n")); 271560484Sobrien free (esyms); 271660484Sobrien 271760484Sobrien return NULL; 271860484Sobrien } 271960484Sobrien 272060484Sobrien for (j = 0, psym = isyms; 272160484Sobrien j < number; 272260484Sobrien j ++, psym ++) 272360484Sobrien { 272460484Sobrien psym->st_name = BYTE_GET (esyms[j].st_name); 272560484Sobrien psym->st_info = BYTE_GET (esyms[j].st_info); 272660484Sobrien psym->st_other = BYTE_GET (esyms[j].st_other); 272760484Sobrien psym->st_shndx = BYTE_GET (esyms[j].st_shndx); 272860484Sobrien psym->st_value = BYTE_GET8 (esyms[j].st_value); 272960484Sobrien psym->st_size = BYTE_GET8 (esyms[j].st_size); 273060484Sobrien } 273160484Sobrien 273260484Sobrien free (esyms); 273360484Sobrien 273460484Sobrien return isyms; 273560484Sobrien} 273660484Sobrien 273760484Sobrienstatic const char * 273860484Sobrienget_elf_section_flags (sh_flags) 273960484Sobrien bfd_vma sh_flags; 274060484Sobrien{ 274160484Sobrien static char buff [32]; 274260484Sobrien 274360484Sobrien * buff = 0; 274477298Sobrien 274560484Sobrien while (sh_flags) 274660484Sobrien { 274760484Sobrien bfd_vma flag; 274860484Sobrien 274960484Sobrien flag = sh_flags & - sh_flags; 275060484Sobrien sh_flags &= ~ flag; 275177298Sobrien 275260484Sobrien switch (flag) 275360484Sobrien { 275460484Sobrien case SHF_WRITE: strcat (buff, "W"); break; 275560484Sobrien case SHF_ALLOC: strcat (buff, "A"); break; 275660484Sobrien case SHF_EXECINSTR: strcat (buff, "X"); break; 275760484Sobrien case SHF_MERGE: strcat (buff, "M"); break; 275860484Sobrien case SHF_STRINGS: strcat (buff, "S"); break; 275960484Sobrien case SHF_INFO_LINK: strcat (buff, "I"); break; 276060484Sobrien case SHF_LINK_ORDER: strcat (buff, "L"); break; 276160484Sobrien case SHF_OS_NONCONFORMING: strcat (buff, "O"); break; 276277298Sobrien case SHF_GROUP: strcat (buff, "G"); break; 276377298Sobrien 276460484Sobrien default: 276560484Sobrien if (flag & SHF_MASKOS) 276660484Sobrien { 276760484Sobrien strcat (buff, "o"); 276860484Sobrien sh_flags &= ~ SHF_MASKOS; 276960484Sobrien } 277060484Sobrien else if (flag & SHF_MASKPROC) 277160484Sobrien { 277260484Sobrien strcat (buff, "p"); 277360484Sobrien sh_flags &= ~ SHF_MASKPROC; 277460484Sobrien } 277560484Sobrien else 277660484Sobrien strcat (buff, "x"); 277760484Sobrien break; 277860484Sobrien } 277960484Sobrien } 278077298Sobrien 278160484Sobrien return buff; 278260484Sobrien} 278360484Sobrien 278460484Sobrienstatic int 278560484Sobrienprocess_section_headers (file) 278660484Sobrien FILE * file; 278760484Sobrien{ 278860484Sobrien Elf_Internal_Shdr * section; 278960484Sobrien int i; 279060484Sobrien 279160484Sobrien section_headers = NULL; 279260484Sobrien 279360484Sobrien if (elf_header.e_shnum == 0) 279460484Sobrien { 279560484Sobrien if (do_sections) 279660484Sobrien printf (_("\nThere are no sections in this file.\n")); 279760484Sobrien 279860484Sobrien return 1; 279960484Sobrien } 280060484Sobrien 280160484Sobrien if (do_sections && !do_header) 280260484Sobrien printf (_("There are %d section headers, starting at offset 0x%lx:\n"), 280360484Sobrien elf_header.e_shnum, (unsigned long) elf_header.e_shoff); 280460484Sobrien 280560484Sobrien if (is_32bit_elf) 280660484Sobrien { 280760484Sobrien if (! get_32bit_section_headers (file)) 280860484Sobrien return 0; 280960484Sobrien } 281060484Sobrien else if (! get_64bit_section_headers (file)) 281160484Sobrien return 0; 281260484Sobrien 281360484Sobrien /* Read in the string table, so that we have names to display. */ 281460484Sobrien section = section_headers + elf_header.e_shstrndx; 281560484Sobrien 281660484Sobrien if (section->sh_size != 0) 281760484Sobrien { 281860484Sobrien GET_DATA_ALLOC (section->sh_offset, section->sh_size, 281960484Sobrien string_table, char *, "string table"); 282077298Sobrien 282177298Sobrien string_table_length = section->sh_size; 282260484Sobrien } 282360484Sobrien 282460484Sobrien /* Scan the sections for the dynamic symbol table 282560484Sobrien and dynamic string table and debug sections. */ 282660484Sobrien dynamic_symbols = NULL; 282760484Sobrien dynamic_strings = NULL; 282860484Sobrien dynamic_syminfo = NULL; 282960484Sobrien 283060484Sobrien for (i = 0, section = section_headers; 283160484Sobrien i < elf_header.e_shnum; 283260484Sobrien i ++, section ++) 283360484Sobrien { 283460484Sobrien char * name = SECTION_NAME (section); 283560484Sobrien 283660484Sobrien if (section->sh_type == SHT_DYNSYM) 283760484Sobrien { 283860484Sobrien if (dynamic_symbols != NULL) 283960484Sobrien { 284060484Sobrien error (_("File contains multiple dynamic symbol tables\n")); 284160484Sobrien continue; 284260484Sobrien } 284360484Sobrien 284460484Sobrien num_dynamic_syms = section->sh_size / section->sh_entsize; 284560484Sobrien dynamic_symbols = 284660484Sobrien GET_ELF_SYMBOLS (file, section->sh_offset, num_dynamic_syms); 284760484Sobrien } 284860484Sobrien else if (section->sh_type == SHT_STRTAB 284960484Sobrien && strcmp (name, ".dynstr") == 0) 285060484Sobrien { 285160484Sobrien if (dynamic_strings != NULL) 285260484Sobrien { 285360484Sobrien error (_("File contains multiple dynamic string tables\n")); 285460484Sobrien continue; 285560484Sobrien } 285660484Sobrien 285760484Sobrien GET_DATA_ALLOC (section->sh_offset, section->sh_size, 285860484Sobrien dynamic_strings, char *, "dynamic strings"); 285960484Sobrien } 286060484Sobrien else if ((do_debugging || do_debug_info || do_debug_abbrevs 286178828Sobrien || do_debug_lines || do_debug_pubnames || do_debug_aranges 286278828Sobrien || do_debug_frames) 286360484Sobrien && strncmp (name, ".debug_", 7) == 0) 286460484Sobrien { 286560484Sobrien name += 7; 286660484Sobrien 286760484Sobrien if (do_debugging 286860484Sobrien || (do_debug_info && (strcmp (name, "info") == 0)) 286960484Sobrien || (do_debug_abbrevs && (strcmp (name, "abbrev") == 0)) 287060484Sobrien || (do_debug_lines && (strcmp (name, "line") == 0)) 287160484Sobrien || (do_debug_pubnames && (strcmp (name, "pubnames") == 0)) 287260484Sobrien || (do_debug_aranges && (strcmp (name, "aranges") == 0)) 287377298Sobrien || (do_debug_frames && (strcmp (name, "frame") == 0)) 287460484Sobrien ) 287560484Sobrien request_dump (i, DEBUG_DUMP); 287660484Sobrien } 287777298Sobrien /* linkonce section to be combined with .debug_info at link time. */ 287877298Sobrien else if ((do_debugging || do_debug_info) 287977298Sobrien && strncmp (name, ".gnu.linkonce.wi.", 17) == 0) 288077298Sobrien request_dump (i, DEBUG_DUMP); 288177298Sobrien else if (do_debug_frames && strcmp (name, ".eh_frame") == 0) 288277298Sobrien request_dump (i, DEBUG_DUMP); 288360484Sobrien } 288460484Sobrien 288560484Sobrien if (! do_sections) 288660484Sobrien return 1; 288760484Sobrien 288860484Sobrien printf (_("\nSection Header%s:\n"), elf_header.e_shnum > 1 ? "s" : ""); 288977298Sobrien 289060484Sobrien if (is_32bit_elf) 289160484Sobrien printf 289260484Sobrien (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n")); 289360484Sobrien else 289460484Sobrien { 289560484Sobrien printf (_(" [Nr] Name Type Address Offset\n")); 289660484Sobrien printf (_(" Size EntSize Flags Link Info Align\n")); 289760484Sobrien } 289860484Sobrien 289960484Sobrien for (i = 0, section = section_headers; 290060484Sobrien i < elf_header.e_shnum; 290160484Sobrien i ++, section ++) 290260484Sobrien { 290360484Sobrien printf (" [%2d] %-17.17s %-15.15s ", 290460484Sobrien i, 290560484Sobrien SECTION_NAME (section), 290660484Sobrien get_section_type_name (section->sh_type)); 290760484Sobrien 290860484Sobrien if (is_32bit_elf) 290960484Sobrien { 291060484Sobrien print_vma (section->sh_addr, LONG_HEX); 291177298Sobrien 291260484Sobrien printf ( " %6.6lx %6.6lx %2.2lx", 291360484Sobrien (unsigned long) section->sh_offset, 291460484Sobrien (unsigned long) section->sh_size, 291560484Sobrien (unsigned long) section->sh_entsize); 291660484Sobrien 291760484Sobrien printf (" %3s ", get_elf_section_flags (section->sh_flags)); 291877298Sobrien 291977298Sobrien printf ("%2ld %3lx %2ld\n", 292060484Sobrien (unsigned long) section->sh_link, 292160484Sobrien (unsigned long) section->sh_info, 292260484Sobrien (unsigned long) section->sh_addralign); 292360484Sobrien } 292460484Sobrien else 292560484Sobrien { 292660484Sobrien putchar (' '); 292760484Sobrien print_vma (section->sh_addr, LONG_HEX); 292860484Sobrien printf (" %8.8lx", section->sh_offset); 292960484Sobrien printf ("\n "); 293060484Sobrien print_vma (section->sh_size, LONG_HEX); 293160484Sobrien printf (" "); 293260484Sobrien print_vma (section->sh_entsize, LONG_HEX); 293377298Sobrien 293460484Sobrien printf (" %3s ", get_elf_section_flags (section->sh_flags)); 293577298Sobrien 293660484Sobrien printf (" %2ld %3lx %ld\n", 293760484Sobrien (unsigned long) section->sh_link, 293860484Sobrien (unsigned long) section->sh_info, 293960484Sobrien (unsigned long) section->sh_addralign); 294060484Sobrien } 294160484Sobrien } 294260484Sobrien 294377298Sobrien printf (_("Key to Flags:\n")); 294477298Sobrien printf (_(" W (write), A (alloc), X (execute), M (merge), S (strings)\n")); 294577298Sobrien printf (_(" I (info), L (link order), G (group), x (unknown)\n")); 294677298Sobrien printf (_(" O (extra OS processing required) o (OS specific), p (processor specific)\n")); 294760484Sobrien 294860484Sobrien return 1; 294960484Sobrien} 295060484Sobrien 295160484Sobrien/* Process the reloc section. */ 295260484Sobrienstatic int 295360484Sobrienprocess_relocs (file) 295460484Sobrien FILE * file; 295560484Sobrien{ 295660484Sobrien unsigned long rel_size; 295760484Sobrien unsigned long rel_offset; 295860484Sobrien 295960484Sobrien 296060484Sobrien if (!do_reloc) 296160484Sobrien return 1; 296260484Sobrien 296360484Sobrien if (do_using_dynamic) 296460484Sobrien { 296560484Sobrien int is_rela = FALSE; 296660484Sobrien 296760484Sobrien rel_size = 0; 296860484Sobrien rel_offset = 0; 296960484Sobrien 297060484Sobrien if (dynamic_info[DT_REL]) 297160484Sobrien { 297260484Sobrien rel_offset = dynamic_info[DT_REL]; 297360484Sobrien rel_size = dynamic_info[DT_RELSZ]; 297460484Sobrien is_rela = FALSE; 297560484Sobrien } 297660484Sobrien else if (dynamic_info [DT_RELA]) 297760484Sobrien { 297860484Sobrien rel_offset = dynamic_info[DT_RELA]; 297960484Sobrien rel_size = dynamic_info[DT_RELASZ]; 298060484Sobrien is_rela = TRUE; 298160484Sobrien } 298260484Sobrien else if (dynamic_info[DT_JMPREL]) 298360484Sobrien { 298460484Sobrien rel_offset = dynamic_info[DT_JMPREL]; 298560484Sobrien rel_size = dynamic_info[DT_PLTRELSZ]; 298660484Sobrien 298760484Sobrien switch (dynamic_info[DT_PLTREL]) 298860484Sobrien { 298960484Sobrien case DT_REL: 299060484Sobrien is_rela = FALSE; 299160484Sobrien break; 299260484Sobrien case DT_RELA: 299360484Sobrien is_rela = TRUE; 299460484Sobrien break; 299560484Sobrien default: 299660484Sobrien is_rela = UNKNOWN; 299760484Sobrien break; 299860484Sobrien } 299960484Sobrien } 300060484Sobrien 300160484Sobrien if (rel_size) 300260484Sobrien { 300360484Sobrien printf 300460484Sobrien (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"), 300560484Sobrien rel_offset, rel_size); 300660484Sobrien 300760484Sobrien dump_relocations (file, rel_offset - loadaddr, rel_size, 300860484Sobrien dynamic_symbols, num_dynamic_syms, dynamic_strings, is_rela); 300960484Sobrien } 301060484Sobrien else 301160484Sobrien printf (_("\nThere are no dynamic relocations in this file.\n")); 301260484Sobrien } 301360484Sobrien else 301460484Sobrien { 301560484Sobrien Elf32_Internal_Shdr * section; 301678828Sobrien unsigned long i; 301778828Sobrien int found = 0; 301860484Sobrien 301960484Sobrien for (i = 0, section = section_headers; 302060484Sobrien i < elf_header.e_shnum; 302160484Sobrien i++, section ++) 302260484Sobrien { 302360484Sobrien if ( section->sh_type != SHT_RELA 302460484Sobrien && section->sh_type != SHT_REL) 302560484Sobrien continue; 302660484Sobrien 302760484Sobrien rel_offset = section->sh_offset; 302860484Sobrien rel_size = section->sh_size; 302960484Sobrien 303060484Sobrien if (rel_size) 303160484Sobrien { 303260484Sobrien Elf32_Internal_Shdr * strsec; 303360484Sobrien Elf32_Internal_Shdr * symsec; 303460484Sobrien Elf_Internal_Sym * symtab; 303560484Sobrien char * strtab; 303660484Sobrien int is_rela; 303760484Sobrien unsigned long nsyms; 303860484Sobrien 303960484Sobrien printf (_("\nRelocation section ")); 304060484Sobrien 304160484Sobrien if (string_table == NULL) 304260484Sobrien printf ("%d", section->sh_name); 304360484Sobrien else 304460484Sobrien printf ("'%s'", SECTION_NAME (section)); 304560484Sobrien 304660484Sobrien printf (_(" at offset 0x%lx contains %lu entries:\n"), 304760484Sobrien rel_offset, (unsigned long) (rel_size / section->sh_entsize)); 304860484Sobrien 304960484Sobrien symsec = section_headers + section->sh_link; 305060484Sobrien 305160484Sobrien nsyms = symsec->sh_size / symsec->sh_entsize; 305260484Sobrien symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms); 305360484Sobrien 305460484Sobrien if (symtab == NULL) 305560484Sobrien continue; 305660484Sobrien 305760484Sobrien strsec = section_headers + symsec->sh_link; 305860484Sobrien 305960484Sobrien GET_DATA_ALLOC (strsec->sh_offset, strsec->sh_size, strtab, 306060484Sobrien char *, "string table"); 306160484Sobrien 306260484Sobrien is_rela = section->sh_type == SHT_RELA; 306360484Sobrien 306460484Sobrien dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela); 306560484Sobrien 306660484Sobrien free (strtab); 306760484Sobrien free (symtab); 306860484Sobrien 306960484Sobrien found = 1; 307060484Sobrien } 307160484Sobrien } 307260484Sobrien 307360484Sobrien if (! found) 307460484Sobrien printf (_("\nThere are no relocations in this file.\n")); 307560484Sobrien } 307660484Sobrien 307760484Sobrien return 1; 307860484Sobrien} 307960484Sobrien 308078828Sobrien#include "unwind-ia64.h" 308160484Sobrien 308278828Sobrien/* An absolute address consists of a section and an offset. If the 308378828Sobrien section is NULL, the offset itself is the address, otherwise, the 308478828Sobrien address equals to LOAD_ADDRESS(section) + offset. */ 308578828Sobrien 308678828Sobrienstruct absaddr 308778828Sobrien { 308878828Sobrien unsigned short section; 308978828Sobrien bfd_vma offset; 309078828Sobrien }; 309178828Sobrien 309278828Sobrienstruct unw_aux_info 309378828Sobrien { 309478828Sobrien struct unw_table_entry 309578828Sobrien { 309678828Sobrien struct absaddr start; 309778828Sobrien struct absaddr end; 309878828Sobrien struct absaddr info; 309978828Sobrien } 310078828Sobrien *table; /* Unwind table. */ 310178828Sobrien unsigned long table_len; /* Length of unwind table. */ 310278828Sobrien unsigned char * info; /* Unwind info. */ 310378828Sobrien unsigned long info_size; /* Size of unwind info. */ 310478828Sobrien bfd_vma info_addr; /* starting address of unwind info. */ 310578828Sobrien bfd_vma seg_base; /* Starting address of segment. */ 310678828Sobrien Elf_Internal_Sym * symtab; /* The symbol table. */ 310778828Sobrien unsigned long nsyms; /* Number of symbols. */ 310878828Sobrien char * strtab; /* The string table. */ 310978828Sobrien unsigned long strtab_size; /* Size of string table. */ 311078828Sobrien }; 311178828Sobrien 311278828Sobrienstatic void find_symbol_for_address PARAMS ((struct unw_aux_info *, 311378828Sobrien struct absaddr, const char **, 311478828Sobrien bfd_vma *)); 311578828Sobrienstatic void dump_ia64_unwind PARAMS ((struct unw_aux_info *)); 311678828Sobrienstatic int slurp_ia64_unwind_table PARAMS ((FILE *, struct unw_aux_info *, 311778828Sobrien Elf32_Internal_Shdr *)); 311878828Sobrien 311960484Sobrienstatic void 312078828Sobrienfind_symbol_for_address (aux, addr, symname, offset) 312178828Sobrien struct unw_aux_info *aux; 312278828Sobrien struct absaddr addr; 312378828Sobrien const char **symname; 312478828Sobrien bfd_vma *offset; 312578828Sobrien{ 312678828Sobrien bfd_vma dist = (bfd_vma) 0x100000; 312778828Sobrien Elf_Internal_Sym *sym, *best = NULL; 312878828Sobrien unsigned long i; 312978828Sobrien 313078828Sobrien for (i = 0, sym = aux->symtab; i < aux->nsyms; ++i, ++sym) 313178828Sobrien { 313278828Sobrien if (ELF_ST_TYPE (sym->st_info) == STT_FUNC 313378828Sobrien && sym->st_name != 0 313478828Sobrien && (addr.section == SHN_UNDEF || addr.section == sym->st_shndx) 313578828Sobrien && addr.offset >= sym->st_value 313678828Sobrien && addr.offset - sym->st_value < dist) 313778828Sobrien { 313878828Sobrien best = sym; 313978828Sobrien dist = addr.offset - sym->st_value; 314078828Sobrien if (!dist) 314178828Sobrien break; 314278828Sobrien } 314378828Sobrien } 314478828Sobrien if (best) 314578828Sobrien { 314678828Sobrien *symname = (best->st_name >= aux->strtab_size 314778828Sobrien ? "<corrupt>" : aux->strtab + best->st_name); 314878828Sobrien *offset = dist; 314978828Sobrien return; 315078828Sobrien } 315178828Sobrien *symname = NULL; 315278828Sobrien *offset = addr.offset; 315378828Sobrien} 315478828Sobrien 315578828Sobrienstatic void 315678828Sobriendump_ia64_unwind (aux) 315778828Sobrien struct unw_aux_info *aux; 315878828Sobrien{ 315978828Sobrien bfd_vma addr_size; 316078828Sobrien struct unw_table_entry * tp; 316178828Sobrien int in_body; 316278828Sobrien 316378828Sobrien addr_size = is_32bit_elf ? 4 : 8; 316478828Sobrien 316578828Sobrien for (tp = aux->table; tp < aux->table + aux->table_len; ++tp) 316678828Sobrien { 316778828Sobrien bfd_vma stamp; 316878828Sobrien bfd_vma offset; 316978828Sobrien const unsigned char * dp; 317078828Sobrien const unsigned char * head; 317178828Sobrien const char * procname; 317278828Sobrien 317378828Sobrien find_symbol_for_address (aux, tp->start, &procname, &offset); 317478828Sobrien 317578828Sobrien fputs ("\n<", stdout); 317678828Sobrien 317778828Sobrien if (procname) 317878828Sobrien { 317978828Sobrien fputs (procname, stdout); 318078828Sobrien 318178828Sobrien if (offset) 318278828Sobrien printf ("+%lx", (unsigned long) offset); 318378828Sobrien } 318478828Sobrien 318578828Sobrien fputs (">: [", stdout); 318678828Sobrien print_vma (tp->start.offset, PREFIX_HEX); 318778828Sobrien fputc ('-', stdout); 318878828Sobrien print_vma (tp->end.offset, PREFIX_HEX); 318978828Sobrien printf ("), info at +0x%lx\n", 319078828Sobrien (unsigned long) (tp->info.offset - aux->seg_base)); 319178828Sobrien 319278828Sobrien head = aux->info + (tp->info.offset - aux->info_addr); 319378828Sobrien stamp = BYTE_GET8 ((unsigned char *) head); 319478828Sobrien 319578828Sobrien printf (" v%u, flags=0x%lx (%s%s ), len=%lu bytes\n", 319678828Sobrien (unsigned) UNW_VER (stamp), 319778828Sobrien (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32), 319878828Sobrien UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "", 319978828Sobrien UNW_FLAG_UHANDLER (stamp) ? " uhandler" : "", 320078828Sobrien (unsigned long) (addr_size * UNW_LENGTH (stamp))); 320178828Sobrien 320278828Sobrien if (UNW_VER (stamp) != 1) 320378828Sobrien { 320478828Sobrien printf ("\tUnknown version.\n"); 320578828Sobrien continue; 320678828Sobrien } 320778828Sobrien 320878828Sobrien in_body = 0; 320978828Sobrien for (dp = head + 8; dp < head + 8 + addr_size * UNW_LENGTH (stamp);) 321078828Sobrien dp = unw_decode (dp, in_body, & in_body); 321178828Sobrien } 321278828Sobrien} 321378828Sobrien 321478828Sobrienstatic int 321578828Sobrienslurp_ia64_unwind_table (file, aux, sec) 321678828Sobrien FILE *file; 321778828Sobrien struct unw_aux_info *aux; 321878828Sobrien Elf32_Internal_Shdr *sec; 321978828Sobrien{ 322078828Sobrien unsigned long size, addr_size, nrelas, i; 322178828Sobrien Elf_Internal_Phdr *prog_hdrs, *seg; 322278828Sobrien struct unw_table_entry *tep; 322378828Sobrien Elf32_Internal_Shdr *relsec; 322478828Sobrien Elf_Internal_Rela *rela, *rp; 322578828Sobrien unsigned char *table, *tp; 322678828Sobrien Elf_Internal_Sym *sym; 322778828Sobrien const char *relname; 322878828Sobrien int result; 322978828Sobrien 323078828Sobrien addr_size = is_32bit_elf ? 4 : 8; 323178828Sobrien 323278828Sobrien /* First, find the starting address of the segment that includes 323378828Sobrien this section: */ 323478828Sobrien 323578828Sobrien if (elf_header.e_phnum) 323678828Sobrien { 323778828Sobrien prog_hdrs = (Elf_Internal_Phdr *) 323878828Sobrien xmalloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); 323978828Sobrien 324078828Sobrien if (is_32bit_elf) 324178828Sobrien result = get_32bit_program_headers (file, prog_hdrs); 324278828Sobrien else 324378828Sobrien result = get_64bit_program_headers (file, prog_hdrs); 324478828Sobrien 324578828Sobrien if (!result) 324678828Sobrien { 324778828Sobrien free (prog_hdrs); 324878828Sobrien return 0; 324978828Sobrien } 325078828Sobrien 325178828Sobrien for (seg = prog_hdrs; seg < prog_hdrs + elf_header.e_phnum; ++seg) 325278828Sobrien { 325378828Sobrien if (seg->p_type != PT_LOAD) 325478828Sobrien continue; 325578828Sobrien 325678828Sobrien if (sec->sh_addr >= seg->p_vaddr 325778828Sobrien && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz)) 325878828Sobrien { 325978828Sobrien aux->seg_base = seg->p_vaddr; 326078828Sobrien break; 326178828Sobrien } 326278828Sobrien } 326378828Sobrien 326478828Sobrien free (prog_hdrs); 326578828Sobrien } 326678828Sobrien 326778828Sobrien /* Second, build the unwind table from the contents of the unwind section: */ 326878828Sobrien size = sec->sh_size; 326978828Sobrien GET_DATA_ALLOC (sec->sh_offset, size, table, char *, "unwind table"); 327078828Sobrien 327178828Sobrien tep = aux->table = xmalloc (size / (3 * addr_size) * sizeof (aux->table[0])); 327278828Sobrien for (tp = table; tp < table + size; tp += 3 * addr_size, ++ tep) 327378828Sobrien { 327478828Sobrien tep->start.section = SHN_UNDEF; 327578828Sobrien tep->end.section = SHN_UNDEF; 327678828Sobrien tep->info.section = SHN_UNDEF; 327778828Sobrien if (is_32bit_elf) 327878828Sobrien { 327978828Sobrien tep->start.offset = byte_get ((unsigned char *) tp + 0, 4); 328078828Sobrien tep->end.offset = byte_get ((unsigned char *) tp + 4, 4); 328178828Sobrien tep->info.offset = byte_get ((unsigned char *) tp + 8, 4); 328278828Sobrien } 328378828Sobrien else 328478828Sobrien { 328578828Sobrien tep->start.offset = BYTE_GET8 ((unsigned char *) tp + 0); 328678828Sobrien tep->end.offset = BYTE_GET8 ((unsigned char *) tp + 8); 328778828Sobrien tep->info.offset = BYTE_GET8 ((unsigned char *) tp + 16); 328878828Sobrien } 328978828Sobrien tep->start.offset += aux->seg_base; 329078828Sobrien tep->end.offset += aux->seg_base; 329178828Sobrien tep->info.offset += aux->seg_base; 329278828Sobrien } 329378828Sobrien free (table); 329478828Sobrien 329578828Sobrien /* Third, apply any relocations to the unwind table: */ 329678828Sobrien 329778828Sobrien for (relsec = section_headers; 329878828Sobrien relsec < section_headers + elf_header.e_shnum; 329978828Sobrien ++relsec) 330078828Sobrien { 330178828Sobrien if (relsec->sh_type != SHT_RELA 330278828Sobrien || section_headers + relsec->sh_info != sec) 330378828Sobrien continue; 330478828Sobrien 330578828Sobrien if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size, 330678828Sobrien & rela, & nrelas)) 330778828Sobrien return 0; 330878828Sobrien 330978828Sobrien for (rp = rela; rp < rela + nrelas; ++rp) 331078828Sobrien { 331178828Sobrien if (is_32bit_elf) 331278828Sobrien { 331378828Sobrien relname = elf_ia64_reloc_type (ELF32_R_TYPE (rp->r_info)); 331478828Sobrien sym = aux->symtab + ELF32_R_SYM (rp->r_info); 331578828Sobrien 331678828Sobrien if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION) 331778828Sobrien { 331878828Sobrien warn (_("Skipping unexpected symbol type %u"), 331978828Sobrien ELF32_ST_TYPE (sym->st_info)); 332078828Sobrien continue; 332178828Sobrien } 332278828Sobrien } 332378828Sobrien else 332478828Sobrien { 332578828Sobrien relname = elf_ia64_reloc_type (ELF64_R_TYPE (rp->r_info)); 332678828Sobrien sym = aux->symtab + ELF64_R_SYM (rp->r_info); 332778828Sobrien 332878828Sobrien if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION) 332978828Sobrien { 333078828Sobrien warn (_("Skipping unexpected symbol type %u"), 333178828Sobrien ELF64_ST_TYPE (sym->st_info)); 333278828Sobrien continue; 333378828Sobrien } 333478828Sobrien } 333578828Sobrien 333678828Sobrien if (strncmp (relname, "R_IA64_SEGREL", 13) != 0) 333778828Sobrien { 333878828Sobrien warn (_("Skipping unexpected relocation type %s"), relname); 333978828Sobrien continue; 334078828Sobrien } 334178828Sobrien 334278828Sobrien i = rp->r_offset / (3 * addr_size); 334378828Sobrien 334478828Sobrien switch (rp->r_offset/addr_size % 3) 334578828Sobrien { 334678828Sobrien case 0: 334778828Sobrien aux->table[i].start.section = sym->st_shndx; 334878828Sobrien aux->table[i].start.offset += rp->r_addend; 334978828Sobrien break; 335078828Sobrien case 1: 335178828Sobrien aux->table[i].end.section = sym->st_shndx; 335278828Sobrien aux->table[i].end.offset += rp->r_addend; 335378828Sobrien break; 335478828Sobrien case 2: 335578828Sobrien aux->table[i].info.section = sym->st_shndx; 335678828Sobrien aux->table[i].info.offset += rp->r_addend; 335778828Sobrien break; 335878828Sobrien default: 335978828Sobrien break; 336078828Sobrien } 336178828Sobrien } 336278828Sobrien 336378828Sobrien free (rela); 336478828Sobrien } 336578828Sobrien 336678828Sobrien aux->table_len = size / (3 * addr_size); 336778828Sobrien return 1; 336878828Sobrien} 336978828Sobrien 337078828Sobrienstatic int 337178828Sobrienprocess_unwind (file) 337278828Sobrien FILE * file; 337378828Sobrien{ 337478828Sobrien Elf32_Internal_Shdr *sec, *unwsec = NULL, *strsec; 337578828Sobrien unsigned long i, addr_size, unwcount = 0, unwstart = 0; 337678828Sobrien struct unw_aux_info aux; 337778828Sobrien 337878828Sobrien if (!do_unwind) 337978828Sobrien return 1; 338078828Sobrien 338178828Sobrien if (elf_header.e_machine != EM_IA_64) 338278828Sobrien { 338378828Sobrien printf (_("\nThere are no unwind sections in this file.\n")); 338478828Sobrien return 1; 338578828Sobrien } 338678828Sobrien 338778828Sobrien memset (& aux, 0, sizeof (aux)); 338878828Sobrien 338978828Sobrien addr_size = is_32bit_elf ? 4 : 8; 339078828Sobrien 339178828Sobrien for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec) 339278828Sobrien { 339378828Sobrien if (sec->sh_type == SHT_SYMTAB) 339478828Sobrien { 339578828Sobrien aux.nsyms = sec->sh_size / sec->sh_entsize; 339678828Sobrien aux.symtab = GET_ELF_SYMBOLS (file, sec->sh_offset, aux.nsyms); 339778828Sobrien 339878828Sobrien strsec = section_headers + sec->sh_link; 339978828Sobrien aux.strtab_size = strsec->sh_size; 340078828Sobrien GET_DATA_ALLOC (strsec->sh_offset, aux.strtab_size, 340178828Sobrien aux.strtab, char *, "string table"); 340278828Sobrien } 340378828Sobrien else if (sec->sh_type == SHT_IA_64_UNWIND) 340478828Sobrien unwcount++; 340578828Sobrien } 340678828Sobrien 340778828Sobrien if (!unwcount) 340878828Sobrien printf (_("\nThere are no unwind sections in this file.\n")); 340978828Sobrien 341078828Sobrien while (unwcount-- > 0) 341178828Sobrien { 341278828Sobrien char *suffix; 341378828Sobrien size_t len, len2; 341478828Sobrien 341578828Sobrien for (i = unwstart, sec = section_headers + unwstart; 341678828Sobrien i < elf_header.e_shnum; ++i, ++sec) 341778828Sobrien if (sec->sh_type == SHT_IA_64_UNWIND) 341878828Sobrien { 341978828Sobrien unwsec = sec; 342078828Sobrien break; 342178828Sobrien } 342278828Sobrien 342378828Sobrien unwstart = i + 1; 342478828Sobrien len = sizeof (ELF_STRING_ia64_unwind_once) - 1; 342578828Sobrien 342678828Sobrien if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once, 342778828Sobrien len) == 0) 342878828Sobrien { 342978828Sobrien /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO */ 343078828Sobrien len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1; 343178828Sobrien suffix = SECTION_NAME (unwsec) + len; 343278828Sobrien for (i = 0, sec = section_headers; i < elf_header.e_shnum; 343378828Sobrien ++i, ++sec) 343478828Sobrien if (strncmp (SECTION_NAME (sec), 343578828Sobrien ELF_STRING_ia64_unwind_info_once, len2) == 0 343678828Sobrien && strcmp (SECTION_NAME (sec) + len2, suffix) == 0) 343778828Sobrien break; 343878828Sobrien } 343978828Sobrien else 344078828Sobrien { 344178828Sobrien /* .IA_64.unwindFOO -> .IA_64.unwind_infoFOO 344278828Sobrien .IA_64.unwind or BAR -> .IA_64.unwind_info */ 344378828Sobrien len = sizeof (ELF_STRING_ia64_unwind) - 1; 344478828Sobrien len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1; 344578828Sobrien suffix = ""; 344678828Sobrien if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind, 344778828Sobrien len) == 0) 344878828Sobrien suffix = SECTION_NAME (unwsec) + len; 344978828Sobrien for (i = 0, sec = section_headers; i < elf_header.e_shnum; 345078828Sobrien ++i, ++sec) 345178828Sobrien if (strncmp (SECTION_NAME (sec), 345278828Sobrien ELF_STRING_ia64_unwind_info, len2) == 0 345378828Sobrien && strcmp (SECTION_NAME (sec) + len2, suffix) == 0) 345478828Sobrien break; 345578828Sobrien } 345678828Sobrien 345778828Sobrien if (i == elf_header.e_shnum) 345878828Sobrien { 345978828Sobrien printf (_("\nCould not find unwind info section for ")); 346078828Sobrien 346178828Sobrien if (string_table == NULL) 346278828Sobrien printf ("%d", unwsec->sh_name); 346378828Sobrien else 346478828Sobrien printf ("'%s'", SECTION_NAME (unwsec)); 346578828Sobrien } 346678828Sobrien else 346778828Sobrien { 346878828Sobrien aux.info_size = sec->sh_size; 346978828Sobrien aux.info_addr = sec->sh_addr; 347078828Sobrien GET_DATA_ALLOC (sec->sh_offset, aux.info_size, aux.info, 347178828Sobrien char *, "unwind info"); 347278828Sobrien 347378828Sobrien printf (_("\nUnwind section ")); 347478828Sobrien 347578828Sobrien if (string_table == NULL) 347678828Sobrien printf ("%d", unwsec->sh_name); 347778828Sobrien else 347878828Sobrien printf ("'%s'", SECTION_NAME (unwsec)); 347978828Sobrien 348078828Sobrien printf (_(" at offset 0x%lx contains %lu entries:\n"), 348178828Sobrien unwsec->sh_offset, 348278828Sobrien (unsigned long) (unwsec->sh_size / (3 * addr_size))); 348378828Sobrien 348478828Sobrien (void) slurp_ia64_unwind_table (file, & aux, unwsec); 348578828Sobrien 348678828Sobrien if (aux.table_len > 0) 348778828Sobrien dump_ia64_unwind (& aux); 348878828Sobrien 348978828Sobrien if (aux.table) 349078828Sobrien free ((char *) aux.table); 349178828Sobrien if (aux.info) 349278828Sobrien free ((char *) aux.info); 349378828Sobrien aux.table = NULL; 349478828Sobrien aux.info = NULL; 349578828Sobrien } 349678828Sobrien } 349778828Sobrien 349878828Sobrien if (aux.symtab) 349978828Sobrien free (aux.symtab); 350078828Sobrien if (aux.strtab) 350178828Sobrien free ((char *) aux.strtab); 350278828Sobrien 350378828Sobrien return 1; 350478828Sobrien} 350578828Sobrien 350678828Sobrienstatic void 350760484Sobriendynamic_segment_mips_val (entry) 350860484Sobrien Elf_Internal_Dyn * entry; 350960484Sobrien{ 351060484Sobrien switch (entry->d_tag) 351160484Sobrien { 351260484Sobrien case DT_MIPS_FLAGS: 351360484Sobrien if (entry->d_un.d_val == 0) 351460484Sobrien printf ("NONE\n"); 351560484Sobrien else 351660484Sobrien { 351760484Sobrien static const char * opts[] = 351860484Sobrien { 351960484Sobrien "QUICKSTART", "NOTPOT", "NO_LIBRARY_REPLACEMENT", 352060484Sobrien "NO_MOVE", "SGI_ONLY", "GUARANTEE_INIT", "DELTA_C_PLUS_PLUS", 352160484Sobrien "GUARANTEE_START_INIT", "PIXIE", "DEFAULT_DELAY_LOAD", 352260484Sobrien "REQUICKSTART", "REQUICKSTARTED", "CORD", "NO_UNRES_UNDEF", 352360484Sobrien "RLD_ORDER_SAFE" 352460484Sobrien }; 352560484Sobrien unsigned int cnt; 352660484Sobrien int first = 1; 352760484Sobrien for (cnt = 0; cnt < NUM_ELEM (opts); ++ cnt) 352860484Sobrien if (entry->d_un.d_val & (1 << cnt)) 352960484Sobrien { 353060484Sobrien printf ("%s%s", first ? "" : " ", opts[cnt]); 353160484Sobrien first = 0; 353260484Sobrien } 353360484Sobrien puts (""); 353460484Sobrien } 353560484Sobrien break; 353660484Sobrien 353760484Sobrien case DT_MIPS_IVERSION: 353860484Sobrien if (dynamic_strings != NULL) 353960484Sobrien printf ("Interface Version: %s\n", 354060484Sobrien dynamic_strings + entry->d_un.d_val); 354160484Sobrien else 354260484Sobrien printf ("%ld\n", (long) entry->d_un.d_ptr); 354360484Sobrien break; 354460484Sobrien 354560484Sobrien case DT_MIPS_TIME_STAMP: 354660484Sobrien { 354760484Sobrien char timebuf[20]; 354860484Sobrien struct tm * tmp; 354960484Sobrien 355060484Sobrien time_t time = entry->d_un.d_val; 355160484Sobrien tmp = gmtime (&time); 355260484Sobrien sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u", 355360484Sobrien tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, 355460484Sobrien tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 355560484Sobrien printf ("Time Stamp: %s\n", timebuf); 355660484Sobrien } 355760484Sobrien break; 355860484Sobrien 355960484Sobrien case DT_MIPS_RLD_VERSION: 356060484Sobrien case DT_MIPS_LOCAL_GOTNO: 356160484Sobrien case DT_MIPS_CONFLICTNO: 356260484Sobrien case DT_MIPS_LIBLISTNO: 356360484Sobrien case DT_MIPS_SYMTABNO: 356460484Sobrien case DT_MIPS_UNREFEXTNO: 356560484Sobrien case DT_MIPS_HIPAGENO: 356660484Sobrien case DT_MIPS_DELTA_CLASS_NO: 356760484Sobrien case DT_MIPS_DELTA_INSTANCE_NO: 356860484Sobrien case DT_MIPS_DELTA_RELOC_NO: 356960484Sobrien case DT_MIPS_DELTA_SYM_NO: 357060484Sobrien case DT_MIPS_DELTA_CLASSSYM_NO: 357160484Sobrien case DT_MIPS_COMPACT_SIZE: 357260484Sobrien printf ("%ld\n", (long) entry->d_un.d_ptr); 357360484Sobrien break; 357460484Sobrien 357560484Sobrien default: 357660484Sobrien printf ("%#lx\n", (long) entry->d_un.d_ptr); 357760484Sobrien } 357860484Sobrien} 357960484Sobrien 358060484Sobrien 358160484Sobrienstatic void 358260484Sobriendynamic_segment_parisc_val (entry) 358360484Sobrien Elf_Internal_Dyn * entry; 358460484Sobrien{ 358560484Sobrien switch (entry->d_tag) 358660484Sobrien { 358760484Sobrien case DT_HP_DLD_FLAGS: 358860484Sobrien { 358960484Sobrien static struct 359060484Sobrien { 359160484Sobrien long int bit; 359260484Sobrien const char * str; 359360484Sobrien } 359460484Sobrien flags[] = 359560484Sobrien { 359660484Sobrien { DT_HP_DEBUG_PRIVATE, "HP_DEBUG_PRIVATE" }, 359760484Sobrien { DT_HP_DEBUG_CALLBACK, "HP_DEBUG_CALLBACK" }, 359860484Sobrien { DT_HP_DEBUG_CALLBACK_BOR, "HP_DEBUG_CALLBACK_BOR" }, 359960484Sobrien { DT_HP_NO_ENVVAR, "HP_NO_ENVVAR" }, 360060484Sobrien { DT_HP_BIND_NOW, "HP_BIND_NOW" }, 360160484Sobrien { DT_HP_BIND_NONFATAL, "HP_BIND_NONFATAL" }, 360260484Sobrien { DT_HP_BIND_VERBOSE, "HP_BIND_VERBOSE" }, 360360484Sobrien { DT_HP_BIND_RESTRICTED, "HP_BIND_RESTRICTED" }, 360460484Sobrien { DT_HP_BIND_SYMBOLIC, "HP_BIND_SYMBOLIC" }, 360560484Sobrien { DT_HP_RPATH_FIRST, "HP_RPATH_FIRST" }, 360660484Sobrien { DT_HP_BIND_DEPTH_FIRST, "HP_BIND_DEPTH_FIRST" } 360760484Sobrien }; 360860484Sobrien int first = 1; 360960484Sobrien size_t cnt; 361060484Sobrien bfd_vma val = entry->d_un.d_val; 361160484Sobrien 361260484Sobrien for (cnt = 0; cnt < sizeof (flags) / sizeof (flags[0]); ++cnt) 361360484Sobrien if (val & flags[cnt].bit) 361460484Sobrien { 361560484Sobrien if (! first) 361660484Sobrien putchar (' '); 361760484Sobrien fputs (flags[cnt].str, stdout); 361860484Sobrien first = 0; 361960484Sobrien val ^= flags[cnt].bit; 362060484Sobrien } 362177298Sobrien 362260484Sobrien if (val != 0 || first) 362360484Sobrien { 362460484Sobrien if (! first) 362560484Sobrien putchar (' '); 362660484Sobrien print_vma (val, HEX); 362760484Sobrien } 362860484Sobrien } 362960484Sobrien break; 363077298Sobrien 363160484Sobrien default: 363260484Sobrien print_vma (entry->d_un.d_ptr, PREFIX_HEX); 363360484Sobrien break; 363460484Sobrien } 363560484Sobrien} 363660484Sobrien 363760484Sobrienstatic int 363860484Sobrienget_32bit_dynamic_segment (file) 363960484Sobrien FILE * file; 364060484Sobrien{ 364160484Sobrien Elf32_External_Dyn * edyn; 364260484Sobrien Elf_Internal_Dyn * entry; 364360484Sobrien bfd_size_type i; 364460484Sobrien 364560484Sobrien GET_DATA_ALLOC (dynamic_addr, dynamic_size, 364660484Sobrien edyn, Elf32_External_Dyn *, "dynamic segment"); 364760484Sobrien 364860484Sobrien /* SGI's ELF has more than one section in the DYNAMIC segment. Determine 364960484Sobrien how large this .dynamic is now. We can do this even before the byte 365060484Sobrien swapping since the DT_NULL tag is recognizable. */ 365160484Sobrien dynamic_size = 0; 365260484Sobrien while (*(Elf32_Word *) edyn [dynamic_size++].d_tag != DT_NULL) 365360484Sobrien ; 365460484Sobrien 365560484Sobrien dynamic_segment = (Elf_Internal_Dyn *) 365660484Sobrien malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); 365760484Sobrien 365860484Sobrien if (dynamic_segment == NULL) 365960484Sobrien { 366060484Sobrien error (_("Out of memory\n")); 366160484Sobrien free (edyn); 366260484Sobrien return 0; 366360484Sobrien } 366460484Sobrien 366560484Sobrien for (i = 0, entry = dynamic_segment; 366660484Sobrien i < dynamic_size; 366760484Sobrien i ++, entry ++) 366860484Sobrien { 366960484Sobrien entry->d_tag = BYTE_GET (edyn [i].d_tag); 367060484Sobrien entry->d_un.d_val = BYTE_GET (edyn [i].d_un.d_val); 367160484Sobrien } 367260484Sobrien 367360484Sobrien free (edyn); 367460484Sobrien 367560484Sobrien return 1; 367660484Sobrien} 367760484Sobrien 367860484Sobrienstatic int 367960484Sobrienget_64bit_dynamic_segment (file) 368060484Sobrien FILE * file; 368160484Sobrien{ 368260484Sobrien Elf64_External_Dyn * edyn; 368360484Sobrien Elf_Internal_Dyn * entry; 368460484Sobrien bfd_size_type i; 368560484Sobrien 368660484Sobrien GET_DATA_ALLOC (dynamic_addr, dynamic_size, 368760484Sobrien edyn, Elf64_External_Dyn *, "dynamic segment"); 368860484Sobrien 368960484Sobrien /* SGI's ELF has more than one section in the DYNAMIC segment. Determine 369060484Sobrien how large this .dynamic is now. We can do this even before the byte 369160484Sobrien swapping since the DT_NULL tag is recognizable. */ 369260484Sobrien dynamic_size = 0; 369360484Sobrien while (*(bfd_vma *) edyn [dynamic_size ++].d_tag != DT_NULL) 369460484Sobrien ; 369560484Sobrien 369660484Sobrien dynamic_segment = (Elf_Internal_Dyn *) 369760484Sobrien malloc (dynamic_size * sizeof (Elf_Internal_Dyn)); 369860484Sobrien 369960484Sobrien if (dynamic_segment == NULL) 370060484Sobrien { 370160484Sobrien error (_("Out of memory\n")); 370260484Sobrien free (edyn); 370360484Sobrien return 0; 370460484Sobrien } 370560484Sobrien 370660484Sobrien for (i = 0, entry = dynamic_segment; 370760484Sobrien i < dynamic_size; 370860484Sobrien i ++, entry ++) 370960484Sobrien { 371060484Sobrien entry->d_tag = BYTE_GET8 (edyn [i].d_tag); 371160484Sobrien entry->d_un.d_val = BYTE_GET8 (edyn [i].d_un.d_val); 371260484Sobrien } 371360484Sobrien 371460484Sobrien free (edyn); 371560484Sobrien 371660484Sobrien return 1; 371760484Sobrien} 371860484Sobrien 371960484Sobrienstatic const char * 372060484Sobrienget_dynamic_flags (flags) 372160484Sobrien bfd_vma flags; 372260484Sobrien{ 372360484Sobrien static char buff [64]; 372460484Sobrien while (flags) 372560484Sobrien { 372660484Sobrien bfd_vma flag; 372760484Sobrien 372860484Sobrien flag = flags & - flags; 372960484Sobrien flags &= ~ flag; 373060484Sobrien 373160484Sobrien switch (flag) 373260484Sobrien { 373360484Sobrien case DF_ORIGIN: strcat (buff, "ORIGIN "); break; 373460484Sobrien case DF_SYMBOLIC: strcat (buff, "SYMBOLIC "); break; 373560484Sobrien case DF_TEXTREL: strcat (buff, "TEXTREL "); break; 373660484Sobrien case DF_BIND_NOW: strcat (buff, "BIND_NOW "); break; 373760484Sobrien default: strcat (buff, "unknown "); break; 373860484Sobrien } 373960484Sobrien } 374060484Sobrien return buff; 374160484Sobrien} 374260484Sobrien 374360484Sobrien/* Parse and display the contents of the dynamic segment. */ 374460484Sobrienstatic int 374560484Sobrienprocess_dynamic_segment (file) 374660484Sobrien FILE * file; 374760484Sobrien{ 374860484Sobrien Elf_Internal_Dyn * entry; 374960484Sobrien bfd_size_type i; 375060484Sobrien 375160484Sobrien if (dynamic_size == 0) 375260484Sobrien { 375360484Sobrien if (do_dynamic) 375460484Sobrien printf (_("\nThere is no dynamic segment in this file.\n")); 375560484Sobrien 375660484Sobrien return 1; 375760484Sobrien } 375860484Sobrien 375960484Sobrien if (is_32bit_elf) 376060484Sobrien { 376160484Sobrien if (! get_32bit_dynamic_segment (file)) 376260484Sobrien return 0; 376360484Sobrien } 376460484Sobrien else if (! get_64bit_dynamic_segment (file)) 376560484Sobrien return 0; 376660484Sobrien 376760484Sobrien /* Find the appropriate symbol table. */ 376860484Sobrien if (dynamic_symbols == NULL) 376960484Sobrien { 377060484Sobrien for (i = 0, entry = dynamic_segment; 377160484Sobrien i < dynamic_size; 377260484Sobrien ++i, ++ entry) 377360484Sobrien { 377460484Sobrien unsigned long offset; 377560484Sobrien 377660484Sobrien if (entry->d_tag != DT_SYMTAB) 377760484Sobrien continue; 377860484Sobrien 377960484Sobrien dynamic_info[DT_SYMTAB] = entry->d_un.d_val; 378060484Sobrien 378160484Sobrien /* Since we do not know how big the symbol table is, 378260484Sobrien we default to reading in the entire file (!) and 378360484Sobrien processing that. This is overkill, I know, but it 378460484Sobrien should work. */ 378560484Sobrien offset = entry->d_un.d_val - loadaddr; 378660484Sobrien 378760484Sobrien if (fseek (file, 0, SEEK_END)) 378860484Sobrien error (_("Unable to seek to end of file!")); 378960484Sobrien 379060484Sobrien if (is_32bit_elf) 379160484Sobrien num_dynamic_syms = (ftell (file) - offset) / sizeof (Elf32_External_Sym); 379260484Sobrien else 379360484Sobrien num_dynamic_syms = (ftell (file) - offset) / sizeof (Elf64_External_Sym); 379460484Sobrien 379560484Sobrien if (num_dynamic_syms < 1) 379660484Sobrien { 379760484Sobrien error (_("Unable to determine the number of symbols to load\n")); 379860484Sobrien continue; 379960484Sobrien } 380060484Sobrien 380160484Sobrien dynamic_symbols = GET_ELF_SYMBOLS (file, offset, num_dynamic_syms); 380260484Sobrien } 380360484Sobrien } 380460484Sobrien 380560484Sobrien /* Similarly find a string table. */ 380660484Sobrien if (dynamic_strings == NULL) 380760484Sobrien { 380860484Sobrien for (i = 0, entry = dynamic_segment; 380960484Sobrien i < dynamic_size; 381060484Sobrien ++i, ++ entry) 381160484Sobrien { 381260484Sobrien unsigned long offset; 381360484Sobrien long str_tab_len; 381460484Sobrien 381560484Sobrien if (entry->d_tag != DT_STRTAB) 381660484Sobrien continue; 381760484Sobrien 381860484Sobrien dynamic_info[DT_STRTAB] = entry->d_un.d_val; 381960484Sobrien 382060484Sobrien /* Since we do not know how big the string table is, 382160484Sobrien we default to reading in the entire file (!) and 382260484Sobrien processing that. This is overkill, I know, but it 382360484Sobrien should work. */ 382460484Sobrien 382560484Sobrien offset = entry->d_un.d_val - loadaddr; 382660484Sobrien if (fseek (file, 0, SEEK_END)) 382760484Sobrien error (_("Unable to seek to end of file\n")); 382860484Sobrien str_tab_len = ftell (file) - offset; 382960484Sobrien 383060484Sobrien if (str_tab_len < 1) 383160484Sobrien { 383260484Sobrien error 383360484Sobrien (_("Unable to determine the length of the dynamic string table\n")); 383460484Sobrien continue; 383560484Sobrien } 383660484Sobrien 383760484Sobrien GET_DATA_ALLOC (offset, str_tab_len, dynamic_strings, char *, 383860484Sobrien "dynamic string table"); 383960484Sobrien 384060484Sobrien break; 384160484Sobrien } 384260484Sobrien } 384360484Sobrien 384460484Sobrien /* And find the syminfo section if available. */ 384560484Sobrien if (dynamic_syminfo == NULL) 384660484Sobrien { 384760484Sobrien unsigned int syminsz = 0; 384860484Sobrien 384960484Sobrien for (i = 0, entry = dynamic_segment; 385060484Sobrien i < dynamic_size; 385160484Sobrien ++i, ++ entry) 385260484Sobrien { 385360484Sobrien if (entry->d_tag == DT_SYMINENT) 385460484Sobrien { 385560484Sobrien /* Note: these braces are necessary to avoid a syntax 385660484Sobrien error from the SunOS4 C compiler. */ 385760484Sobrien assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val); 385860484Sobrien } 385960484Sobrien else if (entry->d_tag == DT_SYMINSZ) 386060484Sobrien syminsz = entry->d_un.d_val; 386160484Sobrien else if (entry->d_tag == DT_SYMINFO) 386260484Sobrien dynamic_syminfo_offset = entry->d_un.d_val - loadaddr; 386360484Sobrien } 386460484Sobrien 386560484Sobrien if (dynamic_syminfo_offset != 0 && syminsz != 0) 386660484Sobrien { 386760484Sobrien Elf_External_Syminfo * extsyminfo; 386860484Sobrien Elf_Internal_Syminfo * syminfo; 386960484Sobrien 387060484Sobrien /* There is a syminfo section. Read the data. */ 387160484Sobrien GET_DATA_ALLOC (dynamic_syminfo_offset, syminsz, extsyminfo, 387260484Sobrien Elf_External_Syminfo *, "symbol information"); 387360484Sobrien 387460484Sobrien dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz); 387560484Sobrien if (dynamic_syminfo == NULL) 387660484Sobrien { 387760484Sobrien error (_("Out of memory\n")); 387860484Sobrien return 0; 387960484Sobrien } 388060484Sobrien 388160484Sobrien dynamic_syminfo_nent = syminsz / sizeof (Elf_External_Syminfo); 388260484Sobrien for (i = 0, syminfo = dynamic_syminfo; i < dynamic_syminfo_nent; 388360484Sobrien ++i, ++syminfo) 388460484Sobrien { 388560484Sobrien syminfo->si_boundto = BYTE_GET (extsyminfo[i].si_boundto); 388660484Sobrien syminfo->si_flags = BYTE_GET (extsyminfo[i].si_flags); 388760484Sobrien } 388860484Sobrien 388960484Sobrien free (extsyminfo); 389060484Sobrien } 389160484Sobrien } 389260484Sobrien 389360484Sobrien if (do_dynamic && dynamic_addr) 389460484Sobrien printf (_("\nDynamic segment at offset 0x%x contains %ld entries:\n"), 389560484Sobrien dynamic_addr, (long) dynamic_size); 389660484Sobrien if (do_dynamic) 389760484Sobrien printf (_(" Tag Type Name/Value\n")); 389860484Sobrien 389960484Sobrien for (i = 0, entry = dynamic_segment; 390060484Sobrien i < dynamic_size; 390160484Sobrien i++, entry ++) 390260484Sobrien { 390360484Sobrien if (do_dynamic) 390460484Sobrien { 390577298Sobrien const char * dtype; 390660484Sobrien 390760484Sobrien putchar (' '); 390860484Sobrien print_vma (entry->d_tag, FULL_HEX); 390960484Sobrien dtype = get_dynamic_type (entry->d_tag); 391060484Sobrien printf (" (%s)%*s", dtype, 391160484Sobrien ((is_32bit_elf ? 27 : 19) 391260484Sobrien - (int) strlen (dtype)), 391360484Sobrien " "); 391460484Sobrien } 391560484Sobrien 391660484Sobrien switch (entry->d_tag) 391760484Sobrien { 391860484Sobrien case DT_FLAGS: 391960484Sobrien if (do_dynamic) 392060484Sobrien printf ("%s", get_dynamic_flags (entry->d_un.d_val)); 392160484Sobrien break; 392277298Sobrien 392360484Sobrien case DT_AUXILIARY: 392460484Sobrien case DT_FILTER: 392568765Sobrien case DT_CONFIG: 392668765Sobrien case DT_DEPAUDIT: 392768765Sobrien case DT_AUDIT: 392860484Sobrien if (do_dynamic) 392960484Sobrien { 393068765Sobrien switch (entry->d_tag) 393168765Sobrien { 393268765Sobrien case DT_AUXILIARY: 393368765Sobrien printf (_("Auxiliary library")); 393468765Sobrien break; 393560484Sobrien 393668765Sobrien case DT_FILTER: 393768765Sobrien printf (_("Filter library")); 393868765Sobrien break; 393968765Sobrien 394068765Sobrien case DT_CONFIG: 394168765Sobrien printf (_("Configuration file")); 394268765Sobrien break; 394368765Sobrien 394468765Sobrien case DT_DEPAUDIT: 394568765Sobrien printf (_("Dependency audit library")); 394668765Sobrien break; 394768765Sobrien 394868765Sobrien case DT_AUDIT: 394968765Sobrien printf (_("Audit library")); 395068765Sobrien break; 395168765Sobrien } 395268765Sobrien 395360484Sobrien if (dynamic_strings) 395460484Sobrien printf (": [%s]\n", dynamic_strings + entry->d_un.d_val); 395560484Sobrien else 395660484Sobrien { 395760484Sobrien printf (": "); 395860484Sobrien print_vma (entry->d_un.d_val, PREFIX_HEX); 395960484Sobrien putchar ('\n'); 396060484Sobrien } 396160484Sobrien } 396260484Sobrien break; 396360484Sobrien 396468765Sobrien case DT_FEATURE: 396560484Sobrien if (do_dynamic) 396660484Sobrien { 396760484Sobrien printf (_("Flags:")); 396860484Sobrien if (entry->d_un.d_val == 0) 396960484Sobrien printf (_(" None\n")); 397060484Sobrien else 397160484Sobrien { 397260484Sobrien unsigned long int val = entry->d_un.d_val; 397360484Sobrien if (val & DTF_1_PARINIT) 397460484Sobrien { 397560484Sobrien printf (" PARINIT"); 397660484Sobrien val ^= DTF_1_PARINIT; 397760484Sobrien } 397868765Sobrien if (val & DTF_1_CONFEXP) 397968765Sobrien { 398068765Sobrien printf (" CONFEXP"); 398168765Sobrien val ^= DTF_1_CONFEXP; 398268765Sobrien } 398360484Sobrien if (val != 0) 398460484Sobrien printf (" %lx", val); 398560484Sobrien puts (""); 398660484Sobrien } 398760484Sobrien } 398860484Sobrien break; 398960484Sobrien 399060484Sobrien case DT_POSFLAG_1: 399160484Sobrien if (do_dynamic) 399260484Sobrien { 399360484Sobrien printf (_("Flags:")); 399460484Sobrien if (entry->d_un.d_val == 0) 399560484Sobrien printf (_(" None\n")); 399660484Sobrien else 399760484Sobrien { 399860484Sobrien unsigned long int val = entry->d_un.d_val; 399960484Sobrien if (val & DF_P1_LAZYLOAD) 400060484Sobrien { 400160484Sobrien printf (" LAZYLOAD"); 400260484Sobrien val ^= DF_P1_LAZYLOAD; 400360484Sobrien } 400460484Sobrien if (val & DF_P1_GROUPPERM) 400560484Sobrien { 400660484Sobrien printf (" GROUPPERM"); 400760484Sobrien val ^= DF_P1_GROUPPERM; 400860484Sobrien } 400960484Sobrien if (val != 0) 401060484Sobrien printf (" %lx", val); 401160484Sobrien puts (""); 401260484Sobrien } 401360484Sobrien } 401460484Sobrien break; 401560484Sobrien 401660484Sobrien case DT_FLAGS_1: 401760484Sobrien if (do_dynamic) 401860484Sobrien { 401960484Sobrien printf (_("Flags:")); 402060484Sobrien if (entry->d_un.d_val == 0) 402160484Sobrien printf (_(" None\n")); 402260484Sobrien else 402360484Sobrien { 402460484Sobrien unsigned long int val = entry->d_un.d_val; 402560484Sobrien if (val & DF_1_NOW) 402660484Sobrien { 402760484Sobrien printf (" NOW"); 402860484Sobrien val ^= DF_1_NOW; 402960484Sobrien } 403060484Sobrien if (val & DF_1_GLOBAL) 403160484Sobrien { 403260484Sobrien printf (" GLOBAL"); 403360484Sobrien val ^= DF_1_GLOBAL; 403460484Sobrien } 403560484Sobrien if (val & DF_1_GROUP) 403660484Sobrien { 403760484Sobrien printf (" GROUP"); 403860484Sobrien val ^= DF_1_GROUP; 403960484Sobrien } 404060484Sobrien if (val & DF_1_NODELETE) 404160484Sobrien { 404260484Sobrien printf (" NODELETE"); 404360484Sobrien val ^= DF_1_NODELETE; 404460484Sobrien } 404560484Sobrien if (val & DF_1_LOADFLTR) 404660484Sobrien { 404760484Sobrien printf (" LOADFLTR"); 404860484Sobrien val ^= DF_1_LOADFLTR; 404960484Sobrien } 405060484Sobrien if (val & DF_1_INITFIRST) 405160484Sobrien { 405260484Sobrien printf (" INITFIRST"); 405360484Sobrien val ^= DF_1_INITFIRST; 405460484Sobrien } 405560484Sobrien if (val & DF_1_NOOPEN) 405660484Sobrien { 405760484Sobrien printf (" NOOPEN"); 405860484Sobrien val ^= DF_1_NOOPEN; 405960484Sobrien } 406060484Sobrien if (val & DF_1_ORIGIN) 406160484Sobrien { 406260484Sobrien printf (" ORIGIN"); 406360484Sobrien val ^= DF_1_ORIGIN; 406460484Sobrien } 406560484Sobrien if (val & DF_1_DIRECT) 406660484Sobrien { 406760484Sobrien printf (" DIRECT"); 406860484Sobrien val ^= DF_1_DIRECT; 406960484Sobrien } 407060484Sobrien if (val & DF_1_TRANS) 407160484Sobrien { 407260484Sobrien printf (" TRANS"); 407360484Sobrien val ^= DF_1_TRANS; 407460484Sobrien } 407560484Sobrien if (val & DF_1_INTERPOSE) 407660484Sobrien { 407760484Sobrien printf (" INTERPOSE"); 407860484Sobrien val ^= DF_1_INTERPOSE; 407960484Sobrien } 408068765Sobrien if (val & DF_1_NODEFLIB) 408168765Sobrien { 408268765Sobrien printf (" NODEFLIB"); 408368765Sobrien val ^= DF_1_NODEFLIB; 408468765Sobrien } 408568765Sobrien if (val & DF_1_NODUMP) 408668765Sobrien { 408768765Sobrien printf (" NODUMP"); 408868765Sobrien val ^= DF_1_NODUMP; 408968765Sobrien } 409068765Sobrien if (val & DF_1_CONLFAT) 409168765Sobrien { 409268765Sobrien printf (" CONLFAT"); 409368765Sobrien val ^= DF_1_CONLFAT; 409468765Sobrien } 409560484Sobrien if (val != 0) 409660484Sobrien printf (" %lx", val); 409760484Sobrien puts (""); 409860484Sobrien } 409960484Sobrien } 410060484Sobrien break; 410160484Sobrien 410260484Sobrien case DT_PLTREL: 410360484Sobrien if (do_dynamic) 410460484Sobrien puts (get_dynamic_type (entry->d_un.d_val)); 410560484Sobrien break; 410660484Sobrien 410760484Sobrien case DT_NULL : 410860484Sobrien case DT_NEEDED : 410960484Sobrien case DT_PLTGOT : 411060484Sobrien case DT_HASH : 411160484Sobrien case DT_STRTAB : 411260484Sobrien case DT_SYMTAB : 411360484Sobrien case DT_RELA : 411460484Sobrien case DT_INIT : 411560484Sobrien case DT_FINI : 411660484Sobrien case DT_SONAME : 411760484Sobrien case DT_RPATH : 411860484Sobrien case DT_SYMBOLIC: 411960484Sobrien case DT_REL : 412060484Sobrien case DT_DEBUG : 412160484Sobrien case DT_TEXTREL : 412260484Sobrien case DT_JMPREL : 412368765Sobrien case DT_RUNPATH : 412460484Sobrien dynamic_info[entry->d_tag] = entry->d_un.d_val; 412560484Sobrien 412660484Sobrien if (do_dynamic) 412760484Sobrien { 412860484Sobrien char * name; 412960484Sobrien 413060484Sobrien if (dynamic_strings == NULL) 413160484Sobrien name = NULL; 413260484Sobrien else 413360484Sobrien name = dynamic_strings + entry->d_un.d_val; 413460484Sobrien 413560484Sobrien if (name) 413660484Sobrien { 413760484Sobrien switch (entry->d_tag) 413860484Sobrien { 413960484Sobrien case DT_NEEDED: 414060484Sobrien printf (_("Shared library: [%s]"), name); 414160484Sobrien 414260484Sobrien if (strcmp (name, program_interpreter) == 0) 414360484Sobrien printf (_(" program interpreter")); 414460484Sobrien break; 414560484Sobrien 414660484Sobrien case DT_SONAME: 414760484Sobrien printf (_("Library soname: [%s]"), name); 414860484Sobrien break; 414960484Sobrien 415060484Sobrien case DT_RPATH: 415160484Sobrien printf (_("Library rpath: [%s]"), name); 415260484Sobrien break; 415360484Sobrien 415468765Sobrien case DT_RUNPATH: 415568765Sobrien printf (_("Library runpath: [%s]"), name); 415668765Sobrien break; 415768765Sobrien 415860484Sobrien default: 415960484Sobrien print_vma (entry->d_un.d_val, PREFIX_HEX); 416060484Sobrien break; 416160484Sobrien } 416260484Sobrien } 416360484Sobrien else 416460484Sobrien print_vma (entry->d_un.d_val, PREFIX_HEX); 416560484Sobrien 416660484Sobrien putchar ('\n'); 416760484Sobrien } 416860484Sobrien break; 416960484Sobrien 417060484Sobrien case DT_PLTRELSZ: 417160484Sobrien case DT_RELASZ : 417260484Sobrien case DT_STRSZ : 417360484Sobrien case DT_RELSZ : 417460484Sobrien case DT_RELAENT : 417560484Sobrien case DT_SYMENT : 417660484Sobrien case DT_RELENT : 417760484Sobrien case DT_PLTPADSZ: 417860484Sobrien case DT_MOVEENT : 417960484Sobrien case DT_MOVESZ : 418060484Sobrien case DT_INIT_ARRAYSZ: 418160484Sobrien case DT_FINI_ARRAYSZ: 418260484Sobrien if (do_dynamic) 418360484Sobrien { 418460484Sobrien print_vma (entry->d_un.d_val, UNSIGNED); 418560484Sobrien printf (" (bytes)\n"); 418660484Sobrien } 418760484Sobrien break; 418860484Sobrien 418960484Sobrien case DT_VERDEFNUM: 419060484Sobrien case DT_VERNEEDNUM: 419160484Sobrien case DT_RELACOUNT: 419260484Sobrien case DT_RELCOUNT: 419360484Sobrien if (do_dynamic) 419460484Sobrien { 419560484Sobrien print_vma (entry->d_un.d_val, UNSIGNED); 419660484Sobrien putchar ('\n'); 419760484Sobrien } 419860484Sobrien break; 419960484Sobrien 420060484Sobrien case DT_SYMINSZ: 420160484Sobrien case DT_SYMINENT: 420260484Sobrien case DT_SYMINFO: 420360484Sobrien case DT_USED: 420460484Sobrien case DT_INIT_ARRAY: 420560484Sobrien case DT_FINI_ARRAY: 420660484Sobrien if (do_dynamic) 420760484Sobrien { 420860484Sobrien if (dynamic_strings != NULL && entry->d_tag == DT_USED) 420960484Sobrien { 421060484Sobrien char * name; 421160484Sobrien 421260484Sobrien name = dynamic_strings + entry->d_un.d_val; 421360484Sobrien 421460484Sobrien if (* name) 421560484Sobrien { 421660484Sobrien printf (_("Not needed object: [%s]\n"), name); 421760484Sobrien break; 421860484Sobrien } 421960484Sobrien } 422060484Sobrien 422160484Sobrien print_vma (entry->d_un.d_val, PREFIX_HEX); 422260484Sobrien putchar ('\n'); 422360484Sobrien } 422460484Sobrien break; 422560484Sobrien 422660484Sobrien case DT_BIND_NOW: 422760484Sobrien /* The value of this entry is ignored. */ 422860484Sobrien break; 422960484Sobrien 423060484Sobrien default: 423160484Sobrien if ((entry->d_tag >= DT_VERSYM) && (entry->d_tag <= DT_VERNEEDNUM)) 423260484Sobrien version_info [DT_VERSIONTAGIDX (entry->d_tag)] = 423360484Sobrien entry->d_un.d_val; 423460484Sobrien 423560484Sobrien if (do_dynamic) 423660484Sobrien { 423760484Sobrien switch (elf_header.e_machine) 423860484Sobrien { 423960484Sobrien case EM_MIPS: 424078828Sobrien case EM_MIPS_RS3_LE: 424160484Sobrien dynamic_segment_mips_val (entry); 424260484Sobrien break; 424360484Sobrien case EM_PARISC: 424460484Sobrien dynamic_segment_parisc_val (entry); 424560484Sobrien break; 424660484Sobrien default: 424760484Sobrien print_vma (entry->d_un.d_val, PREFIX_HEX); 424860484Sobrien putchar ('\n'); 424960484Sobrien } 425060484Sobrien } 425160484Sobrien break; 425260484Sobrien } 425360484Sobrien } 425460484Sobrien 425560484Sobrien return 1; 425660484Sobrien} 425760484Sobrien 425860484Sobrienstatic char * 425960484Sobrienget_ver_flags (flags) 426060484Sobrien unsigned int flags; 426160484Sobrien{ 426260484Sobrien static char buff [32]; 426360484Sobrien 426460484Sobrien buff[0] = 0; 426560484Sobrien 426660484Sobrien if (flags == 0) 426760484Sobrien return _("none"); 426860484Sobrien 426960484Sobrien if (flags & VER_FLG_BASE) 427060484Sobrien strcat (buff, "BASE "); 427160484Sobrien 427260484Sobrien if (flags & VER_FLG_WEAK) 427360484Sobrien { 427460484Sobrien if (flags & VER_FLG_BASE) 427560484Sobrien strcat (buff, "| "); 427660484Sobrien 427760484Sobrien strcat (buff, "WEAK "); 427860484Sobrien } 427960484Sobrien 428060484Sobrien if (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)) 428160484Sobrien strcat (buff, "| <unknown>"); 428260484Sobrien 428360484Sobrien return buff; 428460484Sobrien} 428560484Sobrien 428660484Sobrien/* Display the contents of the version sections. */ 428760484Sobrienstatic int 428860484Sobrienprocess_version_sections (file) 428960484Sobrien FILE * file; 429060484Sobrien{ 429160484Sobrien Elf32_Internal_Shdr * section; 429260484Sobrien unsigned i; 429360484Sobrien int found = 0; 429460484Sobrien 429560484Sobrien if (! do_version) 429660484Sobrien return 1; 429760484Sobrien 429860484Sobrien for (i = 0, section = section_headers; 429960484Sobrien i < elf_header.e_shnum; 430060484Sobrien i++, section ++) 430160484Sobrien { 430260484Sobrien switch (section->sh_type) 430360484Sobrien { 430460484Sobrien case SHT_GNU_verdef: 430560484Sobrien { 430660484Sobrien Elf_External_Verdef * edefs; 430760484Sobrien unsigned int idx; 430860484Sobrien unsigned int cnt; 430960484Sobrien 431060484Sobrien found = 1; 431160484Sobrien 431260484Sobrien printf 431360484Sobrien (_("\nVersion definition section '%s' contains %ld entries:\n"), 431460484Sobrien SECTION_NAME (section), section->sh_info); 431560484Sobrien 431660484Sobrien printf (_(" Addr: 0x")); 431760484Sobrien printf_vma (section->sh_addr); 431860484Sobrien printf (_(" Offset: %#08lx Link: %lx (%s)\n"), 431960484Sobrien (unsigned long) section->sh_offset, section->sh_link, 432060484Sobrien SECTION_NAME (section_headers + section->sh_link)); 432160484Sobrien 432260484Sobrien GET_DATA_ALLOC (section->sh_offset, section->sh_size, 432360484Sobrien edefs, Elf_External_Verdef *, 432460484Sobrien "version definition section"); 432560484Sobrien 432660484Sobrien for (idx = cnt = 0; cnt < section->sh_info; ++ cnt) 432760484Sobrien { 432860484Sobrien char * vstart; 432960484Sobrien Elf_External_Verdef * edef; 433060484Sobrien Elf_Internal_Verdef ent; 433160484Sobrien Elf_External_Verdaux * eaux; 433260484Sobrien Elf_Internal_Verdaux aux; 433360484Sobrien int j; 433460484Sobrien int isum; 433560484Sobrien 433660484Sobrien vstart = ((char *) edefs) + idx; 433760484Sobrien 433860484Sobrien edef = (Elf_External_Verdef *) vstart; 433960484Sobrien 434060484Sobrien ent.vd_version = BYTE_GET (edef->vd_version); 434160484Sobrien ent.vd_flags = BYTE_GET (edef->vd_flags); 434260484Sobrien ent.vd_ndx = BYTE_GET (edef->vd_ndx); 434360484Sobrien ent.vd_cnt = BYTE_GET (edef->vd_cnt); 434460484Sobrien ent.vd_hash = BYTE_GET (edef->vd_hash); 434560484Sobrien ent.vd_aux = BYTE_GET (edef->vd_aux); 434660484Sobrien ent.vd_next = BYTE_GET (edef->vd_next); 434760484Sobrien 434860484Sobrien printf (_(" %#06x: Rev: %d Flags: %s"), 434960484Sobrien idx, ent.vd_version, get_ver_flags (ent.vd_flags)); 435060484Sobrien 435160484Sobrien printf (_(" Index: %d Cnt: %d "), 435260484Sobrien ent.vd_ndx, ent.vd_cnt); 435360484Sobrien 435460484Sobrien vstart += ent.vd_aux; 435560484Sobrien 435660484Sobrien eaux = (Elf_External_Verdaux *) vstart; 435760484Sobrien 435860484Sobrien aux.vda_name = BYTE_GET (eaux->vda_name); 435960484Sobrien aux.vda_next = BYTE_GET (eaux->vda_next); 436060484Sobrien 436160484Sobrien if (dynamic_strings) 436260484Sobrien printf (_("Name: %s\n"), dynamic_strings + aux.vda_name); 436360484Sobrien else 436460484Sobrien printf (_("Name index: %ld\n"), aux.vda_name); 436560484Sobrien 436660484Sobrien isum = idx + ent.vd_aux; 436760484Sobrien 436860484Sobrien for (j = 1; j < ent.vd_cnt; j ++) 436960484Sobrien { 437060484Sobrien isum += aux.vda_next; 437160484Sobrien vstart += aux.vda_next; 437260484Sobrien 437360484Sobrien eaux = (Elf_External_Verdaux *) vstart; 437460484Sobrien 437560484Sobrien aux.vda_name = BYTE_GET (eaux->vda_name); 437660484Sobrien aux.vda_next = BYTE_GET (eaux->vda_next); 437760484Sobrien 437860484Sobrien if (dynamic_strings) 437960484Sobrien printf (_(" %#06x: Parent %d: %s\n"), 438060484Sobrien isum, j, dynamic_strings + aux.vda_name); 438160484Sobrien else 438260484Sobrien printf (_(" %#06x: Parent %d, name index: %ld\n"), 438360484Sobrien isum, j, aux.vda_name); 438460484Sobrien } 438560484Sobrien 438660484Sobrien idx += ent.vd_next; 438760484Sobrien } 438860484Sobrien 438960484Sobrien free (edefs); 439060484Sobrien } 439160484Sobrien break; 439260484Sobrien 439360484Sobrien case SHT_GNU_verneed: 439460484Sobrien { 439560484Sobrien Elf_External_Verneed * eneed; 439660484Sobrien unsigned int idx; 439760484Sobrien unsigned int cnt; 439860484Sobrien 439960484Sobrien found = 1; 440060484Sobrien 440160484Sobrien printf (_("\nVersion needs section '%s' contains %ld entries:\n"), 440260484Sobrien SECTION_NAME (section), section->sh_info); 440360484Sobrien 440460484Sobrien printf (_(" Addr: 0x")); 440560484Sobrien printf_vma (section->sh_addr); 440660484Sobrien printf (_(" Offset: %#08lx Link to section: %ld (%s)\n"), 440760484Sobrien (unsigned long) section->sh_offset, section->sh_link, 440860484Sobrien SECTION_NAME (section_headers + section->sh_link)); 440960484Sobrien 441060484Sobrien GET_DATA_ALLOC (section->sh_offset, section->sh_size, 441160484Sobrien eneed, Elf_External_Verneed *, 441260484Sobrien "version need section"); 441360484Sobrien 441460484Sobrien for (idx = cnt = 0; cnt < section->sh_info; ++cnt) 441560484Sobrien { 441660484Sobrien Elf_External_Verneed * entry; 441760484Sobrien Elf_Internal_Verneed ent; 441860484Sobrien int j; 441960484Sobrien int isum; 442060484Sobrien char * vstart; 442160484Sobrien 442260484Sobrien vstart = ((char *) eneed) + idx; 442360484Sobrien 442460484Sobrien entry = (Elf_External_Verneed *) vstart; 442560484Sobrien 442660484Sobrien ent.vn_version = BYTE_GET (entry->vn_version); 442760484Sobrien ent.vn_cnt = BYTE_GET (entry->vn_cnt); 442860484Sobrien ent.vn_file = BYTE_GET (entry->vn_file); 442960484Sobrien ent.vn_aux = BYTE_GET (entry->vn_aux); 443060484Sobrien ent.vn_next = BYTE_GET (entry->vn_next); 443160484Sobrien 443260484Sobrien printf (_(" %#06x: Version: %d"), idx, ent.vn_version); 443360484Sobrien 443460484Sobrien if (dynamic_strings) 443560484Sobrien printf (_(" File: %s"), dynamic_strings + ent.vn_file); 443660484Sobrien else 443760484Sobrien printf (_(" File: %lx"), ent.vn_file); 443860484Sobrien 443960484Sobrien printf (_(" Cnt: %d\n"), ent.vn_cnt); 444060484Sobrien 444160484Sobrien vstart += ent.vn_aux; 444260484Sobrien 444360484Sobrien for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j) 444460484Sobrien { 444560484Sobrien Elf_External_Vernaux * eaux; 444660484Sobrien Elf_Internal_Vernaux aux; 444760484Sobrien 444860484Sobrien eaux = (Elf_External_Vernaux *) vstart; 444960484Sobrien 445060484Sobrien aux.vna_hash = BYTE_GET (eaux->vna_hash); 445160484Sobrien aux.vna_flags = BYTE_GET (eaux->vna_flags); 445260484Sobrien aux.vna_other = BYTE_GET (eaux->vna_other); 445360484Sobrien aux.vna_name = BYTE_GET (eaux->vna_name); 445460484Sobrien aux.vna_next = BYTE_GET (eaux->vna_next); 445560484Sobrien 445660484Sobrien if (dynamic_strings) 445760484Sobrien printf (_(" %#06x: Name: %s"), 445860484Sobrien isum, dynamic_strings + aux.vna_name); 445960484Sobrien else 446060484Sobrien printf (_(" %#06x: Name index: %lx"), 446160484Sobrien isum, aux.vna_name); 446260484Sobrien 446360484Sobrien printf (_(" Flags: %s Version: %d\n"), 446460484Sobrien get_ver_flags (aux.vna_flags), aux.vna_other); 446560484Sobrien 446660484Sobrien isum += aux.vna_next; 446760484Sobrien vstart += aux.vna_next; 446860484Sobrien } 446960484Sobrien 447060484Sobrien idx += ent.vn_next; 447160484Sobrien } 447260484Sobrien 447360484Sobrien free (eneed); 447460484Sobrien } 447560484Sobrien break; 447660484Sobrien 447760484Sobrien case SHT_GNU_versym: 447860484Sobrien { 447960484Sobrien Elf32_Internal_Shdr * link_section; 448078828Sobrien int total; 448178828Sobrien int cnt; 448278828Sobrien unsigned char * edata; 448378828Sobrien unsigned short * data; 448478828Sobrien char * strtab; 448578828Sobrien Elf_Internal_Sym * symbols; 448660484Sobrien Elf32_Internal_Shdr * string_sec; 448760484Sobrien 448860484Sobrien link_section = section_headers + section->sh_link; 448960484Sobrien total = section->sh_size / section->sh_entsize; 449060484Sobrien 449160484Sobrien found = 1; 449260484Sobrien 449360484Sobrien symbols = GET_ELF_SYMBOLS (file, link_section->sh_offset, 449460484Sobrien link_section->sh_size / link_section->sh_entsize); 449560484Sobrien 449660484Sobrien string_sec = section_headers + link_section->sh_link; 449760484Sobrien 449860484Sobrien GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size, 449960484Sobrien strtab, char *, "version string table"); 450060484Sobrien 450160484Sobrien printf (_("\nVersion symbols section '%s' contains %d entries:\n"), 450260484Sobrien SECTION_NAME (section), total); 450360484Sobrien 450460484Sobrien printf (_(" Addr: ")); 450560484Sobrien printf_vma (section->sh_addr); 450660484Sobrien printf (_(" Offset: %#08lx Link: %lx (%s)\n"), 450760484Sobrien (unsigned long) section->sh_offset, section->sh_link, 450860484Sobrien SECTION_NAME (link_section)); 450960484Sobrien 451060484Sobrien GET_DATA_ALLOC (version_info [DT_VERSIONTAGIDX (DT_VERSYM)] 451160484Sobrien - loadaddr, 451260484Sobrien total * sizeof (short), edata, 451360484Sobrien unsigned char *, "version symbol data"); 451460484Sobrien 451560484Sobrien data = (unsigned short *) malloc (total * sizeof (short)); 451660484Sobrien 451760484Sobrien for (cnt = total; cnt --;) 451860484Sobrien data [cnt] = byte_get (edata + cnt * sizeof (short), 451960484Sobrien sizeof (short)); 452060484Sobrien 452160484Sobrien free (edata); 452260484Sobrien 452360484Sobrien for (cnt = 0; cnt < total; cnt += 4) 452460484Sobrien { 452560484Sobrien int j, nn; 452677298Sobrien int check_def, check_need; 452777298Sobrien char * name; 452860484Sobrien 452960484Sobrien printf (" %03x:", cnt); 453060484Sobrien 453160484Sobrien for (j = 0; (j < 4) && (cnt + j) < total; ++j) 453260484Sobrien switch (data [cnt + j]) 453360484Sobrien { 453460484Sobrien case 0: 453560484Sobrien fputs (_(" 0 (*local*) "), stdout); 453660484Sobrien break; 453760484Sobrien 453860484Sobrien case 1: 453960484Sobrien fputs (_(" 1 (*global*) "), stdout); 454060484Sobrien break; 454160484Sobrien 454260484Sobrien default: 454360484Sobrien nn = printf ("%4x%c", data [cnt + j] & 0x7fff, 454460484Sobrien data [cnt + j] & 0x8000 ? 'h' : ' '); 454560484Sobrien 454677298Sobrien check_def = 1; 454777298Sobrien check_need = 1; 454877298Sobrien if (symbols [cnt + j].st_shndx >= SHN_LORESERVE 454977298Sobrien || section_headers[symbols [cnt + j].st_shndx].sh_type 455077298Sobrien != SHT_NOBITS) 455160484Sobrien { 455277298Sobrien if (symbols [cnt + j].st_shndx == SHN_UNDEF) 455377298Sobrien check_def = 0; 455477298Sobrien else 455577298Sobrien check_need = 0; 455677298Sobrien } 455760484Sobrien 455877298Sobrien if (check_need 455977298Sobrien && version_info [DT_VERSIONTAGIDX (DT_VERNEED)]) 456060484Sobrien { 456160484Sobrien Elf_Internal_Verneed ivn; 456260484Sobrien unsigned long offset; 456360484Sobrien 456460484Sobrien offset = version_info [DT_VERSIONTAGIDX (DT_VERNEED)] 456560484Sobrien - loadaddr; 456660484Sobrien 456760484Sobrien do 456860484Sobrien { 456960484Sobrien Elf_Internal_Vernaux ivna; 457060484Sobrien Elf_External_Verneed evn; 457160484Sobrien Elf_External_Vernaux evna; 457260484Sobrien unsigned long a_off; 457360484Sobrien 457460484Sobrien GET_DATA (offset, evn, "version need"); 457560484Sobrien 457660484Sobrien ivn.vn_aux = BYTE_GET (evn.vn_aux); 457760484Sobrien ivn.vn_next = BYTE_GET (evn.vn_next); 457860484Sobrien 457960484Sobrien a_off = offset + ivn.vn_aux; 458060484Sobrien 458160484Sobrien do 458260484Sobrien { 458360484Sobrien GET_DATA (a_off, evna, 458460484Sobrien "version need aux (2)"); 458560484Sobrien 458660484Sobrien ivna.vna_next = BYTE_GET (evna.vna_next); 458760484Sobrien ivna.vna_other = BYTE_GET (evna.vna_other); 458860484Sobrien 458960484Sobrien a_off += ivna.vna_next; 459060484Sobrien } 459160484Sobrien while (ivna.vna_other != data [cnt + j] 459260484Sobrien && ivna.vna_next != 0); 459360484Sobrien 459460484Sobrien if (ivna.vna_other == data [cnt + j]) 459560484Sobrien { 459660484Sobrien ivna.vna_name = BYTE_GET (evna.vna_name); 459760484Sobrien 459860484Sobrien name = strtab + ivna.vna_name; 459960484Sobrien nn += printf ("(%s%-*s", 460060484Sobrien name, 460160484Sobrien 12 - (int) strlen (name), 460260484Sobrien ")"); 460377298Sobrien check_def = 0; 460460484Sobrien break; 460560484Sobrien } 460660484Sobrien 460760484Sobrien offset += ivn.vn_next; 460860484Sobrien } 460960484Sobrien while (ivn.vn_next); 461060484Sobrien } 461177298Sobrien 461277298Sobrien if (check_def && data [cnt + j] != 0x8001 461377298Sobrien && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) 461460484Sobrien { 461560484Sobrien Elf_Internal_Verdef ivd; 461660484Sobrien Elf_External_Verdef evd; 461760484Sobrien unsigned long offset; 461860484Sobrien 461960484Sobrien offset = version_info 462060484Sobrien [DT_VERSIONTAGIDX (DT_VERDEF)] - loadaddr; 462160484Sobrien 462260484Sobrien do 462360484Sobrien { 462460484Sobrien GET_DATA (offset, evd, "version def"); 462560484Sobrien 462660484Sobrien ivd.vd_next = BYTE_GET (evd.vd_next); 462760484Sobrien ivd.vd_ndx = BYTE_GET (evd.vd_ndx); 462860484Sobrien 462960484Sobrien offset += ivd.vd_next; 463060484Sobrien } 463160484Sobrien while (ivd.vd_ndx != (data [cnt + j] & 0x7fff) 463260484Sobrien && ivd.vd_next != 0); 463360484Sobrien 463460484Sobrien if (ivd.vd_ndx == (data [cnt + j] & 0x7fff)) 463560484Sobrien { 463660484Sobrien Elf_External_Verdaux evda; 463760484Sobrien Elf_Internal_Verdaux ivda; 463860484Sobrien 463960484Sobrien ivd.vd_aux = BYTE_GET (evd.vd_aux); 464060484Sobrien 464160484Sobrien GET_DATA (offset - ivd.vd_next + ivd.vd_aux, 464260484Sobrien evda, "version def aux"); 464360484Sobrien 464460484Sobrien ivda.vda_name = BYTE_GET (evda.vda_name); 464560484Sobrien 464660484Sobrien name = strtab + ivda.vda_name; 464760484Sobrien nn += printf ("(%s%-*s", 464860484Sobrien name, 464960484Sobrien 12 - (int) strlen (name), 465060484Sobrien ")"); 465160484Sobrien } 465260484Sobrien } 465360484Sobrien 465460484Sobrien if (nn < 18) 465560484Sobrien printf ("%*c", 18 - nn, ' '); 465660484Sobrien } 465760484Sobrien 465860484Sobrien putchar ('\n'); 465960484Sobrien } 466060484Sobrien 466160484Sobrien free (data); 466260484Sobrien free (strtab); 466360484Sobrien free (symbols); 466460484Sobrien } 466560484Sobrien break; 466660484Sobrien 466760484Sobrien default: 466860484Sobrien break; 466960484Sobrien } 467060484Sobrien } 467160484Sobrien 467260484Sobrien if (! found) 467360484Sobrien printf (_("\nNo version information found in this file.\n")); 467460484Sobrien 467560484Sobrien return 1; 467660484Sobrien} 467760484Sobrien 467860484Sobrienstatic const char * 467960484Sobrienget_symbol_binding (binding) 468060484Sobrien unsigned int binding; 468160484Sobrien{ 468260484Sobrien static char buff [32]; 468360484Sobrien 468460484Sobrien switch (binding) 468560484Sobrien { 468660484Sobrien case STB_LOCAL: return "LOCAL"; 468760484Sobrien case STB_GLOBAL: return "GLOBAL"; 468860484Sobrien case STB_WEAK: return "WEAK"; 468960484Sobrien default: 469060484Sobrien if (binding >= STB_LOPROC && binding <= STB_HIPROC) 469160484Sobrien sprintf (buff, _("<processor specific>: %d"), binding); 469260484Sobrien else if (binding >= STB_LOOS && binding <= STB_HIOS) 469360484Sobrien sprintf (buff, _("<OS specific>: %d"), binding); 469460484Sobrien else 469560484Sobrien sprintf (buff, _("<unknown>: %d"), binding); 469660484Sobrien return buff; 469760484Sobrien } 469860484Sobrien} 469960484Sobrien 470060484Sobrienstatic const char * 470160484Sobrienget_symbol_type (type) 470260484Sobrien unsigned int type; 470360484Sobrien{ 470460484Sobrien static char buff [32]; 470560484Sobrien 470660484Sobrien switch (type) 470760484Sobrien { 470860484Sobrien case STT_NOTYPE: return "NOTYPE"; 470960484Sobrien case STT_OBJECT: return "OBJECT"; 471060484Sobrien case STT_FUNC: return "FUNC"; 471160484Sobrien case STT_SECTION: return "SECTION"; 471260484Sobrien case STT_FILE: return "FILE"; 471360484Sobrien case STT_COMMON: return "COMMON"; 471460484Sobrien default: 471560484Sobrien if (type >= STT_LOPROC && type <= STT_HIPROC) 471660484Sobrien { 471760484Sobrien if (elf_header.e_machine == EM_ARM && type == STT_ARM_TFUNC) 471860484Sobrien return "THUMB_FUNC"; 471960484Sobrien 472060484Sobrien if (elf_header.e_machine == EM_SPARCV9 && type == STT_REGISTER) 472160484Sobrien return "REGISTER"; 472260484Sobrien 472360484Sobrien if (elf_header.e_machine == EM_PARISC && type == STT_PARISC_MILLI) 472460484Sobrien return "PARISC_MILLI"; 472560484Sobrien 472660484Sobrien sprintf (buff, _("<processor specific>: %d"), type); 472760484Sobrien } 472860484Sobrien else if (type >= STT_LOOS && type <= STT_HIOS) 472960484Sobrien { 473060484Sobrien if (elf_header.e_machine == EM_PARISC) 473160484Sobrien { 473260484Sobrien if (type == STT_HP_OPAQUE) 473360484Sobrien return "HP_OPAQUE"; 473460484Sobrien if (type == STT_HP_STUB) 473560484Sobrien return "HP_STUB"; 473660484Sobrien } 473760484Sobrien 473860484Sobrien sprintf (buff, _("<OS specific>: %d"), type); 473960484Sobrien } 474060484Sobrien else 474160484Sobrien sprintf (buff, _("<unknown>: %d"), type); 474260484Sobrien return buff; 474360484Sobrien } 474460484Sobrien} 474560484Sobrien 474660484Sobrienstatic const char * 474760484Sobrienget_symbol_visibility (visibility) 474860484Sobrien unsigned int visibility; 474960484Sobrien{ 475060484Sobrien switch (visibility) 475160484Sobrien { 475260484Sobrien case STV_DEFAULT: return "DEFAULT"; 475360484Sobrien case STV_INTERNAL: return "INTERNAL"; 475460484Sobrien case STV_HIDDEN: return "HIDDEN"; 475560484Sobrien case STV_PROTECTED: return "PROTECTED"; 475660484Sobrien default: abort (); 475760484Sobrien } 475860484Sobrien} 475960484Sobrien 476060484Sobrienstatic const char * 476160484Sobrienget_symbol_index_type (type) 476260484Sobrien unsigned int type; 476360484Sobrien{ 476460484Sobrien switch (type) 476560484Sobrien { 476660484Sobrien case SHN_UNDEF: return "UND"; 476760484Sobrien case SHN_ABS: return "ABS"; 476860484Sobrien case SHN_COMMON: return "COM"; 476960484Sobrien default: 477060484Sobrien if (type >= SHN_LOPROC && type <= SHN_HIPROC) 477160484Sobrien return "PRC"; 477260484Sobrien else if (type >= SHN_LORESERVE && type <= SHN_HIRESERVE) 477360484Sobrien return "RSV"; 477460484Sobrien else if (type >= SHN_LOOS && type <= SHN_HIOS) 477560484Sobrien return "OS "; 477660484Sobrien else 477760484Sobrien { 477860484Sobrien static char buff [32]; 477960484Sobrien 478060484Sobrien sprintf (buff, "%3d", type); 478160484Sobrien return buff; 478260484Sobrien } 478360484Sobrien } 478460484Sobrien} 478560484Sobrien 478660484Sobrienstatic int * 478760484Sobrienget_dynamic_data (file, number) 478860484Sobrien FILE * file; 478960484Sobrien unsigned int number; 479060484Sobrien{ 479177298Sobrien unsigned char * e_data; 479260484Sobrien int * i_data; 479360484Sobrien 479477298Sobrien e_data = (unsigned char *) malloc (number * 4); 479560484Sobrien 479660484Sobrien if (e_data == NULL) 479760484Sobrien { 479860484Sobrien error (_("Out of memory\n")); 479960484Sobrien return NULL; 480060484Sobrien } 480160484Sobrien 480260484Sobrien if (fread (e_data, 4, number, file) != number) 480360484Sobrien { 480460484Sobrien error (_("Unable to read in dynamic data\n")); 480560484Sobrien return NULL; 480660484Sobrien } 480760484Sobrien 480860484Sobrien i_data = (int *) malloc (number * sizeof (* i_data)); 480960484Sobrien 481060484Sobrien if (i_data == NULL) 481160484Sobrien { 481260484Sobrien error (_("Out of memory\n")); 481360484Sobrien free (e_data); 481460484Sobrien return NULL; 481560484Sobrien } 481660484Sobrien 481760484Sobrien while (number--) 481860484Sobrien i_data [number] = byte_get (e_data + number * 4, 4); 481960484Sobrien 482060484Sobrien free (e_data); 482160484Sobrien 482260484Sobrien return i_data; 482360484Sobrien} 482460484Sobrien 482560484Sobrien/* Dump the symbol table */ 482660484Sobrienstatic int 482760484Sobrienprocess_symbol_table (file) 482860484Sobrien FILE * file; 482960484Sobrien{ 483060484Sobrien Elf32_Internal_Shdr * section; 483177298Sobrien unsigned char nb [4]; 483277298Sobrien unsigned char nc [4]; 483360484Sobrien int nbuckets = 0; 483460484Sobrien int nchains = 0; 483560484Sobrien int * buckets = NULL; 483660484Sobrien int * chains = NULL; 483760484Sobrien 483860484Sobrien if (! do_syms && !do_histogram) 483960484Sobrien return 1; 484060484Sobrien 484160484Sobrien if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL) 484260484Sobrien || do_histogram)) 484360484Sobrien { 484460484Sobrien if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET)) 484560484Sobrien { 484660484Sobrien error (_("Unable to seek to start of dynamic information")); 484760484Sobrien return 0; 484860484Sobrien } 484960484Sobrien 485060484Sobrien if (fread (nb, sizeof (nb), 1, file) != 1) 485160484Sobrien { 485260484Sobrien error (_("Failed to read in number of buckets\n")); 485360484Sobrien return 0; 485460484Sobrien } 485560484Sobrien 485660484Sobrien if (fread (nc, sizeof (nc), 1, file) != 1) 485760484Sobrien { 485860484Sobrien error (_("Failed to read in number of chains\n")); 485960484Sobrien return 0; 486060484Sobrien } 486160484Sobrien 486260484Sobrien nbuckets = byte_get (nb, 4); 486360484Sobrien nchains = byte_get (nc, 4); 486460484Sobrien 486560484Sobrien buckets = get_dynamic_data (file, nbuckets); 486660484Sobrien chains = get_dynamic_data (file, nchains); 486760484Sobrien 486860484Sobrien if (buckets == NULL || chains == NULL) 486960484Sobrien return 0; 487060484Sobrien } 487160484Sobrien 487260484Sobrien if (do_syms 487360484Sobrien && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL) 487460484Sobrien { 487560484Sobrien int hn; 487660484Sobrien int si; 487760484Sobrien 487860484Sobrien printf (_("\nSymbol table for image:\n")); 487960484Sobrien if (is_32bit_elf) 488060484Sobrien printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); 488160484Sobrien else 488260484Sobrien printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n")); 488360484Sobrien 488460484Sobrien for (hn = 0; hn < nbuckets; hn++) 488560484Sobrien { 488660484Sobrien if (! buckets [hn]) 488760484Sobrien continue; 488860484Sobrien 488960484Sobrien for (si = buckets [hn]; si < nchains && si > 0; si = chains [si]) 489060484Sobrien { 489160484Sobrien Elf_Internal_Sym * psym; 489260484Sobrien 489360484Sobrien psym = dynamic_symbols + si; 489460484Sobrien 489560484Sobrien printf (" %3d %3d: ", si, hn); 489660484Sobrien print_vma (psym->st_value, LONG_HEX); 489760484Sobrien putchar (' ' ); 489860484Sobrien print_vma (psym->st_size, DEC_5); 489977298Sobrien 490060484Sobrien printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info))); 490160484Sobrien printf (" %6s", get_symbol_binding (ELF_ST_BIND (psym->st_info))); 490260484Sobrien printf (" %3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other))); 490360484Sobrien printf (" %3.3s", get_symbol_index_type (psym->st_shndx)); 490460484Sobrien printf (" %s\n", dynamic_strings + psym->st_name); 490560484Sobrien } 490660484Sobrien } 490760484Sobrien } 490860484Sobrien else if (do_syms && !do_using_dynamic) 490960484Sobrien { 491060484Sobrien unsigned int i; 491160484Sobrien 491260484Sobrien for (i = 0, section = section_headers; 491360484Sobrien i < elf_header.e_shnum; 491460484Sobrien i++, section++) 491560484Sobrien { 491660484Sobrien unsigned int si; 491760484Sobrien char * strtab; 491860484Sobrien Elf_Internal_Sym * symtab; 491960484Sobrien Elf_Internal_Sym * psym; 492060484Sobrien 492160484Sobrien 492260484Sobrien if ( section->sh_type != SHT_SYMTAB 492360484Sobrien && section->sh_type != SHT_DYNSYM) 492460484Sobrien continue; 492560484Sobrien 492660484Sobrien printf (_("\nSymbol table '%s' contains %lu entries:\n"), 492760484Sobrien SECTION_NAME (section), 492860484Sobrien (unsigned long) (section->sh_size / section->sh_entsize)); 492960484Sobrien if (is_32bit_elf) 493060484Sobrien printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); 493160484Sobrien else 493260484Sobrien printf (_(" Num: Value Size Type Bind Vis Ndx Name\n")); 493360484Sobrien 493460484Sobrien symtab = GET_ELF_SYMBOLS (file, section->sh_offset, 493560484Sobrien section->sh_size / section->sh_entsize); 493660484Sobrien if (symtab == NULL) 493760484Sobrien continue; 493860484Sobrien 493960484Sobrien if (section->sh_link == elf_header.e_shstrndx) 494060484Sobrien strtab = string_table; 494160484Sobrien else 494260484Sobrien { 494360484Sobrien Elf32_Internal_Shdr * string_sec; 494460484Sobrien 494560484Sobrien string_sec = section_headers + section->sh_link; 494660484Sobrien 494760484Sobrien GET_DATA_ALLOC (string_sec->sh_offset, string_sec->sh_size, 494860484Sobrien strtab, char *, "string table"); 494960484Sobrien } 495060484Sobrien 495160484Sobrien for (si = 0, psym = symtab; 495260484Sobrien si < section->sh_size / section->sh_entsize; 495360484Sobrien si ++, psym ++) 495460484Sobrien { 495560484Sobrien printf ("%6d: ", si); 495660484Sobrien print_vma (psym->st_value, LONG_HEX); 495760484Sobrien putchar (' '); 495860484Sobrien print_vma (psym->st_size, DEC_5); 495960484Sobrien printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info))); 496060484Sobrien printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info))); 496160484Sobrien printf (" %-3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other))); 496260484Sobrien printf (" %4s", get_symbol_index_type (psym->st_shndx)); 496360484Sobrien printf (" %s", strtab + psym->st_name); 496460484Sobrien 496560484Sobrien if (section->sh_type == SHT_DYNSYM && 496660484Sobrien version_info [DT_VERSIONTAGIDX (DT_VERSYM)] != 0) 496760484Sobrien { 496860484Sobrien unsigned char data[2]; 496960484Sobrien unsigned short vers_data; 497060484Sobrien unsigned long offset; 497160484Sobrien int is_nobits; 497260484Sobrien int check_def; 497360484Sobrien 497460484Sobrien offset = version_info [DT_VERSIONTAGIDX (DT_VERSYM)] 497560484Sobrien - loadaddr; 497660484Sobrien 497760484Sobrien GET_DATA (offset + si * sizeof (vers_data), data, 497860484Sobrien "version data"); 497960484Sobrien 498060484Sobrien vers_data = byte_get (data, 2); 498160484Sobrien 498260484Sobrien is_nobits = psym->st_shndx < SHN_LORESERVE ? 498360484Sobrien (section_headers [psym->st_shndx].sh_type == SHT_NOBITS) 498460484Sobrien : 0; 498560484Sobrien 498660484Sobrien check_def = (psym->st_shndx != SHN_UNDEF); 498760484Sobrien 498860484Sobrien if ((vers_data & 0x8000) || vers_data > 1) 498960484Sobrien { 499077298Sobrien if (version_info [DT_VERSIONTAGIDX (DT_VERNEED)] 499177298Sobrien && (is_nobits || ! check_def)) 499260484Sobrien { 499360484Sobrien Elf_External_Verneed evn; 499460484Sobrien Elf_Internal_Verneed ivn; 499560484Sobrien Elf_Internal_Vernaux ivna; 499660484Sobrien 499760484Sobrien /* We must test both. */ 499860484Sobrien offset = version_info 499960484Sobrien [DT_VERSIONTAGIDX (DT_VERNEED)] - loadaddr; 500060484Sobrien 500160484Sobrien do 500260484Sobrien { 500360484Sobrien unsigned long vna_off; 500460484Sobrien 500560484Sobrien GET_DATA (offset, evn, "version need"); 500660484Sobrien 500760484Sobrien ivn.vn_aux = BYTE_GET (evn.vn_aux); 500860484Sobrien ivn.vn_next = BYTE_GET (evn.vn_next); 500960484Sobrien 501060484Sobrien vna_off = offset + ivn.vn_aux; 501160484Sobrien 501260484Sobrien do 501360484Sobrien { 501460484Sobrien Elf_External_Vernaux evna; 501560484Sobrien 501660484Sobrien GET_DATA (vna_off, evna, 501760484Sobrien "version need aux (3)"); 501860484Sobrien 501960484Sobrien ivna.vna_other = BYTE_GET (evna.vna_other); 502060484Sobrien ivna.vna_next = BYTE_GET (evna.vna_next); 502160484Sobrien ivna.vna_name = BYTE_GET (evna.vna_name); 502260484Sobrien 502360484Sobrien vna_off += ivna.vna_next; 502460484Sobrien } 502560484Sobrien while (ivna.vna_other != vers_data 502660484Sobrien && ivna.vna_next != 0); 502760484Sobrien 502860484Sobrien if (ivna.vna_other == vers_data) 502960484Sobrien break; 503060484Sobrien 503160484Sobrien offset += ivn.vn_next; 503260484Sobrien } 503360484Sobrien while (ivn.vn_next != 0); 503460484Sobrien 503560484Sobrien if (ivna.vna_other == vers_data) 503660484Sobrien { 503760484Sobrien printf ("@%s (%d)", 503860484Sobrien strtab + ivna.vna_name, ivna.vna_other); 503960484Sobrien check_def = 0; 504060484Sobrien } 504160484Sobrien else if (! is_nobits) 504260484Sobrien error (_("bad dynamic symbol")); 504360484Sobrien else 504460484Sobrien check_def = 1; 504560484Sobrien } 504660484Sobrien 504760484Sobrien if (check_def) 504860484Sobrien { 504977298Sobrien if (vers_data != 0x8001 505077298Sobrien && version_info [DT_VERSIONTAGIDX (DT_VERDEF)]) 505160484Sobrien { 505260484Sobrien Elf_Internal_Verdef ivd; 505360484Sobrien Elf_Internal_Verdaux ivda; 505460484Sobrien Elf_External_Verdaux evda; 505560484Sobrien unsigned long offset; 505660484Sobrien 505760484Sobrien offset = 505860484Sobrien version_info [DT_VERSIONTAGIDX (DT_VERDEF)] 505960484Sobrien - loadaddr; 506060484Sobrien 506160484Sobrien do 506260484Sobrien { 506360484Sobrien Elf_External_Verdef evd; 506460484Sobrien 506560484Sobrien GET_DATA (offset, evd, "version def"); 506660484Sobrien 506760484Sobrien ivd.vd_ndx = BYTE_GET (evd.vd_ndx); 506860484Sobrien ivd.vd_aux = BYTE_GET (evd.vd_aux); 506960484Sobrien ivd.vd_next = BYTE_GET (evd.vd_next); 507060484Sobrien 507160484Sobrien offset += ivd.vd_next; 507260484Sobrien } 507360484Sobrien while (ivd.vd_ndx != (vers_data & 0x7fff) 507460484Sobrien && ivd.vd_next != 0); 507560484Sobrien 507660484Sobrien offset -= ivd.vd_next; 507760484Sobrien offset += ivd.vd_aux; 507860484Sobrien 507960484Sobrien GET_DATA (offset, evda, "version def aux"); 508060484Sobrien 508160484Sobrien ivda.vda_name = BYTE_GET (evda.vda_name); 508260484Sobrien 508360484Sobrien if (psym->st_name != ivda.vda_name) 508460484Sobrien printf ((vers_data & 0x8000) 508560484Sobrien ? "@%s" : "@@%s", 508660484Sobrien strtab + ivda.vda_name); 508760484Sobrien } 508860484Sobrien } 508960484Sobrien } 509060484Sobrien } 509160484Sobrien 509260484Sobrien putchar ('\n'); 509360484Sobrien } 509460484Sobrien 509560484Sobrien free (symtab); 509660484Sobrien if (strtab != string_table) 509760484Sobrien free (strtab); 509860484Sobrien } 509960484Sobrien } 510060484Sobrien else if (do_syms) 510160484Sobrien printf 510260484Sobrien (_("\nDynamic symbol information is not available for displaying symbols.\n")); 510360484Sobrien 510460484Sobrien if (do_histogram && buckets != NULL) 510560484Sobrien { 510677298Sobrien int * lengths; 510777298Sobrien int * counts; 510877298Sobrien int hn; 510977298Sobrien int si; 511077298Sobrien int maxlength = 0; 511177298Sobrien int nzero_counts = 0; 511277298Sobrien int nsyms = 0; 511360484Sobrien 511460484Sobrien printf (_("\nHistogram for bucket list length (total of %d buckets):\n"), 511560484Sobrien nbuckets); 511660484Sobrien printf (_(" Length Number %% of total Coverage\n")); 511760484Sobrien 511860484Sobrien lengths = (int *) calloc (nbuckets, sizeof (int)); 511960484Sobrien if (lengths == NULL) 512060484Sobrien { 512160484Sobrien error (_("Out of memory")); 512260484Sobrien return 0; 512360484Sobrien } 512460484Sobrien for (hn = 0; hn < nbuckets; ++hn) 512560484Sobrien { 512660484Sobrien if (! buckets [hn]) 512760484Sobrien continue; 512860484Sobrien 512960484Sobrien for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si]) 513060484Sobrien { 513160484Sobrien ++ nsyms; 513260484Sobrien if (maxlength < ++lengths[hn]) 513360484Sobrien ++ maxlength; 513460484Sobrien } 513560484Sobrien } 513660484Sobrien 513760484Sobrien counts = (int *) calloc (maxlength + 1, sizeof (int)); 513860484Sobrien if (counts == NULL) 513960484Sobrien { 514060484Sobrien error (_("Out of memory")); 514160484Sobrien return 0; 514260484Sobrien } 514360484Sobrien 514460484Sobrien for (hn = 0; hn < nbuckets; ++hn) 514560484Sobrien ++ counts [lengths [hn]]; 514660484Sobrien 514760484Sobrien if (nbuckets > 0) 514860484Sobrien { 514960484Sobrien printf (" 0 %-10d (%5.1f%%)\n", 515060484Sobrien counts[0], (counts[0] * 100.0) / nbuckets); 515160484Sobrien for (si = 1; si <= maxlength; ++si) 515260484Sobrien { 515360484Sobrien nzero_counts += counts[si] * si; 515460484Sobrien printf ("%7d %-10d (%5.1f%%) %5.1f%%\n", 515560484Sobrien si, counts[si], (counts[si] * 100.0) / nbuckets, 515660484Sobrien (nzero_counts * 100.0) / nsyms); 515760484Sobrien } 515860484Sobrien } 515960484Sobrien 516060484Sobrien free (counts); 516160484Sobrien free (lengths); 516260484Sobrien } 516360484Sobrien 516460484Sobrien if (buckets != NULL) 516560484Sobrien { 516660484Sobrien free (buckets); 516760484Sobrien free (chains); 516860484Sobrien } 516960484Sobrien 517060484Sobrien return 1; 517160484Sobrien} 517260484Sobrien 517360484Sobrienstatic int 517460484Sobrienprocess_syminfo (file) 517560484Sobrien FILE * file ATTRIBUTE_UNUSED; 517660484Sobrien{ 517760484Sobrien unsigned int i; 517860484Sobrien 517960484Sobrien if (dynamic_syminfo == NULL 518060484Sobrien || !do_dynamic) 518160484Sobrien /* No syminfo, this is ok. */ 518260484Sobrien return 1; 518360484Sobrien 518460484Sobrien /* There better should be a dynamic symbol section. */ 518560484Sobrien if (dynamic_symbols == NULL || dynamic_strings == NULL) 518660484Sobrien return 0; 518760484Sobrien 518860484Sobrien if (dynamic_addr) 518960484Sobrien printf (_("\nDynamic info segment at offset 0x%lx contains %d entries:\n"), 519060484Sobrien dynamic_syminfo_offset, dynamic_syminfo_nent); 519160484Sobrien 519260484Sobrien printf (_(" Num: Name BoundTo Flags\n")); 519360484Sobrien for (i = 0; i < dynamic_syminfo_nent; ++i) 519460484Sobrien { 519560484Sobrien unsigned short int flags = dynamic_syminfo[i].si_flags; 519660484Sobrien 519760484Sobrien printf ("%4d: %-30s ", i, 519860484Sobrien dynamic_strings + dynamic_symbols[i].st_name); 519960484Sobrien 520060484Sobrien switch (dynamic_syminfo[i].si_boundto) 520160484Sobrien { 520260484Sobrien case SYMINFO_BT_SELF: 520360484Sobrien fputs ("SELF ", stdout); 520460484Sobrien break; 520560484Sobrien case SYMINFO_BT_PARENT: 520660484Sobrien fputs ("PARENT ", stdout); 520760484Sobrien break; 520860484Sobrien default: 520960484Sobrien if (dynamic_syminfo[i].si_boundto > 0 521060484Sobrien && dynamic_syminfo[i].si_boundto < dynamic_size) 521160484Sobrien printf ("%-10s ", 521260484Sobrien dynamic_strings 521360484Sobrien + dynamic_segment[dynamic_syminfo[i].si_boundto].d_un.d_val); 521460484Sobrien else 521560484Sobrien printf ("%-10d ", dynamic_syminfo[i].si_boundto); 521660484Sobrien break; 521760484Sobrien } 521860484Sobrien 521960484Sobrien if (flags & SYMINFO_FLG_DIRECT) 522060484Sobrien printf (" DIRECT"); 522160484Sobrien if (flags & SYMINFO_FLG_PASSTHRU) 522260484Sobrien printf (" PASSTHRU"); 522360484Sobrien if (flags & SYMINFO_FLG_COPY) 522460484Sobrien printf (" COPY"); 522560484Sobrien if (flags & SYMINFO_FLG_LAZYLOAD) 522660484Sobrien printf (" LAZYLOAD"); 522760484Sobrien 522860484Sobrien puts (""); 522960484Sobrien } 523060484Sobrien 523160484Sobrien return 1; 523260484Sobrien} 523360484Sobrien 523460484Sobrien#ifdef SUPPORT_DISASSEMBLY 523560484Sobrienstatic void 523660484Sobriendisassemble_section (section, file) 523760484Sobrien Elf32_Internal_Shdr * section; 523860484Sobrien FILE * file; 523960484Sobrien{ 524060484Sobrien printf (_("\nAssembly dump of section %s\n"), 524160484Sobrien SECTION_NAME (section)); 524260484Sobrien 524360484Sobrien /* XXX -- to be done --- XXX */ 524460484Sobrien 524560484Sobrien return 1; 524660484Sobrien} 524760484Sobrien#endif 524860484Sobrien 524960484Sobrienstatic int 525060484Sobriendump_section (section, file) 525160484Sobrien Elf32_Internal_Shdr * section; 525260484Sobrien FILE * file; 525360484Sobrien{ 525460484Sobrien bfd_size_type bytes; 525560484Sobrien bfd_vma addr; 525660484Sobrien unsigned char * data; 525760484Sobrien unsigned char * start; 525860484Sobrien 525960484Sobrien bytes = section->sh_size; 526060484Sobrien 526160484Sobrien if (bytes == 0) 526260484Sobrien { 526360484Sobrien printf (_("\nSection '%s' has no data to dump.\n"), 526460484Sobrien SECTION_NAME (section)); 526560484Sobrien return 0; 526660484Sobrien } 526760484Sobrien else 526860484Sobrien printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section)); 526960484Sobrien 527060484Sobrien addr = section->sh_addr; 527160484Sobrien 527260484Sobrien GET_DATA_ALLOC (section->sh_offset, bytes, start, unsigned char *, 527360484Sobrien "section data"); 527460484Sobrien 527560484Sobrien data = start; 527660484Sobrien 527760484Sobrien while (bytes) 527860484Sobrien { 527960484Sobrien int j; 528060484Sobrien int k; 528160484Sobrien int lbytes; 528260484Sobrien 528360484Sobrien lbytes = (bytes > 16 ? 16 : bytes); 528460484Sobrien 528560484Sobrien printf (" 0x%8.8lx ", (unsigned long) addr); 528660484Sobrien 528760484Sobrien switch (elf_header.e_ident [EI_DATA]) 528860484Sobrien { 528960484Sobrien default: 529060484Sobrien case ELFDATA2LSB: 529160484Sobrien for (j = 15; j >= 0; j --) 529260484Sobrien { 529360484Sobrien if (j < lbytes) 529460484Sobrien printf ("%2.2x", data [j]); 529560484Sobrien else 529660484Sobrien printf (" "); 529760484Sobrien 529860484Sobrien if (!(j & 0x3)) 529960484Sobrien printf (" "); 530060484Sobrien } 530160484Sobrien break; 530260484Sobrien 530360484Sobrien case ELFDATA2MSB: 530460484Sobrien for (j = 0; j < 16; j++) 530560484Sobrien { 530660484Sobrien if (j < lbytes) 530760484Sobrien printf ("%2.2x", data [j]); 530860484Sobrien else 530960484Sobrien printf (" "); 531060484Sobrien 531160484Sobrien if ((j & 3) == 3) 531260484Sobrien printf (" "); 531360484Sobrien } 531460484Sobrien break; 531560484Sobrien } 531660484Sobrien 531760484Sobrien for (j = 0; j < lbytes; j++) 531860484Sobrien { 531960484Sobrien k = data [j]; 532060484Sobrien if (k >= ' ' && k < 0x80) 532160484Sobrien printf ("%c", k); 532260484Sobrien else 532360484Sobrien printf ("."); 532460484Sobrien } 532560484Sobrien 532660484Sobrien putchar ('\n'); 532760484Sobrien 532860484Sobrien data += lbytes; 532960484Sobrien addr += lbytes; 533060484Sobrien bytes -= lbytes; 533160484Sobrien } 533260484Sobrien 533360484Sobrien free (start); 533460484Sobrien 533560484Sobrien return 1; 533660484Sobrien} 533760484Sobrien 533860484Sobrien 533960484Sobrienstatic unsigned long int 534060484Sobrienread_leb128 (data, length_return, sign) 534160484Sobrien unsigned char * data; 534260484Sobrien int * length_return; 534360484Sobrien int sign; 534460484Sobrien{ 534560484Sobrien unsigned long int result = 0; 534660484Sobrien unsigned int num_read = 0; 534760484Sobrien int shift = 0; 534860484Sobrien unsigned char byte; 534960484Sobrien 535060484Sobrien do 535160484Sobrien { 535260484Sobrien byte = * data ++; 535360484Sobrien num_read ++; 535460484Sobrien 535560484Sobrien result |= (byte & 0x7f) << shift; 535660484Sobrien 535760484Sobrien shift += 7; 535860484Sobrien 535960484Sobrien } 536060484Sobrien while (byte & 0x80); 536160484Sobrien 536260484Sobrien if (length_return != NULL) 536360484Sobrien * length_return = num_read; 536460484Sobrien 536560484Sobrien if (sign && (shift < 32) && (byte & 0x40)) 536660484Sobrien result |= -1 << shift; 536760484Sobrien 536860484Sobrien return result; 536960484Sobrien} 537060484Sobrien 537160484Sobrientypedef struct State_Machine_Registers 537260484Sobrien{ 537360484Sobrien unsigned long address; 537460484Sobrien unsigned int file; 537560484Sobrien unsigned int line; 537660484Sobrien unsigned int column; 537760484Sobrien int is_stmt; 537860484Sobrien int basic_block; 537960484Sobrien int end_sequence; 538060484Sobrien/* This variable hold the number of the last entry seen 538160484Sobrien in the File Table. */ 538260484Sobrien unsigned int last_file_entry; 538360484Sobrien} SMR; 538460484Sobrien 538560484Sobrienstatic SMR state_machine_regs; 538660484Sobrien 538760484Sobrienstatic void 538860484Sobrienreset_state_machine (is_stmt) 538960484Sobrien int is_stmt; 539060484Sobrien{ 539160484Sobrien state_machine_regs.address = 0; 539260484Sobrien state_machine_regs.file = 1; 539360484Sobrien state_machine_regs.line = 1; 539460484Sobrien state_machine_regs.column = 0; 539560484Sobrien state_machine_regs.is_stmt = is_stmt; 539660484Sobrien state_machine_regs.basic_block = 0; 539760484Sobrien state_machine_regs.end_sequence = 0; 539860484Sobrien state_machine_regs.last_file_entry = 0; 539960484Sobrien} 540060484Sobrien 540160484Sobrien/* Handled an extend line op. Returns true if this is the end 540260484Sobrien of sequence. */ 540360484Sobrienstatic int 540460484Sobrienprocess_extended_line_op (data, is_stmt, pointer_size) 540560484Sobrien unsigned char * data; 540660484Sobrien int is_stmt; 540760484Sobrien int pointer_size; 540860484Sobrien{ 540960484Sobrien unsigned char op_code; 541060484Sobrien int bytes_read; 541160484Sobrien unsigned int len; 541260484Sobrien unsigned char * name; 541360484Sobrien unsigned long adr; 541460484Sobrien 541560484Sobrien len = read_leb128 (data, & bytes_read, 0); 541660484Sobrien data += bytes_read; 541760484Sobrien 541860484Sobrien if (len == 0) 541960484Sobrien { 542060484Sobrien warn (_("badly formed extended line op encountered!")); 542160484Sobrien return bytes_read; 542260484Sobrien } 542360484Sobrien 542460484Sobrien len += bytes_read; 542560484Sobrien op_code = * data ++; 542660484Sobrien 542760484Sobrien printf (_(" Extended opcode %d: "), op_code); 542860484Sobrien 542960484Sobrien switch (op_code) 543060484Sobrien { 543160484Sobrien case DW_LNE_end_sequence: 543260484Sobrien printf (_("End of Sequence\n\n")); 543360484Sobrien reset_state_machine (is_stmt); 543460484Sobrien break; 543560484Sobrien 543660484Sobrien case DW_LNE_set_address: 543760484Sobrien adr = byte_get (data, pointer_size); 543860484Sobrien printf (_("set Address to 0x%lx\n"), adr); 543960484Sobrien state_machine_regs.address = adr; 544060484Sobrien break; 544160484Sobrien 544260484Sobrien case DW_LNE_define_file: 544360484Sobrien printf (_(" define new File Table entry\n")); 544460484Sobrien printf (_(" Entry\tDir\tTime\tSize\tName\n")); 544560484Sobrien 544660484Sobrien printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); 544760484Sobrien name = data; 544877298Sobrien data += strlen ((char *) data) + 1; 544960484Sobrien printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); 545060484Sobrien data += bytes_read; 545160484Sobrien printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); 545260484Sobrien data += bytes_read; 545360484Sobrien printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); 545460484Sobrien printf (_("%s\n\n"), name); 545560484Sobrien break; 545660484Sobrien 545760484Sobrien default: 545860484Sobrien printf (_("UNKNOWN: length %d\n"), len - bytes_read); 545960484Sobrien break; 546060484Sobrien } 546160484Sobrien 546260484Sobrien return len; 546360484Sobrien} 546460484Sobrien 546560484Sobrien/* Size of pointers in the .debug_line section. This information is not 546660484Sobrien really present in that section. It's obtained before dumping the debug 546760484Sobrien sections by doing some pre-scan of the .debug_info section. */ 546860484Sobrienstatic int debug_line_pointer_size = 4; 546960484Sobrien 547060484Sobrienstatic int 547160484Sobriendisplay_debug_lines (section, start, file) 547260484Sobrien Elf32_Internal_Shdr * section; 547360484Sobrien unsigned char * start; 547460484Sobrien FILE * file ATTRIBUTE_UNUSED; 547560484Sobrien{ 547660484Sobrien DWARF2_External_LineInfo * external; 547760484Sobrien DWARF2_Internal_LineInfo info; 547860484Sobrien unsigned char * standard_opcodes; 547960484Sobrien unsigned char * data = start; 548060484Sobrien unsigned char * end = start + section->sh_size; 548160484Sobrien unsigned char * end_of_sequence; 548260484Sobrien int i; 548360484Sobrien 548460484Sobrien printf (_("\nDump of debug contents of section %s:\n\n"), 548560484Sobrien SECTION_NAME (section)); 548660484Sobrien 548760484Sobrien while (data < end) 548860484Sobrien { 548960484Sobrien external = (DWARF2_External_LineInfo *) data; 549060484Sobrien 549160484Sobrien /* Check the length of the block. */ 549260484Sobrien info.li_length = BYTE_GET (external->li_length); 549377298Sobrien if (info.li_length + sizeof (external->li_length) > section->sh_size) 549460484Sobrien { 549560484Sobrien warn 549660484Sobrien (_("The line info appears to be corrupt - the section is too small\n")); 549760484Sobrien return 0; 549860484Sobrien } 549960484Sobrien 550060484Sobrien /* Check its version number. */ 550160484Sobrien info.li_version = BYTE_GET (external->li_version); 550260484Sobrien if (info.li_version != 2) 550360484Sobrien { 550460484Sobrien warn (_("Only DWARF version 2 line info is currently supported.\n")); 550560484Sobrien return 0; 550660484Sobrien } 550760484Sobrien 550860484Sobrien info.li_prologue_length = BYTE_GET (external->li_prologue_length); 550960484Sobrien info.li_min_insn_length = BYTE_GET (external->li_min_insn_length); 551060484Sobrien info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt); 551160484Sobrien info.li_line_base = BYTE_GET (external->li_line_base); 551260484Sobrien info.li_line_range = BYTE_GET (external->li_line_range); 551360484Sobrien info.li_opcode_base = BYTE_GET (external->li_opcode_base); 551460484Sobrien 551560484Sobrien /* Sign extend the line base field. */ 551660484Sobrien info.li_line_base <<= 24; 551760484Sobrien info.li_line_base >>= 24; 551860484Sobrien 551960484Sobrien printf (_(" Length: %ld\n"), info.li_length); 552060484Sobrien printf (_(" DWARF Version: %d\n"), info.li_version); 552178828Sobrien printf (_(" Prologue Length: %d\n"), info.li_prologue_length); 552260484Sobrien printf (_(" Minimum Instruction Length: %d\n"), info.li_min_insn_length); 552360484Sobrien printf (_(" Initial value of 'is_stmt': %d\n"), info.li_default_is_stmt); 552460484Sobrien printf (_(" Line Base: %d\n"), info.li_line_base); 552560484Sobrien printf (_(" Line Range: %d\n"), info.li_line_range); 552660484Sobrien printf (_(" Opcode Base: %d\n"), info.li_opcode_base); 552760484Sobrien 552877298Sobrien end_of_sequence = data + info.li_length + sizeof (external->li_length); 552960484Sobrien 553060484Sobrien reset_state_machine (info.li_default_is_stmt); 553160484Sobrien 553260484Sobrien /* Display the contents of the Opcodes table. */ 553360484Sobrien standard_opcodes = data + sizeof (* external); 553460484Sobrien 553560484Sobrien printf (_("\n Opcodes:\n")); 553660484Sobrien 553760484Sobrien for (i = 1; i < info.li_opcode_base; i++) 553860484Sobrien printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i - 1]); 553960484Sobrien 554060484Sobrien /* Display the contents of the Directory table. */ 554160484Sobrien data = standard_opcodes + info.li_opcode_base - 1; 554260484Sobrien 554360484Sobrien if (* data == 0) 554460484Sobrien printf (_("\n The Directory Table is empty.\n")); 554560484Sobrien else 554660484Sobrien { 554760484Sobrien printf (_("\n The Directory Table:\n")); 554860484Sobrien 554960484Sobrien while (* data != 0) 555060484Sobrien { 555160484Sobrien printf (_(" %s\n"), data); 555260484Sobrien 555377298Sobrien data += strlen ((char *) data) + 1; 555460484Sobrien } 555560484Sobrien } 555660484Sobrien 555760484Sobrien /* Skip the NUL at the end of the table. */ 555860484Sobrien data ++; 555960484Sobrien 556060484Sobrien /* Display the contents of the File Name table. */ 556160484Sobrien if (* data == 0) 556260484Sobrien printf (_("\n The File Name Table is empty.\n")); 556360484Sobrien else 556460484Sobrien { 556560484Sobrien printf (_("\n The File Name Table:\n")); 556660484Sobrien printf (_(" Entry\tDir\tTime\tSize\tName\n")); 556760484Sobrien 556860484Sobrien while (* data != 0) 556960484Sobrien { 557077298Sobrien unsigned char * name; 557160484Sobrien int bytes_read; 557260484Sobrien 557360484Sobrien printf (_(" %d\t"), ++ state_machine_regs.last_file_entry); 557460484Sobrien name = data; 557560484Sobrien 557677298Sobrien data += strlen ((char *) data) + 1; 557760484Sobrien 557860484Sobrien printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); 557960484Sobrien data += bytes_read; 558060484Sobrien printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); 558160484Sobrien data += bytes_read; 558260484Sobrien printf (_("%lu\t"), read_leb128 (data, & bytes_read, 0)); 558360484Sobrien data += bytes_read; 558460484Sobrien printf (_("%s\n"), name); 558560484Sobrien } 558660484Sobrien } 558760484Sobrien 558860484Sobrien /* Skip the NUL at the end of the table. */ 558960484Sobrien data ++; 559060484Sobrien 559160484Sobrien /* Now display the statements. */ 559260484Sobrien printf (_("\n Line Number Statements:\n")); 559360484Sobrien 559460484Sobrien 559560484Sobrien while (data < end_of_sequence) 559660484Sobrien { 559760484Sobrien unsigned char op_code; 559860484Sobrien int adv; 559960484Sobrien int bytes_read; 560060484Sobrien 560160484Sobrien op_code = * data ++; 560260484Sobrien 560360484Sobrien switch (op_code) 560460484Sobrien { 560560484Sobrien case DW_LNS_extended_op: 560660484Sobrien data += process_extended_line_op (data, info.li_default_is_stmt, 560760484Sobrien debug_line_pointer_size); 560860484Sobrien break; 560960484Sobrien 561060484Sobrien case DW_LNS_copy: 561160484Sobrien printf (_(" Copy\n")); 561260484Sobrien break; 561360484Sobrien 561460484Sobrien case DW_LNS_advance_pc: 561560484Sobrien adv = info.li_min_insn_length * read_leb128 (data, & bytes_read, 0); 561660484Sobrien data += bytes_read; 561760484Sobrien state_machine_regs.address += adv; 561860484Sobrien printf (_(" Advance PC by %d to %lx\n"), adv, 561960484Sobrien state_machine_regs.address); 562060484Sobrien break; 562160484Sobrien 562260484Sobrien case DW_LNS_advance_line: 562360484Sobrien adv = read_leb128 (data, & bytes_read, 1); 562460484Sobrien data += bytes_read; 562560484Sobrien state_machine_regs.line += adv; 562660484Sobrien printf (_(" Advance Line by %d to %d\n"), adv, 562760484Sobrien state_machine_regs.line); 562860484Sobrien break; 562960484Sobrien 563060484Sobrien case DW_LNS_set_file: 563160484Sobrien adv = read_leb128 (data, & bytes_read, 0); 563260484Sobrien data += bytes_read; 563360484Sobrien printf (_(" Set File Name to entry %d in the File Name Table\n"), 563460484Sobrien adv); 563560484Sobrien state_machine_regs.file = adv; 563660484Sobrien break; 563760484Sobrien 563860484Sobrien case DW_LNS_set_column: 563960484Sobrien adv = read_leb128 (data, & bytes_read, 0); 564060484Sobrien data += bytes_read; 564160484Sobrien printf (_(" Set column to %d\n"), adv); 564260484Sobrien state_machine_regs.column = adv; 564360484Sobrien break; 564460484Sobrien 564560484Sobrien case DW_LNS_negate_stmt: 564660484Sobrien adv = state_machine_regs.is_stmt; 564760484Sobrien adv = ! adv; 564860484Sobrien printf (_(" Set is_stmt to %d\n"), adv); 564960484Sobrien state_machine_regs.is_stmt = adv; 565060484Sobrien break; 565160484Sobrien 565260484Sobrien case DW_LNS_set_basic_block: 565360484Sobrien printf (_(" Set basic block\n")); 565460484Sobrien state_machine_regs.basic_block = 1; 565560484Sobrien break; 565660484Sobrien 565760484Sobrien case DW_LNS_const_add_pc: 565860484Sobrien adv = (((255 - info.li_opcode_base) / info.li_line_range) 565960484Sobrien * info.li_min_insn_length); 566060484Sobrien state_machine_regs.address += adv; 566160484Sobrien printf (_(" Advance PC by constant %d to 0x%lx\n"), adv, 566260484Sobrien state_machine_regs.address); 566360484Sobrien break; 566460484Sobrien 566560484Sobrien case DW_LNS_fixed_advance_pc: 566660484Sobrien adv = byte_get (data, 2); 566760484Sobrien data += 2; 566860484Sobrien state_machine_regs.address += adv; 566960484Sobrien printf (_(" Advance PC by fixed size amount %d to 0x%lx\n"), 567060484Sobrien adv, state_machine_regs.address); 567160484Sobrien break; 567260484Sobrien 567360484Sobrien default: 567460484Sobrien op_code -= info.li_opcode_base; 567560484Sobrien adv = (op_code / info.li_line_range) * info.li_min_insn_length; 567660484Sobrien state_machine_regs.address += adv; 567760484Sobrien printf (_(" Special opcode %d: advance Address by %d to 0x%lx"), 567860484Sobrien op_code, adv, state_machine_regs.address); 567960484Sobrien adv = (op_code % info.li_line_range) + info.li_line_base; 568060484Sobrien state_machine_regs.line += adv; 568160484Sobrien printf (_(" and Line by %d to %d\n"), 568260484Sobrien adv, state_machine_regs.line); 568360484Sobrien break; 568460484Sobrien } 568560484Sobrien } 568660484Sobrien printf ("\n"); 568760484Sobrien } 568860484Sobrien 568960484Sobrien return 1; 569060484Sobrien} 569160484Sobrien 569260484Sobrienstatic int 569360484Sobriendisplay_debug_pubnames (section, start, file) 569460484Sobrien Elf32_Internal_Shdr * section; 569560484Sobrien unsigned char * start; 569660484Sobrien FILE * file ATTRIBUTE_UNUSED; 569760484Sobrien{ 569860484Sobrien DWARF2_External_PubNames * external; 569960484Sobrien DWARF2_Internal_PubNames pubnames; 570060484Sobrien unsigned char * end; 570160484Sobrien 570260484Sobrien end = start + section->sh_size; 570360484Sobrien 570460484Sobrien printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); 570560484Sobrien 570660484Sobrien while (start < end) 570760484Sobrien { 570860484Sobrien unsigned char * data; 570960484Sobrien unsigned long offset; 571060484Sobrien 571160484Sobrien external = (DWARF2_External_PubNames *) start; 571260484Sobrien 571360484Sobrien pubnames.pn_length = BYTE_GET (external->pn_length); 571460484Sobrien pubnames.pn_version = BYTE_GET (external->pn_version); 571560484Sobrien pubnames.pn_offset = BYTE_GET (external->pn_offset); 571660484Sobrien pubnames.pn_size = BYTE_GET (external->pn_size); 571760484Sobrien 571860484Sobrien data = start + sizeof (* external); 571960484Sobrien start += pubnames.pn_length + sizeof (external->pn_length); 572060484Sobrien 572160484Sobrien if (pubnames.pn_version != 2) 572260484Sobrien { 572368765Sobrien static int warned = 0; 572468765Sobrien 572568765Sobrien if (! warned) 572668765Sobrien { 572768765Sobrien warn (_("Only DWARF 2 pubnames are currently supported\n")); 572868765Sobrien warned = 1; 572968765Sobrien } 573077298Sobrien 573160484Sobrien continue; 573260484Sobrien } 573360484Sobrien 573460484Sobrien printf (_(" Length: %ld\n"), 573560484Sobrien pubnames.pn_length); 573660484Sobrien printf (_(" Version: %d\n"), 573760484Sobrien pubnames.pn_version); 573860484Sobrien printf (_(" Offset into .debug_info section: %ld\n"), 573960484Sobrien pubnames.pn_offset); 574060484Sobrien printf (_(" Size of area in .debug_info section: %ld\n"), 574160484Sobrien pubnames.pn_size); 574260484Sobrien 574360484Sobrien printf (_("\n Offset\tName\n")); 574460484Sobrien 574560484Sobrien do 574660484Sobrien { 574760484Sobrien offset = byte_get (data, 4); 574860484Sobrien 574960484Sobrien if (offset != 0) 575060484Sobrien { 575160484Sobrien data += 4; 575260484Sobrien printf (" %ld\t\t%s\n", offset, data); 575377298Sobrien data += strlen ((char *) data) + 1; 575460484Sobrien } 575560484Sobrien } 575660484Sobrien while (offset != 0); 575760484Sobrien } 575860484Sobrien 575960484Sobrien printf ("\n"); 576060484Sobrien return 1; 576160484Sobrien} 576260484Sobrien 576360484Sobrienstatic char * 576460484Sobrienget_TAG_name (tag) 576560484Sobrien unsigned long tag; 576660484Sobrien{ 576760484Sobrien switch (tag) 576860484Sobrien { 576960484Sobrien case DW_TAG_padding: return "DW_TAG_padding"; 577060484Sobrien case DW_TAG_array_type: return "DW_TAG_array_type"; 577160484Sobrien case DW_TAG_class_type: return "DW_TAG_class_type"; 577260484Sobrien case DW_TAG_entry_point: return "DW_TAG_entry_point"; 577360484Sobrien case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type"; 577460484Sobrien case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter"; 577560484Sobrien case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration"; 577660484Sobrien case DW_TAG_label: return "DW_TAG_label"; 577760484Sobrien case DW_TAG_lexical_block: return "DW_TAG_lexical_block"; 577860484Sobrien case DW_TAG_member: return "DW_TAG_member"; 577960484Sobrien case DW_TAG_pointer_type: return "DW_TAG_pointer_type"; 578060484Sobrien case DW_TAG_reference_type: return "DW_TAG_reference_type"; 578160484Sobrien case DW_TAG_compile_unit: return "DW_TAG_compile_unit"; 578260484Sobrien case DW_TAG_string_type: return "DW_TAG_string_type"; 578360484Sobrien case DW_TAG_structure_type: return "DW_TAG_structure_type"; 578460484Sobrien case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type"; 578560484Sobrien case DW_TAG_typedef: return "DW_TAG_typedef"; 578660484Sobrien case DW_TAG_union_type: return "DW_TAG_union_type"; 578760484Sobrien case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters"; 578860484Sobrien case DW_TAG_variant: return "DW_TAG_variant"; 578960484Sobrien case DW_TAG_common_block: return "DW_TAG_common_block"; 579060484Sobrien case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion"; 579160484Sobrien case DW_TAG_inheritance: return "DW_TAG_inheritance"; 579260484Sobrien case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine"; 579360484Sobrien case DW_TAG_module: return "DW_TAG_module"; 579460484Sobrien case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type"; 579560484Sobrien case DW_TAG_set_type: return "DW_TAG_set_type"; 579660484Sobrien case DW_TAG_subrange_type: return "DW_TAG_subrange_type"; 579760484Sobrien case DW_TAG_with_stmt: return "DW_TAG_with_stmt"; 579860484Sobrien case DW_TAG_access_declaration: return "DW_TAG_access_declaration"; 579960484Sobrien case DW_TAG_base_type: return "DW_TAG_base_type"; 580060484Sobrien case DW_TAG_catch_block: return "DW_TAG_catch_block"; 580160484Sobrien case DW_TAG_const_type: return "DW_TAG_const_type"; 580260484Sobrien case DW_TAG_constant: return "DW_TAG_constant"; 580360484Sobrien case DW_TAG_enumerator: return "DW_TAG_enumerator"; 580460484Sobrien case DW_TAG_file_type: return "DW_TAG_file_type"; 580560484Sobrien case DW_TAG_friend: return "DW_TAG_friend"; 580660484Sobrien case DW_TAG_namelist: return "DW_TAG_namelist"; 580760484Sobrien case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; 580860484Sobrien case DW_TAG_packed_type: return "DW_TAG_packed_type"; 580960484Sobrien case DW_TAG_subprogram: return "DW_TAG_subprogram"; 581060484Sobrien case DW_TAG_template_type_param: return "DW_TAG_template_type_param"; 581160484Sobrien case DW_TAG_template_value_param: return "DW_TAG_template_value_param"; 581260484Sobrien case DW_TAG_thrown_type: return "DW_TAG_thrown_type"; 581360484Sobrien case DW_TAG_try_block: return "DW_TAG_try_block"; 581460484Sobrien case DW_TAG_variant_part: return "DW_TAG_variant_part"; 581560484Sobrien case DW_TAG_variable: return "DW_TAG_variable"; 581660484Sobrien case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; 581760484Sobrien case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; 581860484Sobrien case DW_TAG_format_label: return "DW_TAG_format_label"; 581960484Sobrien case DW_TAG_function_template: return "DW_TAG_function_template"; 582060484Sobrien case DW_TAG_class_template: return "DW_TAG_class_template"; 582160484Sobrien default: 582260484Sobrien { 582360484Sobrien static char buffer [100]; 582460484Sobrien 582560484Sobrien sprintf (buffer, _("Unknown TAG value: %lx"), tag); 582660484Sobrien return buffer; 582760484Sobrien } 582860484Sobrien } 582960484Sobrien} 583060484Sobrien 583160484Sobrienstatic char * 583260484Sobrienget_AT_name (attribute) 583360484Sobrien unsigned long attribute; 583460484Sobrien{ 583560484Sobrien switch (attribute) 583660484Sobrien { 583760484Sobrien case DW_AT_sibling: return "DW_AT_sibling"; 583860484Sobrien case DW_AT_location: return "DW_AT_location"; 583960484Sobrien case DW_AT_name: return "DW_AT_name"; 584060484Sobrien case DW_AT_ordering: return "DW_AT_ordering"; 584160484Sobrien case DW_AT_subscr_data: return "DW_AT_subscr_data"; 584260484Sobrien case DW_AT_byte_size: return "DW_AT_byte_size"; 584360484Sobrien case DW_AT_bit_offset: return "DW_AT_bit_offset"; 584460484Sobrien case DW_AT_bit_size: return "DW_AT_bit_size"; 584560484Sobrien case DW_AT_element_list: return "DW_AT_element_list"; 584660484Sobrien case DW_AT_stmt_list: return "DW_AT_stmt_list"; 584760484Sobrien case DW_AT_low_pc: return "DW_AT_low_pc"; 584860484Sobrien case DW_AT_high_pc: return "DW_AT_high_pc"; 584960484Sobrien case DW_AT_language: return "DW_AT_language"; 585060484Sobrien case DW_AT_member: return "DW_AT_member"; 585160484Sobrien case DW_AT_discr: return "DW_AT_discr"; 585260484Sobrien case DW_AT_discr_value: return "DW_AT_discr_value"; 585360484Sobrien case DW_AT_visibility: return "DW_AT_visibility"; 585460484Sobrien case DW_AT_import: return "DW_AT_import"; 585560484Sobrien case DW_AT_string_length: return "DW_AT_string_length"; 585660484Sobrien case DW_AT_common_reference: return "DW_AT_common_reference"; 585760484Sobrien case DW_AT_comp_dir: return "DW_AT_comp_dir"; 585860484Sobrien case DW_AT_const_value: return "DW_AT_const_value"; 585960484Sobrien case DW_AT_containing_type: return "DW_AT_containing_type"; 586060484Sobrien case DW_AT_default_value: return "DW_AT_default_value"; 586160484Sobrien case DW_AT_inline: return "DW_AT_inline"; 586260484Sobrien case DW_AT_is_optional: return "DW_AT_is_optional"; 586360484Sobrien case DW_AT_lower_bound: return "DW_AT_lower_bound"; 586460484Sobrien case DW_AT_producer: return "DW_AT_producer"; 586560484Sobrien case DW_AT_prototyped: return "DW_AT_prototyped"; 586660484Sobrien case DW_AT_return_addr: return "DW_AT_return_addr"; 586760484Sobrien case DW_AT_start_scope: return "DW_AT_start_scope"; 586860484Sobrien case DW_AT_stride_size: return "DW_AT_stride_size"; 586960484Sobrien case DW_AT_upper_bound: return "DW_AT_upper_bound"; 587060484Sobrien case DW_AT_abstract_origin: return "DW_AT_abstract_origin"; 587160484Sobrien case DW_AT_accessibility: return "DW_AT_accessibility"; 587260484Sobrien case DW_AT_address_class: return "DW_AT_address_class"; 587360484Sobrien case DW_AT_artificial: return "DW_AT_artificial"; 587460484Sobrien case DW_AT_base_types: return "DW_AT_base_types"; 587560484Sobrien case DW_AT_calling_convention: return "DW_AT_calling_convention"; 587660484Sobrien case DW_AT_count: return "DW_AT_count"; 587760484Sobrien case DW_AT_data_member_location: return "DW_AT_data_member_location"; 587860484Sobrien case DW_AT_decl_column: return "DW_AT_decl_column"; 587960484Sobrien case DW_AT_decl_file: return "DW_AT_decl_file"; 588060484Sobrien case DW_AT_decl_line: return "DW_AT_decl_line"; 588160484Sobrien case DW_AT_declaration: return "DW_AT_declaration"; 588260484Sobrien case DW_AT_discr_list: return "DW_AT_discr_list"; 588360484Sobrien case DW_AT_encoding: return "DW_AT_encoding"; 588460484Sobrien case DW_AT_external: return "DW_AT_external"; 588560484Sobrien case DW_AT_frame_base: return "DW_AT_frame_base"; 588660484Sobrien case DW_AT_friend: return "DW_AT_friend"; 588760484Sobrien case DW_AT_identifier_case: return "DW_AT_identifier_case"; 588860484Sobrien case DW_AT_macro_info: return "DW_AT_macro_info"; 588960484Sobrien case DW_AT_namelist_items: return "DW_AT_namelist_items"; 589060484Sobrien case DW_AT_priority: return "DW_AT_priority"; 589160484Sobrien case DW_AT_segment: return "DW_AT_segment"; 589260484Sobrien case DW_AT_specification: return "DW_AT_specification"; 589360484Sobrien case DW_AT_static_link: return "DW_AT_static_link"; 589460484Sobrien case DW_AT_type: return "DW_AT_type"; 589560484Sobrien case DW_AT_use_location: return "DW_AT_use_location"; 589660484Sobrien case DW_AT_variable_parameter: return "DW_AT_variable_parameter"; 589760484Sobrien case DW_AT_virtuality: return "DW_AT_virtuality"; 589860484Sobrien case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; 589960484Sobrien case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; 590060484Sobrien case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin"; 590160484Sobrien case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin"; 590260484Sobrien case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin"; 590360484Sobrien case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor"; 590460484Sobrien case DW_AT_MIPS_software_pipeline_depth: return "DW_AT_MIPS_software_pipeline_depth"; 590560484Sobrien case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name"; 590660484Sobrien case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride"; 590760484Sobrien case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name"; 590860484Sobrien case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin"; 590960484Sobrien case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines"; 591060484Sobrien case DW_AT_sf_names: return "DW_AT_sf_names"; 591160484Sobrien case DW_AT_src_info: return "DW_AT_src_info"; 591260484Sobrien case DW_AT_mac_info: return "DW_AT_mac_info"; 591360484Sobrien case DW_AT_src_coords: return "DW_AT_src_coords"; 591460484Sobrien case DW_AT_body_begin: return "DW_AT_body_begin"; 591560484Sobrien case DW_AT_body_end: return "DW_AT_body_end"; 591660484Sobrien default: 591760484Sobrien { 591860484Sobrien static char buffer [100]; 591960484Sobrien 592060484Sobrien sprintf (buffer, _("Unknown AT value: %lx"), attribute); 592160484Sobrien return buffer; 592260484Sobrien } 592360484Sobrien } 592460484Sobrien} 592560484Sobrien 592660484Sobrienstatic char * 592760484Sobrienget_FORM_name (form) 592860484Sobrien unsigned long form; 592960484Sobrien{ 593060484Sobrien switch (form) 593160484Sobrien { 593260484Sobrien case DW_FORM_addr: return "DW_FORM_addr"; 593360484Sobrien case DW_FORM_block2: return "DW_FORM_block2"; 593460484Sobrien case DW_FORM_block4: return "DW_FORM_block4"; 593560484Sobrien case DW_FORM_data2: return "DW_FORM_data2"; 593660484Sobrien case DW_FORM_data4: return "DW_FORM_data4"; 593760484Sobrien case DW_FORM_data8: return "DW_FORM_data8"; 593860484Sobrien case DW_FORM_string: return "DW_FORM_string"; 593960484Sobrien case DW_FORM_block: return "DW_FORM_block"; 594060484Sobrien case DW_FORM_block1: return "DW_FORM_block1"; 594160484Sobrien case DW_FORM_data1: return "DW_FORM_data1"; 594260484Sobrien case DW_FORM_flag: return "DW_FORM_flag"; 594360484Sobrien case DW_FORM_sdata: return "DW_FORM_sdata"; 594460484Sobrien case DW_FORM_strp: return "DW_FORM_strp"; 594560484Sobrien case DW_FORM_udata: return "DW_FORM_udata"; 594660484Sobrien case DW_FORM_ref_addr: return "DW_FORM_ref_addr"; 594760484Sobrien case DW_FORM_ref1: return "DW_FORM_ref1"; 594860484Sobrien case DW_FORM_ref2: return "DW_FORM_ref2"; 594960484Sobrien case DW_FORM_ref4: return "DW_FORM_ref4"; 595060484Sobrien case DW_FORM_ref8: return "DW_FORM_ref8"; 595160484Sobrien case DW_FORM_ref_udata: return "DW_FORM_ref_udata"; 595260484Sobrien case DW_FORM_indirect: return "DW_FORM_indirect"; 595360484Sobrien default: 595460484Sobrien { 595560484Sobrien static char buffer [100]; 595660484Sobrien 595760484Sobrien sprintf (buffer, _("Unknown FORM value: %lx"), form); 595860484Sobrien return buffer; 595960484Sobrien } 596060484Sobrien } 596160484Sobrien} 596260484Sobrien 596360484Sobrien/* FIXME: There are better and more effiecint ways to handle 596460484Sobrien these structures. For now though, I just want something that 596560484Sobrien is simple to implement. */ 596660484Sobrientypedef struct abbrev_attr 596760484Sobrien{ 596860484Sobrien unsigned long attribute; 596960484Sobrien unsigned long form; 597060484Sobrien struct abbrev_attr * next; 597160484Sobrien} 597260484Sobrienabbrev_attr; 597360484Sobrien 597460484Sobrientypedef struct abbrev_entry 597560484Sobrien{ 597660484Sobrien unsigned long entry; 597760484Sobrien unsigned long tag; 597860484Sobrien int children; 597960484Sobrien struct abbrev_attr * first_attr; 598060484Sobrien struct abbrev_attr * last_attr; 598160484Sobrien struct abbrev_entry * next; 598260484Sobrien} 598360484Sobrienabbrev_entry; 598460484Sobrien 598560484Sobrienstatic abbrev_entry * first_abbrev = NULL; 598660484Sobrienstatic abbrev_entry * last_abbrev = NULL; 598760484Sobrien 598860484Sobrienstatic void 598960484Sobrienfree_abbrevs PARAMS ((void)) 599060484Sobrien{ 599160484Sobrien abbrev_entry * abbrev; 599260484Sobrien 599360484Sobrien for (abbrev = first_abbrev; abbrev;) 599460484Sobrien { 599560484Sobrien abbrev_entry * next = abbrev->next; 599660484Sobrien abbrev_attr * attr; 599760484Sobrien 599860484Sobrien for (attr = abbrev->first_attr; attr;) 599960484Sobrien { 600060484Sobrien abbrev_attr * next = attr->next; 600160484Sobrien 600260484Sobrien free (attr); 600360484Sobrien attr = next; 600460484Sobrien } 600560484Sobrien 600660484Sobrien free (abbrev); 600760484Sobrien abbrev = next; 600860484Sobrien } 600960484Sobrien 601060484Sobrien last_abbrev = first_abbrev = NULL; 601160484Sobrien} 601260484Sobrien 601360484Sobrienstatic void 601460484Sobrienadd_abbrev (number, tag, children) 601560484Sobrien unsigned long number; 601660484Sobrien unsigned long tag; 601760484Sobrien int children; 601860484Sobrien{ 601960484Sobrien abbrev_entry * entry; 602060484Sobrien 602160484Sobrien entry = (abbrev_entry *) malloc (sizeof (* entry)); 602260484Sobrien 602360484Sobrien if (entry == NULL) 602460484Sobrien /* ugg */ 602560484Sobrien return; 602660484Sobrien 602760484Sobrien entry->entry = number; 602860484Sobrien entry->tag = tag; 602960484Sobrien entry->children = children; 603060484Sobrien entry->first_attr = NULL; 603160484Sobrien entry->last_attr = NULL; 603260484Sobrien entry->next = NULL; 603360484Sobrien 603460484Sobrien if (first_abbrev == NULL) 603560484Sobrien first_abbrev = entry; 603660484Sobrien else 603760484Sobrien last_abbrev->next = entry; 603860484Sobrien 603960484Sobrien last_abbrev = entry; 604060484Sobrien} 604160484Sobrien 604260484Sobrienstatic void 604360484Sobrienadd_abbrev_attr (attribute, form) 604460484Sobrien unsigned long attribute; 604560484Sobrien unsigned long form; 604660484Sobrien{ 604760484Sobrien abbrev_attr * attr; 604860484Sobrien 604960484Sobrien attr = (abbrev_attr *) malloc (sizeof (* attr)); 605060484Sobrien 605160484Sobrien if (attr == NULL) 605260484Sobrien /* ugg */ 605360484Sobrien return; 605460484Sobrien 605560484Sobrien attr->attribute = attribute; 605660484Sobrien attr->form = form; 605760484Sobrien attr->next = NULL; 605860484Sobrien 605960484Sobrien if (last_abbrev->first_attr == NULL) 606060484Sobrien last_abbrev->first_attr = attr; 606160484Sobrien else 606260484Sobrien last_abbrev->last_attr->next = attr; 606360484Sobrien 606460484Sobrien last_abbrev->last_attr = attr; 606560484Sobrien} 606660484Sobrien 606760484Sobrien/* Processes the (partial) contents of a .debug_abbrev section. 606860484Sobrien Returns NULL if the end of the section was encountered. 606960484Sobrien Returns the address after the last byte read if the end of 607060484Sobrien an abbreviation set was found. */ 607160484Sobrien 607260484Sobrienstatic unsigned char * 607360484Sobrienprocess_abbrev_section (start, end) 607460484Sobrien unsigned char * start; 607560484Sobrien unsigned char * end; 607660484Sobrien{ 607760484Sobrien if (first_abbrev != NULL) 607860484Sobrien return NULL; 607960484Sobrien 608060484Sobrien while (start < end) 608160484Sobrien { 608260484Sobrien int bytes_read; 608360484Sobrien unsigned long entry; 608460484Sobrien unsigned long tag; 608560484Sobrien unsigned long attribute; 608660484Sobrien int children; 608760484Sobrien 608860484Sobrien entry = read_leb128 (start, & bytes_read, 0); 608960484Sobrien start += bytes_read; 609060484Sobrien 609160484Sobrien /* A single zero is supposed to end the section according 609260484Sobrien to the standard. If there's more, then signal that to 609360484Sobrien the caller. */ 609460484Sobrien if (entry == 0) 609560484Sobrien return start == end ? NULL : start; 609660484Sobrien 609760484Sobrien tag = read_leb128 (start, & bytes_read, 0); 609860484Sobrien start += bytes_read; 609960484Sobrien 610060484Sobrien children = * start ++; 610160484Sobrien 610260484Sobrien add_abbrev (entry, tag, children); 610360484Sobrien 610460484Sobrien do 610560484Sobrien { 610660484Sobrien unsigned long form; 610760484Sobrien 610860484Sobrien attribute = read_leb128 (start, & bytes_read, 0); 610960484Sobrien start += bytes_read; 611060484Sobrien 611160484Sobrien form = read_leb128 (start, & bytes_read, 0); 611260484Sobrien start += bytes_read; 611360484Sobrien 611460484Sobrien if (attribute != 0) 611560484Sobrien add_abbrev_attr (attribute, form); 611660484Sobrien } 611760484Sobrien while (attribute != 0); 611860484Sobrien } 611960484Sobrien 612060484Sobrien return NULL; 612160484Sobrien} 612260484Sobrien 612360484Sobrien 612460484Sobrienstatic int 612560484Sobriendisplay_debug_abbrev (section, start, file) 612660484Sobrien Elf32_Internal_Shdr * section; 612760484Sobrien unsigned char * start; 612860484Sobrien FILE * file ATTRIBUTE_UNUSED; 612960484Sobrien{ 613077298Sobrien abbrev_entry * entry; 613160484Sobrien unsigned char * end = start + section->sh_size; 613260484Sobrien 613360484Sobrien printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section)); 613460484Sobrien 613560484Sobrien do 613660484Sobrien { 613760484Sobrien start = process_abbrev_section (start, end); 613860484Sobrien 613960484Sobrien printf (_(" Number TAG\n")); 614060484Sobrien 614160484Sobrien for (entry = first_abbrev; entry; entry = entry->next) 614260484Sobrien { 614360484Sobrien abbrev_attr * attr; 614460484Sobrien 614560484Sobrien printf (_(" %ld %s [%s]\n"), 614660484Sobrien entry->entry, 614760484Sobrien get_TAG_name (entry->tag), 614860484Sobrien entry->children ? _("has children") : _("no children")); 614960484Sobrien 615060484Sobrien for (attr = entry->first_attr; attr; attr = attr->next) 615160484Sobrien { 615260484Sobrien printf (_(" %-18s %s\n"), 615360484Sobrien get_AT_name (attr->attribute), 615460484Sobrien get_FORM_name (attr->form)); 615560484Sobrien } 615660484Sobrien } 615760484Sobrien } 615860484Sobrien while (start); 615960484Sobrien 616060484Sobrien printf ("\n"); 616160484Sobrien 616260484Sobrien return 1; 616360484Sobrien} 616460484Sobrien 616560484Sobrien 616660484Sobrienstatic unsigned char * 616760484Sobriendisplay_block (data, length) 616860484Sobrien unsigned char * data; 616960484Sobrien unsigned long length; 617060484Sobrien{ 617160484Sobrien printf (_(" %lu byte block: "), length); 617260484Sobrien 617360484Sobrien while (length --) 617460484Sobrien printf ("%lx ", (unsigned long) byte_get (data ++, 1)); 617560484Sobrien 617660484Sobrien return data; 617760484Sobrien} 617860484Sobrien 617960484Sobrienstatic void 618077298Sobriendecode_location_expression (data, pointer_size, length) 618160484Sobrien unsigned char * data; 618260484Sobrien unsigned int pointer_size; 618377298Sobrien unsigned long length; 618460484Sobrien{ 618577298Sobrien unsigned op; 618677298Sobrien int bytes_read; 618777298Sobrien unsigned long uvalue; 618877298Sobrien unsigned char * end = data + length; 618960484Sobrien 619077298Sobrien while (data < end) 619160484Sobrien { 619277298Sobrien op = * data ++; 619360484Sobrien 619477298Sobrien switch (op) 619577298Sobrien { 619677298Sobrien case DW_OP_addr: 619777298Sobrien printf ("DW_OP_addr: %lx", 619877298Sobrien (unsigned long) byte_get (data, pointer_size)); 619977298Sobrien data += pointer_size; 620077298Sobrien break; 620177298Sobrien case DW_OP_deref: 620277298Sobrien printf ("DW_OP_deref"); 620377298Sobrien break; 620477298Sobrien case DW_OP_const1u: 620577298Sobrien printf ("DW_OP_const1u: %lu", (unsigned long) byte_get (data++, 1)); 620677298Sobrien break; 620777298Sobrien case DW_OP_const1s: 620877298Sobrien printf ("DW_OP_const1s: %ld", (long) byte_get (data++, 1)); 620977298Sobrien break; 621077298Sobrien case DW_OP_const2u: 621177298Sobrien printf ("DW_OP_const2u: %lu", (unsigned long) byte_get (data, 2)); 621277298Sobrien data += 2; 621377298Sobrien break; 621477298Sobrien case DW_OP_const2s: 621577298Sobrien printf ("DW_OP_const2s: %ld", (long) byte_get (data, 2)); 621677298Sobrien data += 2; 621777298Sobrien break; 621877298Sobrien case DW_OP_const4u: 621977298Sobrien printf ("DW_OP_const4u: %lu", (unsigned long) byte_get (data, 4)); 622077298Sobrien data += 4; 622177298Sobrien break; 622277298Sobrien case DW_OP_const4s: 622377298Sobrien printf ("DW_OP_const4s: %ld", (long) byte_get (data, 4)); 622477298Sobrien data += 4; 622577298Sobrien break; 622677298Sobrien case DW_OP_const8u: 622777298Sobrien printf ("DW_OP_const8u: %lu %lu", (unsigned long) byte_get (data, 4), 622877298Sobrien (unsigned long) byte_get (data + 4, 4)); 622977298Sobrien data += 8; 623077298Sobrien break; 623177298Sobrien case DW_OP_const8s: 623277298Sobrien printf ("DW_OP_const8s: %ld %ld", (long) byte_get (data, 4), 623377298Sobrien (long) byte_get (data + 4, 4)); 623477298Sobrien data += 8; 623577298Sobrien break; 623677298Sobrien case DW_OP_constu: 623777298Sobrien printf ("DW_OP_constu: %lu", read_leb128 (data, &bytes_read, 0)); 623877298Sobrien data += bytes_read; 623977298Sobrien break; 624077298Sobrien case DW_OP_consts: 624177298Sobrien printf ("DW_OP_consts: %ld", read_leb128 (data, &bytes_read, 1)); 624277298Sobrien data += bytes_read; 624377298Sobrien break; 624477298Sobrien case DW_OP_dup: 624577298Sobrien printf ("DW_OP_dup"); 624677298Sobrien break; 624777298Sobrien case DW_OP_drop: 624877298Sobrien printf ("DW_OP_drop"); 624977298Sobrien break; 625077298Sobrien case DW_OP_over: 625177298Sobrien printf ("DW_OP_over"); 625277298Sobrien break; 625377298Sobrien case DW_OP_pick: 625477298Sobrien printf ("DW_OP_pick: %ld", (unsigned long) byte_get (data++, 1)); 625577298Sobrien break; 625677298Sobrien case DW_OP_swap: 625777298Sobrien printf ("DW_OP_swap"); 625877298Sobrien break; 625977298Sobrien case DW_OP_rot: 626077298Sobrien printf ("DW_OP_rot"); 626177298Sobrien break; 626277298Sobrien case DW_OP_xderef: 626377298Sobrien printf ("DW_OP_xderef"); 626477298Sobrien break; 626577298Sobrien case DW_OP_abs: 626677298Sobrien printf ("DW_OP_abs"); 626777298Sobrien break; 626877298Sobrien case DW_OP_and: 626977298Sobrien printf ("DW_OP_and"); 627077298Sobrien break; 627177298Sobrien case DW_OP_div: 627277298Sobrien printf ("DW_OP_div"); 627377298Sobrien break; 627477298Sobrien case DW_OP_minus: 627577298Sobrien printf ("DW_OP_minus"); 627677298Sobrien break; 627777298Sobrien case DW_OP_mod: 627877298Sobrien printf ("DW_OP_mod"); 627977298Sobrien break; 628077298Sobrien case DW_OP_mul: 628177298Sobrien printf ("DW_OP_mul"); 628277298Sobrien break; 628377298Sobrien case DW_OP_neg: 628477298Sobrien printf ("DW_OP_neg"); 628577298Sobrien break; 628677298Sobrien case DW_OP_not: 628777298Sobrien printf ("DW_OP_not"); 628877298Sobrien break; 628977298Sobrien case DW_OP_or: 629077298Sobrien printf ("DW_OP_or"); 629177298Sobrien break; 629277298Sobrien case DW_OP_plus: 629377298Sobrien printf ("DW_OP_plus"); 629477298Sobrien break; 629577298Sobrien case DW_OP_plus_uconst: 629677298Sobrien printf ("DW_OP_plus_uconst: %lu", 629777298Sobrien read_leb128 (data, &bytes_read, 0)); 629877298Sobrien data += bytes_read; 629977298Sobrien break; 630077298Sobrien case DW_OP_shl: 630177298Sobrien printf ("DW_OP_shl"); 630277298Sobrien break; 630377298Sobrien case DW_OP_shr: 630477298Sobrien printf ("DW_OP_shr"); 630577298Sobrien break; 630677298Sobrien case DW_OP_shra: 630777298Sobrien printf ("DW_OP_shra"); 630877298Sobrien break; 630977298Sobrien case DW_OP_xor: 631077298Sobrien printf ("DW_OP_xor"); 631177298Sobrien break; 631277298Sobrien case DW_OP_bra: 631377298Sobrien printf ("DW_OP_bra: %ld", (long) byte_get (data, 2)); 631477298Sobrien data += 2; 631577298Sobrien break; 631677298Sobrien case DW_OP_eq: 631777298Sobrien printf ("DW_OP_eq"); 631877298Sobrien break; 631977298Sobrien case DW_OP_ge: 632077298Sobrien printf ("DW_OP_ge"); 632177298Sobrien break; 632277298Sobrien case DW_OP_gt: 632377298Sobrien printf ("DW_OP_gt"); 632477298Sobrien break; 632577298Sobrien case DW_OP_le: 632677298Sobrien printf ("DW_OP_le"); 632777298Sobrien break; 632877298Sobrien case DW_OP_lt: 632977298Sobrien printf ("DW_OP_lt"); 633077298Sobrien break; 633177298Sobrien case DW_OP_ne: 633277298Sobrien printf ("DW_OP_ne"); 633377298Sobrien break; 633477298Sobrien case DW_OP_skip: 633577298Sobrien printf ("DW_OP_skip: %ld", (long) byte_get (data, 2)); 633677298Sobrien data += 2; 633777298Sobrien break; 633877298Sobrien 633977298Sobrien case DW_OP_lit0: 634077298Sobrien case DW_OP_lit1: 634177298Sobrien case DW_OP_lit2: 634277298Sobrien case DW_OP_lit3: 634377298Sobrien case DW_OP_lit4: 634477298Sobrien case DW_OP_lit5: 634577298Sobrien case DW_OP_lit6: 634677298Sobrien case DW_OP_lit7: 634777298Sobrien case DW_OP_lit8: 634877298Sobrien case DW_OP_lit9: 634977298Sobrien case DW_OP_lit10: 635077298Sobrien case DW_OP_lit11: 635177298Sobrien case DW_OP_lit12: 635277298Sobrien case DW_OP_lit13: 635377298Sobrien case DW_OP_lit14: 635477298Sobrien case DW_OP_lit15: 635577298Sobrien case DW_OP_lit16: 635677298Sobrien case DW_OP_lit17: 635777298Sobrien case DW_OP_lit18: 635877298Sobrien case DW_OP_lit19: 635977298Sobrien case DW_OP_lit20: 636077298Sobrien case DW_OP_lit21: 636177298Sobrien case DW_OP_lit22: 636277298Sobrien case DW_OP_lit23: 636377298Sobrien case DW_OP_lit24: 636477298Sobrien case DW_OP_lit25: 636577298Sobrien case DW_OP_lit26: 636677298Sobrien case DW_OP_lit27: 636777298Sobrien case DW_OP_lit28: 636877298Sobrien case DW_OP_lit29: 636977298Sobrien case DW_OP_lit30: 637077298Sobrien case DW_OP_lit31: 637177298Sobrien printf ("DW_OP_lit%d", op - DW_OP_lit0); 637277298Sobrien break; 637377298Sobrien 637477298Sobrien case DW_OP_reg0: 637577298Sobrien case DW_OP_reg1: 637677298Sobrien case DW_OP_reg2: 637777298Sobrien case DW_OP_reg3: 637877298Sobrien case DW_OP_reg4: 637977298Sobrien case DW_OP_reg5: 638077298Sobrien case DW_OP_reg6: 638177298Sobrien case DW_OP_reg7: 638277298Sobrien case DW_OP_reg8: 638377298Sobrien case DW_OP_reg9: 638477298Sobrien case DW_OP_reg10: 638577298Sobrien case DW_OP_reg11: 638677298Sobrien case DW_OP_reg12: 638777298Sobrien case DW_OP_reg13: 638877298Sobrien case DW_OP_reg14: 638977298Sobrien case DW_OP_reg15: 639077298Sobrien case DW_OP_reg16: 639177298Sobrien case DW_OP_reg17: 639277298Sobrien case DW_OP_reg18: 639377298Sobrien case DW_OP_reg19: 639477298Sobrien case DW_OP_reg20: 639577298Sobrien case DW_OP_reg21: 639677298Sobrien case DW_OP_reg22: 639777298Sobrien case DW_OP_reg23: 639877298Sobrien case DW_OP_reg24: 639977298Sobrien case DW_OP_reg25: 640077298Sobrien case DW_OP_reg26: 640177298Sobrien case DW_OP_reg27: 640277298Sobrien case DW_OP_reg28: 640377298Sobrien case DW_OP_reg29: 640477298Sobrien case DW_OP_reg30: 640577298Sobrien case DW_OP_reg31: 640677298Sobrien printf ("DW_OP_reg%d", op - DW_OP_reg0); 640777298Sobrien break; 640877298Sobrien 640977298Sobrien case DW_OP_breg0: 641077298Sobrien case DW_OP_breg1: 641177298Sobrien case DW_OP_breg2: 641277298Sobrien case DW_OP_breg3: 641377298Sobrien case DW_OP_breg4: 641477298Sobrien case DW_OP_breg5: 641577298Sobrien case DW_OP_breg6: 641677298Sobrien case DW_OP_breg7: 641777298Sobrien case DW_OP_breg8: 641877298Sobrien case DW_OP_breg9: 641977298Sobrien case DW_OP_breg10: 642077298Sobrien case DW_OP_breg11: 642177298Sobrien case DW_OP_breg12: 642277298Sobrien case DW_OP_breg13: 642377298Sobrien case DW_OP_breg14: 642477298Sobrien case DW_OP_breg15: 642577298Sobrien case DW_OP_breg16: 642677298Sobrien case DW_OP_breg17: 642777298Sobrien case DW_OP_breg18: 642877298Sobrien case DW_OP_breg19: 642977298Sobrien case DW_OP_breg20: 643077298Sobrien case DW_OP_breg21: 643177298Sobrien case DW_OP_breg22: 643277298Sobrien case DW_OP_breg23: 643377298Sobrien case DW_OP_breg24: 643477298Sobrien case DW_OP_breg25: 643577298Sobrien case DW_OP_breg26: 643677298Sobrien case DW_OP_breg27: 643777298Sobrien case DW_OP_breg28: 643877298Sobrien case DW_OP_breg29: 643977298Sobrien case DW_OP_breg30: 644077298Sobrien case DW_OP_breg31: 644177298Sobrien printf ("DW_OP_breg%d: %ld", op - DW_OP_breg0, 644277298Sobrien read_leb128 (data, &bytes_read, 1)); 644377298Sobrien data += bytes_read; 644477298Sobrien break; 644577298Sobrien 644677298Sobrien case DW_OP_regx: 644777298Sobrien printf ("DW_OP_regx: %lu", read_leb128 (data, &bytes_read, 0)); 644877298Sobrien data += bytes_read; 644977298Sobrien break; 645077298Sobrien case DW_OP_fbreg: 645177298Sobrien printf ("DW_OP_fbreg: %ld", read_leb128 (data, &bytes_read, 1)); 645277298Sobrien data += bytes_read; 645377298Sobrien break; 645477298Sobrien case DW_OP_bregx: 645577298Sobrien uvalue = read_leb128 (data, &bytes_read, 0); 645677298Sobrien data += bytes_read; 645777298Sobrien printf ("DW_OP_bregx: %lu %ld", uvalue, 645877298Sobrien read_leb128 (data, &bytes_read, 1)); 645977298Sobrien data += bytes_read; 646077298Sobrien break; 646177298Sobrien case DW_OP_piece: 646277298Sobrien printf ("DW_OP_piece: %lu", read_leb128 (data, &bytes_read, 0)); 646377298Sobrien data += bytes_read; 646477298Sobrien break; 646577298Sobrien case DW_OP_deref_size: 646677298Sobrien printf ("DW_OP_deref_size: %ld", (long) byte_get (data++, 1)); 646777298Sobrien break; 646877298Sobrien case DW_OP_xderef_size: 646977298Sobrien printf ("DW_OP_xderef_size: %ld", (long) byte_get (data++, 1)); 647077298Sobrien break; 647177298Sobrien case DW_OP_nop: 647277298Sobrien printf ("DW_OP_nop"); 647377298Sobrien break; 647477298Sobrien 647577298Sobrien default: 647677298Sobrien if (op >= DW_OP_lo_user 647777298Sobrien && op <= DW_OP_hi_user) 647877298Sobrien printf (_("(User defined location op)")); 647977298Sobrien else 648077298Sobrien printf (_("(Unknown location op)")); 648177298Sobrien /* No way to tell where the next op is, so just bail. */ 648277298Sobrien return; 648377298Sobrien } 648460484Sobrien } 648560484Sobrien} 648660484Sobrien 648760484Sobrien 648860484Sobrienstatic unsigned char * 648977298Sobrienread_and_display_attr (attribute, form, data, cu_offset, pointer_size) 649060484Sobrien unsigned long attribute; 649160484Sobrien unsigned long form; 649260484Sobrien unsigned char * data; 649377298Sobrien unsigned long cu_offset; 649460484Sobrien unsigned long pointer_size; 649560484Sobrien{ 649660484Sobrien unsigned long uvalue = 0; 649760484Sobrien unsigned char * block_start = NULL; 649860484Sobrien int bytes_read; 649960484Sobrien 650060484Sobrien printf (" %-18s:", get_AT_name (attribute)); 650160484Sobrien 650260484Sobrien switch (form) 650360484Sobrien { 650477298Sobrien default: 650577298Sobrien break; 650660484Sobrien 650760484Sobrien case DW_FORM_ref_addr: 650860484Sobrien case DW_FORM_addr: 650960484Sobrien uvalue = byte_get (data, pointer_size); 651060484Sobrien data += pointer_size; 651160484Sobrien break; 651260484Sobrien 651360484Sobrien case DW_FORM_ref1: 651460484Sobrien case DW_FORM_flag: 651560484Sobrien case DW_FORM_data1: 651660484Sobrien uvalue = byte_get (data ++, 1); 651760484Sobrien break; 651860484Sobrien 651960484Sobrien case DW_FORM_ref2: 652060484Sobrien case DW_FORM_data2: 652160484Sobrien uvalue = byte_get (data, 2); 652260484Sobrien data += 2; 652360484Sobrien break; 652460484Sobrien 652560484Sobrien case DW_FORM_ref4: 652660484Sobrien case DW_FORM_data4: 652760484Sobrien uvalue = byte_get (data, 4); 652860484Sobrien data += 4; 652960484Sobrien break; 653060484Sobrien 653177298Sobrien case DW_FORM_sdata: 653277298Sobrien uvalue = read_leb128 (data, & bytes_read, 1); 653377298Sobrien data += bytes_read; 653477298Sobrien break; 653577298Sobrien 653677298Sobrien case DW_FORM_ref_udata: 653777298Sobrien case DW_FORM_udata: 653877298Sobrien uvalue = read_leb128 (data, & bytes_read, 0); 653977298Sobrien data += bytes_read; 654077298Sobrien break; 654177298Sobrien } 654277298Sobrien 654377298Sobrien switch (form) 654477298Sobrien { 654577298Sobrien case DW_FORM_ref_addr: 654677298Sobrien printf (" <#%lx>", uvalue); 654777298Sobrien break; 654877298Sobrien 654977298Sobrien case DW_FORM_ref1: 655077298Sobrien case DW_FORM_ref2: 655177298Sobrien case DW_FORM_ref4: 655277298Sobrien case DW_FORM_ref_udata: 655377298Sobrien printf (" <%lx>", uvalue + cu_offset); 655477298Sobrien break; 655577298Sobrien 655677298Sobrien case DW_FORM_addr: 655777298Sobrien printf (" %#lx", uvalue); 655877298Sobrien 655977298Sobrien case DW_FORM_flag: 656077298Sobrien case DW_FORM_data1: 656177298Sobrien case DW_FORM_data2: 656277298Sobrien case DW_FORM_data4: 656377298Sobrien case DW_FORM_sdata: 656477298Sobrien case DW_FORM_udata: 656577298Sobrien printf (" %ld", uvalue); 656677298Sobrien break; 656777298Sobrien 656860484Sobrien case DW_FORM_ref8: 656960484Sobrien case DW_FORM_data8: 657060484Sobrien uvalue = byte_get (data, 4); 657160484Sobrien printf (" %lx", uvalue); 657260484Sobrien printf (" %lx", (unsigned long) byte_get (data + 4, 4)); 657360484Sobrien data += 8; 657460484Sobrien break; 657560484Sobrien 657660484Sobrien case DW_FORM_string: 657760484Sobrien printf (" %s", data); 657877298Sobrien data += strlen ((char *) data) + 1; 657960484Sobrien break; 658060484Sobrien 658160484Sobrien case DW_FORM_block: 658260484Sobrien uvalue = read_leb128 (data, & bytes_read, 0); 658360484Sobrien block_start = data + bytes_read; 658460484Sobrien data = display_block (block_start, uvalue); 658560484Sobrien break; 658660484Sobrien 658760484Sobrien case DW_FORM_block1: 658860484Sobrien uvalue = byte_get (data, 1); 658960484Sobrien block_start = data + 1; 659060484Sobrien data = display_block (block_start, uvalue); 659160484Sobrien break; 659260484Sobrien 659360484Sobrien case DW_FORM_block2: 659460484Sobrien uvalue = byte_get (data, 2); 659560484Sobrien block_start = data + 2; 659660484Sobrien data = display_block (block_start, uvalue); 659760484Sobrien break; 659860484Sobrien 659960484Sobrien case DW_FORM_block4: 660060484Sobrien uvalue = byte_get (data, 4); 660160484Sobrien block_start = data + 4; 660260484Sobrien data = display_block (block_start, uvalue); 660360484Sobrien break; 660460484Sobrien 660560484Sobrien case DW_FORM_strp: 660660484Sobrien case DW_FORM_indirect: 660760484Sobrien warn (_("Unable to handle FORM: %d"), form); 660860484Sobrien break; 660960484Sobrien 661060484Sobrien default: 661160484Sobrien warn (_("Unrecognised form: %d"), form); 661260484Sobrien break; 661360484Sobrien } 661460484Sobrien 661560484Sobrien /* For some attributes we can display futher information. */ 661660484Sobrien 661760484Sobrien printf ("\t"); 661860484Sobrien 661960484Sobrien switch (attribute) 662060484Sobrien { 662160484Sobrien case DW_AT_inline: 662260484Sobrien switch (uvalue) 662360484Sobrien { 662460484Sobrien case DW_INL_not_inlined: printf (_("(not inlined)")); break; 662560484Sobrien case DW_INL_inlined: printf (_("(inlined)")); break; 662660484Sobrien case DW_INL_declared_not_inlined: printf (_("(declared as inline but ignored)")); break; 662760484Sobrien case DW_INL_declared_inlined: printf (_("(declared as inline and inlined)")); break; 662860484Sobrien default: printf (_(" (Unknown inline attribute value: %lx)"), uvalue); break; 662960484Sobrien } 663060484Sobrien break; 663160484Sobrien 663260484Sobrien case DW_AT_language: 663360484Sobrien switch (uvalue) 663460484Sobrien { 663560484Sobrien case DW_LANG_C: printf ("(non-ANSI C)"); break; 663660484Sobrien case DW_LANG_C89: printf ("(ANSI C)"); break; 663760484Sobrien case DW_LANG_C_plus_plus: printf ("(C++)"); break; 663860484Sobrien case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break; 663960484Sobrien case DW_LANG_Fortran90: printf ("(Fortran 90)"); break; 664060484Sobrien case DW_LANG_Modula2: printf ("(Modula 2)"); break; 664160484Sobrien case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break; 664260484Sobrien case DW_LANG_Ada83: printf ("(Ada)"); break; 664360484Sobrien case DW_LANG_Cobol74: printf ("(Cobol 74)"); break; 664460484Sobrien case DW_LANG_Cobol85: printf ("(Cobol 85)"); break; 664560484Sobrien case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break; 664660484Sobrien default: printf ("(Unknown: %lx)", uvalue); break; 664760484Sobrien } 664860484Sobrien break; 664960484Sobrien 665060484Sobrien case DW_AT_encoding: 665160484Sobrien switch (uvalue) 665260484Sobrien { 665360484Sobrien case DW_ATE_void: printf ("(void)"); break; 665460484Sobrien case DW_ATE_address: printf ("(machine address)"); break; 665560484Sobrien case DW_ATE_boolean: printf ("(boolean)"); break; 665660484Sobrien case DW_ATE_complex_float: printf ("(complex float)"); break; 665760484Sobrien case DW_ATE_float: printf ("(float)"); break; 665860484Sobrien case DW_ATE_signed: printf ("(signed)"); break; 665960484Sobrien case DW_ATE_signed_char: printf ("(signed char)"); break; 666060484Sobrien case DW_ATE_unsigned: printf ("(unsigned)"); break; 666160484Sobrien case DW_ATE_unsigned_char: printf ("(unsigned char)"); break; 666260484Sobrien default: 666360484Sobrien if (uvalue >= DW_ATE_lo_user 666460484Sobrien && uvalue <= DW_ATE_hi_user) 666560484Sobrien printf ("(user defined type)"); 666660484Sobrien else 666760484Sobrien printf ("(unknown type)"); 666860484Sobrien break; 666960484Sobrien } 667060484Sobrien break; 667160484Sobrien 667260484Sobrien case DW_AT_accessibility: 667360484Sobrien switch (uvalue) 667460484Sobrien { 667560484Sobrien case DW_ACCESS_public: printf ("(public)"); break; 667660484Sobrien case DW_ACCESS_protected: printf ("(protected)"); break; 667760484Sobrien case DW_ACCESS_private: printf ("(private)"); break; 667860484Sobrien default: printf ("(unknown accessibility)"); break; 667960484Sobrien } 668060484Sobrien break; 668160484Sobrien 668260484Sobrien case DW_AT_visibility: 668360484Sobrien switch (uvalue) 668460484Sobrien { 668560484Sobrien case DW_VIS_local: printf ("(local)"); break; 668660484Sobrien case DW_VIS_exported: printf ("(exported)"); break; 668760484Sobrien case DW_VIS_qualified: printf ("(qualified)"); break; 668860484Sobrien default: printf ("(unknown visibility)"); break; 668960484Sobrien } 669060484Sobrien break; 669160484Sobrien 669260484Sobrien case DW_AT_virtuality: 669360484Sobrien switch (uvalue) 669460484Sobrien { 669560484Sobrien case DW_VIRTUALITY_none: printf ("(none)"); break; 669660484Sobrien case DW_VIRTUALITY_virtual: printf ("(virtual)"); break; 669760484Sobrien case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break; 669860484Sobrien default: printf ("(unknown virtuality)"); break; 669960484Sobrien } 670060484Sobrien break; 670160484Sobrien 670260484Sobrien case DW_AT_identifier_case: 670360484Sobrien switch (uvalue) 670460484Sobrien { 670560484Sobrien case DW_ID_case_sensitive: printf ("(case_sensitive)"); break; 670660484Sobrien case DW_ID_up_case: printf ("(up_case)"); break; 670760484Sobrien case DW_ID_down_case: printf ("(down_case)"); break; 670860484Sobrien case DW_ID_case_insensitive: printf ("(case_insensitive)"); break; 670960484Sobrien default: printf ("(unknown case)"); break; 671060484Sobrien } 671160484Sobrien break; 671260484Sobrien 671360484Sobrien case DW_AT_calling_convention: 671460484Sobrien switch (uvalue) 671560484Sobrien { 671660484Sobrien case DW_CC_normal: printf ("(normal)"); break; 671760484Sobrien case DW_CC_program: printf ("(program)"); break; 671860484Sobrien case DW_CC_nocall: printf ("(nocall)"); break; 671960484Sobrien default: 672060484Sobrien if (uvalue >= DW_CC_lo_user 672160484Sobrien && uvalue <= DW_CC_hi_user) 672260484Sobrien printf ("(user defined)"); 672360484Sobrien else 672460484Sobrien printf ("(unknown convention)"); 672560484Sobrien } 672660484Sobrien break; 672760484Sobrien 672877298Sobrien case DW_AT_frame_base: 672960484Sobrien case DW_AT_location: 673060484Sobrien case DW_AT_data_member_location: 673160484Sobrien case DW_AT_vtable_elem_location: 673277298Sobrien if (block_start) 673377298Sobrien { 673477298Sobrien printf ("("); 673577298Sobrien decode_location_expression (block_start, pointer_size, uvalue); 673677298Sobrien printf (")"); 673777298Sobrien } 673860484Sobrien break; 673960484Sobrien 674060484Sobrien default: 674160484Sobrien break; 674260484Sobrien } 674360484Sobrien 674460484Sobrien printf ("\n"); 674560484Sobrien return data; 674660484Sobrien} 674760484Sobrien 674860484Sobrienstatic int 674960484Sobriendisplay_debug_info (section, start, file) 675060484Sobrien Elf32_Internal_Shdr * section; 675160484Sobrien unsigned char * start; 675260484Sobrien FILE * file; 675360484Sobrien{ 675460484Sobrien unsigned char * end = start + section->sh_size; 675560484Sobrien unsigned char * section_begin = start; 675660484Sobrien 675760484Sobrien printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); 675860484Sobrien 675960484Sobrien while (start < end) 676060484Sobrien { 676160484Sobrien DWARF2_External_CompUnit * external; 676260484Sobrien DWARF2_Internal_CompUnit compunit; 676360484Sobrien unsigned char * tags; 676460484Sobrien int i; 676560484Sobrien int level; 676677298Sobrien unsigned long cu_offset; 676760484Sobrien 676860484Sobrien external = (DWARF2_External_CompUnit *) start; 676960484Sobrien 677060484Sobrien compunit.cu_length = BYTE_GET (external->cu_length); 677160484Sobrien compunit.cu_version = BYTE_GET (external->cu_version); 677260484Sobrien compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset); 677360484Sobrien compunit.cu_pointer_size = BYTE_GET (external->cu_pointer_size); 677460484Sobrien 677560484Sobrien tags = start + sizeof (* external); 677677298Sobrien cu_offset = start - section_begin; 677760484Sobrien start += compunit.cu_length + sizeof (external->cu_length); 677860484Sobrien 677977298Sobrien printf (_(" Compilation Unit @ %lx:\n"), cu_offset); 678077298Sobrien printf (_(" Length: %ld\n"), compunit.cu_length); 678177298Sobrien printf (_(" Version: %d\n"), compunit.cu_version); 678277298Sobrien printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset); 678377298Sobrien printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size); 678477298Sobrien 678560484Sobrien if (compunit.cu_version != 2) 678660484Sobrien { 678760484Sobrien warn (_("Only version 2 DWARF debug information is currently supported.\n")); 678860484Sobrien continue; 678960484Sobrien } 679060484Sobrien 679160484Sobrien if (first_abbrev != NULL) 679260484Sobrien free_abbrevs (); 679360484Sobrien 679460484Sobrien /* Read in the abbrevs used by this compilation unit. */ 679560484Sobrien 679660484Sobrien { 679760484Sobrien Elf32_Internal_Shdr * sec; 679860484Sobrien unsigned char * begin; 679960484Sobrien 680060484Sobrien /* Locate the .debug_abbrev section and process it. */ 680160484Sobrien for (i = 0, sec = section_headers; 680260484Sobrien i < elf_header.e_shnum; 680360484Sobrien i ++, sec ++) 680460484Sobrien if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0) 680560484Sobrien break; 680660484Sobrien 680760484Sobrien if (i == -1 || sec->sh_size == 0) 680860484Sobrien { 680960484Sobrien warn (_("Unable to locate .debug_abbrev section!\n")); 681060484Sobrien return 0; 681160484Sobrien } 681260484Sobrien 681360484Sobrien GET_DATA_ALLOC (sec->sh_offset, sec->sh_size, begin, unsigned char *, 681460484Sobrien "debug_abbrev section data"); 681560484Sobrien 681660484Sobrien process_abbrev_section (begin + compunit.cu_abbrev_offset, 681760484Sobrien begin + sec->sh_size); 681860484Sobrien 681960484Sobrien free (begin); 682060484Sobrien } 682160484Sobrien 682260484Sobrien level = 0; 682360484Sobrien while (tags < start) 682460484Sobrien { 682560484Sobrien int bytes_read; 682660484Sobrien unsigned long abbrev_number; 682760484Sobrien abbrev_entry * entry; 682860484Sobrien abbrev_attr * attr; 682960484Sobrien 683060484Sobrien abbrev_number = read_leb128 (tags, & bytes_read, 0); 683160484Sobrien tags += bytes_read; 683260484Sobrien 683360484Sobrien /* A null DIE marks the end of a list of children. */ 683460484Sobrien if (abbrev_number == 0) 683560484Sobrien { 683660484Sobrien --level; 683760484Sobrien continue; 683860484Sobrien } 683960484Sobrien 684060484Sobrien /* Scan through the abbreviation list until we reach the 684160484Sobrien correct entry. */ 684260484Sobrien for (entry = first_abbrev; 684360484Sobrien entry && entry->entry != abbrev_number; 684460484Sobrien entry = entry->next) 684560484Sobrien continue; 684660484Sobrien 684760484Sobrien if (entry == NULL) 684860484Sobrien { 684960484Sobrien warn (_("Unable to locate entry %lu in the abbreviation table\n"), 685060484Sobrien abbrev_number); 685160484Sobrien return 0; 685260484Sobrien } 685360484Sobrien 685460484Sobrien printf (_(" <%d><%x>: Abbrev Number: %lu (%s)\n"), 685560484Sobrien level, tags - section_begin - bytes_read, 685660484Sobrien abbrev_number, 685760484Sobrien get_TAG_name (entry->tag)); 685860484Sobrien 685960484Sobrien for (attr = entry->first_attr; attr; attr = attr->next) 686060484Sobrien tags = read_and_display_attr (attr->attribute, 686160484Sobrien attr->form, 686277298Sobrien tags, cu_offset, 686360484Sobrien compunit.cu_pointer_size); 686460484Sobrien 686560484Sobrien if (entry->children) 686660484Sobrien ++level; 686760484Sobrien } 686860484Sobrien } 686960484Sobrien 687060484Sobrien printf ("\n"); 687160484Sobrien 687260484Sobrien return 1; 687360484Sobrien} 687460484Sobrien 687560484Sobrienstatic int 687660484Sobriendisplay_debug_aranges (section, start, file) 687760484Sobrien Elf32_Internal_Shdr * section; 687860484Sobrien unsigned char * start; 687960484Sobrien FILE * file ATTRIBUTE_UNUSED; 688060484Sobrien{ 688160484Sobrien unsigned char * end = start + section->sh_size; 688260484Sobrien 688360484Sobrien printf (_("The section %s contains:\n\n"), SECTION_NAME (section)); 688460484Sobrien 688560484Sobrien while (start < end) 688660484Sobrien { 688760484Sobrien DWARF2_External_ARange * external; 688860484Sobrien DWARF2_Internal_ARange arange; 688960484Sobrien unsigned char * ranges; 689060484Sobrien unsigned long length; 689160484Sobrien unsigned long address; 689260484Sobrien int excess; 689360484Sobrien 689460484Sobrien external = (DWARF2_External_ARange *) start; 689560484Sobrien 689660484Sobrien arange.ar_length = BYTE_GET (external->ar_length); 689760484Sobrien arange.ar_version = BYTE_GET (external->ar_version); 689860484Sobrien arange.ar_info_offset = BYTE_GET (external->ar_info_offset); 689960484Sobrien arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size); 690060484Sobrien arange.ar_segment_size = BYTE_GET (external->ar_segment_size); 690160484Sobrien 690268765Sobrien if (arange.ar_version != 2) 690368765Sobrien { 690468765Sobrien warn (_("Only DWARF 2 aranges are currently supported.\n")); 690568765Sobrien break; 690668765Sobrien } 690768765Sobrien 690860484Sobrien printf (_(" Length: %ld\n"), arange.ar_length); 690960484Sobrien printf (_(" Version: %d\n"), arange.ar_version); 691060484Sobrien printf (_(" Offset into .debug_info: %lx\n"), arange.ar_info_offset); 691160484Sobrien printf (_(" Pointer Size: %d\n"), arange.ar_pointer_size); 691260484Sobrien printf (_(" Segment Size: %d\n"), arange.ar_segment_size); 691360484Sobrien 691460484Sobrien printf (_("\n Address Length\n")); 691560484Sobrien 691660484Sobrien ranges = start + sizeof (* external); 691760484Sobrien 691860484Sobrien /* Must pad to an alignment boundary that is twice the pointer size. */ 691977298Sobrien excess = sizeof (* external) % (2 * arange.ar_pointer_size); 692060484Sobrien if (excess) 692160484Sobrien ranges += (2 * arange.ar_pointer_size) - excess; 692260484Sobrien 692360484Sobrien for (;;) 692460484Sobrien { 692560484Sobrien address = byte_get (ranges, arange.ar_pointer_size); 692660484Sobrien 692760484Sobrien ranges += arange.ar_pointer_size; 692860484Sobrien 692960484Sobrien length = byte_get (ranges, arange.ar_pointer_size); 693060484Sobrien 693160484Sobrien ranges += arange.ar_pointer_size; 693260484Sobrien 693360484Sobrien /* A pair of zeros marks the end of the list. */ 693460484Sobrien if (address == 0 && length == 0) 693560484Sobrien break; 693660484Sobrien 693760484Sobrien printf (" %8.8lx %lu\n", address, length); 693860484Sobrien } 693960484Sobrien 694060484Sobrien start += arange.ar_length + sizeof (external->ar_length); 694160484Sobrien } 694260484Sobrien 694360484Sobrien printf ("\n"); 694460484Sobrien 694560484Sobrien return 1; 694660484Sobrien} 694760484Sobrien 694877298Sobrientypedef struct Frame_Chunk 694977298Sobrien{ 695077298Sobrien struct Frame_Chunk * next; 695177298Sobrien unsigned char * chunk_start; 695277298Sobrien int ncols; 695377298Sobrien /* DW_CFA_{undefined,same_value,offset,register,unreferenced} */ 695477298Sobrien short int * col_type; 695577298Sobrien int * col_offset; 695677298Sobrien char * augmentation; 695777298Sobrien unsigned int code_factor; 695878828Sobrien int data_factor; 695977298Sobrien unsigned long pc_begin; 696077298Sobrien unsigned long pc_range; 696177298Sobrien int cfa_reg; 696277298Sobrien int cfa_offset; 696377298Sobrien int ra; 696478828Sobrien unsigned char fde_encoding; 696577298Sobrien} 696677298SobrienFrame_Chunk; 696760484Sobrien 696877298Sobrien/* A marker for a col_type that means this column was never referenced 696977298Sobrien in the frame info. */ 697077298Sobrien#define DW_CFA_unreferenced (-1) 697177298Sobrien 697277298Sobrienstatic void 697377298Sobrienframe_need_space (fc, reg) 697477298Sobrien Frame_Chunk * fc; 697577298Sobrien int reg; 697677298Sobrien{ 697777298Sobrien int prev = fc->ncols; 697877298Sobrien 697977298Sobrien if (reg < fc->ncols) 698077298Sobrien return; 698177298Sobrien 698277298Sobrien fc->ncols = reg + 1; 698377298Sobrien fc->col_type = (short int *) xrealloc (fc->col_type, 698477298Sobrien fc->ncols * sizeof (short int)); 698577298Sobrien fc->col_offset = (int *) xrealloc (fc->col_offset, 698677298Sobrien fc->ncols * sizeof (int)); 698777298Sobrien 698877298Sobrien while (prev < fc->ncols) 698977298Sobrien { 699077298Sobrien fc->col_type[prev] = DW_CFA_unreferenced; 699177298Sobrien fc->col_offset[prev] = 0; 699277298Sobrien prev++; 699377298Sobrien } 699477298Sobrien} 699577298Sobrien 699677298Sobrienstatic void 699777298Sobrienframe_display_row (fc, need_col_headers, max_regs) 699877298Sobrien Frame_Chunk * fc; 699977298Sobrien int * need_col_headers; 700077298Sobrien int * max_regs; 700177298Sobrien{ 700277298Sobrien int r; 700377298Sobrien char tmp[100]; 700477298Sobrien 700577298Sobrien if (* max_regs < fc->ncols) 700677298Sobrien * max_regs = fc->ncols; 700777298Sobrien 700877298Sobrien if (* need_col_headers) 700977298Sobrien { 701077298Sobrien * need_col_headers = 0; 701177298Sobrien 701277298Sobrien printf (" LOC CFA "); 701377298Sobrien 701477298Sobrien for (r = 0; r < * max_regs; r++) 701577298Sobrien if (fc->col_type[r] != DW_CFA_unreferenced) 701677298Sobrien { 701777298Sobrien if (r == fc->ra) 701877298Sobrien printf ("ra "); 701977298Sobrien else 702077298Sobrien printf ("r%-4d", r); 702177298Sobrien } 702277298Sobrien 702377298Sobrien printf ("\n"); 702477298Sobrien } 702577298Sobrien 702678828Sobrien printf ("%08lx ", fc->pc_begin); 702777298Sobrien sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset); 702877298Sobrien printf ("%-8s ", tmp); 702977298Sobrien 703077298Sobrien for (r = 0; r < fc->ncols; r++) 703177298Sobrien { 703277298Sobrien if (fc->col_type[r] != DW_CFA_unreferenced) 703377298Sobrien { 703477298Sobrien switch (fc->col_type[r]) 703577298Sobrien { 703677298Sobrien case DW_CFA_undefined: 703777298Sobrien strcpy (tmp, "u"); 703877298Sobrien break; 703977298Sobrien case DW_CFA_same_value: 704077298Sobrien strcpy (tmp, "s"); 704177298Sobrien break; 704277298Sobrien case DW_CFA_offset: 704377298Sobrien sprintf (tmp, "c%+d", fc->col_offset[r]); 704477298Sobrien break; 704577298Sobrien case DW_CFA_register: 704677298Sobrien sprintf (tmp, "r%d", fc->col_offset[r]); 704777298Sobrien break; 704877298Sobrien default: 704977298Sobrien strcpy (tmp, "n/a"); 705077298Sobrien break; 705177298Sobrien } 705277298Sobrien printf ("%-5s", tmp); 705377298Sobrien } 705477298Sobrien } 705577298Sobrien printf ("\n"); 705677298Sobrien} 705777298Sobrien 705878828Sobrienstatic int 705978828Sobriensize_of_encoded_value (encoding) 706078828Sobrien int encoding; 706178828Sobrien{ 706278828Sobrien switch (encoding & 0x7) 706378828Sobrien { 706478828Sobrien default: /* ??? */ 706578828Sobrien case 0: return is_32bit_elf ? 4 : 8; 706678828Sobrien case 2: return 2; 706778828Sobrien case 3: return 4; 706878828Sobrien case 4: return 8; 706978828Sobrien } 707078828Sobrien} 707178828Sobrien 707277298Sobrien#define GET(N) byte_get (start, N); start += N 707377298Sobrien#define LEB() read_leb128 (start, & length_return, 0); start += length_return 707477298Sobrien#define SLEB() read_leb128 (start, & length_return, 1); start += length_return 707577298Sobrien 707660484Sobrienstatic int 707777298Sobriendisplay_debug_frames (section, start, file) 707877298Sobrien Elf32_Internal_Shdr * section; 707977298Sobrien unsigned char * start; 708077298Sobrien FILE * file ATTRIBUTE_UNUSED; 708177298Sobrien{ 708277298Sobrien unsigned char * end = start + section->sh_size; 708377298Sobrien unsigned char * section_start = start; 708477298Sobrien Frame_Chunk * chunks = 0; 708577298Sobrien Frame_Chunk * remembered_state = 0; 708677298Sobrien Frame_Chunk * rs; 708777298Sobrien int is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0); 708877298Sobrien int length_return; 708977298Sobrien int max_regs = 0; 709078828Sobrien int addr_size = is_32bit_elf ? 4 : 8; 709177298Sobrien 709277298Sobrien printf (_("The section %s contains:\n"), SECTION_NAME (section)); 709377298Sobrien 709477298Sobrien while (start < end) 709577298Sobrien { 709677298Sobrien unsigned char * saved_start; 709777298Sobrien unsigned char * block_end; 709877298Sobrien unsigned long length; 709977298Sobrien unsigned long cie_id; 710077298Sobrien Frame_Chunk * fc; 710177298Sobrien Frame_Chunk * cie; 710277298Sobrien int need_col_headers = 1; 710378828Sobrien unsigned char * augmentation_data = NULL; 710478828Sobrien unsigned long augmentation_data_len = 0; 710578828Sobrien int encoded_ptr_size = addr_size; 710677298Sobrien 710777298Sobrien saved_start = start; 710877298Sobrien length = byte_get (start, 4); start += 4; 710977298Sobrien 711077298Sobrien if (length == 0) 711177298Sobrien return 1; 711277298Sobrien 711377298Sobrien block_end = saved_start + length + 4; 711477298Sobrien cie_id = byte_get (start, 4); start += 4; 711577298Sobrien 711677298Sobrien if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID)) 711777298Sobrien { 711878828Sobrien int version; 711978828Sobrien 712077298Sobrien fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk)); 712177298Sobrien memset (fc, 0, sizeof (Frame_Chunk)); 712277298Sobrien 712377298Sobrien fc->next = chunks; 712477298Sobrien chunks = fc; 712577298Sobrien fc->chunk_start = saved_start; 712677298Sobrien fc->ncols = 0; 712777298Sobrien fc->col_type = (short int *) xmalloc (sizeof (short int)); 712877298Sobrien fc->col_offset = (int *) xmalloc (sizeof (int)); 712977298Sobrien frame_need_space (fc, max_regs-1); 713077298Sobrien 713178828Sobrien version = *start++; 713278828Sobrien 713377298Sobrien fc->augmentation = start; 713478828Sobrien start = strchr (start, '\0') + 1; 713577298Sobrien 713677298Sobrien if (fc->augmentation[0] == 'z') 713777298Sobrien { 713877298Sobrien fc->code_factor = LEB (); 713977298Sobrien fc->data_factor = SLEB (); 714077298Sobrien fc->ra = byte_get (start, 1); start += 1; 714178828Sobrien augmentation_data_len = LEB (); 714278828Sobrien augmentation_data = start; 714378828Sobrien start += augmentation_data_len; 714477298Sobrien } 714577298Sobrien else if (strcmp (fc->augmentation, "eh") == 0) 714677298Sobrien { 714778828Sobrien start += addr_size; 714877298Sobrien fc->code_factor = LEB (); 714977298Sobrien fc->data_factor = SLEB (); 715077298Sobrien fc->ra = byte_get (start, 1); start += 1; 715177298Sobrien } 715277298Sobrien else 715377298Sobrien { 715477298Sobrien fc->code_factor = LEB (); 715577298Sobrien fc->data_factor = SLEB (); 715677298Sobrien fc->ra = byte_get (start, 1); start += 1; 715777298Sobrien } 715877298Sobrien cie = fc; 715977298Sobrien 716078828Sobrien if (do_debug_frames_interp) 716178828Sobrien printf ("\n%08lx %08lx %08lx CIE \"%s\" cf=%d df=%d ra=%d\n", 716278828Sobrien (unsigned long)(saved_start - section_start), length, cie_id, 716378828Sobrien fc->augmentation, fc->code_factor, fc->data_factor, 716478828Sobrien fc->ra); 716578828Sobrien else 716678828Sobrien { 716778828Sobrien printf ("\n%08lx %08lx %08lx CIE\n", 716878828Sobrien (unsigned long)(saved_start - section_start), length, cie_id); 716978828Sobrien printf (" Version: %d\n", version); 717078828Sobrien printf (" Augmentation: \"%s\"\n", fc->augmentation); 717178828Sobrien printf (" Code alignment factor: %u\n", fc->code_factor); 717278828Sobrien printf (" Data alignment factor: %d\n", fc->data_factor); 717378828Sobrien printf (" Return address column: %d\n", fc->ra); 717478828Sobrien 717578828Sobrien if (augmentation_data_len) 717678828Sobrien { 717778828Sobrien unsigned long i; 717878828Sobrien printf (" Augmentation data: "); 717978828Sobrien for (i = 0; i < augmentation_data_len; ++i) 718078828Sobrien printf (" %02x", augmentation_data[i]); 718178828Sobrien putchar ('\n'); 718278828Sobrien } 718378828Sobrien putchar ('\n'); 718478828Sobrien } 718578828Sobrien 718678828Sobrien if (augmentation_data_len) 718778828Sobrien { 718878828Sobrien unsigned char *p, *q; 718978828Sobrien p = fc->augmentation + 1; 719078828Sobrien q = augmentation_data; 719178828Sobrien 719278828Sobrien while (1) 719378828Sobrien { 719478828Sobrien if (*p == 'L') 719578828Sobrien q++; 719678828Sobrien else if (*p == 'P') 719778828Sobrien q += 1 + size_of_encoded_value (*q); 719878828Sobrien else if (*p == 'R') 719978828Sobrien fc->fde_encoding = *q++; 720078828Sobrien else 720178828Sobrien break; 720278828Sobrien p++; 720378828Sobrien } 720478828Sobrien 720578828Sobrien if (fc->fde_encoding) 720678828Sobrien encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); 720778828Sobrien } 720878828Sobrien 720977298Sobrien frame_need_space (fc, fc->ra); 721077298Sobrien } 721177298Sobrien else 721277298Sobrien { 721377298Sobrien unsigned char * look_for; 721477298Sobrien static Frame_Chunk fde_fc; 721577298Sobrien 721677298Sobrien fc = & fde_fc; 721777298Sobrien memset (fc, 0, sizeof (Frame_Chunk)); 721877298Sobrien 721978828Sobrien look_for = is_eh ? start - 4 - cie_id : section_start + cie_id; 722077298Sobrien 722178828Sobrien for (cie=chunks; cie ; cie = cie->next) 722278828Sobrien if (cie->chunk_start == look_for) 722378828Sobrien break; 722477298Sobrien 722577298Sobrien if (!cie) 722677298Sobrien { 722778828Sobrien warn ("Invalid CIE pointer %08lx in FDE at %08lx\n", 722878828Sobrien cie_id, saved_start); 722977298Sobrien start = block_end; 723077298Sobrien fc->ncols = 0; 723177298Sobrien fc->col_type = (short int *) xmalloc (sizeof (short int)); 723277298Sobrien fc->col_offset = (int *) xmalloc (sizeof (int)); 723377298Sobrien frame_need_space (fc, max_regs - 1); 723477298Sobrien cie = fc; 723577298Sobrien fc->augmentation = ""; 723678828Sobrien fc->fde_encoding = 0; 723777298Sobrien } 723877298Sobrien else 723977298Sobrien { 724077298Sobrien fc->ncols = cie->ncols; 724177298Sobrien fc->col_type = (short int *) xmalloc (fc->ncols * sizeof (short int)); 724277298Sobrien fc->col_offset = (int *) xmalloc (fc->ncols * sizeof (int)); 724377298Sobrien memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int)); 724477298Sobrien memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int)); 724577298Sobrien fc->augmentation = cie->augmentation; 724677298Sobrien fc->code_factor = cie->code_factor; 724777298Sobrien fc->data_factor = cie->data_factor; 724877298Sobrien fc->cfa_reg = cie->cfa_reg; 724977298Sobrien fc->cfa_offset = cie->cfa_offset; 725077298Sobrien fc->ra = cie->ra; 725177298Sobrien frame_need_space (fc, max_regs-1); 725278828Sobrien fc->fde_encoding = cie->fde_encoding; 725377298Sobrien } 725477298Sobrien 725578828Sobrien if (fc->fde_encoding) 725678828Sobrien encoded_ptr_size = size_of_encoded_value (fc->fde_encoding); 725778828Sobrien 725878828Sobrien fc->pc_begin = byte_get (start, encoded_ptr_size); 725978828Sobrien start += encoded_ptr_size; 726078828Sobrien fc->pc_range = byte_get (start, encoded_ptr_size); 726178828Sobrien start += encoded_ptr_size; 726278828Sobrien 726377298Sobrien if (cie->augmentation[0] == 'z') 726477298Sobrien { 726578828Sobrien augmentation_data_len = LEB (); 726678828Sobrien augmentation_data = start; 726778828Sobrien start += augmentation_data_len; 726877298Sobrien } 726977298Sobrien 727078828Sobrien printf ("\n%08lx %08lx %08lx FDE cie=%08x pc=%08lx..%08lx\n", 727178828Sobrien (unsigned long)(saved_start - section_start), length, cie_id, 727278828Sobrien cie->chunk_start - section_start, fc->pc_begin, 727377298Sobrien fc->pc_begin + fc->pc_range); 727478828Sobrien if (! do_debug_frames_interp && augmentation_data_len) 727578828Sobrien { 727678828Sobrien unsigned long i; 727778828Sobrien printf (" Augmentation data: "); 727878828Sobrien for (i = 0; i < augmentation_data_len; ++i) 727978828Sobrien printf (" %02x", augmentation_data[i]); 728078828Sobrien putchar ('\n'); 728178828Sobrien putchar ('\n'); 728278828Sobrien } 728377298Sobrien } 728477298Sobrien 728577298Sobrien /* At this point, fc is the current chunk, cie (if any) is set, and we're 728677298Sobrien about to interpret instructions for the chunk. */ 728777298Sobrien 728878828Sobrien if (do_debug_frames_interp) 728977298Sobrien { 729077298Sobrien /* Start by making a pass over the chunk, allocating storage 729177298Sobrien and taking note of what registers are used. */ 729277298Sobrien unsigned char * tmp = start; 729377298Sobrien 729477298Sobrien while (start < block_end) 729577298Sobrien { 729677298Sobrien unsigned op, opa; 729777298Sobrien unsigned long reg; 729878828Sobrien 729977298Sobrien op = * start ++; 730077298Sobrien opa = op & 0x3f; 730177298Sobrien if (op & 0xc0) 730277298Sobrien op &= 0xc0; 730378828Sobrien 730477298Sobrien /* Warning: if you add any more cases to this switch, be 730577298Sobrien sure to add them to the corresponding switch below. */ 730677298Sobrien switch (op) 730777298Sobrien { 730877298Sobrien case DW_CFA_advance_loc: 730977298Sobrien break; 731077298Sobrien case DW_CFA_offset: 731177298Sobrien LEB (); 731277298Sobrien frame_need_space (fc, opa); 731377298Sobrien fc->col_type[opa] = DW_CFA_undefined; 731477298Sobrien break; 731577298Sobrien case DW_CFA_restore: 731677298Sobrien frame_need_space (fc, opa); 731777298Sobrien fc->col_type[opa] = DW_CFA_undefined; 731877298Sobrien break; 731977298Sobrien case DW_CFA_set_loc: 732078828Sobrien start += encoded_ptr_size; 732177298Sobrien break; 732277298Sobrien case DW_CFA_advance_loc1: 732377298Sobrien start += 1; 732477298Sobrien break; 732577298Sobrien case DW_CFA_advance_loc2: 732677298Sobrien start += 2; 732777298Sobrien break; 732877298Sobrien case DW_CFA_advance_loc4: 732977298Sobrien start += 4; 733077298Sobrien break; 733177298Sobrien case DW_CFA_offset_extended: 733277298Sobrien reg = LEB (); LEB (); 733377298Sobrien frame_need_space (fc, reg); 733477298Sobrien fc->col_type[reg] = DW_CFA_undefined; 733577298Sobrien break; 733677298Sobrien case DW_CFA_restore_extended: 733777298Sobrien reg = LEB (); 733877298Sobrien frame_need_space (fc, reg); 733977298Sobrien fc->col_type[reg] = DW_CFA_undefined; 734077298Sobrien break; 734177298Sobrien case DW_CFA_undefined: 734277298Sobrien reg = LEB (); 734377298Sobrien frame_need_space (fc, reg); 734477298Sobrien fc->col_type[reg] = DW_CFA_undefined; 734577298Sobrien break; 734677298Sobrien case DW_CFA_same_value: 734777298Sobrien reg = LEB (); 734877298Sobrien frame_need_space (fc, reg); 734977298Sobrien fc->col_type[reg] = DW_CFA_undefined; 735077298Sobrien break; 735177298Sobrien case DW_CFA_register: 735277298Sobrien reg = LEB (); LEB (); 735377298Sobrien frame_need_space (fc, reg); 735477298Sobrien fc->col_type[reg] = DW_CFA_undefined; 735577298Sobrien break; 735677298Sobrien case DW_CFA_def_cfa: 735777298Sobrien LEB (); LEB (); 735877298Sobrien break; 735977298Sobrien case DW_CFA_def_cfa_register: 736077298Sobrien LEB (); 736177298Sobrien break; 736277298Sobrien case DW_CFA_def_cfa_offset: 736377298Sobrien LEB (); 736477298Sobrien break; 736577298Sobrien#ifndef DW_CFA_GNU_args_size 736677298Sobrien#define DW_CFA_GNU_args_size 0x2e 736777298Sobrien#endif 736877298Sobrien case DW_CFA_GNU_args_size: 736977298Sobrien LEB (); 737078828Sobrien break; 737177298Sobrien#ifndef DW_CFA_GNU_negative_offset_extended 737277298Sobrien#define DW_CFA_GNU_negative_offset_extended 0x2f 737377298Sobrien#endif 737477298Sobrien case DW_CFA_GNU_negative_offset_extended: 737578828Sobrien reg = LEB (); LEB (); 737677298Sobrien frame_need_space (fc, reg); 737777298Sobrien fc->col_type[reg] = DW_CFA_undefined; 737878828Sobrien 737977298Sobrien default: 738077298Sobrien break; 738177298Sobrien } 738277298Sobrien } 738377298Sobrien start = tmp; 738477298Sobrien } 738577298Sobrien 738677298Sobrien /* Now we know what registers are used, make a second pass over 738777298Sobrien the chunk, this time actually printing out the info. */ 738877298Sobrien 738977298Sobrien while (start < block_end) 739077298Sobrien { 739177298Sobrien unsigned op, opa; 739277298Sobrien unsigned long ul, reg, roffs; 739377298Sobrien long l, ofs; 739477298Sobrien bfd_vma vma; 739577298Sobrien 739677298Sobrien op = * start ++; 739777298Sobrien opa = op & 0x3f; 739877298Sobrien if (op & 0xc0) 739977298Sobrien op &= 0xc0; 740077298Sobrien 740177298Sobrien /* Warning: if you add any more cases to this switch, be 740277298Sobrien sure to add them to the corresponding switch above. */ 740377298Sobrien switch (op) 740477298Sobrien { 740577298Sobrien case DW_CFA_advance_loc: 740678828Sobrien if (do_debug_frames_interp) 740778828Sobrien frame_display_row (fc, &need_col_headers, &max_regs); 740878828Sobrien else 740978828Sobrien printf (" DW_CFA_advance_loc: %d to %08lx\n", 741078828Sobrien opa * fc->code_factor, 741178828Sobrien fc->pc_begin + opa * fc->code_factor); 741277298Sobrien fc->pc_begin += opa * fc->code_factor; 741377298Sobrien break; 741477298Sobrien 741577298Sobrien case DW_CFA_offset: 741677298Sobrien roffs = LEB (); 741778828Sobrien if (! do_debug_frames_interp) 741878828Sobrien printf (" DW_CFA_offset: r%d at cfa%+ld\n", 741978828Sobrien opa, roffs * fc->data_factor); 742077298Sobrien fc->col_type[opa] = DW_CFA_offset; 742177298Sobrien fc->col_offset[opa] = roffs * fc->data_factor; 742277298Sobrien break; 742377298Sobrien 742477298Sobrien case DW_CFA_restore: 742578828Sobrien if (! do_debug_frames_interp) 742678828Sobrien printf (" DW_CFA_restore: r%d\n", opa); 742777298Sobrien fc->col_type[opa] = cie->col_type[opa]; 742877298Sobrien fc->col_offset[opa] = cie->col_offset[opa]; 742977298Sobrien break; 743077298Sobrien 743177298Sobrien case DW_CFA_set_loc: 743278828Sobrien vma = byte_get (start, encoded_ptr_size); 743378828Sobrien start += encoded_ptr_size; 743478828Sobrien if (do_debug_frames_interp) 743578828Sobrien frame_display_row (fc, &need_col_headers, &max_regs); 743678828Sobrien else 743778828Sobrien printf (" DW_CFA_set_loc: %08lx\n", (unsigned long)vma); 743877298Sobrien fc->pc_begin = vma; 743977298Sobrien break; 744077298Sobrien 744177298Sobrien case DW_CFA_advance_loc1: 744277298Sobrien ofs = byte_get (start, 1); start += 1; 744378828Sobrien if (do_debug_frames_interp) 744478828Sobrien frame_display_row (fc, &need_col_headers, &max_regs); 744578828Sobrien else 744678828Sobrien printf (" DW_CFA_advance_loc1: %ld to %08lx\n", 744778828Sobrien ofs * fc->code_factor, 744878828Sobrien fc->pc_begin + ofs * fc->code_factor); 744977298Sobrien fc->pc_begin += ofs * fc->code_factor; 745077298Sobrien break; 745177298Sobrien 745277298Sobrien case DW_CFA_advance_loc2: 745377298Sobrien ofs = byte_get (start, 2); start += 2; 745478828Sobrien if (do_debug_frames_interp) 745578828Sobrien frame_display_row (fc, &need_col_headers, &max_regs); 745678828Sobrien else 745778828Sobrien printf (" DW_CFA_advance_loc2: %ld to %08lx\n", 745878828Sobrien ofs * fc->code_factor, 745978828Sobrien fc->pc_begin + ofs * fc->code_factor); 746077298Sobrien fc->pc_begin += ofs * fc->code_factor; 746177298Sobrien break; 746277298Sobrien 746377298Sobrien case DW_CFA_advance_loc4: 746477298Sobrien ofs = byte_get (start, 4); start += 4; 746578828Sobrien if (do_debug_frames_interp) 746678828Sobrien frame_display_row (fc, &need_col_headers, &max_regs); 746778828Sobrien else 746878828Sobrien printf (" DW_CFA_advance_loc4: %ld to %08lx\n", 746978828Sobrien ofs * fc->code_factor, 747078828Sobrien fc->pc_begin + ofs * fc->code_factor); 747177298Sobrien fc->pc_begin += ofs * fc->code_factor; 747277298Sobrien break; 747377298Sobrien 747477298Sobrien case DW_CFA_offset_extended: 747577298Sobrien reg = LEB (); 747677298Sobrien roffs = LEB (); 747778828Sobrien if (! do_debug_frames_interp) 747878828Sobrien printf (" DW_CFA_offset_extended: r%ld at cfa%+ld\n", 747978828Sobrien reg, roffs * fc->data_factor); 748077298Sobrien fc->col_type[reg] = DW_CFA_offset; 748177298Sobrien fc->col_offset[reg] = roffs * fc->data_factor; 748277298Sobrien break; 748377298Sobrien 748477298Sobrien case DW_CFA_restore_extended: 748577298Sobrien reg = LEB (); 748678828Sobrien if (! do_debug_frames_interp) 748778828Sobrien printf (" DW_CFA_restore_extended: r%ld\n", reg); 748877298Sobrien fc->col_type[reg] = cie->col_type[reg]; 748977298Sobrien fc->col_offset[reg] = cie->col_offset[reg]; 749077298Sobrien break; 749177298Sobrien 749277298Sobrien case DW_CFA_undefined: 749377298Sobrien reg = LEB (); 749478828Sobrien if (! do_debug_frames_interp) 749578828Sobrien printf (" DW_CFA_undefined: r%ld\n", reg); 749677298Sobrien fc->col_type[reg] = DW_CFA_undefined; 749777298Sobrien fc->col_offset[reg] = 0; 749877298Sobrien break; 749977298Sobrien 750077298Sobrien case DW_CFA_same_value: 750177298Sobrien reg = LEB (); 750278828Sobrien if (! do_debug_frames_interp) 750378828Sobrien printf (" DW_CFA_same_value: r%ld\n", reg); 750477298Sobrien fc->col_type[reg] = DW_CFA_same_value; 750577298Sobrien fc->col_offset[reg] = 0; 750677298Sobrien break; 750777298Sobrien 750877298Sobrien case DW_CFA_register: 750977298Sobrien reg = LEB (); 751077298Sobrien roffs = LEB (); 751178828Sobrien if (! do_debug_frames_interp) 751278828Sobrien printf (" DW_CFA_register: r%ld\n", reg); 751377298Sobrien fc->col_type[reg] = DW_CFA_register; 751477298Sobrien fc->col_offset[reg] = roffs; 751577298Sobrien break; 751677298Sobrien 751777298Sobrien case DW_CFA_remember_state: 751878828Sobrien if (! do_debug_frames_interp) 751978828Sobrien printf (" DW_CFA_remember_state\n"); 752077298Sobrien rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk)); 752177298Sobrien rs->ncols = fc->ncols; 752277298Sobrien rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int)); 752377298Sobrien rs->col_offset = (int *) xmalloc (rs->ncols * sizeof (int)); 752477298Sobrien memcpy (rs->col_type, fc->col_type, rs->ncols); 752577298Sobrien memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int)); 752677298Sobrien rs->next = remembered_state; 752777298Sobrien remembered_state = rs; 752877298Sobrien break; 752977298Sobrien 753077298Sobrien case DW_CFA_restore_state: 753178828Sobrien if (! do_debug_frames_interp) 753278828Sobrien printf (" DW_CFA_restore_state\n"); 753377298Sobrien rs = remembered_state; 753477298Sobrien remembered_state = rs->next; 753577298Sobrien frame_need_space (fc, rs->ncols-1); 753677298Sobrien memcpy (fc->col_type, rs->col_type, rs->ncols); 753777298Sobrien memcpy (fc->col_offset, rs->col_offset, rs->ncols * sizeof (int)); 753877298Sobrien free (rs->col_type); 753977298Sobrien free (rs->col_offset); 754077298Sobrien free (rs); 754177298Sobrien break; 754277298Sobrien 754377298Sobrien case DW_CFA_def_cfa: 754477298Sobrien fc->cfa_reg = LEB (); 754577298Sobrien fc->cfa_offset = LEB (); 754678828Sobrien if (! do_debug_frames_interp) 754778828Sobrien printf (" DW_CFA_def_cfa: r%d ofs %d\n", 754878828Sobrien fc->cfa_reg, fc->cfa_offset); 754977298Sobrien break; 755077298Sobrien 755177298Sobrien case DW_CFA_def_cfa_register: 755277298Sobrien fc->cfa_reg = LEB (); 755378828Sobrien if (! do_debug_frames_interp) 755478828Sobrien printf (" DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg); 755577298Sobrien break; 755677298Sobrien 755777298Sobrien case DW_CFA_def_cfa_offset: 755877298Sobrien fc->cfa_offset = LEB (); 755978828Sobrien if (! do_debug_frames_interp) 756078828Sobrien printf (" DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset); 756177298Sobrien break; 756277298Sobrien 756377298Sobrien case DW_CFA_nop: 756478828Sobrien if (! do_debug_frames_interp) 756578828Sobrien printf (" DW_CFA_nop\n"); 756677298Sobrien break; 756777298Sobrien 756877298Sobrien#ifndef DW_CFA_GNU_window_save 756977298Sobrien#define DW_CFA_GNU_window_save 0x2d 757077298Sobrien#endif 757177298Sobrien case DW_CFA_GNU_window_save: 757278828Sobrien if (! do_debug_frames_interp) 757378828Sobrien printf (" DW_CFA_GNU_window_save\n"); 757477298Sobrien break; 757577298Sobrien 757677298Sobrien case DW_CFA_GNU_args_size: 757777298Sobrien ul = LEB (); 757878828Sobrien if (! do_debug_frames_interp) 757978828Sobrien printf (" DW_CFA_GNU_args_size: %ld\n", ul); 758077298Sobrien break; 758177298Sobrien 758277298Sobrien case DW_CFA_GNU_negative_offset_extended: 758377298Sobrien reg = LEB (); 758477298Sobrien l = - LEB (); 758577298Sobrien frame_need_space (fc, reg); 758678828Sobrien if (! do_debug_frames_interp) 758778828Sobrien printf (" DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n", 758878828Sobrien reg, l * fc->data_factor); 758977298Sobrien fc->col_type[reg] = DW_CFA_offset; 759077298Sobrien fc->col_offset[reg] = l * fc->data_factor; 759177298Sobrien break; 759277298Sobrien 759377298Sobrien default: 759477298Sobrien fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op); 759577298Sobrien start = block_end; 759677298Sobrien } 759777298Sobrien } 759877298Sobrien 759978828Sobrien if (do_debug_frames_interp) 760078828Sobrien frame_display_row (fc, &need_col_headers, &max_regs); 760177298Sobrien 760277298Sobrien start = block_end; 760377298Sobrien } 760477298Sobrien 760577298Sobrien printf ("\n"); 760677298Sobrien 760777298Sobrien return 1; 760877298Sobrien} 760977298Sobrien 761077298Sobrien#undef GET 761177298Sobrien#undef LEB 761277298Sobrien#undef SLEB 761377298Sobrien 761477298Sobrienstatic int 761560484Sobriendisplay_debug_not_supported (section, start, file) 761660484Sobrien Elf32_Internal_Shdr * section; 761760484Sobrien unsigned char * start ATTRIBUTE_UNUSED; 761860484Sobrien FILE * file ATTRIBUTE_UNUSED; 761960484Sobrien{ 762060484Sobrien printf (_("Displaying the debug contents of section %s is not yet supported.\n"), 762160484Sobrien SECTION_NAME (section)); 762260484Sobrien 762360484Sobrien return 1; 762460484Sobrien} 762560484Sobrien 762660484Sobrien/* Pre-scan the .debug_info section to record the size of address. 762760484Sobrien When dumping the .debug_line, we use that size information, assuming 762860484Sobrien that all compilation units have the same address size. */ 762960484Sobrienstatic int 763060484Sobrienprescan_debug_info (section, start, file) 763160484Sobrien Elf32_Internal_Shdr * section ATTRIBUTE_UNUSED; 763260484Sobrien unsigned char * start; 763360484Sobrien FILE * file ATTRIBUTE_UNUSED; 763460484Sobrien{ 763560484Sobrien DWARF2_External_CompUnit * external; 763660484Sobrien 763760484Sobrien external = (DWARF2_External_CompUnit *) start; 763860484Sobrien 763960484Sobrien debug_line_pointer_size = BYTE_GET (external->cu_pointer_size); 764060484Sobrien return 0; 764160484Sobrien} 764260484Sobrien 764360484Sobrien /* A structure containing the name of a debug section and a pointer 764460484Sobrien to a function that can decode it. The third field is a prescan 764560484Sobrien function to be run over the section before displaying any of the 764660484Sobrien sections. */ 764760484Sobrienstruct 764860484Sobrien{ 764960484Sobrien char * name; 765060484Sobrien int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); 765160484Sobrien int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *)); 765260484Sobrien} 765360484Sobriendebug_displays[] = 765460484Sobrien{ 765560484Sobrien { ".debug_info", display_debug_info, prescan_debug_info }, 765660484Sobrien { ".debug_abbrev", display_debug_abbrev, NULL }, 765760484Sobrien { ".debug_line", display_debug_lines, NULL }, 765860484Sobrien { ".debug_aranges", display_debug_aranges, NULL }, 765960484Sobrien { ".debug_pubnames", display_debug_pubnames, NULL }, 766077298Sobrien { ".debug_frame", display_debug_frames, NULL }, 766177298Sobrien { ".eh_frame", display_debug_frames, NULL }, 766260484Sobrien { ".debug_macinfo", display_debug_not_supported, NULL }, 766360484Sobrien { ".debug_str", display_debug_not_supported, NULL }, 766460484Sobrien { ".debug_static_func", display_debug_not_supported, NULL }, 766560484Sobrien { ".debug_static_vars", display_debug_not_supported, NULL }, 766660484Sobrien { ".debug_types", display_debug_not_supported, NULL }, 766760484Sobrien { ".debug_weaknames", display_debug_not_supported, NULL } 766860484Sobrien}; 766960484Sobrien 767060484Sobrienstatic int 767160484Sobriendisplay_debug_section (section, file) 767260484Sobrien Elf32_Internal_Shdr * section; 767360484Sobrien FILE * file; 767460484Sobrien{ 767560484Sobrien char * name = SECTION_NAME (section); 767660484Sobrien bfd_size_type length; 767760484Sobrien unsigned char * start; 767860484Sobrien int i; 767960484Sobrien 768060484Sobrien length = section->sh_size; 768160484Sobrien if (length == 0) 768260484Sobrien { 768360484Sobrien printf (_("\nSection '%s' has no debugging data.\n"), name); 768460484Sobrien return 0; 768560484Sobrien } 768660484Sobrien 768760484Sobrien GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *, 768860484Sobrien "debug section data"); 768960484Sobrien 769060484Sobrien /* See if we know how to display the contents of this section. */ 769177298Sobrien if (strncmp (name, ".gnu.linkonce.wi.", 17) == 0) 769278828Sobrien name = ".debug_info"; 769377298Sobrien 769460484Sobrien for (i = NUM_ELEM (debug_displays); i--;) 769560484Sobrien if (strcmp (debug_displays[i].name, name) == 0) 769660484Sobrien { 769760484Sobrien debug_displays[i].display (section, start, file); 769860484Sobrien break; 769960484Sobrien } 770060484Sobrien 770160484Sobrien if (i == -1) 770260484Sobrien printf (_("Unrecognised debug section: %s\n"), name); 770360484Sobrien 770460484Sobrien free (start); 770560484Sobrien 770660484Sobrien /* If we loaded in the abbrev section at some point, 770760484Sobrien we must release it here. */ 770860484Sobrien if (first_abbrev != NULL) 770960484Sobrien free_abbrevs (); 771060484Sobrien 771160484Sobrien return 1; 771260484Sobrien} 771360484Sobrien 771460484Sobrienstatic int 771560484Sobrienprocess_section_contents (file) 771660484Sobrien FILE * file; 771760484Sobrien{ 771860484Sobrien Elf32_Internal_Shdr * section; 771978828Sobrien unsigned int i; 772060484Sobrien 772160484Sobrien if (! do_dump) 772260484Sobrien return 1; 772360484Sobrien 772460484Sobrien /* Pre-scan the debug sections to find some debug information not 772560484Sobrien present in some of them. For the .debug_line, we must find out the 772660484Sobrien size of address (specified in .debug_info and .debug_aranges). */ 772760484Sobrien for (i = 0, section = section_headers; 772860484Sobrien i < elf_header.e_shnum && i < num_dump_sects; 772960484Sobrien i ++, section ++) 773060484Sobrien { 773160484Sobrien char * name = SECTION_NAME (section); 773260484Sobrien int j; 773360484Sobrien 773460484Sobrien if (section->sh_size == 0) 773560484Sobrien continue; 773660484Sobrien 773760484Sobrien /* See if there is some pre-scan operation for this section. */ 773860484Sobrien for (j = NUM_ELEM (debug_displays); j--;) 773960484Sobrien if (strcmp (debug_displays[j].name, name) == 0) 774060484Sobrien { 774160484Sobrien if (debug_displays[j].prescan != NULL) 774260484Sobrien { 774360484Sobrien bfd_size_type length; 774460484Sobrien unsigned char * start; 774560484Sobrien 774660484Sobrien length = section->sh_size; 774760484Sobrien GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *, 774860484Sobrien "debug section data"); 774960484Sobrien 775060484Sobrien debug_displays[j].prescan (section, start, file); 775160484Sobrien free (start); 775260484Sobrien } 775360484Sobrien 775460484Sobrien break; 775560484Sobrien } 775660484Sobrien } 775760484Sobrien 775860484Sobrien for (i = 0, section = section_headers; 775960484Sobrien i < elf_header.e_shnum && i < num_dump_sects; 776060484Sobrien i ++, section ++) 776160484Sobrien { 776260484Sobrien#ifdef SUPPORT_DISASSEMBLY 776360484Sobrien if (dump_sects[i] & DISASS_DUMP) 776460484Sobrien disassemble_section (section, file); 776560484Sobrien#endif 776660484Sobrien if (dump_sects[i] & HEX_DUMP) 776760484Sobrien dump_section (section, file); 776860484Sobrien 776960484Sobrien if (dump_sects[i] & DEBUG_DUMP) 777060484Sobrien display_debug_section (section, file); 777160484Sobrien } 777260484Sobrien 777360484Sobrien if (i < num_dump_sects) 777460484Sobrien warn (_("Some sections were not dumped because they do not exist!\n")); 777560484Sobrien 777660484Sobrien return 1; 777760484Sobrien} 777860484Sobrien 777960484Sobrienstatic void 778060484Sobrienprocess_mips_fpe_exception (mask) 778160484Sobrien int mask; 778260484Sobrien{ 778360484Sobrien if (mask) 778460484Sobrien { 778560484Sobrien int first = 1; 778660484Sobrien if (mask & OEX_FPU_INEX) 778760484Sobrien fputs ("INEX", stdout), first = 0; 778860484Sobrien if (mask & OEX_FPU_UFLO) 778960484Sobrien printf ("%sUFLO", first ? "" : "|"), first = 0; 779060484Sobrien if (mask & OEX_FPU_OFLO) 779160484Sobrien printf ("%sOFLO", first ? "" : "|"), first = 0; 779260484Sobrien if (mask & OEX_FPU_DIV0) 779360484Sobrien printf ("%sDIV0", first ? "" : "|"), first = 0; 779460484Sobrien if (mask & OEX_FPU_INVAL) 779560484Sobrien printf ("%sINVAL", first ? "" : "|"); 779660484Sobrien } 779760484Sobrien else 779860484Sobrien fputs ("0", stdout); 779960484Sobrien} 780060484Sobrien 780160484Sobrienstatic int 780260484Sobrienprocess_mips_specific (file) 780360484Sobrien FILE * file; 780460484Sobrien{ 780560484Sobrien Elf_Internal_Dyn * entry; 780660484Sobrien size_t liblist_offset = 0; 780760484Sobrien size_t liblistno = 0; 780860484Sobrien size_t conflictsno = 0; 780960484Sobrien size_t options_offset = 0; 781060484Sobrien size_t conflicts_offset = 0; 781160484Sobrien 781260484Sobrien /* We have a lot of special sections. Thanks SGI! */ 781360484Sobrien if (dynamic_segment == NULL) 781460484Sobrien /* No information available. */ 781560484Sobrien return 0; 781660484Sobrien 781760484Sobrien for (entry = dynamic_segment; entry->d_tag != DT_NULL; ++entry) 781860484Sobrien switch (entry->d_tag) 781960484Sobrien { 782060484Sobrien case DT_MIPS_LIBLIST: 782160484Sobrien liblist_offset = entry->d_un.d_val - loadaddr; 782260484Sobrien break; 782360484Sobrien case DT_MIPS_LIBLISTNO: 782460484Sobrien liblistno = entry->d_un.d_val; 782560484Sobrien break; 782660484Sobrien case DT_MIPS_OPTIONS: 782760484Sobrien options_offset = entry->d_un.d_val - loadaddr; 782860484Sobrien break; 782960484Sobrien case DT_MIPS_CONFLICT: 783060484Sobrien conflicts_offset = entry->d_un.d_val - loadaddr; 783160484Sobrien break; 783260484Sobrien case DT_MIPS_CONFLICTNO: 783360484Sobrien conflictsno = entry->d_un.d_val; 783460484Sobrien break; 783560484Sobrien default: 783660484Sobrien break; 783760484Sobrien } 783860484Sobrien 783960484Sobrien if (liblist_offset != 0 && liblistno != 0 && do_dynamic) 784060484Sobrien { 784160484Sobrien Elf32_External_Lib * elib; 784260484Sobrien size_t cnt; 784360484Sobrien 784460484Sobrien GET_DATA_ALLOC (liblist_offset, liblistno * sizeof (Elf32_External_Lib), 784560484Sobrien elib, Elf32_External_Lib *, "liblist"); 784660484Sobrien 784760484Sobrien printf ("\nSection '.liblist' contains %lu entries:\n", 784860484Sobrien (unsigned long) liblistno); 784960484Sobrien fputs (" Library Time Stamp Checksum Version Flags\n", 785060484Sobrien stdout); 785160484Sobrien 785260484Sobrien for (cnt = 0; cnt < liblistno; ++cnt) 785360484Sobrien { 785460484Sobrien Elf32_Lib liblist; 785560484Sobrien time_t time; 785660484Sobrien char timebuf[20]; 785760484Sobrien struct tm * tmp; 785860484Sobrien 785960484Sobrien liblist.l_name = BYTE_GET (elib[cnt].l_name); 786060484Sobrien time = BYTE_GET (elib[cnt].l_time_stamp); 786160484Sobrien liblist.l_checksum = BYTE_GET (elib[cnt].l_checksum); 786260484Sobrien liblist.l_version = BYTE_GET (elib[cnt].l_version); 786360484Sobrien liblist.l_flags = BYTE_GET (elib[cnt].l_flags); 786460484Sobrien 786560484Sobrien tmp = gmtime (&time); 786660484Sobrien sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u", 786760484Sobrien tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, 786860484Sobrien tmp->tm_hour, tmp->tm_min, tmp->tm_sec); 786960484Sobrien 787060484Sobrien printf ("%3lu: %-20s %s %#10lx %-7ld", (unsigned long) cnt, 787160484Sobrien dynamic_strings + liblist.l_name, timebuf, 787260484Sobrien liblist.l_checksum, liblist.l_version); 787360484Sobrien 787460484Sobrien if (liblist.l_flags == 0) 787560484Sobrien puts (" NONE"); 787660484Sobrien else 787760484Sobrien { 787860484Sobrien static const struct 787960484Sobrien { 788060484Sobrien const char * name; 788160484Sobrien int bit; 788260484Sobrien } 788360484Sobrien l_flags_vals[] = 788460484Sobrien { 788560484Sobrien { " EXACT_MATCH", LL_EXACT_MATCH }, 788660484Sobrien { " IGNORE_INT_VER", LL_IGNORE_INT_VER }, 788760484Sobrien { " REQUIRE_MINOR", LL_REQUIRE_MINOR }, 788860484Sobrien { " EXPORTS", LL_EXPORTS }, 788960484Sobrien { " DELAY_LOAD", LL_DELAY_LOAD }, 789060484Sobrien { " DELTA", LL_DELTA } 789160484Sobrien }; 789260484Sobrien int flags = liblist.l_flags; 789360484Sobrien size_t fcnt; 789460484Sobrien 789560484Sobrien for (fcnt = 0; 789660484Sobrien fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]); 789760484Sobrien ++fcnt) 789860484Sobrien if ((flags & l_flags_vals[fcnt].bit) != 0) 789960484Sobrien { 790060484Sobrien fputs (l_flags_vals[fcnt].name, stdout); 790160484Sobrien flags ^= l_flags_vals[fcnt].bit; 790260484Sobrien } 790360484Sobrien if (flags != 0) 790460484Sobrien printf (" %#x", (unsigned int) flags); 790560484Sobrien 790660484Sobrien puts (""); 790760484Sobrien } 790860484Sobrien } 790960484Sobrien 791060484Sobrien free (elib); 791160484Sobrien } 791260484Sobrien 791360484Sobrien if (options_offset != 0) 791460484Sobrien { 791560484Sobrien Elf_External_Options * eopt; 791660484Sobrien Elf_Internal_Shdr * sect = section_headers; 791760484Sobrien Elf_Internal_Options * iopt; 791860484Sobrien Elf_Internal_Options * option; 791960484Sobrien size_t offset; 792060484Sobrien int cnt; 792160484Sobrien 792260484Sobrien /* Find the section header so that we get the size. */ 792360484Sobrien while (sect->sh_type != SHT_MIPS_OPTIONS) 792460484Sobrien ++ sect; 792560484Sobrien 792660484Sobrien GET_DATA_ALLOC (options_offset, sect->sh_size, eopt, 792760484Sobrien Elf_External_Options *, "options"); 792860484Sobrien 792960484Sobrien iopt = (Elf_Internal_Options *) malloc ((sect->sh_size / sizeof (eopt)) 793077298Sobrien * sizeof (* iopt)); 793160484Sobrien if (iopt == NULL) 793260484Sobrien { 793360484Sobrien error (_("Out of memory")); 793460484Sobrien return 0; 793560484Sobrien } 793660484Sobrien 793760484Sobrien offset = cnt = 0; 793860484Sobrien option = iopt; 793977298Sobrien 794060484Sobrien while (offset < sect->sh_size) 794160484Sobrien { 794260484Sobrien Elf_External_Options * eoption; 794360484Sobrien 794460484Sobrien eoption = (Elf_External_Options *) ((char *) eopt + offset); 794560484Sobrien 794660484Sobrien option->kind = BYTE_GET (eoption->kind); 794760484Sobrien option->size = BYTE_GET (eoption->size); 794860484Sobrien option->section = BYTE_GET (eoption->section); 794960484Sobrien option->info = BYTE_GET (eoption->info); 795060484Sobrien 795160484Sobrien offset += option->size; 795277298Sobrien 795360484Sobrien ++option; 795460484Sobrien ++cnt; 795560484Sobrien } 795660484Sobrien 795760484Sobrien printf (_("\nSection '%s' contains %d entries:\n"), 795877298Sobrien SECTION_NAME (sect), cnt); 795960484Sobrien 796060484Sobrien option = iopt; 796177298Sobrien 796260484Sobrien while (cnt-- > 0) 796360484Sobrien { 796460484Sobrien size_t len; 796560484Sobrien 796660484Sobrien switch (option->kind) 796760484Sobrien { 796860484Sobrien case ODK_NULL: 796960484Sobrien /* This shouldn't happen. */ 797060484Sobrien printf (" NULL %d %lx", option->section, option->info); 797160484Sobrien break; 797260484Sobrien case ODK_REGINFO: 797360484Sobrien printf (" REGINFO "); 797460484Sobrien if (elf_header.e_machine == EM_MIPS) 797560484Sobrien { 797660484Sobrien /* 32bit form. */ 797777298Sobrien Elf32_External_RegInfo * ereg; 797877298Sobrien Elf32_RegInfo reginfo; 797960484Sobrien 798060484Sobrien ereg = (Elf32_External_RegInfo *) (option + 1); 798160484Sobrien reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); 798260484Sobrien reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); 798360484Sobrien reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); 798460484Sobrien reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); 798560484Sobrien reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); 798660484Sobrien reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value); 798760484Sobrien 798860484Sobrien printf ("GPR %08lx GP 0x%lx\n", 798960484Sobrien reginfo.ri_gprmask, 799060484Sobrien (unsigned long) reginfo.ri_gp_value); 799160484Sobrien printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", 799260484Sobrien reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], 799360484Sobrien reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); 799460484Sobrien } 799560484Sobrien else 799660484Sobrien { 799760484Sobrien /* 64 bit form. */ 799860484Sobrien Elf64_External_RegInfo * ereg; 799960484Sobrien Elf64_Internal_RegInfo reginfo; 800060484Sobrien 800160484Sobrien ereg = (Elf64_External_RegInfo *) (option + 1); 800260484Sobrien reginfo.ri_gprmask = BYTE_GET (ereg->ri_gprmask); 800360484Sobrien reginfo.ri_cprmask[0] = BYTE_GET (ereg->ri_cprmask[0]); 800460484Sobrien reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]); 800560484Sobrien reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]); 800660484Sobrien reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]); 800760484Sobrien reginfo.ri_gp_value = BYTE_GET8 (ereg->ri_gp_value); 800860484Sobrien 800960484Sobrien printf ("GPR %08lx GP 0x", 801060484Sobrien reginfo.ri_gprmask); 801160484Sobrien printf_vma (reginfo.ri_gp_value); 801260484Sobrien printf ("\n"); 801360484Sobrien 801460484Sobrien printf (" CPR0 %08lx CPR1 %08lx CPR2 %08lx CPR3 %08lx\n", 801560484Sobrien reginfo.ri_cprmask[0], reginfo.ri_cprmask[1], 801660484Sobrien reginfo.ri_cprmask[2], reginfo.ri_cprmask[3]); 801760484Sobrien } 801860484Sobrien ++option; 801960484Sobrien continue; 802060484Sobrien case ODK_EXCEPTIONS: 802160484Sobrien fputs (" EXCEPTIONS fpe_min(", stdout); 802260484Sobrien process_mips_fpe_exception (option->info & OEX_FPU_MIN); 802360484Sobrien fputs (") fpe_max(", stdout); 802460484Sobrien process_mips_fpe_exception ((option->info & OEX_FPU_MAX) >> 8); 802560484Sobrien fputs (")", stdout); 802660484Sobrien 802760484Sobrien if (option->info & OEX_PAGE0) 802860484Sobrien fputs (" PAGE0", stdout); 802960484Sobrien if (option->info & OEX_SMM) 803060484Sobrien fputs (" SMM", stdout); 803160484Sobrien if (option->info & OEX_FPDBUG) 803260484Sobrien fputs (" FPDBUG", stdout); 803360484Sobrien if (option->info & OEX_DISMISS) 803460484Sobrien fputs (" DISMISS", stdout); 803560484Sobrien break; 803660484Sobrien case ODK_PAD: 803760484Sobrien fputs (" PAD ", stdout); 803860484Sobrien if (option->info & OPAD_PREFIX) 803960484Sobrien fputs (" PREFIX", stdout); 804060484Sobrien if (option->info & OPAD_POSTFIX) 804160484Sobrien fputs (" POSTFIX", stdout); 804260484Sobrien if (option->info & OPAD_SYMBOL) 804360484Sobrien fputs (" SYMBOL", stdout); 804460484Sobrien break; 804560484Sobrien case ODK_HWPATCH: 804660484Sobrien fputs (" HWPATCH ", stdout); 804760484Sobrien if (option->info & OHW_R4KEOP) 804860484Sobrien fputs (" R4KEOP", stdout); 804960484Sobrien if (option->info & OHW_R8KPFETCH) 805060484Sobrien fputs (" R8KPFETCH", stdout); 805160484Sobrien if (option->info & OHW_R5KEOP) 805260484Sobrien fputs (" R5KEOP", stdout); 805360484Sobrien if (option->info & OHW_R5KCVTL) 805460484Sobrien fputs (" R5KCVTL", stdout); 805560484Sobrien break; 805660484Sobrien case ODK_FILL: 805760484Sobrien fputs (" FILL ", stdout); 805860484Sobrien /* XXX Print content of info word? */ 805960484Sobrien break; 806060484Sobrien case ODK_TAGS: 806160484Sobrien fputs (" TAGS ", stdout); 806260484Sobrien /* XXX Print content of info word? */ 806360484Sobrien break; 806460484Sobrien case ODK_HWAND: 806560484Sobrien fputs (" HWAND ", stdout); 806660484Sobrien if (option->info & OHWA0_R4KEOP_CHECKED) 806760484Sobrien fputs (" R4KEOP_CHECKED", stdout); 806860484Sobrien if (option->info & OHWA0_R4KEOP_CLEAN) 806960484Sobrien fputs (" R4KEOP_CLEAN", stdout); 807060484Sobrien break; 807160484Sobrien case ODK_HWOR: 807260484Sobrien fputs (" HWOR ", stdout); 807360484Sobrien if (option->info & OHWA0_R4KEOP_CHECKED) 807460484Sobrien fputs (" R4KEOP_CHECKED", stdout); 807560484Sobrien if (option->info & OHWA0_R4KEOP_CLEAN) 807660484Sobrien fputs (" R4KEOP_CLEAN", stdout); 807760484Sobrien break; 807860484Sobrien case ODK_GP_GROUP: 807960484Sobrien printf (" GP_GROUP %#06lx self-contained %#06lx", 808060484Sobrien option->info & OGP_GROUP, 808160484Sobrien (option->info & OGP_SELF) >> 16); 808260484Sobrien break; 808360484Sobrien case ODK_IDENT: 808460484Sobrien printf (" IDENT %#06lx self-contained %#06lx", 808560484Sobrien option->info & OGP_GROUP, 808660484Sobrien (option->info & OGP_SELF) >> 16); 808760484Sobrien break; 808860484Sobrien default: 808960484Sobrien /* This shouldn't happen. */ 809060484Sobrien printf (" %3d ??? %d %lx", 809160484Sobrien option->kind, option->section, option->info); 809260484Sobrien break; 809360484Sobrien } 809460484Sobrien 809577298Sobrien len = sizeof (* eopt); 809660484Sobrien while (len < option->size) 809760484Sobrien if (((char *) option)[len] >= ' ' 809860484Sobrien && ((char *) option)[len] < 0x7f) 809960484Sobrien printf ("%c", ((char *) option)[len++]); 810060484Sobrien else 810160484Sobrien printf ("\\%03o", ((char *) option)[len++]); 810260484Sobrien 810360484Sobrien fputs ("\n", stdout); 810460484Sobrien ++option; 810560484Sobrien } 810660484Sobrien 810760484Sobrien free (eopt); 810860484Sobrien } 810960484Sobrien 811060484Sobrien if (conflicts_offset != 0 && conflictsno != 0) 811160484Sobrien { 811260484Sobrien Elf32_External_Conflict * econf32; 811360484Sobrien Elf64_External_Conflict * econf64; 811460484Sobrien Elf32_Conflict * iconf; 811560484Sobrien size_t cnt; 811660484Sobrien 811760484Sobrien if (dynamic_symbols == NULL) 811860484Sobrien { 811960484Sobrien error (_("conflict list with without table")); 812060484Sobrien return 0; 812160484Sobrien } 812260484Sobrien 812377298Sobrien iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (* iconf)); 812460484Sobrien if (iconf == NULL) 812560484Sobrien { 812660484Sobrien error (_("Out of memory")); 812760484Sobrien return 0; 812860484Sobrien } 812960484Sobrien 813060484Sobrien if (is_32bit_elf) 813160484Sobrien { 813277298Sobrien GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (* econf32), 813360484Sobrien econf32, Elf32_External_Conflict *, "conflict"); 813460484Sobrien 813560484Sobrien for (cnt = 0; cnt < conflictsno; ++cnt) 813660484Sobrien iconf[cnt] = BYTE_GET (econf32[cnt]); 813760484Sobrien } 813860484Sobrien else 813960484Sobrien { 814077298Sobrien GET_DATA_ALLOC (conflicts_offset, conflictsno * sizeof (* econf64), 814160484Sobrien econf64, Elf64_External_Conflict *, "conflict"); 814260484Sobrien 814360484Sobrien for (cnt = 0; cnt < conflictsno; ++cnt) 814460484Sobrien iconf[cnt] = BYTE_GET (econf64[cnt]); 814560484Sobrien } 814660484Sobrien 814760484Sobrien printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno); 814860484Sobrien puts (_(" Num: Index Value Name")); 814960484Sobrien 815060484Sobrien for (cnt = 0; cnt < conflictsno; ++cnt) 815160484Sobrien { 815260484Sobrien Elf_Internal_Sym * psym = &dynamic_symbols[iconf[cnt]]; 815360484Sobrien 815460484Sobrien printf ("%5lu: %8lu ", (unsigned long) cnt, iconf[cnt]); 815560484Sobrien print_vma (psym->st_value, FULL_HEX); 815660484Sobrien printf (" %s\n", dynamic_strings + psym->st_name); 815760484Sobrien } 815860484Sobrien 815960484Sobrien free (iconf); 816060484Sobrien } 816160484Sobrien 816260484Sobrien return 1; 816360484Sobrien} 816460484Sobrien 816560484Sobrienstatic char * 816660484Sobrienget_note_type (e_type) 816760484Sobrien unsigned e_type; 816860484Sobrien{ 816960484Sobrien static char buff[64]; 817060484Sobrien 817160484Sobrien switch (e_type) 817260484Sobrien { 817360484Sobrien case NT_PRSTATUS: return _("NT_PRSTATUS (prstatus structure)"); 817460484Sobrien case NT_FPREGSET: return _("NT_FPREGSET (floating point registers)"); 817560484Sobrien case NT_PRPSINFO: return _("NT_PRPSINFO (prpsinfo structure)"); 817660484Sobrien case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)"); 817760484Sobrien case NT_PRXFPREG: return _("NT_PRXFPREG (user_xfpregs structure)"); 817860484Sobrien case NT_PSTATUS: return _("NT_PSTATUS (pstatus structure)"); 817960484Sobrien case NT_FPREGS: return _("NT_FPREGS (floating point registers)"); 818060484Sobrien case NT_PSINFO: return _("NT_PSINFO (psinfo structure)"); 818160484Sobrien case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)"); 818260484Sobrien case NT_LWPSINFO: return _("NT_LWPSINFO (lwpsinfo_t structure)"); 818360484Sobrien case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus strcuture)"); 818460484Sobrien default: 818560484Sobrien sprintf (buff, _("Unknown note type: (0x%08x)"), e_type); 818660484Sobrien return buff; 818760484Sobrien } 818860484Sobrien} 818960484Sobrien 819060484Sobrien/* Note that by the ELF standard, the name field is already null byte 819160484Sobrien terminated, and namesz includes the terminating null byte. 819260484Sobrien I.E. the value of namesz for the name "FSF" is 4. 819360484Sobrien 819460484Sobrien If the value of namesz is zero, there is no name present. */ 819560484Sobrienstatic int 819660484Sobrienprocess_note (pnote) 819760484Sobrien Elf32_Internal_Note * pnote; 819860484Sobrien{ 819960484Sobrien printf (" %s\t\t0x%08lx\t%s\n", 820060484Sobrien pnote->namesz ? pnote->namedata : "(NONE)", 820178828Sobrien pnote->descsz, get_note_type (pnote->type)); 820260484Sobrien return 1; 820360484Sobrien} 820460484Sobrien 820560484Sobrien 820660484Sobrienstatic int 820760484Sobrienprocess_corefile_note_segment (file, offset, length) 820860484Sobrien FILE * file; 820960484Sobrien bfd_vma offset; 821060484Sobrien bfd_vma length; 821160484Sobrien{ 821260484Sobrien Elf_External_Note * pnotes; 821360484Sobrien Elf_External_Note * external; 821460484Sobrien int res = 1; 821560484Sobrien 821660484Sobrien if (length <= 0) 821760484Sobrien return 0; 821860484Sobrien 821960484Sobrien GET_DATA_ALLOC (offset, length, pnotes, Elf_External_Note *, "notes"); 822060484Sobrien 822160484Sobrien external = pnotes; 822260484Sobrien 822360484Sobrien printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"), 822477298Sobrien (unsigned long) offset, (unsigned long) length); 822560484Sobrien printf (_(" Owner\t\tData size\tDescription\n")); 822660484Sobrien 822760484Sobrien while (external < (Elf_External_Note *)((char *) pnotes + length)) 822860484Sobrien { 822960484Sobrien Elf32_Internal_Note inote; 823060484Sobrien char * temp = NULL; 823160484Sobrien 823260484Sobrien inote.type = BYTE_GET (external->type); 823360484Sobrien inote.namesz = BYTE_GET (external->namesz); 823460484Sobrien inote.namedata = external->name; 823560484Sobrien inote.descsz = BYTE_GET (external->descsz); 823660484Sobrien inote.descdata = inote.namedata + align_power (inote.namesz, 2); 823760484Sobrien inote.descpos = offset + (inote.descdata - (char *) pnotes); 823877298Sobrien 823960484Sobrien external = (Elf_External_Note *)(inote.descdata + align_power (inote.descsz, 2)); 824060484Sobrien 824160484Sobrien /* Verify that name is null terminated. It appears that at least 824260484Sobrien one version of Linux (RedHat 6.0) generates corefiles that don't 824360484Sobrien comply with the ELF spec by failing to include the null byte in 824460484Sobrien namesz. */ 824560484Sobrien if (inote.namedata[inote.namesz] != '\0') 824660484Sobrien { 824760484Sobrien temp = malloc (inote.namesz + 1); 824877298Sobrien 824960484Sobrien if (temp == NULL) 825060484Sobrien { 825160484Sobrien error (_("Out of memory\n")); 825260484Sobrien res = 0; 825360484Sobrien break; 825460484Sobrien } 825577298Sobrien 825660484Sobrien strncpy (temp, inote.namedata, inote.namesz); 825760484Sobrien temp[inote.namesz] = 0; 825877298Sobrien 825960484Sobrien /* warn (_("'%s' NOTE name not properly null terminated\n"), temp); */ 826060484Sobrien inote.namedata = temp; 826160484Sobrien } 826260484Sobrien 826360484Sobrien res &= process_note (& inote); 826460484Sobrien 826560484Sobrien if (temp != NULL) 826660484Sobrien { 826760484Sobrien free (temp); 826860484Sobrien temp = NULL; 826960484Sobrien } 827060484Sobrien } 827160484Sobrien 827260484Sobrien free (pnotes); 827360484Sobrien 827460484Sobrien return res; 827560484Sobrien} 827660484Sobrien 827760484Sobrienstatic int 827860484Sobrienprocess_corefile_note_segments (file) 827960484Sobrien FILE * file; 828060484Sobrien{ 828160484Sobrien Elf_Internal_Phdr * program_headers; 828260484Sobrien Elf_Internal_Phdr * segment; 828360484Sobrien unsigned int i; 828460484Sobrien int res = 1; 828560484Sobrien 828660484Sobrien program_headers = (Elf_Internal_Phdr *) malloc 828760484Sobrien (elf_header.e_phnum * sizeof (Elf_Internal_Phdr)); 828860484Sobrien 828960484Sobrien if (program_headers == NULL) 829060484Sobrien { 829160484Sobrien error (_("Out of memory\n")); 829260484Sobrien return 0; 829360484Sobrien } 829460484Sobrien 829560484Sobrien if (is_32bit_elf) 829660484Sobrien i = get_32bit_program_headers (file, program_headers); 829760484Sobrien else 829860484Sobrien i = get_64bit_program_headers (file, program_headers); 829960484Sobrien 830060484Sobrien if (i == 0) 830160484Sobrien { 830260484Sobrien free (program_headers); 830360484Sobrien return 0; 830460484Sobrien } 830560484Sobrien 830660484Sobrien for (i = 0, segment = program_headers; 830760484Sobrien i < elf_header.e_phnum; 830860484Sobrien i ++, segment ++) 830960484Sobrien { 831060484Sobrien if (segment->p_type == PT_NOTE) 831160484Sobrien res &= process_corefile_note_segment (file, 831260484Sobrien (bfd_vma) segment->p_offset, 831360484Sobrien (bfd_vma) segment->p_filesz); 831460484Sobrien } 831560484Sobrien 831660484Sobrien free (program_headers); 831760484Sobrien 831860484Sobrien return res; 831960484Sobrien} 832060484Sobrien 832160484Sobrienstatic int 832260484Sobrienprocess_corefile_contents (file) 832360484Sobrien FILE * file; 832460484Sobrien{ 832560484Sobrien /* If we have not been asked to display the notes then do nothing. */ 832660484Sobrien if (! do_notes) 832760484Sobrien return 1; 832860484Sobrien 832960484Sobrien /* If file is not a core file then exit. */ 833060484Sobrien if (elf_header.e_type != ET_CORE) 833160484Sobrien return 1; 833260484Sobrien 833360484Sobrien /* No program headers means no NOTE segment. */ 833460484Sobrien if (elf_header.e_phnum == 0) 833560484Sobrien { 833660484Sobrien printf (_("No note segments present in the core file.\n")); 833760484Sobrien return 1; 833860484Sobrien } 833960484Sobrien 834060484Sobrien return process_corefile_note_segments (file); 834160484Sobrien} 834260484Sobrien 834360484Sobrienstatic int 834460484Sobrienprocess_arch_specific (file) 834560484Sobrien FILE * file; 834660484Sobrien{ 834760484Sobrien if (! do_arch) 834860484Sobrien return 1; 834960484Sobrien 835060484Sobrien switch (elf_header.e_machine) 835160484Sobrien { 835260484Sobrien case EM_MIPS: 835378828Sobrien case EM_MIPS_RS3_LE: 835460484Sobrien return process_mips_specific (file); 835560484Sobrien break; 835660484Sobrien default: 835760484Sobrien break; 835860484Sobrien } 835960484Sobrien return 1; 836060484Sobrien} 836160484Sobrien 836260484Sobrienstatic int 836360484Sobrienget_file_header (file) 836460484Sobrien FILE * file; 836560484Sobrien{ 836660484Sobrien /* Read in the identity array. */ 836760484Sobrien if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1) 836860484Sobrien return 0; 836960484Sobrien 837060484Sobrien /* Determine how to read the rest of the header. */ 837160484Sobrien switch (elf_header.e_ident [EI_DATA]) 837260484Sobrien { 837360484Sobrien default: /* fall through */ 837460484Sobrien case ELFDATANONE: /* fall through */ 837560484Sobrien case ELFDATA2LSB: byte_get = byte_get_little_endian; break; 837660484Sobrien case ELFDATA2MSB: byte_get = byte_get_big_endian; break; 837760484Sobrien } 837860484Sobrien 837960484Sobrien /* For now we only support 32 bit and 64 bit ELF files. */ 838060484Sobrien is_32bit_elf = (elf_header.e_ident [EI_CLASS] != ELFCLASS64); 838160484Sobrien 838260484Sobrien /* Read in the rest of the header. */ 838360484Sobrien if (is_32bit_elf) 838460484Sobrien { 838560484Sobrien Elf32_External_Ehdr ehdr32; 838660484Sobrien 838760484Sobrien if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT, 1, file) != 1) 838860484Sobrien return 0; 838960484Sobrien 839060484Sobrien elf_header.e_type = BYTE_GET (ehdr32.e_type); 839160484Sobrien elf_header.e_machine = BYTE_GET (ehdr32.e_machine); 839260484Sobrien elf_header.e_version = BYTE_GET (ehdr32.e_version); 839360484Sobrien elf_header.e_entry = BYTE_GET (ehdr32.e_entry); 839460484Sobrien elf_header.e_phoff = BYTE_GET (ehdr32.e_phoff); 839560484Sobrien elf_header.e_shoff = BYTE_GET (ehdr32.e_shoff); 839660484Sobrien elf_header.e_flags = BYTE_GET (ehdr32.e_flags); 839760484Sobrien elf_header.e_ehsize = BYTE_GET (ehdr32.e_ehsize); 839860484Sobrien elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize); 839960484Sobrien elf_header.e_phnum = BYTE_GET (ehdr32.e_phnum); 840060484Sobrien elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize); 840160484Sobrien elf_header.e_shnum = BYTE_GET (ehdr32.e_shnum); 840260484Sobrien elf_header.e_shstrndx = BYTE_GET (ehdr32.e_shstrndx); 840360484Sobrien } 840460484Sobrien else 840560484Sobrien { 840660484Sobrien Elf64_External_Ehdr ehdr64; 840760484Sobrien 840860484Sobrien /* If we have been compiled with sizeof (bfd_vma) == 4, then 840960484Sobrien we will not be able to cope with the 64bit data found in 841060484Sobrien 64 ELF files. Detect this now and abort before we start 841160484Sobrien overwritting things. */ 841260484Sobrien if (sizeof (bfd_vma) < 8) 841360484Sobrien { 841460484Sobrien error (_("This instance of readelf has been built without support for a\n")); 841560484Sobrien error (_("64 bit data type and so it cannot read 64 bit ELF files.\n")); 841660484Sobrien return 0; 841760484Sobrien } 841860484Sobrien 841960484Sobrien if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 1, file) != 1) 842060484Sobrien return 0; 842160484Sobrien 842260484Sobrien elf_header.e_type = BYTE_GET (ehdr64.e_type); 842360484Sobrien elf_header.e_machine = BYTE_GET (ehdr64.e_machine); 842460484Sobrien elf_header.e_version = BYTE_GET (ehdr64.e_version); 842560484Sobrien elf_header.e_entry = BYTE_GET8 (ehdr64.e_entry); 842660484Sobrien elf_header.e_phoff = BYTE_GET8 (ehdr64.e_phoff); 842760484Sobrien elf_header.e_shoff = BYTE_GET8 (ehdr64.e_shoff); 842860484Sobrien elf_header.e_flags = BYTE_GET (ehdr64.e_flags); 842960484Sobrien elf_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize); 843060484Sobrien elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize); 843160484Sobrien elf_header.e_phnum = BYTE_GET (ehdr64.e_phnum); 843260484Sobrien elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize); 843360484Sobrien elf_header.e_shnum = BYTE_GET (ehdr64.e_shnum); 843460484Sobrien elf_header.e_shstrndx = BYTE_GET (ehdr64.e_shstrndx); 843560484Sobrien } 843660484Sobrien 843760484Sobrien return 1; 843860484Sobrien} 843960484Sobrien 844060484Sobrienstatic void 844160484Sobrienprocess_file (file_name) 844260484Sobrien char * file_name; 844360484Sobrien{ 844460484Sobrien FILE * file; 844560484Sobrien struct stat statbuf; 844660484Sobrien unsigned int i; 844760484Sobrien 844860484Sobrien if (stat (file_name, & statbuf) < 0) 844960484Sobrien { 845060484Sobrien error (_("Cannot stat input file %s.\n"), file_name); 845160484Sobrien return; 845260484Sobrien } 845360484Sobrien 845460484Sobrien file = fopen (file_name, "rb"); 845560484Sobrien if (file == NULL) 845660484Sobrien { 845760484Sobrien error (_("Input file %s not found.\n"), file_name); 845860484Sobrien return; 845960484Sobrien } 846060484Sobrien 846160484Sobrien if (! get_file_header (file)) 846260484Sobrien { 846360484Sobrien error (_("%s: Failed to read file header\n"), file_name); 846460484Sobrien fclose (file); 846560484Sobrien return; 846660484Sobrien } 846760484Sobrien 846860484Sobrien /* Initialise per file variables. */ 846960484Sobrien for (i = NUM_ELEM (version_info); i--;) 847060484Sobrien version_info[i] = 0; 847160484Sobrien 847260484Sobrien for (i = NUM_ELEM (dynamic_info); i--;) 847360484Sobrien dynamic_info[i] = 0; 847460484Sobrien 847560484Sobrien /* Process the file. */ 847660484Sobrien if (show_name) 847760484Sobrien printf (_("\nFile: %s\n"), file_name); 847860484Sobrien 847960484Sobrien if (! process_file_header ()) 848060484Sobrien { 848160484Sobrien fclose (file); 848260484Sobrien return; 848360484Sobrien } 848460484Sobrien 848560484Sobrien process_section_headers (file); 848660484Sobrien 848760484Sobrien process_program_headers (file); 848860484Sobrien 848960484Sobrien process_dynamic_segment (file); 849060484Sobrien 849160484Sobrien process_relocs (file); 849260484Sobrien 849378828Sobrien process_unwind (file); 849478828Sobrien 849560484Sobrien process_symbol_table (file); 849660484Sobrien 849760484Sobrien process_syminfo (file); 849860484Sobrien 849960484Sobrien process_version_sections (file); 850060484Sobrien 850160484Sobrien process_section_contents (file); 850260484Sobrien 850360484Sobrien process_corefile_contents (file); 850460484Sobrien 850560484Sobrien process_arch_specific (file); 850660484Sobrien 850760484Sobrien fclose (file); 850860484Sobrien 850960484Sobrien if (section_headers) 851060484Sobrien { 851160484Sobrien free (section_headers); 851260484Sobrien section_headers = NULL; 851360484Sobrien } 851460484Sobrien 851560484Sobrien if (string_table) 851660484Sobrien { 851760484Sobrien free (string_table); 851860484Sobrien string_table = NULL; 851977298Sobrien string_table_length = 0; 852060484Sobrien } 852160484Sobrien 852260484Sobrien if (dynamic_strings) 852360484Sobrien { 852460484Sobrien free (dynamic_strings); 852560484Sobrien dynamic_strings = NULL; 852660484Sobrien } 852760484Sobrien 852860484Sobrien if (dynamic_symbols) 852960484Sobrien { 853060484Sobrien free (dynamic_symbols); 853160484Sobrien dynamic_symbols = NULL; 853260484Sobrien num_dynamic_syms = 0; 853360484Sobrien } 853460484Sobrien 853560484Sobrien if (dynamic_syminfo) 853660484Sobrien { 853760484Sobrien free (dynamic_syminfo); 853860484Sobrien dynamic_syminfo = NULL; 853960484Sobrien } 854060484Sobrien} 854160484Sobrien 854260484Sobrien#ifdef SUPPORT_DISASSEMBLY 854360484Sobrien/* Needed by the i386 disassembler. For extra credit, someone could 854460484Sobrien fix this so that we insert symbolic addresses here, esp for GOT/PLT 854560484Sobrien symbols */ 854660484Sobrien 854760484Sobrienvoid 854860484Sobrienprint_address (unsigned int addr, FILE * outfile) 854960484Sobrien{ 855060484Sobrien fprintf (outfile,"0x%8.8x", addr); 855160484Sobrien} 855260484Sobrien 855360484Sobrien/* Needed by the i386 disassembler. */ 855460484Sobrienvoid 855560484Sobriendb_task_printsym (unsigned int addr) 855660484Sobrien{ 855760484Sobrien print_address (addr, stderr); 855860484Sobrien} 855960484Sobrien#endif 856060484Sobrien 856160484Sobrienint 856260484Sobrienmain (argc, argv) 856360484Sobrien int argc; 856460484Sobrien char ** argv; 856560484Sobrien{ 856660484Sobrien#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 856760484Sobrien setlocale (LC_MESSAGES, ""); 856860484Sobrien#endif 856960484Sobrien bindtextdomain (PACKAGE, LOCALEDIR); 857060484Sobrien textdomain (PACKAGE); 857160484Sobrien 857260484Sobrien parse_args (argc, argv); 857360484Sobrien 857460484Sobrien if (optind < (argc - 1)) 857560484Sobrien show_name = 1; 857660484Sobrien 857760484Sobrien while (optind < argc) 857860484Sobrien process_file (argv [optind ++]); 857960484Sobrien 858060484Sobrien if (dump_sects != NULL) 858160484Sobrien free (dump_sects); 858260484Sobrien 858360484Sobrien return 0; 858460484Sobrien} 8585