/* readelf.c -- display contents of an ELF format file
- Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Originally developed by Eric Youngdale <eric@andante.jic.com>
Modifications by Nick Clifton <nickc@redhat.com>
#include "elf/mmix.h"
#include "elf/mn10200.h"
#include "elf/mn10300.h"
+#include "elf/msp430.h"
#include "elf/or32.h"
#include "elf/pj.h"
#include "elf/ppc.h"
+#include "elf/ppc64.h"
#include "elf/s390.h"
#include "elf/sh.h"
#include "elf/sparc.h"
#include "elf/vax.h"
#include "elf/x86-64.h"
#include "elf/xstormy16.h"
+#include "elf/iq2000.h"
+#include "elf/xtensa.h"
#include "bucomm.h"
#include "getopt.h"
+#include "libiberty.h"
char *program_name = "readelf";
-unsigned int dynamic_addr;
+unsigned long dynamic_addr;
bfd_size_type dynamic_size;
-unsigned int rela_addr;
-unsigned int rela_size;
char *dynamic_strings;
char *string_table;
unsigned long string_table_length;
unsigned long dynamic_syminfo_offset;
unsigned int dynamic_syminfo_nent;
char program_interpreter[64];
-int dynamic_info[DT_JMPREL + 1];
-int version_info[16];
-int loadaddr = 0;
+bfd_vma dynamic_info[DT_JMPREL + 1];
+bfd_vma version_info[16];
Elf_Internal_Ehdr elf_header;
Elf_Internal_Shdr *section_headers;
+Elf_Internal_Phdr *program_headers;
Elf_Internal_Dyn *dynamic_segment;
Elf_Internal_Shdr *symtab_shndx_hdr;
int show_name;
print_mode;
/* Forward declarations for dumb compilers. */
-static void print_vma
+static void print_vma
PARAMS ((bfd_vma, print_mode));
-static void print_symbol
+static void print_symbol
PARAMS ((int, const char *));
-static bfd_vma (*byte_get)
+static bfd_vma (*byte_get)
PARAMS ((unsigned char *, int));
-static bfd_vma byte_get_little_endian
+static bfd_vma byte_get_little_endian
PARAMS ((unsigned char *, int));
-static bfd_vma byte_get_big_endian
+static bfd_vma byte_get_big_endian
PARAMS ((unsigned char *, int));
-static const char *get_mips_dynamic_type
+static bfd_vma byte_get_signed
+ PARAMS ((unsigned char *, int));
+static void (*byte_put)
+ PARAMS ((unsigned char *, bfd_vma, int));
+static void byte_put_little_endian
+ PARAMS ((unsigned char *, bfd_vma, int));
+static void byte_put_big_endian
+ PARAMS ((unsigned char *, bfd_vma, int));
+static const char *get_mips_dynamic_type
+ PARAMS ((unsigned long));
+static const char *get_sparc64_dynamic_type
PARAMS ((unsigned long));
-static const char *get_sparc64_dynamic_type
+static const char *get_ppc64_dynamic_type
PARAMS ((unsigned long));
-static const char *get_ppc64_dynamic_type
+static const char *get_parisc_dynamic_type
PARAMS ((unsigned long));
-static const char *get_parisc_dynamic_type
+static const char *get_ia64_dynamic_type
PARAMS ((unsigned long));
-static const char *get_dynamic_type
+static const char *get_dynamic_type
PARAMS ((unsigned long));
-static int slurp_rela_relocs
+static int slurp_rela_relocs
PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **,
unsigned long *));
-static int slurp_rel_relocs
+static int slurp_rel_relocs
PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **,
unsigned long *));
-static int dump_relocations
+static int dump_relocations
PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *,
unsigned long, char *, int));
-static char *get_file_type
+static char *get_file_type
PARAMS ((unsigned));
-static char *get_machine_name
+static char *get_machine_name
PARAMS ((unsigned));
-static void decode_ARM_machine_flags
+static void decode_ARM_machine_flags
PARAMS ((unsigned, char[]));
-static char *get_machine_flags
+static char *get_machine_flags
PARAMS ((unsigned, unsigned));
-static const char *get_mips_segment_type
+static const char *get_mips_segment_type
PARAMS ((unsigned long));
-static const char *get_parisc_segment_type
+static const char *get_parisc_segment_type
PARAMS ((unsigned long));
-static const char *get_ia64_segment_type
+static const char *get_ia64_segment_type
PARAMS ((unsigned long));
-static const char *get_segment_type
+static const char *get_segment_type
PARAMS ((unsigned long));
-static const char *get_mips_section_type_name
+static const char *get_mips_section_type_name
PARAMS ((unsigned int));
static const char *get_parisc_section_type_name
PARAMS ((unsigned int));
-static const char *get_ia64_section_type_name
+static const char *get_ia64_section_type_name
PARAMS ((unsigned int));
-static const char *get_section_type_name
+static const char *get_section_type_name
PARAMS ((unsigned int));
-static const char *get_symbol_binding
+static const char *get_symbol_binding
PARAMS ((unsigned int));
-static const char *get_symbol_type
+static const char *get_symbol_type
PARAMS ((unsigned int));
-static const char *get_symbol_visibility
+static const char *get_symbol_visibility
PARAMS ((unsigned int));
-static const char *get_symbol_index_type
+static const char *get_symbol_index_type
PARAMS ((unsigned int));
-static const char *get_dynamic_flags
+static const char *get_dynamic_flags
PARAMS ((bfd_vma));
-static void usage
+static void usage
PARAMS ((void));
-static void parse_args
+static void parse_args
PARAMS ((int, char **));
-static int process_file_header
+static int process_file_header
PARAMS ((void));
-static int process_program_headers
+static int process_program_headers
PARAMS ((FILE *));
-static int process_section_headers
+static int process_section_headers
PARAMS ((FILE *));
-static int process_unwind
+static int process_unwind
PARAMS ((FILE *));
-static void dynamic_segment_mips_val
+static void dynamic_segment_mips_val
+ PARAMS ((Elf_Internal_Dyn *));
+static void dynamic_segment_parisc_val
PARAMS ((Elf_Internal_Dyn *));
-static void dynamic_segment_parisc_val
+static void dynamic_segment_ia64_val
PARAMS ((Elf_Internal_Dyn *));
-static int process_dynamic_segment
+static int process_dynamic_segment
PARAMS ((FILE *));
-static int process_symbol_table
+static int process_symbol_table
PARAMS ((FILE *));
-static int process_syminfo
+static int process_syminfo
PARAMS ((FILE *));
-static int process_section_contents
+static int process_section_contents
PARAMS ((FILE *));
-static void process_mips_fpe_exception
+static void process_mips_fpe_exception
PARAMS ((int));
-static int process_mips_specific
+static int process_mips_specific
PARAMS ((FILE *));
-static int process_file
+static int process_file
PARAMS ((char *));
-static int process_relocs
+static int process_relocs
PARAMS ((FILE *));
-static int process_version_sections
+static int process_version_sections
PARAMS ((FILE *));
-static char *get_ver_flags
+static char *get_ver_flags
PARAMS ((unsigned int));
-static int get_32bit_section_headers
+static int get_32bit_section_headers
PARAMS ((FILE *, unsigned int));
-static int get_64bit_section_headers
+static int get_64bit_section_headers
PARAMS ((FILE *, unsigned int));
-static int get_32bit_program_headers
+static int get_32bit_program_headers
PARAMS ((FILE *, Elf_Internal_Phdr *));
-static int get_64bit_program_headers
+static int get_64bit_program_headers
PARAMS ((FILE *, Elf_Internal_Phdr *));
-static int get_file_header
+static int get_program_headers
PARAMS ((FILE *));
-static Elf_Internal_Sym *get_32bit_elf_symbols
+static int get_file_header
+ PARAMS ((FILE *));
+static Elf_Internal_Sym *get_32bit_elf_symbols
PARAMS ((FILE *, Elf_Internal_Shdr *));
-static Elf_Internal_Sym *get_64bit_elf_symbols
+static Elf_Internal_Sym *get_64bit_elf_symbols
PARAMS ((FILE *, Elf_Internal_Shdr *));
-static const char *get_elf_section_flags
+static const char *get_elf_section_flags
PARAMS ((bfd_vma));
-static int *get_dynamic_data
+static int *get_dynamic_data
PARAMS ((FILE *, unsigned int));
-static int get_32bit_dynamic_segment
+static int get_32bit_dynamic_segment
PARAMS ((FILE *));
-static int get_64bit_dynamic_segment
+static int get_64bit_dynamic_segment
PARAMS ((FILE *));
+static long offset_from_vma
+ PARAMS ((FILE *, bfd_vma vma, bfd_size_type size));
#ifdef SUPPORT_DISASSEMBLY
-static int disassemble_section
+static int disassemble_section
PARAMS ((Elf_Internal_Shdr *, FILE *));
#endif
-static int dump_section
+static int dump_section
PARAMS ((Elf_Internal_Shdr *, FILE *));
-static int display_debug_section
+static int display_debug_section
PARAMS ((Elf_Internal_Shdr *, FILE *));
-static int display_debug_info
+static int display_debug_info
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
static int display_debug_not_supported
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int prescan_debug_info
+static int prescan_debug_info
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_lines
+static int display_debug_lines
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_pubnames
+static int display_debug_pubnames
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_abbrev
+static int display_debug_abbrev
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_aranges
+static int display_debug_aranges
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_frames
+static int display_debug_frames
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_macinfo
+static int display_debug_macinfo
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_str
+static int display_debug_str
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_loc
+static int display_debug_loc
PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static unsigned char *process_abbrev_section
+static unsigned char *process_abbrev_section
PARAMS ((unsigned char *, unsigned char *));
-static void load_debug_str
+static void load_debug_str
PARAMS ((FILE *));
-static void free_debug_str
+static void free_debug_str
PARAMS ((void));
-static const char *fetch_indirect_string
+static const char *fetch_indirect_string
PARAMS ((unsigned long));
-static void load_debug_loc
+static void load_debug_loc
PARAMS ((FILE *));
-static void free_debug_loc
+static void free_debug_loc
PARAMS ((void));
-static unsigned long read_leb128
+static unsigned long read_leb128
PARAMS ((unsigned char *, int *, int));
-static int process_extended_line_op
+static int process_extended_line_op
PARAMS ((unsigned char *, int, int));
-static void reset_state_machine
+static void reset_state_machine
PARAMS ((int));
-static char *get_TAG_name
+static char *get_TAG_name
PARAMS ((unsigned long));
-static char *get_AT_name
+static char *get_AT_name
PARAMS ((unsigned long));
-static char *get_FORM_name
+static char *get_FORM_name
PARAMS ((unsigned long));
-static void free_abbrevs
+static void free_abbrevs
PARAMS ((void));
-static void add_abbrev
+static void add_abbrev
PARAMS ((unsigned long, unsigned long, int));
-static void add_abbrev_attr
+static void add_abbrev_attr
PARAMS ((unsigned long, unsigned long));
-static unsigned char *read_and_display_attr
+static unsigned char *read_and_display_attr
PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long,
- unsigned long));
+ unsigned long, unsigned long, int));
static unsigned char *read_and_display_attr_value
PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long,
- unsigned long));
-static unsigned char *display_block
+ unsigned long, unsigned long, int));
+static unsigned char *display_block
PARAMS ((unsigned char *, unsigned long));
-static void decode_location_expression
+static void decode_location_expression
PARAMS ((unsigned char *, unsigned int, unsigned long));
-static void request_dump
+static void request_dump
PARAMS ((unsigned int, int));
-static const char *get_elf_class
+static const char *get_elf_class
PARAMS ((unsigned int));
-static const char *get_data_encoding
+static const char *get_data_encoding
PARAMS ((unsigned int));
-static const char *get_osabi_name
+static const char *get_osabi_name
PARAMS ((unsigned int));
-static int guess_is_rela
+static int guess_is_rela
PARAMS ((unsigned long));
-static const char *get_note_type
+static const char *get_note_type
PARAMS ((unsigned int));
-static const char *get_netbsd_elfcore_note_type
+static const char *get_netbsd_elfcore_note_type
PARAMS ((unsigned int));
-static int process_note
+static int process_note
PARAMS ((Elf_Internal_Note *));
-static int process_corefile_note_segment
+static int process_corefile_note_segment
PARAMS ((FILE *, bfd_vma, bfd_vma));
static int process_corefile_note_segments
PARAMS ((FILE *));
-static int process_corefile_contents
+static int process_corefile_contents
PARAMS ((FILE *));
-static int process_arch_specific
+static int process_arch_specific
PARAMS ((FILE *));
-static int process_gnu_liblist
+static int process_gnu_liblist
PARAMS ((FILE *));
typedef int Elf32_Word;
#define SECTION_HEADER(I) (section_headers + SECTION_HEADER_INDEX (I))
-#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
+#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
#define BYTE_GET(field) byte_get (field, sizeof (field))
if (fseek (file, offset, SEEK_SET))
{
- error (_("Unable to seek to %x for %s\n"), offset, reason);
+ error (_("Unable to seek to 0x%x for %s\n"), offset, reason);
return NULL;
}
if (mvar == NULL)
{
- error (_("Out of memory allocating %d bytes for %s\n"),
+ error (_("Out of memory allocating 0x%x bytes for %s\n"),
size, reason);
return NULL;
}
if (fread (mvar, size, 1, file) != 1)
{
- error (_("Unable to read in %d bytes of %s\n"), size, reason);
+ error (_("Unable to read in 0x%x bytes of %s\n"), size, reason);
if (mvar != var)
free (mvar);
return NULL;
}
}
+static bfd_vma
+byte_get_signed (field, size)
+ unsigned char *field;
+ int size;
+{
+ bfd_vma x = byte_get (field, size);
+
+ switch (size)
+ {
+ case 1:
+ return (x ^ 0x80) - 0x80;
+ case 2:
+ return (x ^ 0x8000) - 0x8000;
+ case 4:
+ return (x ^ 0x80000000) - 0x80000000;
+ case 8:
+ case -8:
+ return x;
+ default:
+ abort ();
+ }
+}
+
+static void
+byte_put_little_endian (field, value, size)
+ unsigned char * field;
+ bfd_vma value;
+ int size;
+{
+ switch (size)
+ {
+ case 8:
+ field[7] = (((value >> 24) >> 24) >> 8) & 0xff;
+ field[6] = ((value >> 24) >> 24) & 0xff;
+ field[5] = ((value >> 24) >> 16) & 0xff;
+ field[4] = ((value >> 24) >> 8) & 0xff;
+ /* Fall through. */
+ case 4:
+ field[3] = (value >> 24) & 0xff;
+ field[2] = (value >> 16) & 0xff;
+ /* Fall through. */
+ case 2:
+ field[1] = (value >> 8) & 0xff;
+ /* Fall through. */
+ case 1:
+ field[0] = value & 0xff;
+ break;
+
+ default:
+ error (_("Unhandled data length: %d\n"), size);
+ abort ();
+ }
+}
+
/* Print a VMA value. */
static void
print_vma (vma, mode)
{
switch (mode)
{
- case FULL_HEX: printf ("0x"); /* drop through */
- case LONG_HEX: printf ("%8.8lx", (unsigned long) vma); break;
- case PREFIX_HEX: printf ("0x"); /* drop through */
- case HEX: printf ("%lx", (unsigned long) vma); break;
- case DEC: printf ("%ld", (unsigned long) vma); break;
- case DEC_5: printf ("%5ld", (long) vma); break;
- case UNSIGNED: printf ("%lu", (unsigned long) vma); break;
+ case FULL_HEX:
+ printf ("0x");
+ /* Drop through. */
+ case LONG_HEX:
+ printf ("%8.8lx", (unsigned long) vma);
+ break;
+
+ case DEC_5:
+ if (vma <= 99999)
+ {
+ printf ("%5ld", (long) vma);
+ break;
+ }
+ /* Drop through. */
+ case PREFIX_HEX:
+ printf ("0x");
+ /* Drop through. */
+ case HEX:
+ printf ("%lx", (unsigned long) vma);
+ break;
+
+ case DEC:
+ printf ("%ld", (unsigned long) vma);
+ break;
+
+ case UNSIGNED:
+ printf ("%lu", (unsigned long) vma);
+ break;
}
}
#ifdef BFD64
{
case FULL_HEX:
printf ("0x");
- /* drop through */
+ /* Drop through. */
case LONG_HEX:
printf_vma (vma);
case PREFIX_HEX:
printf ("0x");
- /* drop through */
+ /* Drop through. */
case HEX:
#if BFD_HOST_64BIT_LONG
case DEC_5:
#if BFD_HOST_64BIT_LONG
- printf ("%5ld", vma);
+ if (vma <= 99999)
+ printf ("%5ld", vma);
+ else
+ printf ("%#lx", vma);
#else
if (_bfd_int64_high (vma))
/* ugg */
printf ("++%ld", _bfd_int64_low (vma));
- else
+ else if (vma <= 99999)
printf ("%5ld", _bfd_int64_low (vma));
+ else
+ printf ("%#lx", _bfd_int64_low (vma));
#endif
break;
}
}
+static void
+byte_put_big_endian (field, value, size)
+ unsigned char * field;
+ bfd_vma value;
+ int size;
+{
+ switch (size)
+ {
+ case 8:
+ field[7] = value & 0xff;
+ field[6] = (value >> 8) & 0xff;
+ field[5] = (value >> 16) & 0xff;
+ field[4] = (value >> 24) & 0xff;
+ value >>= 16;
+ value >>= 16;
+ /* Fall through. */
+ case 4:
+ field[3] = value & 0xff;
+ field[2] = (value >> 8) & 0xff;
+ value >>= 16;
+ /* Fall through. */
+ case 2:
+ field[1] = value & 0xff;
+ value >>= 8;
+ /* Fall through. */
+ case 1:
+ field[0] = value & 0xff;
+ break;
+
+ default:
+ error (_("Unhandled data length: %d\n"), size);
+ abort ();
+ }
+}
+
/* Guess the relocation size commonly used by the specific machines. */
static int
case EM_S390:
case EM_S390_OLD:
case EM_MMIX:
+ case EM_MSP430:
+ case EM_MSP430_OLD:
case EM_XSTORMY16:
case EM_VAX:
case EM_IP2K:
case EM_IP2K_OLD:
+ case EM_IQ2000:
+ case EM_XTENSA:
+ case EM_XTENSA_OLD:
return TRUE;
case EM_MMA:
}
/* Display the contents of the relocation data found at the specified offset. */
+
static int
dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
FILE *file;
if (is_rela)
{
if (do_wide)
- printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n"));
+ printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n"));
else
printf (_(" Offset Info Type Sym. Value Sym. Name + Addend\n"));
}
else
{
if (do_wide)
- printf (_(" Offset Info Type Symbol's Value Symbol's Name\n"));
+ printf (_(" Offset Info Type Symbol's Value Symbol's Name\n"));
else
printf (_(" Offset Info Type Sym. Value Sym. Name\n"));
}
}
else
{
+ /* The #ifdef BFD64 below is to prevent a compile time warning.
+ We know that if we do not have a 64 bit data type that we
+ will never execute this code anyway. */
+#ifdef BFD64
if (elf_header.e_machine == EM_MIPS)
{
+ /* In little-endian objects, r_info isn't really a 64-bit
+ little-endian value: it has a 32-bit little-endian
+ symbol index followed by four individual byte fields.
+ Reorder INFO accordingly. */
+ if (elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+ info = (((info & 0xffffffff) << 32)
+ | ((info >> 56) & 0xff)
+ | ((info >> 40) & 0xff00)
+ | ((info >> 24) & 0xff0000)
+ | ((info >> 8) & 0xff000000));
type = ELF64_MIPS_R_TYPE (info);
type2 = ELF64_MIPS_R_TYPE2 (info);
type3 = ELF64_MIPS_R_TYPE3 (info);
type = ELF64_R_TYPE_ID (info);
else
type = ELF64_R_TYPE (info);
- /* The #ifdef BFD64 below is to prevent a compile time warning.
- We know that if we do not have a 64 bit data type that we
- will never execute this code anyway. */
-#ifdef BFD64
+
symtab_index = ELF64_R_SYM (info);
#endif
}
rtype = elf_mmix_reloc_type (type);
break;
+ case EM_MSP430:
+ case EM_MSP430_OLD:
+ rtype = elf_msp430_reloc_type (type);
+ break;
+
case EM_PPC:
- case EM_PPC64:
rtype = elf_ppc_reloc_type (type);
break;
+ case EM_PPC64:
+ rtype = elf_ppc64_reloc_type (type);
+ break;
+
case EM_MIPS:
case EM_MIPS_RS3_LE:
rtype = elf_mips_reloc_type (type);
case EM_IP2K_OLD:
rtype = elf_ip2k_reloc_type (type);
break;
+
+ case EM_IQ2000:
+ rtype = elf_iq2000_reloc_type (type);
+ break;
+
+ case EM_XTENSA_OLD:
+ case EM_XTENSA:
+ rtype = elf_xtensa_reloc_type (type);
+ break;
}
if (rtype == NULL)
printf (_("unrecognized: %-7lx"), type);
#endif
else
- printf (do_wide ? "%-21.21s" : "%-17.17s", rtype);
+ printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
if (symtab_index)
{
}
}
+static const char *
+get_ia64_dynamic_type (type)
+ unsigned long type;
+{
+ switch (type)
+ {
+ case DT_IA_64_PLT_RESERVE: return "IA_64_PLT_RESERVE";
+ default:
+ return NULL;
+ }
+}
+
static const char *
get_dynamic_type (type)
unsigned long type;
case EM_PPC64:
result = get_ppc64_dynamic_type (type);
break;
+ case EM_IA_64:
+ result = get_ia64_dynamic_type (type);
+ break;
default:
result = NULL;
break;
case EM_MCORE: return "MCORE";
case EM_ARM: return "ARM";
case EM_OLD_ALPHA: return "Digital Alpha (old)";
- case EM_SH: return "Hitachi SH";
+ case EM_SH: return "Renesas / SuperH SH";
case EM_SPARCV9: return "Sparc v9";
case EM_TRICORE: return "Siemens Tricore";
case EM_ARC: return "ARC";
- case EM_H8_300: return "Hitachi H8/300";
- case EM_H8_300H: return "Hitachi H8/300H";
- case EM_H8S: return "Hitachi H8S";
- case EM_H8_500: return "Hitachi H8/500";
+ case EM_H8_300: return "Renesas H8/300";
+ case EM_H8_300H: return "Renesas H8/300H";
+ case EM_H8S: return "Renesas H8S";
+ case EM_H8_500: return "Renesas H8/500";
case EM_IA_64: return "Intel IA-64";
case EM_MIPS_X: return "Stanford MIPS-X";
case EM_COLDFIRE: return "Motorola Coldfire";
case EM_CYGNUS_D30V:
case EM_D30V: return "d30v";
case EM_CYGNUS_M32R:
- case EM_M32R: return "Mitsubishi M32r";
+ case EM_M32R: return "Renesas M32R (formerly Mitsubishi M32r)";
case EM_CYGNUS_V850:
case EM_V850: return "NEC v850";
case EM_CYGNUS_MN10300:
case EM_ZSP: return "LSI Logic's 16-bit DSP processor";
case EM_MMIX: return "Donald Knuth's educational 64-bit processor";
case EM_HUANY: return "Harvard Universitys's machine-independent object format";
- case EM_PRISM: return "SiTera Prism";
+ case EM_PRISM: return "Vitesse Prism";
case EM_X86_64: return "Advanced Micro Devices X86-64";
case EM_S390_OLD:
case EM_S390: return "IBM S/390";
case EM_DLX: return "OpenDLX";
case EM_IP2K_OLD:
case EM_IP2K: return "Ubicom IP2xxx 8-bit microcontrollers";
+ case EM_IQ2000: return "Vitesse IQ2000";
+ case EM_XTENSA_OLD:
+ case EM_XTENSA: return "Tensilica Xtensa Processor";
default:
sprintf (buff, _("<unknown>: %x"), e_machine);
return buff;
strcat (buf, ", software FP");
break;
+ case EF_ARM_MAVERICK_FLOAT:
+ strcat (buf, ", Maverick FP");
+ break;
+
default:
unknown = 1;
break;
case E_MIPS_ARCH_4: strcat (buf, ", mips4"); break;
case E_MIPS_ARCH_5: strcat (buf, ", mips5"); break;
case E_MIPS_ARCH_32: strcat (buf, ", mips32"); break;
+ case E_MIPS_ARCH_32R2: strcat (buf, ", mips32r2"); break;
case E_MIPS_ARCH_64: strcat (buf, ", mips64"); break;
default: strcat (buf, ", unknown ISA"); break;
}
case PT_GNU_EH_FRAME:
return "GNU_EH_FRAME";
+ case PT_GNU_STACK: return "STACK";
default:
if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
get_ia64_section_type_name (sh_type)
unsigned int sh_type;
{
+ /* If the top 8 bits are 0x78 the next 8 are the os/abi ID. */
+ if ((sh_type & 0xFF000000) == SHT_IA_64_LOPSREG)
+ return get_osabi_name ((sh_type & 0x00FF0000) >> 16);
+
switch (sh_type)
{
- case SHT_IA_64_EXT: return "IA_64_EXT";
- case SHT_IA_64_UNWIND: return "IA_64_UNWIND";
+ case SHT_IA_64_EXT: return "IA_64_EXT";
+ case SHT_IA_64_UNWIND: return "IA_64_UNWIND";
+ case SHT_IA_64_PRIORITY_INIT: return "IA_64_PRIORITY_INIT";
default:
break;
}
usage ();
while ((c = getopt_long
- (argc, argv, "ersuahnldSDAIw::x:i:vVW", options, NULL)) != EOF)
+ (argc, argv, "ersuahnldSDAIw::x:i:vVWH", options, NULL)) != EOF)
{
char *cp;
int section;
case ELFOSABI_TRU64: return "UNIX - TRU64";
case ELFOSABI_MODESTO: return "Novell - Modesto";
case ELFOSABI_OPENBSD: return "UNIX - OpenBSD";
+ case ELFOSABI_OPENVMS: return "VMS - OpenVMS";
+ case ELFOSABI_NSK: return "HP - Non-Stop Kernel";
+ case ELFOSABI_AROS: return "Amiga Research OS";
case ELFOSABI_STANDALONE: return _("Standalone App");
case ELFOSABI_ARM: return "ARM";
default:
}
/* Decode the data held in 'elf_header'. */
+
static int
process_file_header ()
{
return 1;
}
+/* Returns 1 if the program headers were read into `program_headers'. */
+
+static int
+get_program_headers (file)
+ FILE *file;
+{
+ Elf_Internal_Phdr *phdrs;
+
+ /* Check cache of prior read. */
+ if (program_headers != NULL)
+ return 1;
+
+ phdrs = (Elf_Internal_Phdr *) malloc
+ (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+
+ if (phdrs == NULL)
+ {
+ error (_("Out of memory\n"));
+ return 0;
+ }
+
+ if (is_32bit_elf
+ ? get_32bit_program_headers (file, phdrs)
+ : get_64bit_program_headers (file, phdrs))
+ {
+ program_headers = phdrs;
+ return 1;
+ }
+
+ free (phdrs);
+ return 0;
+}
+
/* Returns 1 if the program headers were loaded. */
static int
process_program_headers (file)
FILE *file;
{
- Elf_Internal_Phdr *program_headers;
Elf_Internal_Phdr *segment;
unsigned int i;
printf ("\n");
}
- program_headers = (Elf_Internal_Phdr *) malloc
- (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
- if (program_headers == NULL)
- {
- error (_("Out of memory\n"));
+ if (! get_program_headers (file))
return 0;
- }
-
- if (is_32bit_elf)
- i = get_32bit_program_headers (file, program_headers);
- else
- i = get_64bit_program_headers (file, program_headers);
-
- if (i == 0)
- {
- free (program_headers);
- return 0;
- }
if (do_segments)
{
}
}
- loadaddr = -1;
dynamic_addr = 0;
dynamic_size = 0;
switch (segment->p_type)
{
- case PT_LOAD:
- if (loadaddr == -1)
- loadaddr = (segment->p_vaddr & 0xfffff000)
- - (segment->p_offset & 0xfffff000);
- break;
-
case PT_DYNAMIC:
if (dynamic_addr)
error (_("more than one dynamic segment\n"));
putc ('\n', stdout);
}
- if (loadaddr == -1)
- {
- /* Very strange. */
- loadaddr = 0;
- }
-
if (do_segments && section_headers != NULL)
{
printf (_("\n Section to Segment mapping:\n"));
}
}
- free (program_headers);
-
return 1;
}
+/* Find the file offset corresponding to VMA by using the program headers. */
+
+static long
+offset_from_vma (file, vma, size)
+ FILE *file;
+ bfd_vma vma;
+ bfd_size_type size;
+{
+ Elf_Internal_Phdr *seg;
+
+ if (! get_program_headers (file))
+ {
+ warn (_("Cannot interpret virtual addresses without program headers.\n"));
+ return (long) vma;
+ }
+
+ for (seg = program_headers;
+ seg < program_headers + elf_header.e_phnum;
+ ++seg)
+ {
+ if (seg->p_type != PT_LOAD)
+ continue;
+
+ if (vma >= (seg->p_vaddr & -seg->p_align)
+ && vma + size <= seg->p_vaddr + seg->p_filesz)
+ return vma - seg->p_vaddr + seg->p_offset;
+ }
+
+ warn (_("Virtual address 0x%lx not located in any PT_LOAD segment.\n"),
+ (long) vma);
+ return (long) vma;
+}
+
+
static int
get_32bit_section_headers (file, num)
FILE *file;
string_table = (char *) get_data (NULL, file, section->sh_offset,
section->sh_size, _("string table"));
+ if (string_table == NULL)
+ return 0;
+
string_table_length = section->sh_size;
}
return 1;
}
+struct
+{
+ const char *name;
+ int reloc;
+ int size;
+ int rela;
+} dynamic_relocations [] =
+{
+ { "REL", DT_REL, DT_RELSZ, FALSE },
+ { "RELA", DT_RELA, DT_RELASZ, TRUE },
+ { "PLT", DT_JMPREL, DT_PLTRELSZ, UNKNOWN }
+};
+
/* Process the reloc section. */
static int
process_relocs (file)
if (do_using_dynamic)
{
- int is_rela = FALSE;
-
- rel_size = 0;
- rel_offset = 0;
+ int is_rela;
+ const char *name;
+ int has_dynamic_reloc;
+ unsigned int i;
+
+ has_dynamic_reloc = 0;
- if (dynamic_info[DT_REL])
- {
- rel_offset = dynamic_info[DT_REL];
- rel_size = dynamic_info[DT_RELSZ];
- is_rela = FALSE;
- }
- else if (dynamic_info[DT_RELA])
+ for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++)
{
- rel_offset = dynamic_info[DT_RELA];
- rel_size = dynamic_info[DT_RELASZ];
- is_rela = TRUE;
- }
- else if (dynamic_info[DT_JMPREL])
- {
- rel_offset = dynamic_info[DT_JMPREL];
- rel_size = dynamic_info[DT_PLTRELSZ];
+ is_rela = dynamic_relocations [i].rela;
+ name = dynamic_relocations [i].name;
+ rel_size = dynamic_info [dynamic_relocations [i].size];
+ rel_offset = dynamic_info [dynamic_relocations [i].reloc];
+
+ has_dynamic_reloc |= rel_size;
- switch (dynamic_info[DT_PLTREL])
+ if (is_rela == UNKNOWN)
{
- case DT_REL:
- is_rela = FALSE;
- break;
- case DT_RELA:
- is_rela = TRUE;
- break;
- default:
- is_rela = UNKNOWN;
- break;
+ if (dynamic_relocations [i].reloc == DT_JMPREL)
+ switch (dynamic_info[DT_PLTREL])
+ {
+ case DT_REL:
+ is_rela = FALSE;
+ break;
+ case DT_RELA:
+ is_rela = TRUE;
+ break;
+ }
}
- }
-
- if (rel_size)
- {
- printf
- (_("\nRelocation section at offset 0x%lx contains %ld bytes:\n"),
- rel_offset, rel_size);
- dump_relocations (file, rel_offset - loadaddr, rel_size,
- dynamic_symbols, num_dynamic_syms, dynamic_strings, is_rela);
+ if (rel_size)
+ {
+ printf
+ (_("\n'%s' relocation section at offset 0x%lx contains %ld bytes:\n"),
+ name, rel_offset, rel_size);
+
+ dump_relocations (file,
+ offset_from_vma (file, rel_offset, rel_size),
+ rel_size,
+ dynamic_symbols, num_dynamic_syms,
+ dynamic_strings, is_rela);
+ }
}
- else
+
+ if (! has_dynamic_reloc)
printf (_("\nThere are no dynamic relocations in this file.\n"));
}
else
Elf_Internal_Shdr *sec;
{
unsigned long size, addr_size, nrelas, i;
- Elf_Internal_Phdr *prog_hdrs, *seg;
+ Elf_Internal_Phdr *seg;
struct unw_table_entry *tep;
Elf_Internal_Shdr *relsec;
Elf_Internal_Rela *rela, *rp;
unsigned char *table, *tp;
Elf_Internal_Sym *sym;
const char *relname;
- int result;
addr_size = is_32bit_elf ? 4 : 8;
if (elf_header.e_phnum)
{
- prog_hdrs = (Elf_Internal_Phdr *)
- xmalloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
- if (is_32bit_elf)
- result = get_32bit_program_headers (file, prog_hdrs);
- else
- result = get_64bit_program_headers (file, prog_hdrs);
-
- if (!result)
- {
- free (prog_hdrs);
+ if (! get_program_headers (file))
return 0;
- }
- for (seg = prog_hdrs; seg < prog_hdrs + elf_header.e_phnum; ++seg)
+ for (seg = program_headers;
+ seg < program_headers + elf_header.e_phnum;
+ ++seg)
{
if (seg->p_type != PT_LOAD)
continue;
break;
}
}
-
- free (prog_hdrs);
}
/* Second, build the unwind table from the contents of the unwind section: */
putchar ('\n');
}
+static void
+dynamic_segment_ia64_val (entry)
+ Elf_Internal_Dyn *entry;
+{
+ switch (entry->d_tag)
+ {
+ case DT_IA_64_PLT_RESERVE:
+ /* First 3 slots reserved. */
+ print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+ printf (" -- ");
+ print_vma (entry->d_un.d_ptr + (3 * 8), PREFIX_HEX);
+ break;
+
+ default:
+ print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+ break;
+ }
+ putchar ('\n');
+}
+
static int
get_32bit_dynamic_segment (file)
FILE *file;
we default to reading in the entire file (!) and
processing that. This is overkill, I know, but it
should work. */
- section.sh_offset = entry->d_un.d_val - loadaddr;
+ section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0);
if (fseek (file, 0, SEEK_END))
error (_("Unable to seek to end of file!"));
processing that. This is overkill, I know, but it
should work. */
- offset = entry->d_un.d_val - loadaddr;
+ offset = offset_from_vma (file, entry->d_un.d_val, 0);
if (fseek (file, 0, SEEK_END))
error (_("Unable to seek to end of file\n"));
str_tab_len = ftell (file) - offset;
/* And find the syminfo section if available. */
if (dynamic_syminfo == NULL)
{
- unsigned int syminsz = 0;
+ unsigned long syminsz = 0;
for (i = 0, entry = dynamic_segment;
i < dynamic_size;
else if (entry->d_tag == DT_SYMINSZ)
syminsz = entry->d_un.d_val;
else if (entry->d_tag == DT_SYMINFO)
- dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
+ dynamic_syminfo_offset = offset_from_vma (file, entry->d_un.d_val,
+ syminsz);
}
if (dynamic_syminfo_offset != 0 && syminsz != 0)
}
if (do_dynamic && dynamic_addr)
- printf (_("\nDynamic segment at offset 0x%x contains %ld entries:\n"),
+ printf (_("\nDynamic segment at offset 0x%lx contains %ld entries:\n"),
dynamic_addr, (long) dynamic_size);
if (do_dynamic)
printf (_(" Tag Type Name/Value\n"));
break;
case DT_PLTREL:
+ dynamic_info[entry->d_tag] = entry->d_un.d_val;
if (do_dynamic)
puts (get_dynamic_type (entry->d_un.d_val));
break;
case DT_RELAENT :
case DT_SYMENT :
case DT_RELENT :
+ dynamic_info[entry->d_tag] = entry->d_un.d_val;
case DT_PLTPADSZ:
case DT_MOVEENT :
case DT_MOVESZ :
case EM_PARISC:
dynamic_segment_parisc_val (entry);
break;
+ case EM_IA_64:
+ dynamic_segment_ia64_val (entry);
+ break;
default:
print_vma (entry->d_un.d_val, PREFIX_HEX);
putchar ('\n');
edata =
((unsigned char *)
get_data (NULL, file,
- version_info[DT_VERSIONTAGIDX (DT_VERSYM)] - loadaddr,
+ offset_from_vma
+ (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
+ total * sizeof (short)),
total * sizeof (short), _("version symbol data")));
if (!edata)
{
Elf_Internal_Verneed ivn;
unsigned long offset;
- offset = version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
- - loadaddr;
+ offset = offset_from_vma
+ (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
+ sizeof (Elf_External_Verneed));
do
{
Elf_External_Verdef evd;
unsigned long offset;
- offset = (version_info[DT_VERSIONTAGIDX (DT_VERDEF)]
- - loadaddr);
+ offset = offset_from_vma
+ (file, version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
+ sizeof evd);
do
{
if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
|| do_histogram))
{
- if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
+ if (fseek (file, offset_from_vma (file, dynamic_info[DT_HASH],
+ sizeof nb + sizeof nc),
+ SEEK_SET))
{
error (_("Unable to seek to start of dynamic information"));
return 0;
int is_nobits;
int check_def;
- offset = version_info[DT_VERSIONTAGIDX (DT_VERSYM)]
- - loadaddr;
+ offset = offset_from_vma
+ (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
+ sizeof data + si * sizeof (vers_data));
get_data (&data, file, offset + si * sizeof (vers_data),
sizeof (data), _("version data"));
Elf_Internal_Vernaux ivna;
/* We must test both. */
- offset = (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
- - loadaddr);
+ offset = offset_from_vma
+ (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
+ sizeof evn);
do
{
Elf_External_Verdaux evda;
unsigned long offset;
- offset
- = (version_info[DT_VERSIONTAGIDX (DT_VERDEF)]
- - loadaddr);
+ offset = offset_from_vma
+ (file,
+ version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
+ sizeof (Elf_External_Verdef));
do
{
unsigned char * start;
FILE *file ATTRIBUTE_UNUSED;
{
- DWARF2_External_LineInfo *external;
+ unsigned char *hdrptr;
DWARF2_Internal_LineInfo info;
unsigned char *standard_opcodes;
unsigned char *data = start;
unsigned char *end = start + section->sh_size;
unsigned char *end_of_sequence;
int i;
+ int offset_size;
+ int initial_length_size;
printf (_("\nDump of debug contents of section %s:\n\n"),
SECTION_NAME (section));
while (data < end)
{
- external = (DWARF2_External_LineInfo *) data;
+ hdrptr = data;
/* Check the length of the block. */
- info.li_length = BYTE_GET (external->li_length);
+ info.li_length = byte_get (hdrptr, 4);
+ hdrptr += 4;
if (info.li_length == 0xffffffff)
{
- warn (_("64-bit DWARF line info is not supported yet.\n"));
- break;
+ /* This section is 64-bit DWARF 3. */
+ info.li_length = byte_get (hdrptr, 8);
+ hdrptr += 8;
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
}
- if (info.li_length + sizeof (external->li_length) > section->sh_size)
+ if (info.li_length + initial_length_size > section->sh_size)
{
warn
(_("The line info appears to be corrupt - the section is too small\n"));
}
/* Check its version number. */
- info.li_version = BYTE_GET (external->li_version);
- if (info.li_version != 2)
+ info.li_version = byte_get (hdrptr, 2);
+ hdrptr += 2;
+ if (info.li_version != 2 && info.li_version != 3)
{
- warn (_("Only DWARF version 2 line info is currently supported.\n"));
+ warn (_("Only DWARF version 2 and 3 line info is currently supported.\n"));
return 0;
}
- info.li_prologue_length = BYTE_GET (external->li_prologue_length);
- info.li_min_insn_length = BYTE_GET (external->li_min_insn_length);
- info.li_default_is_stmt = BYTE_GET (external->li_default_is_stmt);
- info.li_line_base = BYTE_GET (external->li_line_base);
- info.li_line_range = BYTE_GET (external->li_line_range);
- info.li_opcode_base = BYTE_GET (external->li_opcode_base);
+ info.li_prologue_length = byte_get (hdrptr, offset_size);
+ hdrptr += offset_size;
+ info.li_min_insn_length = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_default_is_stmt = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_line_base = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_line_range = byte_get (hdrptr, 1);
+ hdrptr++;
+ info.li_opcode_base = byte_get (hdrptr, 1);
+ hdrptr++;
/* Sign extend the line base field. */
info.li_line_base <<= 24;
printf (_(" Line Range: %d\n"), info.li_line_range);
printf (_(" Opcode Base: %d\n"), info.li_opcode_base);
- end_of_sequence = data + info.li_length + sizeof (external->li_length);
+ end_of_sequence = data + info.li_length + initial_length_size;
reset_state_machine (info.li_default_is_stmt);
/* Display the contents of the Opcodes table. */
- standard_opcodes = data + sizeof (*external);
+ standard_opcodes = hdrptr;
printf (_("\n Opcodes:\n"));
unsigned char *start;
FILE *file ATTRIBUTE_UNUSED;
{
- DWARF2_External_PubNames *external;
DWARF2_Internal_PubNames pubnames;
unsigned char *end;
{
unsigned char *data;
unsigned long offset;
+ int offset_size, initial_length_size;
- external = (DWARF2_External_PubNames *) start;
-
- pubnames.pn_length = BYTE_GET (external->pn_length);
- pubnames.pn_version = BYTE_GET (external->pn_version);
- pubnames.pn_offset = BYTE_GET (external->pn_offset);
- pubnames.pn_size = BYTE_GET (external->pn_size);
-
- data = start + sizeof (*external);
- start += pubnames.pn_length + sizeof (external->pn_length);
+ data = start;
+ pubnames.pn_length = byte_get (data, 4);
+ data += 4;
if (pubnames.pn_length == 0xffffffff)
{
- warn (_("64-bit DWARF pubnames are not supported yet.\n"));
- break;
+ pubnames.pn_length = byte_get (data, 8);
+ data += 8;
+ offset_size = 8;
+ initial_length_size = 12;
}
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
+ }
+
+ pubnames.pn_version = byte_get (data, 2);
+ data += 2;
+ pubnames.pn_offset = byte_get (data, offset_size);
+ data += offset_size;
+ pubnames.pn_size = byte_get (data, offset_size);
+ data += offset_size;
+
+ start += pubnames.pn_length + initial_length_size;
- if (pubnames.pn_version != 2)
+ if (pubnames.pn_version != 2 && pubnames.pn_version != 3)
{
static int warned = 0;
if (! warned)
{
- warn (_("Only DWARF 2 pubnames are currently supported\n"));
+ warn (_("Only DWARF 2 and 3 pubnames are currently supported\n"));
warned = 1;
}
do
{
- offset = byte_get (data, 4);
+ offset = byte_get (data, offset_size);
if (offset != 0)
{
- data += 4;
+ data += offset_size;
printf (" %ld\t\t%s\n", offset, data);
data += strlen ((char *) data) + 1;
}
case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type";
case DW_TAG_partial_unit: return "DW_TAG_partial_unit";
case DW_TAG_imported_unit: return "DW_TAG_imported_unit";
+ /* UPC values. */
+ case DW_TAG_upc_shared_type: return "DW_TAG_upc_shared_type";
+ case DW_TAG_upc_strict_type: return "DW_TAG_upc_strict_type";
+ case DW_TAG_upc_relaxed_type: return "DW_TAG_upc_relaxed_type";
default:
{
static char buffer[100];
case DW_AT_body_begin: return "DW_AT_body_begin";
case DW_AT_body_end: return "DW_AT_body_end";
case DW_AT_GNU_vector: return "DW_AT_GNU_vector";
+ /* UPC extension. */
+ case DW_AT_upc_threads_scaled: return "DW_AT_upc_threads_scaled";
default:
{
static char buffer[100];
}
/* Separate the ops. */
- printf ("; ");
+ if (data < end)
+ printf ("; ");
}
}
while (1)
{
- /* Normally, the lists in the debug_loc section are related to a
- given compilation unit, and thus, we would use the
- pointer size of that compilation unit. However, since we are
- displaying it seperately here, we either have to store
- pointer sizes of all compilation units, or assume they don't
- change. We assume, like the debug_line display, that
- it doesn't change. */
+ /* Normally, the lists in the debug_loc section are related to a
+ given compilation unit, and thus, we would use the pointer size
+ of that compilation unit. However, since we are displaying it
+ seperately here, we either have to store pointer sizes of all
+ compilation units, or assume they don't change. We assume,
+ like the debug_line display, that it doesn't change. */
begin = byte_get (start, debug_line_pointer_size);
start += debug_line_pointer_size;
end = byte_get (start, debug_line_pointer_size);
if (begin == 0 && end == 0)
break;
+ /* For now, skip any base address specifiers. */
+ if (begin == 0xffffffff)
+ continue;
+
begin += addr;
end += addr;
}
static unsigned char *
-read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
+read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size,
+ offset_size, dwarf_version)
unsigned long attribute;
unsigned long form;
unsigned char *data;
unsigned long cu_offset;
unsigned long pointer_size;
+ unsigned long offset_size;
+ int dwarf_version;
{
unsigned long uvalue = 0;
unsigned char *block_start = NULL;
break;
case DW_FORM_ref_addr:
+ if (dwarf_version == 2)
+ {
+ uvalue = byte_get (data, pointer_size);
+ data += pointer_size;
+ }
+ else if (dwarf_version == 3)
+ {
+ uvalue = byte_get (data, offset_size);
+ data += offset_size;
+ }
+ else
+ {
+ error (_("Internal error: DWARF version is not 2 or 3.\n"));
+ }
+ break;
+
case DW_FORM_addr:
uvalue = byte_get (data, pointer_size);
data += pointer_size;
break;
case DW_FORM_strp:
- uvalue = byte_get (data, /* offset_size */ 4);
- data += /* offset_size */ 4;
+ uvalue = byte_get (data, offset_size);
+ data += offset_size;
break;
case DW_FORM_ref1:
data += bytes_read;
printf (" %s", get_FORM_name (form));
return read_and_display_attr_value (attribute, form, data, cu_offset,
- pointer_size);
+ pointer_size, offset_size,
+ dwarf_version);
}
switch (form)
case DW_LANG_Fortran95: printf ("(Fortran 95)"); break;
/* MIPS extension. */
case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
+ /* UPC extension. */
+ case DW_LANG_Upc: printf ("(Unified Parallel C)"); break;
default:
printf ("(Unknown: %lx)", uvalue);
break;
decode_location_expression (block_start, pointer_size, uvalue);
printf (")");
}
- else if (form == DW_FORM_data4)
+ else if (form == DW_FORM_data4 || form == DW_FORM_data8)
{
printf ("(");
printf ("location list");
}
static unsigned char *
-read_and_display_attr (attribute, form, data, cu_offset, pointer_size)
+read_and_display_attr (attribute, form, data, cu_offset, pointer_size,
+ offset_size, dwarf_version)
unsigned long attribute;
unsigned long form;
unsigned char *data;
unsigned long cu_offset;
unsigned long pointer_size;
+ unsigned long offset_size;
+ int dwarf_version;
{
printf (" %-18s:", get_AT_name (attribute));
data = read_and_display_attr_value (attribute, form, data, cu_offset,
- pointer_size);
+ pointer_size, offset_size, dwarf_version);
printf ("\n");
return data;
}
while (start < end)
{
- DWARF2_External_CompUnit *external;
DWARF2_Internal_CompUnit compunit;
Elf_Internal_Shdr *relsec;
+ unsigned char *hdrptr;
+ unsigned char *cu_abbrev_offset_ptr;
unsigned char *tags;
unsigned int i;
int level;
unsigned long cu_offset;
+ int offset_size;
+ int initial_length_size;
- external = (DWARF2_External_CompUnit *) start;
+ hdrptr = start;
- compunit.cu_length = BYTE_GET (external->cu_length);
- compunit.cu_version = BYTE_GET (external->cu_version);
- compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset);
- compunit.cu_pointer_size = BYTE_GET (external->cu_pointer_size);
+ compunit.cu_length = byte_get (hdrptr, 4);
+ hdrptr += 4;
if (compunit.cu_length == 0xffffffff)
{
- warn (_("64-bit DWARF debug info is not supported yet.\n"));
- break;
+ compunit.cu_length = byte_get (hdrptr, 8);
+ hdrptr += 8;
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
}
- /* Check for RELA relocations in the
- abbrev_offset address, and apply them. */
+ compunit.cu_version = byte_get (hdrptr, 2);
+ hdrptr += 2;
+
+ /* Apply addends of RELA relocations. */
for (relsec = section_headers;
relsec < section_headers + elf_header.e_shnum;
++relsec)
for (rp = rela; rp < rela + nrelas; ++rp)
{
- if (rp->r_offset
- != (bfd_vma) ((unsigned char *) &external->cu_abbrev_offset
- - section_begin))
+ unsigned char *loc;
+
+ if (rp->r_offset >= (bfd_vma) (hdrptr - section_begin)
+ && section->sh_size > (bfd_vma) offset_size
+ && rp->r_offset <= section->sh_size - offset_size)
+ loc = section_begin + rp->r_offset;
+ else
continue;
if (is_32bit_elf)
}
}
- compunit.cu_abbrev_offset = rp->r_addend;
- break;
+ byte_put (loc, rp->r_addend, offset_size);
}
free (rela);
break;
}
- tags = start + sizeof (*external);
+ cu_abbrev_offset_ptr = hdrptr;
+ compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
+ hdrptr += offset_size;
+
+ compunit.cu_pointer_size = byte_get (hdrptr, 1);
+ hdrptr += 1;
+
+ tags = hdrptr;
cu_offset = start - section_begin;
- start += compunit.cu_length + sizeof (external->cu_length);
+ start += compunit.cu_length + initial_length_size;
printf (_(" Compilation Unit @ %lx:\n"), cu_offset);
printf (_(" Length: %ld\n"), compunit.cu_length);
printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size);
- if (compunit.cu_version != 2)
+ if (compunit.cu_version != 2 && compunit.cu_version != 3)
{
- warn (_("Only version 2 DWARF debug information is currently supported.\n"));
+ warn (_("Only version 2 and 3 DWARF debug information is currently supported.\n"));
continue;
}
tags = read_and_display_attr (attr->attribute,
attr->form,
tags, cu_offset,
- compunit.cu_pointer_size);
+ compunit.cu_pointer_size,
+ offset_size,
+ compunit.cu_version);
if (entry->children)
++level;
while (start < end)
{
- DWARF2_External_ARange *external;
+ unsigned char *hdrptr;
DWARF2_Internal_ARange arange;
unsigned char *ranges;
unsigned long length;
unsigned long address;
int excess;
+ int offset_size;
+ int initial_length_size;
- external = (DWARF2_External_ARange *) start;
+ hdrptr = start;
- arange.ar_length = BYTE_GET (external->ar_length);
- arange.ar_version = BYTE_GET (external->ar_version);
- arange.ar_info_offset = BYTE_GET (external->ar_info_offset);
- arange.ar_pointer_size = BYTE_GET (external->ar_pointer_size);
- arange.ar_segment_size = BYTE_GET (external->ar_segment_size);
+ arange.ar_length = byte_get (hdrptr, 4);
+ hdrptr += 4;
if (arange.ar_length == 0xffffffff)
{
- warn (_("64-bit DWARF aranges are not supported yet.\n"));
- break;
+ arange.ar_length = byte_get (hdrptr, 8);
+ hdrptr += 8;
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
}
- if (arange.ar_version != 2)
+ arange.ar_version = byte_get (hdrptr, 2);
+ hdrptr += 2;
+
+ arange.ar_info_offset = byte_get (hdrptr, offset_size);
+ hdrptr += offset_size;
+
+ arange.ar_pointer_size = byte_get (hdrptr, 1);
+ hdrptr += 1;
+
+ arange.ar_segment_size = byte_get (hdrptr, 1);
+ hdrptr += 1;
+
+ if (arange.ar_version != 2 && arange.ar_version != 3)
{
- warn (_("Only DWARF 2 aranges are currently supported.\n"));
+ warn (_("Only DWARF 2 and 3 aranges are currently supported.\n"));
break;
}
printf (_("\n Address Length\n"));
- ranges = start + sizeof (*external);
+ ranges = hdrptr;
/* Must pad to an alignment boundary that is twice the pointer size. */
- excess = sizeof (*external) % (2 * arange.ar_pointer_size);
+ excess = (hdrptr - start) % (2 * arange.ar_pointer_size);
if (excess)
ranges += (2 * arange.ar_pointer_size) - excess;
printf (" %8.8lx %lu\n", address, length);
}
- start += arange.ar_length + sizeof (external->ar_length);
+ start += arange.ar_length + initial_length_size;
}
printf ("\n");
int cfa_offset;
int ra;
unsigned char fde_encoding;
+ unsigned char cfa_exp;
}
Frame_Chunk;
static void frame_need_space PARAMS ((Frame_Chunk *, int));
static void frame_display_row PARAMS ((Frame_Chunk *, int *, int *));
static int size_of_encoded_value PARAMS ((int));
+static bfd_vma get_encoded_value PARAMS ((unsigned char *, int));
static void
frame_need_space (fc, reg)
}
printf ("%08lx ", fc->pc_begin);
- sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
+ if (fc->cfa_exp)
+ strcpy (tmp, "exp");
+ else
+ sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
printf ("%-8s ", tmp);
for (r = 0; r < fc->ncols; r++)
case DW_CFA_register:
sprintf (tmp, "r%d", fc->col_offset[r]);
break;
+ case DW_CFA_expression:
+ strcpy (tmp, "exp");
+ break;
default:
strcpy (tmp, "n/a");
break;
}
}
+static bfd_vma
+get_encoded_value (data, encoding)
+ unsigned char *data;
+ int encoding;
+{
+ int size = size_of_encoded_value (encoding);
+ if (encoding & DW_EH_PE_signed)
+ return byte_get_signed (data, size);
+ else
+ return byte_get (data, size);
+}
+
#define GET(N) byte_get (start, N); start += N
#define LEB() read_leb128 (start, & length_return, 0); start += length_return
#define SLEB() read_leb128 (start, & length_return, 1); start += length_return
unsigned char *augmentation_data = NULL;
unsigned long augmentation_data_len = 0;
int encoded_ptr_size = addr_size;
+ int offset_size;
+ int initial_length_size;
saved_start = start;
length = byte_get (start, 4); start += 4;
if (length == 0xffffffff)
{
- warn (_("64-bit DWARF format frames are not supported yet.\n"));
- break;
+ length = byte_get (start, 8);
+ start += 8;
+ offset_size = 8;
+ initial_length_size = 12;
+ }
+ else
+ {
+ offset_size = 4;
+ initial_length_size = 4;
}
- block_end = saved_start + length + 4;
- cie_id = byte_get (start, 4); start += 4;
+ block_end = saved_start + length + initial_length_size;
+ cie_id = byte_get (start, offset_size); start += offset_size;
if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
{
if (fc->fde_encoding)
encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
- fc->pc_begin = byte_get (start, encoded_ptr_size);
+ fc->pc_begin = get_encoded_value (start, fc->fde_encoding);
if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
fc->pc_begin += section->sh_addr + (start - section_start);
start += encoded_ptr_size;
/* At this point, fc is the current chunk, cie (if any) is set, and we're
about to interpret instructions for the chunk. */
-
- if (do_debug_frames_interp)
+ /* ??? At present we need to do this always, since this sizes the
+ fc->col_type and fc->col_offset arrays, which we write into always.
+ We should probably split the interpreted and non-interpreted bits
+ into two different routines, since there's so much that doesn't
+ really overlap between them. */
+ if (1 || do_debug_frames_interp)
{
/* Start by making a pass over the chunk, allocating storage
and taking note of what registers are used. */
while (start < block_end)
{
unsigned op, opa;
- unsigned long reg;
+ unsigned long reg, tmp;
op = *start++;
opa = op & 0x3f;
case DW_CFA_def_cfa_offset:
LEB ();
break;
+ case DW_CFA_def_cfa_expression:
+ tmp = LEB ();
+ start += tmp;
+ break;
+ case DW_CFA_expression:
+ reg = LEB ();
+ tmp = LEB ();
+ start += tmp;
+ frame_need_space (fc, reg);
+ fc->col_type[reg] = DW_CFA_undefined;
+ break;
case DW_CFA_offset_extended_sf:
reg = LEB (); SLEB ();
frame_need_space (fc, reg);
case DW_CFA_def_cfa_offset_sf:
SLEB ();
break;
+ case DW_CFA_MIPS_advance_loc8:
+ start += 8;
+ break;
case DW_CFA_GNU_args_size:
LEB ();
break;
break;
case DW_CFA_set_loc:
- vma = byte_get (start, encoded_ptr_size);
+ vma = get_encoded_value (start, fc->fde_encoding);
if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
vma += section->sh_addr + (start - section_start);
start += encoded_ptr_size;
reg = LEB ();
roffs = LEB ();
if (! do_debug_frames_interp)
- printf (" DW_CFA_register: r%ld\n", reg);
+ printf (" DW_CFA_register: r%ld in r%ld\n", reg, roffs);
fc->col_type[reg] = DW_CFA_register;
fc->col_offset[reg] = roffs;
break;
case DW_CFA_def_cfa:
fc->cfa_reg = LEB ();
fc->cfa_offset = LEB ();
+ fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa: r%d ofs %d\n",
fc->cfa_reg, fc->cfa_offset);
case DW_CFA_def_cfa_register:
fc->cfa_reg = LEB ();
+ fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
break;
printf (" DW_CFA_nop\n");
break;
+ case DW_CFA_def_cfa_expression:
+ ul = LEB ();
+ if (! do_debug_frames_interp)
+ {
+ printf (" DW_CFA_def_cfa_expression (");
+ decode_location_expression (start, addr_size, ul);
+ printf (")\n");
+ }
+ fc->cfa_exp = 1;
+ start += ul;
+ break;
+
+ case DW_CFA_expression:
+ reg = LEB ();
+ ul = LEB ();
+ if (! do_debug_frames_interp)
+ {
+ printf (" DW_CFA_expression: r%ld (", reg);
+ decode_location_expression (start, addr_size, ul);
+ printf (")\n");
+ }
+ fc->col_type[reg] = DW_CFA_expression;
+ start += ul;
+ break;
+
case DW_CFA_offset_extended_sf:
reg = LEB ();
l = SLEB ();
case DW_CFA_def_cfa_sf:
fc->cfa_reg = LEB ();
fc->cfa_offset = SLEB ();
+ fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_sf: r%d ofs %d\n",
fc->cfa_reg, fc->cfa_offset);
printf (" DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
break;
+ case DW_CFA_MIPS_advance_loc8:
+ ofs = byte_get (start, 8); start += 8;
+ if (do_debug_frames_interp)
+ frame_display_row (fc, &need_col_headers, &max_regs);
+ else
+ printf (" DW_CFA_MIPS_advance_loc8: %ld to %08lx\n",
+ ofs * fc->code_factor,
+ fc->pc_begin + ofs * fc->code_factor);
+ fc->pc_begin += ofs * fc->code_factor;
+ break;
+
case DW_CFA_GNU_window_save:
if (! do_debug_frames_interp)
printf (" DW_CFA_GNU_window_save\n");
fc->col_offset[reg] = l * fc->data_factor;
break;
- /* FIXME: How do we handle these? */
- case DW_CFA_def_cfa_expression:
- fprintf (stderr, "unsupported DW_CFA_def_cfa_expression\n");
- start = block_end;
- break;
-
- case DW_CFA_expression:
- fprintf (stderr, "unsupported DW_CFA_expression\n");
- start = block_end;
- break;
-
default:
fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op);
start = block_end;
unsigned char *start;
FILE *file ATTRIBUTE_UNUSED;
{
- DWARF2_External_CompUnit *external;
+ unsigned long length;
- external = (DWARF2_External_CompUnit *) start;
+ /* Read the first 4 bytes. For a 32-bit DWARF section, this will
+ be the length. For a 64-bit DWARF section, it'll be the escape
+ code 0xffffffff followed by an 8 byte length. For the purposes
+ of this prescan, we don't care about the actual length, but the
+ presence of the escape bytes does affect the location of the byte
+ which describes the address size. */
+ length = byte_get (start, 4);
- debug_line_pointer_size = BYTE_GET (external->cu_pointer_size);
+ if (length == 0xffffffff)
+ {
+ /* For 64-bit DWARF, the 1-byte address_size field is 22 bytes
+ from the start of the section. This is computed as follows:
+
+ unit_length: 12 bytes
+ version: 2 bytes
+ debug_abbrev_offset: 8 bytes
+ -----------------------------
+ Total: 22 bytes */
+
+ debug_line_pointer_size = byte_get (start + 22, 1);
+ }
+ else
+ {
+ /* For 32-bit DWARF, the 1-byte address_size field is 10 bytes from
+ the start of the section:
+ unit_length: 4 bytes
+ version: 2 bytes
+ debug_abbrev_offset: 4 bytes
+ -----------------------------
+ Total: 10 bytes */
+
+ debug_line_pointer_size = byte_get (start + 10, 1);
+ }
return 0;
}
switch (entry->d_tag)
{
case DT_MIPS_LIBLIST:
- liblist_offset = entry->d_un.d_val - loadaddr;
+ liblist_offset
+ = offset_from_vma (file, entry->d_un.d_val,
+ liblistno * sizeof (Elf32_External_Lib));
break;
case DT_MIPS_LIBLISTNO:
liblistno = entry->d_un.d_val;
break;
case DT_MIPS_OPTIONS:
- options_offset = entry->d_un.d_val - loadaddr;
+ options_offset = offset_from_vma (file, entry->d_un.d_val, 0);
break;
case DT_MIPS_CONFLICT:
- conflicts_offset = entry->d_un.d_val - loadaddr;
+ conflicts_offset
+ = offset_from_vma (file, entry->d_un.d_val,
+ conflictsno * sizeof (Elf32_External_Conflict));
break;
case DT_MIPS_CONFLICTNO:
conflictsno = entry->d_un.d_val;
process_corefile_note_segments (file)
FILE *file;
{
- Elf_Internal_Phdr *program_headers;
Elf_Internal_Phdr *segment;
unsigned int i;
int res = 1;
- program_headers = (Elf_Internal_Phdr *) malloc
- (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
- if (program_headers == NULL)
- {
- error (_("Out of memory\n"));
- return 0;
- }
-
- if (is_32bit_elf)
- i = get_32bit_program_headers (file, program_headers);
- else
- i = get_64bit_program_headers (file, program_headers);
-
- if (i == 0)
- {
- free (program_headers);
+ if (! get_program_headers (file))
return 0;
- }
for (i = 0, segment = program_headers;
i < elf_header.e_phnum;
(bfd_vma) segment->p_filesz);
}
- free (program_headers);
-
return res;
}
{
default: /* fall through */
case ELFDATANONE: /* fall through */
- case ELFDATA2LSB: byte_get = byte_get_little_endian; break;
- case ELFDATA2MSB: byte_get = byte_get_big_endian; break;
+ case ELFDATA2LSB:
+ byte_get = byte_get_little_endian;
+ byte_put = byte_put_little_endian;
+ break;
+ case ELFDATA2MSB:
+ byte_get = byte_get_big_endian;
+ byte_put = byte_put_big_endian;
+ break;
}
/* For now we only support 32 bit and 64 bit ELF files. */
fclose (file);
+ if (program_headers)
+ {
+ free (program_headers);
+ program_headers = NULL;
+ }
+
if (section_headers)
{
free (section_headers);
char **argv;
{
int err;
+ char *cmdline_dump_sects = NULL;
+ unsigned num_cmdline_dump_sects = 0;
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
setlocale (LC_MESSAGES, "");
if (optind < (argc - 1))
show_name = 1;
+ /* When processing more than one file remember the dump requests
+ issued on command line to reset them after each file. */
+ if (optind + 1 < argc && dump_sects != NULL)
+ {
+ cmdline_dump_sects = malloc (num_dump_sects);
+ if (cmdline_dump_sects == NULL)
+ error (_("Out of memory allocating dump request table."));
+ else
+ {
+ memcpy (cmdline_dump_sects, dump_sects, num_dump_sects);
+ num_cmdline_dump_sects = num_dump_sects;
+ }
+ }
+
err = 0;
while (optind < argc)
- err |= process_file (argv[optind++]);
+ {
+ err |= process_file (argv[optind++]);
+
+ /* Reset dump requests. */
+ if (optind < argc && dump_sects != NULL)
+ {
+ num_dump_sects = num_cmdline_dump_sects;
+ if (num_cmdline_dump_sects > 0)
+ memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects);
+ }
+ }
if (dump_sects != NULL)
free (dump_sects);
+ if (cmdline_dump_sects != NULL)
+ free (cmdline_dump_sects);
return err;
}