#include "elf/x86-64.h"
#include "elf/xstormy16.h"
#include "elf/iq2000.h"
+#include "elf/xtensa.h"
+
+#include "aout/ar.h"
#include "bucomm.h"
#include "getopt.h"
+#include "libiberty.h"
char *program_name = "readelf";
+long archive_file_offset;
+unsigned long archive_file_size;
unsigned long dynamic_addr;
bfd_size_type dynamic_size;
char *dynamic_strings;
unsigned long dynamic_syminfo_offset;
unsigned int dynamic_syminfo_nent;
char program_interpreter[64];
-long dynamic_info[DT_JMPREL + 1];
-long version_info[16];
-long 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
- PARAMS ((bfd_vma, print_mode));
-static void print_symbol
- PARAMS ((int, const char *));
-static bfd_vma (*byte_get)
- PARAMS ((unsigned char *, int));
-static bfd_vma byte_get_little_endian
- PARAMS ((unsigned char *, int));
-static bfd_vma byte_get_big_endian
- PARAMS ((unsigned char *, int));
-static const char *get_mips_dynamic_type
- PARAMS ((unsigned long));
-static const char *get_sparc64_dynamic_type
- PARAMS ((unsigned long));
-static const char *get_ppc64_dynamic_type
- PARAMS ((unsigned long));
-static const char *get_parisc_dynamic_type
- PARAMS ((unsigned long));
-static const char *get_dynamic_type
- PARAMS ((unsigned long));
-static int slurp_rela_relocs
- PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **,
- unsigned long *));
-static int slurp_rel_relocs
- PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **,
- unsigned long *));
-static int dump_relocations
- PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *,
- unsigned long, char *, int));
-static char *get_file_type
- PARAMS ((unsigned));
-static char *get_machine_name
- PARAMS ((unsigned));
-static void decode_ARM_machine_flags
- PARAMS ((unsigned, char[]));
-static char *get_machine_flags
- PARAMS ((unsigned, unsigned));
-static const char *get_mips_segment_type
- PARAMS ((unsigned long));
-static const char *get_parisc_segment_type
- PARAMS ((unsigned long));
-static const char *get_ia64_segment_type
- PARAMS ((unsigned long));
-static const char *get_segment_type
- PARAMS ((unsigned long));
-static const char *get_mips_section_type_name
- PARAMS ((unsigned int));
-static const char *get_parisc_section_type_name
- PARAMS ((unsigned int));
-static const char *get_ia64_section_type_name
- PARAMS ((unsigned int));
-static const char *get_section_type_name
- PARAMS ((unsigned int));
-static const char *get_symbol_binding
- PARAMS ((unsigned int));
-static const char *get_symbol_type
- PARAMS ((unsigned int));
-static const char *get_symbol_visibility
- PARAMS ((unsigned int));
-static const char *get_symbol_index_type
- PARAMS ((unsigned int));
-static const char *get_dynamic_flags
- PARAMS ((bfd_vma));
-static void usage
- PARAMS ((void));
-static void parse_args
- PARAMS ((int, char **));
-static int process_file_header
- PARAMS ((void));
-static int process_program_headers
- PARAMS ((FILE *));
-static int process_section_headers
- PARAMS ((FILE *));
-static int process_unwind
- PARAMS ((FILE *));
-static void dynamic_segment_mips_val
- PARAMS ((Elf_Internal_Dyn *));
-static void dynamic_segment_parisc_val
- PARAMS ((Elf_Internal_Dyn *));
-static int process_dynamic_segment
- PARAMS ((FILE *));
-static int process_symbol_table
- PARAMS ((FILE *));
-static int process_syminfo
- PARAMS ((FILE *));
-static int process_section_contents
- PARAMS ((FILE *));
-static void process_mips_fpe_exception
- PARAMS ((int));
-static int process_mips_specific
- PARAMS ((FILE *));
-static int process_file
- PARAMS ((char *));
-static int process_relocs
- PARAMS ((FILE *));
-static int process_version_sections
- PARAMS ((FILE *));
-static char *get_ver_flags
- PARAMS ((unsigned int));
-static int get_32bit_section_headers
- PARAMS ((FILE *, unsigned int));
-static int get_64bit_section_headers
- PARAMS ((FILE *, unsigned int));
-static int get_32bit_program_headers
- PARAMS ((FILE *, Elf_Internal_Phdr *));
-static int get_64bit_program_headers
- PARAMS ((FILE *, Elf_Internal_Phdr *));
-static int get_file_header
- PARAMS ((FILE *));
-static Elf_Internal_Sym *get_32bit_elf_symbols
- PARAMS ((FILE *, Elf_Internal_Shdr *));
-static Elf_Internal_Sym *get_64bit_elf_symbols
- PARAMS ((FILE *, Elf_Internal_Shdr *));
-static const char *get_elf_section_flags
- PARAMS ((bfd_vma));
-static int *get_dynamic_data
- PARAMS ((FILE *, unsigned int));
-static int get_32bit_dynamic_segment
- PARAMS ((FILE *));
-static int get_64bit_dynamic_segment
- PARAMS ((FILE *));
-#ifdef SUPPORT_DISASSEMBLY
-static int disassemble_section
- PARAMS ((Elf_Internal_Shdr *, FILE *));
-#endif
-static int dump_section
- PARAMS ((Elf_Internal_Shdr *, FILE *));
-static int display_debug_section
- PARAMS ((Elf_Internal_Shdr *, FILE *));
-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
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_lines
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_pubnames
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_abbrev
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_aranges
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_frames
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_macinfo
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_str
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static int display_debug_loc
- PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
-static unsigned char *process_abbrev_section
- PARAMS ((unsigned char *, unsigned char *));
-static void load_debug_str
- PARAMS ((FILE *));
-static void free_debug_str
- PARAMS ((void));
-static const char *fetch_indirect_string
- PARAMS ((unsigned long));
-static void load_debug_loc
- PARAMS ((FILE *));
-static void free_debug_loc
- PARAMS ((void));
-static unsigned long read_leb128
- PARAMS ((unsigned char *, int *, int));
-static int process_extended_line_op
- PARAMS ((unsigned char *, int, int));
-static void reset_state_machine
- PARAMS ((int));
-static char *get_TAG_name
- PARAMS ((unsigned long));
-static char *get_AT_name
- PARAMS ((unsigned long));
-static char *get_FORM_name
- PARAMS ((unsigned long));
-static void free_abbrevs
- PARAMS ((void));
-static void add_abbrev
- PARAMS ((unsigned long, unsigned long, int));
-static void add_abbrev_attr
- PARAMS ((unsigned long, unsigned long));
-static unsigned char *read_and_display_attr
- PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long,
- unsigned long));
-static unsigned char *read_and_display_attr_value
- PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long,
- unsigned long));
-static unsigned char *display_block
- PARAMS ((unsigned char *, unsigned long));
-static void decode_location_expression
- PARAMS ((unsigned char *, unsigned int, unsigned long));
-static void request_dump
- PARAMS ((unsigned int, int));
-static const char *get_elf_class
- PARAMS ((unsigned int));
-static const char *get_data_encoding
- PARAMS ((unsigned int));
-static const char *get_osabi_name
- PARAMS ((unsigned int));
-static int guess_is_rela
- PARAMS ((unsigned long));
-static const char *get_note_type
- PARAMS ((unsigned int));
-static const char *get_netbsd_elfcore_note_type
- PARAMS ((unsigned int));
-static int process_note
- PARAMS ((Elf_Internal_Note *));
-static int process_corefile_note_segment
- PARAMS ((FILE *, bfd_vma, bfd_vma));
-static int process_corefile_note_segments
- PARAMS ((FILE *));
-static int process_corefile_contents
- PARAMS ((FILE *));
-static int process_arch_specific
- PARAMS ((FILE *));
-static int process_gnu_liblist
- PARAMS ((FILE *));
+static bfd_vma (*byte_get) (unsigned char *, int);
+static void (*byte_put) (unsigned char *, bfd_vma, int);
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))
static void
-error VPARAMS ((const char *message, ...))
+error (const char *message, ...)
{
- VA_OPEN (args, message);
- VA_FIXEDARG (args, const char *, message);
+ va_list args;
+ va_start (args, message);
fprintf (stderr, _("%s: Error: "), program_name);
vfprintf (stderr, message, args);
- VA_CLOSE (args);
+ va_end (args);
}
static void
-warn VPARAMS ((const char *message, ...))
+warn (const char *message, ...)
{
- VA_OPEN (args, message);
- VA_FIXEDARG (args, const char *, message);
+ va_list args;
+ va_start (args, message);
fprintf (stderr, _("%s: Warning: "), program_name);
vfprintf (stderr, message, args);
- VA_CLOSE (args);
+ va_end (args);
}
-static PTR get_data PARAMS ((PTR, FILE *, long, size_t, const char *));
-
-static PTR
-get_data (var, file, offset, size, reason)
- PTR var;
- FILE *file;
- long offset;
- size_t size;
- const char *reason;
+static void *
+get_data (void *var, FILE *file, long offset, size_t size, const char *reason)
{
- PTR mvar;
+ void *mvar;
if (size == 0)
return NULL;
- if (fseek (file, offset, SEEK_SET))
+ if (fseek (file, archive_file_offset + offset, SEEK_SET))
{
- error (_("Unable to seek to %x for %s\n"), offset, reason);
+ error (_("Unable to seek to 0x%x for %s\n"),
+ archive_file_offset + offset, reason);
return NULL;
}
mvar = var;
if (mvar == NULL)
{
- mvar = (PTR) malloc (size);
+ mvar = malloc (size);
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_little_endian (field, size)
- unsigned char *field;
- int size;
+byte_get_little_endian (unsigned char *field, int size)
{
switch (size)
{
/* This is a special case, generated by the BYTE_GET8 macro.
It means that we are loading an 8 byte value from a field
in an external structure into an 8 byte value in a field
- in an internal strcuture. */
+ in an internal structure. */
return ((bfd_vma) (field[0]))
| (((bfd_vma) (field[1])) << 8)
| (((bfd_vma) (field[2])) << 16)
}
}
+static bfd_vma
+byte_get_signed (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 (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)
- bfd_vma vma;
- print_mode mode;
+print_vma (bfd_vma vma, print_mode mode)
{
#ifdef BFD64
if (is_32bit_elf)
{
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;
truncating or padding as necessary. */
static void
-print_symbol (width, symbol)
- int width;
- const char *symbol;
+print_symbol (int width, const char *symbol)
{
if (do_wide)
printf ("%s", symbol);
}
static bfd_vma
-byte_get_big_endian (field, size)
- unsigned char *field;
- int size;
+byte_get_big_endian (unsigned char *field, int size)
{
switch (size)
{
/* This is a special case, generated by the BYTE_GET8 macro.
It means that we are loading an 8 byte value from a field
in an external structure into an 8 byte value in a field
- in an internal strcuture. */
+ in an internal structure. */
return ((bfd_vma) (field[7]))
| (((bfd_vma) (field[6])) << 8)
| (((bfd_vma) (field[5])) << 16)
}
}
+static void
+byte_put_big_endian (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
-guess_is_rela (e_machine)
- unsigned long e_machine;
+guess_is_rela (unsigned long e_machine)
{
switch (e_machine)
{
case EM_IP2K:
case EM_IP2K_OLD:
case EM_IQ2000:
+ case EM_XTENSA:
+ case EM_XTENSA_OLD:
return TRUE;
case EM_MMA:
}
static int
-slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp)
- FILE *file;
- unsigned long rel_offset;
- unsigned long rel_size;
- Elf_Internal_Rela **relasp;
- unsigned long *nrelasp;
+slurp_rela_relocs (FILE *file,
+ unsigned long rel_offset,
+ unsigned long rel_size,
+ Elf_Internal_Rela **relasp,
+ unsigned long *nrelasp)
{
Elf_Internal_Rela *relas;
unsigned long nrelas;
{
Elf32_External_Rela *erelas;
- erelas = (Elf32_External_Rela *) get_data (NULL, file, rel_offset,
- rel_size, _("relocs"));
+ erelas = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
if (!erelas)
return 0;
nrelas = rel_size / sizeof (Elf32_External_Rela);
- relas = (Elf_Internal_Rela *)
- malloc (nrelas * sizeof (Elf_Internal_Rela));
+ relas = malloc (nrelas * sizeof (Elf_Internal_Rela));
if (relas == NULL)
{
{
Elf64_External_Rela *erelas;
- erelas = (Elf64_External_Rela *) get_data (NULL, file, rel_offset,
- rel_size, _("relocs"));
+ erelas = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
if (!erelas)
return 0;
nrelas = rel_size / sizeof (Elf64_External_Rela);
- relas = (Elf_Internal_Rela *)
- malloc (nrelas * sizeof (Elf_Internal_Rela));
+ relas = malloc (nrelas * sizeof (Elf_Internal_Rela));
if (relas == NULL)
{
}
static int
-slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
- FILE *file;
- unsigned long rel_offset;
- unsigned long rel_size;
- Elf_Internal_Rela **relsp;
- unsigned long *nrelsp;
+slurp_rel_relocs (FILE *file,
+ unsigned long rel_offset,
+ unsigned long rel_size,
+ Elf_Internal_Rela **relsp,
+ unsigned long *nrelsp)
{
Elf_Internal_Rela *rels;
unsigned long nrels;
{
Elf32_External_Rel *erels;
- erels = (Elf32_External_Rel *) get_data (NULL, file, rel_offset,
- rel_size, _("relocs"));
+ erels = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
if (!erels)
return 0;
nrels = rel_size / sizeof (Elf32_External_Rel);
- rels = (Elf_Internal_Rela *) malloc (nrels * sizeof (Elf_Internal_Rela));
+ rels = malloc (nrels * sizeof (Elf_Internal_Rela));
if (rels == NULL)
{
{
Elf64_External_Rel *erels;
- erels = (Elf64_External_Rel *) get_data (NULL, file, rel_offset,
- rel_size, _("relocs"));
+ erels = get_data (NULL, file, rel_offset, rel_size, _("relocs"));
if (!erels)
return 0;
nrels = rel_size / sizeof (Elf64_External_Rel);
- rels = (Elf_Internal_Rela *) malloc (nrels * sizeof (Elf_Internal_Rela));
+ rels = malloc (nrels * sizeof (Elf_Internal_Rela));
if (rels == NULL)
{
return 1;
}
-/* Display the contents of the relocation data found at the specified offset. */
+/* Display the contents of the relocation data found at the specified
+ offset. */
+
static int
-dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
- FILE *file;
- unsigned long rel_offset;
- unsigned long rel_size;
- Elf_Internal_Sym *symtab;
- unsigned long nsyms;
- char *strtab;
- int is_rela;
+dump_relocations (FILE *file,
+ unsigned long rel_offset,
+ unsigned long rel_size,
+ Elf_Internal_Sym *symtab,
+ unsigned long nsyms,
+ char *strtab,
+ int is_rela)
{
unsigned int i;
Elf_Internal_Rela *rels;
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"));
}
bfd_vma info;
bfd_vma symtab_index;
bfd_vma type;
- bfd_vma type2 = (bfd_vma) NULL;
- bfd_vma type3 = (bfd_vma) NULL;
+ bfd_vma type2 = 0;
+ bfd_vma type3 = 0;
offset = rels[i].r_offset;
info = rels[i].r_info;
}
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
}
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)
{
sec_name = "ABS";
else if (psym->st_shndx == SHN_COMMON)
sec_name = "COMMON";
+ else if (elf_header.e_machine == EM_IA_64
+ && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX
+ && psym->st_shndx == SHN_IA_64_ANSI_COMMON)
+ sec_name = "ANSI_COM";
else
{
sprintf (name_buf, "<section 0x%x>",
}
static const char *
-get_mips_dynamic_type (type)
- unsigned long type;
+get_mips_dynamic_type (unsigned long type)
{
switch (type)
{
}
static const char *
-get_sparc64_dynamic_type (type)
- unsigned long type;
+get_sparc64_dynamic_type (unsigned long type)
{
switch (type)
{
}
static const char *
-get_ppc64_dynamic_type (type)
- unsigned long type;
+get_ppc64_dynamic_type (unsigned long type)
{
switch (type)
{
}
static const char *
-get_parisc_dynamic_type (type)
- unsigned long type;
+get_parisc_dynamic_type (unsigned long type)
{
switch (type)
{
}
static const char *
-get_dynamic_type (type)
- unsigned long type;
+get_ia64_dynamic_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 (unsigned long type)
{
static char buff[32];
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;
}
static char *
-get_file_type (e_type)
- unsigned e_type;
+get_file_type (unsigned e_type)
{
static char buff[32];
}
static char *
-get_machine_name (e_machine)
- unsigned e_machine;
+get_machine_name (unsigned e_machine)
{
static char buff[64]; /* XXX */
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_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;
}
static void
-decode_ARM_machine_flags (e_flags, buf)
- unsigned e_flags;
- char buf[];
+decode_ARM_machine_flags (unsigned e_flags, char buf[])
{
unsigned eabi;
int unknown = 0;
strcat (buf, ", software FP");
break;
+ case EF_ARM_MAVERICK_FLOAT:
+ strcat (buf, ", Maverick FP");
+ break;
+
default:
unknown = 1;
break;
}
static char *
-get_machine_flags (e_flags, e_machine)
- unsigned e_flags;
- unsigned e_machine;
+get_machine_flags (unsigned e_flags, unsigned e_machine)
{
static char buf[1024];
case EM_CYGNUS_V850:
switch (e_flags & EF_V850_ARCH)
{
+ case E_V850E1_ARCH:
+ strcat (buf, ", v850e1");
+ break;
case E_V850E_ARCH:
strcat (buf, ", v850e");
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;
+ case E_MIPS_ARCH_64R2: strcat (buf, ", mips64r2"); break;
default: strcat (buf, ", unknown ISA"); break;
}
}
static const char *
-get_mips_segment_type (type)
- unsigned long type;
+get_osabi_name (unsigned int osabi)
+{
+ static char buff[32];
+
+ switch (osabi)
+ {
+ case ELFOSABI_NONE: return "UNIX - System V";
+ case ELFOSABI_HPUX: return "UNIX - HP-UX";
+ case ELFOSABI_NETBSD: return "UNIX - NetBSD";
+ case ELFOSABI_LINUX: return "UNIX - Linux";
+ case ELFOSABI_HURD: return "GNU/Hurd";
+ case ELFOSABI_SOLARIS: return "UNIX - Solaris";
+ case ELFOSABI_AIX: return "UNIX - AIX";
+ case ELFOSABI_IRIX: return "UNIX - IRIX";
+ case ELFOSABI_FREEBSD: return "UNIX - FreeBSD";
+ case ELFOSABI_TRU64: return "UNIX - TRU64";
+ case ELFOSABI_MODESTO: return "Novell - Modesto";
+ case ELFOSABI_OPENBSD: return "UNIX - OpenBSD";
+ case ELFOSABI_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:
+ sprintf (buff, _("<unknown: %x>"), osabi);
+ return buff;
+ }
+}
+
+static const char *
+get_mips_segment_type (unsigned long type)
{
switch (type)
{
}
static const char *
-get_parisc_segment_type (type)
- unsigned long type;
+get_parisc_segment_type (unsigned long type)
{
switch (type)
{
}
static const char *
-get_ia64_segment_type (type)
- unsigned long type;
+get_ia64_segment_type (unsigned long type)
{
switch (type)
{
}
static const char *
-get_segment_type (p_type)
- unsigned long p_type;
+get_segment_type (unsigned long p_type)
{
static char buff[32];
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))
}
static const char *
-get_mips_section_type_name (sh_type)
- unsigned int sh_type;
+get_mips_section_type_name (unsigned int sh_type)
{
switch (sh_type)
{
}
static const char *
-get_parisc_section_type_name (sh_type)
- unsigned int sh_type;
+get_parisc_section_type_name (unsigned int sh_type)
{
switch (sh_type)
{
}
static const char *
-get_ia64_section_type_name (sh_type)
- unsigned int sh_type;
+get_ia64_section_type_name (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;
}
}
static const char *
-get_section_type_name (sh_type)
- unsigned int sh_type;
+get_section_type_name (unsigned int sh_type)
{
static char buff[32];
};
static void
-usage ()
+usage (void)
{
fprintf (stdout, _("Usage: readelf <option(s)> elf-file(s)\n"));
fprintf (stdout, _(" Display information about the contents of ELF format files\n"));
}
static void
-request_dump (section, type)
- unsigned int section;
- int type;
+request_dump (unsigned int section, int type)
{
if (section >= num_dump_sects)
{
char *new_dump_sects;
- new_dump_sects = (char *) calloc (section + 1, 1);
+ new_dump_sects = calloc (section + 1, 1);
if (new_dump_sects == NULL)
error (_("Out of memory allocating dump request table."));
}
static void
-parse_args (argc, argv)
- int argc;
- char **argv;
+parse_args (int argc, char **argv)
{
int c;
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;
}
static const char *
-get_elf_class (elf_class)
- unsigned int elf_class;
+get_elf_class (unsigned int elf_class)
{
static char buff[32];
}
static const char *
-get_data_encoding (encoding)
- unsigned int encoding;
+get_data_encoding (unsigned int encoding)
{
static char buff[32];
}
}
-static const char *
-get_osabi_name (osabi)
- unsigned int osabi;
-{
- static char buff[32];
-
- switch (osabi)
- {
- case ELFOSABI_NONE: return "UNIX - System V";
- case ELFOSABI_HPUX: return "UNIX - HP-UX";
- case ELFOSABI_NETBSD: return "UNIX - NetBSD";
- case ELFOSABI_LINUX: return "UNIX - Linux";
- case ELFOSABI_HURD: return "GNU/Hurd";
- case ELFOSABI_SOLARIS: return "UNIX - Solaris";
- case ELFOSABI_AIX: return "UNIX - AIX";
- case ELFOSABI_IRIX: return "UNIX - IRIX";
- case ELFOSABI_FREEBSD: return "UNIX - FreeBSD";
- case ELFOSABI_TRU64: return "UNIX - TRU64";
- case ELFOSABI_MODESTO: return "Novell - Modesto";
- case ELFOSABI_OPENBSD: return "UNIX - OpenBSD";
- case ELFOSABI_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:
- sprintf (buff, _("<unknown: %x>"), osabi);
- return buff;
- }
-}
-
/* Decode the data held in 'elf_header'. */
+
static int
-process_file_header ()
+process_file_header (void)
{
if ( elf_header.e_ident[EI_MAG0] != ELFMAG0
|| elf_header.e_ident[EI_MAG1] != ELFMAG1
static int
-get_32bit_program_headers (file, program_headers)
- FILE *file;
- Elf_Internal_Phdr *program_headers;
+get_32bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
{
Elf32_External_Phdr *phdrs;
Elf32_External_Phdr *external;
Elf_Internal_Phdr *internal;
unsigned int i;
- phdrs = ((Elf32_External_Phdr *)
- get_data (NULL, file, elf_header.e_phoff,
- elf_header.e_phentsize * elf_header.e_phnum,
- _("program headers")));
+ phdrs = get_data (NULL, file, elf_header.e_phoff,
+ elf_header.e_phentsize * elf_header.e_phnum,
+ _("program headers"));
if (!phdrs)
return 0;
}
static int
-get_64bit_program_headers (file, program_headers)
- FILE *file;
- Elf_Internal_Phdr *program_headers;
+get_64bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
{
Elf64_External_Phdr *phdrs;
Elf64_External_Phdr *external;
Elf_Internal_Phdr *internal;
unsigned int i;
- phdrs = ((Elf64_External_Phdr *)
- get_data (NULL, file, elf_header.e_phoff,
- elf_header.e_phentsize * elf_header.e_phnum,
- _("program headers")));
+ phdrs = get_data (NULL, file, elf_header.e_phoff,
+ elf_header.e_phentsize * elf_header.e_phnum,
+ _("program headers"));
if (!phdrs)
return 0;
return 1;
}
+/* Returns 1 if the program headers were read into `program_headers'. */
+
+static int
+get_program_headers (FILE *file)
+{
+ Elf_Internal_Phdr *phdrs;
+
+ /* Check cache of prior read. */
+ if (program_headers != NULL)
+ return 1;
+
+ phdrs = 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;
+process_program_headers (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"));
- 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;
- }
if (do_segments)
{
}
}
- loadaddr = -1;
dynamic_addr = 0;
dynamic_size = 0;
switch (segment->p_type)
{
- case PT_LOAD:
- if (loadaddr == -1)
- {
- unsigned long align_mask = -segment->p_align;
-
- if (align_mask == 0)
- --align_mask;
- loadaddr = ((segment->p_vaddr & align_mask)
- - (segment->p_offset & align_mask));
- }
- break;
-
case PT_DYNAMIC:
if (dynamic_addr)
error (_("more than one dynamic segment\n"));
break;
case PT_INTERP:
- if (fseek (file, (long) segment->p_offset, SEEK_SET))
+ if (fseek (file, archive_file_offset + (long) segment->p_offset,
+ SEEK_SET))
error (_("Unable to find program interpreter name\n"));
else
{
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 *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;
- unsigned int num;
+get_32bit_section_headers (FILE *file, unsigned int num)
{
Elf32_External_Shdr *shdrs;
Elf_Internal_Shdr *internal;
unsigned int i;
- shdrs = ((Elf32_External_Shdr *)
- get_data (NULL, file, elf_header.e_shoff,
- elf_header.e_shentsize * num,
- _("section headers")));
+ shdrs = get_data (NULL, file, elf_header.e_shoff,
+ elf_header.e_shentsize * num, _("section headers"));
if (!shdrs)
return 0;
- section_headers = ((Elf_Internal_Shdr *)
- malloc (num * sizeof (Elf_Internal_Shdr)));
+ section_headers = malloc (num * sizeof (Elf_Internal_Shdr));
if (section_headers == NULL)
{
}
static int
-get_64bit_section_headers (file, num)
- FILE *file;
- unsigned int num;
+get_64bit_section_headers (FILE *file, unsigned int num)
{
Elf64_External_Shdr *shdrs;
Elf_Internal_Shdr *internal;
unsigned int i;
- shdrs = ((Elf64_External_Shdr *)
- get_data (NULL, file, elf_header.e_shoff,
- elf_header.e_shentsize * num,
- _("section headers")));
+ shdrs = get_data (NULL, file, elf_header.e_shoff,
+ elf_header.e_shentsize * num, _("section headers"));
if (!shdrs)
return 0;
- section_headers = ((Elf_Internal_Shdr *)
- malloc (num * sizeof (Elf_Internal_Shdr)));
+ section_headers = malloc (num * sizeof (Elf_Internal_Shdr));
if (section_headers == NULL)
{
}
static Elf_Internal_Sym *
-get_32bit_elf_symbols (file, section)
- FILE *file;
- Elf_Internal_Shdr *section;
+get_32bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
{
unsigned long number;
Elf32_External_Sym *esyms;
Elf_Internal_Sym *psym;
unsigned int j;
- esyms = ((Elf32_External_Sym *)
- get_data (NULL, file, section->sh_offset,
- section->sh_size, _("symbols")));
+ esyms = get_data (NULL, file, section->sh_offset, section->sh_size,
+ _("symbols"));
if (!esyms)
return NULL;
&& (symtab_shndx_hdr->sh_link
== (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
{
- shndx = ((Elf_External_Sym_Shndx *)
- get_data (NULL, file, symtab_shndx_hdr->sh_offset,
- symtab_shndx_hdr->sh_size, _("symtab shndx")));
+ shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
+ symtab_shndx_hdr->sh_size, _("symtab shndx"));
if (!shndx)
{
free (esyms);
}
number = section->sh_size / section->sh_entsize;
- isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
+ isyms = malloc (number * sizeof (Elf_Internal_Sym));
if (isyms == NULL)
{
}
static Elf_Internal_Sym *
-get_64bit_elf_symbols (file, section)
- FILE *file;
- Elf_Internal_Shdr *section;
+get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
{
unsigned long number;
Elf64_External_Sym *esyms;
Elf_Internal_Sym *psym;
unsigned int j;
- esyms = ((Elf64_External_Sym *)
- get_data (NULL, file, section->sh_offset,
- section->sh_size, _("symbols")));
+ esyms = get_data (NULL, file, section->sh_offset, section->sh_size,
+ _("symbols"));
if (!esyms)
return NULL;
&& (symtab_shndx_hdr->sh_link
== (unsigned long) SECTION_HEADER_NUM (section - section_headers)))
{
- shndx = ((Elf_External_Sym_Shndx *)
- get_data (NULL, file, symtab_shndx_hdr->sh_offset,
- symtab_shndx_hdr->sh_size, _("symtab shndx")));
+ shndx = get_data (NULL, file, symtab_shndx_hdr->sh_offset,
+ symtab_shndx_hdr->sh_size, _("symtab shndx"));
if (!shndx)
{
free (esyms);
}
number = section->sh_size / section->sh_entsize;
- isyms = (Elf_Internal_Sym *) malloc (number * sizeof (Elf_Internal_Sym));
+ isyms = malloc (number * sizeof (Elf_Internal_Sym));
if (isyms == NULL)
{
}
static const char *
-get_elf_section_flags (sh_flags)
- bfd_vma sh_flags;
+get_elf_section_flags (bfd_vma sh_flags)
{
static char buff[32];
}
static int
-process_section_headers (file)
- FILE *file;
+process_section_headers (FILE *file)
{
Elf_Internal_Shdr *section;
unsigned int i;
if (section->sh_size != 0)
{
- string_table = (char *) get_data (NULL, file, section->sh_offset,
- section->sh_size, _("string table"));
+ string_table = get_data (NULL, file, section->sh_offset,
+ section->sh_size, _("string table"));
+ if (string_table == NULL)
+ return 0;
+
string_table_length = section->sh_size;
}
continue;
}
- dynamic_strings = (char *) get_data (NULL, file, section->sh_offset,
- section->sh_size,
- _("dynamic strings"));
+ dynamic_strings = get_data (NULL, file, section->sh_offset,
+ section->sh_size, _("dynamic strings"));
}
else if (section->sh_type == SHT_SYMTAB_SHNDX)
{
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)
- FILE *file;
+process_relocs (FILE *file)
{
unsigned long rel_size;
unsigned long rel_offset;
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])
- {
- rel_offset = dynamic_info[DT_RELA];
- rel_size = dynamic_info[DT_RELASZ];
- is_rela = TRUE;
- }
- else if (dynamic_info[DT_JMPREL])
+ for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++)
{
- 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
strsec = SECTION_HEADER (symsec->sh_link);
- strtab = (char *) get_data (NULL, file, strsec->sh_offset,
- strsec->sh_size,
- _("string table"));
+ strtab = get_data (NULL, file, strsec->sh_offset,
+ strsec->sh_size, _("string table"));
}
is_rela = section->sh_type == SHT_RELA;
unsigned long strtab_size; /* Size of string table. */
};
-static void find_symbol_for_address
- PARAMS ((struct unw_aux_info *, struct absaddr, const char **, bfd_vma *));
-static void dump_ia64_unwind
- PARAMS ((struct unw_aux_info *));
-static int slurp_ia64_unwind_table
- PARAMS ((FILE *, struct unw_aux_info *, Elf_Internal_Shdr *));
-
static void
-find_symbol_for_address (aux, addr, symname, offset)
- struct unw_aux_info *aux;
- struct absaddr addr;
- const char **symname;
- bfd_vma *offset;
+find_symbol_for_address (struct unw_aux_info *aux,
+ struct absaddr addr,
+ const char **symname,
+ bfd_vma *offset)
{
- bfd_vma dist = (bfd_vma) 0x100000;
+ bfd_vma dist = 0x100000;
Elf_Internal_Sym *sym, *best = NULL;
unsigned long i;
}
static void
-dump_ia64_unwind (aux)
- struct unw_aux_info *aux;
+dump_ia64_unwind (struct unw_aux_info *aux)
{
bfd_vma addr_size;
struct unw_table_entry *tp;
}
static int
-slurp_ia64_unwind_table (file, aux, sec)
- FILE *file;
- struct unw_aux_info *aux;
- Elf_Internal_Shdr *sec;
+slurp_ia64_unwind_table (FILE *file,
+ struct unw_aux_info *aux,
+ 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: */
size = sec->sh_size;
- table = (char *) get_data (NULL, file, sec->sh_offset,
- size, _("unwind table"));
+ table = get_data (NULL, file, sec->sh_offset, size, _("unwind table"));
if (!table)
return 0;
}
static int
-process_unwind (file)
- FILE *file;
+process_unwind (FILE *file)
{
Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec;
unsigned long i, addr_size, unwcount = 0, unwstart = 0;
strsec = SECTION_HEADER (sec->sh_link);
aux.strtab_size = strsec->sh_size;
- aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset,
- aux.strtab_size, _("string table"));
+ aux.strtab = get_data (NULL, file, strsec->sh_offset,
+ aux.strtab_size, _("string table"));
}
else if (sec->sh_type == SHT_IA_64_UNWIND)
unwcount++;
{
aux.info_size = sec->sh_size;
aux.info_addr = sec->sh_addr;
- aux.info = (char *) get_data (NULL, file, sec->sh_offset,
- aux.info_size, _("unwind info"));
+ aux.info = get_data (NULL, file, sec->sh_offset, aux.info_size,
+ _("unwind info"));
printf (_("\nUnwind section "));
}
static void
-dynamic_segment_mips_val (entry)
- Elf_Internal_Dyn *entry;
+dynamic_segment_mips_val (Elf_Internal_Dyn *entry)
{
switch (entry->d_tag)
{
static void
-dynamic_segment_parisc_val (entry)
- Elf_Internal_Dyn *entry;
+dynamic_segment_parisc_val (Elf_Internal_Dyn *entry)
{
switch (entry->d_tag)
{
putchar ('\n');
}
+static void
+dynamic_segment_ia64_val (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;
+get_32bit_dynamic_segment (FILE *file)
{
Elf32_External_Dyn *edyn;
Elf_Internal_Dyn *entry;
bfd_size_type i;
- edyn = (Elf32_External_Dyn *) get_data (NULL, file, dynamic_addr,
- dynamic_size, _("dynamic segment"));
+ edyn = get_data (NULL, file, dynamic_addr, dynamic_size,
+ _("dynamic segment"));
if (!edyn)
return 0;
while (*(Elf32_Word *) edyn[dynamic_size++].d_tag != DT_NULL)
;
- dynamic_segment = (Elf_Internal_Dyn *)
- malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
+ dynamic_segment = malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
if (dynamic_segment == NULL)
{
}
static int
-get_64bit_dynamic_segment (file)
- FILE *file;
+get_64bit_dynamic_segment (FILE *file)
{
Elf64_External_Dyn *edyn;
Elf_Internal_Dyn *entry;
bfd_size_type i;
- edyn = (Elf64_External_Dyn *) get_data (NULL, file, dynamic_addr,
- dynamic_size, _("dynamic segment"));
+ edyn = get_data (NULL, file, dynamic_addr, dynamic_size,
+ _("dynamic segment"));
if (!edyn)
return 0;
while (*(bfd_vma *) edyn[dynamic_size++].d_tag != DT_NULL)
;
- dynamic_segment = (Elf_Internal_Dyn *)
- malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
+ dynamic_segment = malloc (dynamic_size * sizeof (Elf_Internal_Dyn));
if (dynamic_segment == NULL)
{
}
static const char *
-get_dynamic_flags (flags)
- bfd_vma flags;
+get_dynamic_flags (bfd_vma flags)
{
static char buff[128];
char *p = buff;
/* Parse and display the contents of the dynamic segment. */
static int
-process_dynamic_segment (file)
- FILE *file;
+process_dynamic_segment (FILE *file)
{
Elf_Internal_Dyn *entry;
bfd_size_type i;
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!"));
+ if (archive_file_offset != 0)
+ section.sh_size = archive_file_size - section.sh_offset;
+ else
+ {
+ if (fseek (file, 0, SEEK_END))
+ error (_("Unable to seek to end of file!"));
+
+ section.sh_size = ftell (file) - section.sh_offset;
+ }
- section.sh_size = ftell (file) - section.sh_offset;
if (is_32bit_elf)
section.sh_entsize = sizeof (Elf32_External_Sym);
else
processing that. This is overkill, I know, but it
should work. */
- offset = entry->d_un.d_val - loadaddr;
- if (fseek (file, 0, SEEK_END))
- error (_("Unable to seek to end of file\n"));
- str_tab_len = ftell (file) - offset;
+ offset = offset_from_vma (file, entry->d_un.d_val, 0);
+
+ if (archive_file_offset != 0)
+ str_tab_len = archive_file_size - offset;
+ else
+ {
+ if (fseek (file, 0, SEEK_END))
+ error (_("Unable to seek to end of file\n"));
+ str_tab_len = ftell (file) - offset;
+ }
if (str_tab_len < 1)
{
continue;
}
- dynamic_strings = (char *) get_data (NULL, file, offset, str_tab_len,
- _("dynamic string table"));
+ dynamic_strings = get_data (NULL, file, offset, str_tab_len,
+ _("dynamic string table"));
break;
}
}
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)
Elf_Internal_Syminfo *syminfo;
/* There is a syminfo section. Read the data. */
- extsyminfo = ((Elf_External_Syminfo *)
- get_data (NULL, file, dynamic_syminfo_offset,
- syminsz, _("symbol information")));
+ extsyminfo = get_data (NULL, file, dynamic_syminfo_offset, syminsz,
+ _("symbol information"));
if (!extsyminfo)
return 0;
- dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz);
+ dynamic_syminfo = malloc (syminsz);
if (dynamic_syminfo == NULL)
{
error (_("Out of memory\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');
}
static char *
-get_ver_flags (flags)
- unsigned int flags;
+get_ver_flags (unsigned int flags)
{
static char buff[32];
/* Display the contents of the version sections. */
static int
-process_version_sections (file)
- FILE *file;
+process_version_sections (FILE *file)
{
Elf_Internal_Shdr *section;
unsigned i;
(unsigned long) section->sh_offset, section->sh_link,
SECTION_NAME (SECTION_HEADER (section->sh_link)));
- edefs = ((Elf_External_Verdef *)
- get_data (NULL, file, section->sh_offset,
- section->sh_size,
- _("version definition section")));
+ edefs = get_data (NULL, file, section->sh_offset, section->sh_size,
+ _("version definition section"));
if (!edefs)
break;
(unsigned long) section->sh_offset, section->sh_link,
SECTION_NAME (SECTION_HEADER (section->sh_link)));
- eneed = ((Elf_External_Verneed *)
- get_data (NULL, file, section->sh_offset,
- section->sh_size, _("version need section")));
+ eneed = get_data (NULL, file, section->sh_offset, section->sh_size,
+ _("version need section"));
if (!eneed)
break;
aux.vna_next = BYTE_GET (eaux->vna_next);
if (dynamic_strings)
- printf (_(" %#06x: Name: %s"),
+ printf (_(" %#06x: Name: %s"),
isum, dynamic_strings + aux.vna_name);
else
- printf (_(" %#06x: Name index: %lx"),
+ printf (_(" %#06x: Name index: %lx"),
isum, aux.vna_name);
printf (_(" Flags: %s Version: %d\n"),
char *strtab;
Elf_Internal_Sym *symbols;
Elf_Internal_Shdr *string_sec;
+ long off;
link_section = SECTION_HEADER (section->sh_link);
total = section->sh_size / section->sh_entsize;
string_sec = SECTION_HEADER (link_section->sh_link);
- strtab = (char *) get_data (NULL, file, string_sec->sh_offset,
- string_sec->sh_size,
- _("version string table"));
+ strtab = get_data (NULL, file, string_sec->sh_offset,
+ string_sec->sh_size, _("version string table"));
if (!strtab)
break;
(unsigned long) section->sh_offset, section->sh_link,
SECTION_NAME (link_section));
- edata =
- ((unsigned char *)
- get_data (NULL, file,
- version_info[DT_VERSIONTAGIDX (DT_VERSYM)] - loadaddr,
- total * sizeof (short), _("version symbol data")));
+ off = offset_from_vma (file,
+ version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
+ total * sizeof (short));
+ edata = get_data (NULL, file, off, total * sizeof (short),
+ _("version symbol data"));
if (!edata)
{
free (strtab);
break;
}
- data = (unsigned short *) malloc (total * sizeof (short));
+ data = malloc (total * sizeof (short));
for (cnt = total; cnt --;)
data[cnt] = byte_get (edata + cnt * sizeof (short),
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
{
}
static const char *
-get_symbol_binding (binding)
- unsigned int binding;
+get_symbol_binding (unsigned int binding)
{
static char buff[32];
}
static const char *
-get_symbol_type (type)
- unsigned int type;
+get_symbol_type (unsigned int type)
{
static char buff[32];
}
static const char *
-get_symbol_visibility (visibility)
- unsigned int visibility;
+get_symbol_visibility (unsigned int visibility)
{
switch (visibility)
{
}
static const char *
-get_symbol_index_type (type)
- unsigned int type;
+get_symbol_index_type (unsigned int type)
{
static char buff[32];
case SHN_ABS: return "ABS";
case SHN_COMMON: return "COM";
default:
- if (type >= SHN_LOPROC && type <= SHN_HIPROC)
+ if (type == SHN_IA_64_ANSI_COMMON
+ && elf_header.e_machine == EM_IA_64
+ && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
+ return "ANSI_COM";
+ else if (type >= SHN_LOPROC && type <= SHN_HIPROC)
sprintf (buff, "PRC[0x%04x]", type);
else if (type >= SHN_LOOS && type <= SHN_HIOS)
sprintf (buff, "OS [0x%04x]", type);
}
static int *
-get_dynamic_data (file, number)
- FILE *file;
- unsigned int number;
+get_dynamic_data (FILE *file, unsigned int number)
{
unsigned char *e_data;
int *i_data;
- e_data = (unsigned char *) malloc (number * 4);
+ e_data = malloc (number * 4);
if (e_data == NULL)
{
return NULL;
}
- i_data = (int *) malloc (number * sizeof (*i_data));
+ i_data = malloc (number * sizeof (*i_data));
if (i_data == NULL)
{
/* Dump the symbol table. */
static int
-process_symbol_table (file)
- FILE *file;
+process_symbol_table (FILE *file)
{
Elf_Internal_Shdr *section;
unsigned char nb[4];
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,
+ (archive_file_offset
+ + 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;
string_sec = SECTION_HEADER (section->sh_link);
- strtab = (char *) get_data (NULL, file, string_sec->sh_offset,
- string_sec->sh_size,
- _("string table"));
+ strtab = get_data (NULL, file, string_sec->sh_offset,
+ string_sec->sh_size, _("string table"));
}
for (si = 0, psym = symtab;
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
{
nbuckets);
printf (_(" Length Number %% of total Coverage\n"));
- lengths = (int *) calloc (nbuckets, sizeof (int));
+ lengths = calloc (nbuckets, sizeof (int));
if (lengths == NULL)
{
error (_("Out of memory"));
}
}
- counts = (int *) calloc (maxlength + 1, sizeof (int));
+ counts = calloc (maxlength + 1, sizeof (int));
if (counts == NULL)
{
error (_("Out of memory"));
}
static int
-process_syminfo (file)
- FILE *file ATTRIBUTE_UNUSED;
+process_syminfo (FILE *file ATTRIBUTE_UNUSED)
{
unsigned int i;
#ifdef SUPPORT_DISASSEMBLY
static void
-disassemble_section (section, file)
- Elf_Internal_Shdr *section;
- FILE *file;
+disassemble_section (Elf_Internal_Shdr *section, FILE *file)
{
printf (_("\nAssembly dump of section %s\n"),
SECTION_NAME (section));
#endif
static int
-dump_section (section, file)
- Elf_Internal_Shdr *section;
- FILE *file;
+dump_section (Elf_Internal_Shdr *section, FILE *file)
{
bfd_size_type bytes;
bfd_vma addr;
bytes = section->sh_size;
- if (bytes == 0)
+ if (bytes == 0 || section->sh_type == SHT_NOBITS)
{
printf (_("\nSection '%s' has no data to dump.\n"),
SECTION_NAME (section));
addr = section->sh_addr;
- start = (unsigned char *) get_data (NULL, file, section->sh_offset, bytes,
- _("section data"));
+ start = get_data (NULL, file, section->sh_offset, bytes, _("section data"));
if (!start)
return 0;
for (j = 0; j < lbytes; j++)
{
k = data[j];
- if (k >= ' ' && k < 0x80)
+ if (k >= ' ' && k < 0x7f)
printf ("%c", k);
else
printf (".");
static unsigned long int
-read_leb128 (data, length_return, sign)
- unsigned char *data;
- int *length_return;
- int sign;
+read_leb128 (unsigned char *data, int *length_return, int sign)
{
unsigned long int result = 0;
unsigned int num_read = 0;
static SMR state_machine_regs;
static void
-reset_state_machine (is_stmt)
- int is_stmt;
+reset_state_machine (int is_stmt)
{
state_machine_regs.address = 0;
state_machine_regs.file = 1;
/* Handled an extend line op. Returns true if this is the end
of sequence. */
static int
-process_extended_line_op (data, is_stmt, pointer_size)
- unsigned char *data;
- int is_stmt;
- int pointer_size;
+process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size)
{
unsigned char op_code;
int bytes_read;
static int debug_line_pointer_size = 4;
static int
-display_debug_lines (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char * start;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_lines (Elf_Internal_Shdr *section,
+ 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"));
}
static int
-display_debug_pubnames (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_pubnames (Elf_Internal_Shdr *section,
+ 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;
}
- if (pubnames.pn_version != 2)
+ 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 && 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;
}
}
static char *
-get_TAG_name (tag)
- unsigned long tag;
+get_TAG_name (unsigned long tag)
{
switch (tag)
{
}
static char *
-get_AT_name (attribute)
- unsigned long attribute;
+get_AT_name (unsigned long attribute)
{
switch (attribute)
{
}
static char *
-get_FORM_name (form)
- unsigned long form;
+get_FORM_name (unsigned long form)
{
switch (form)
{
}
}
-/* FIXME: There are better and more effiecint ways to handle
+/* FIXME: There are better and more efficient ways to handle
these structures. For now though, I just want something that
is simple to implement. */
typedef struct abbrev_attr
static abbrev_entry *last_abbrev = NULL;
static void
-free_abbrevs ()
+free_abbrevs (void)
{
abbrev_entry *abbrev;
}
static void
-add_abbrev (number, tag, children)
- unsigned long number;
- unsigned long tag;
- int children;
+add_abbrev (unsigned long number, unsigned long tag, int children)
{
abbrev_entry *entry;
- entry = (abbrev_entry *) malloc (sizeof (*entry));
+ entry = malloc (sizeof (*entry));
if (entry == NULL)
/* ugg */
}
static void
-add_abbrev_attr (attribute, form)
- unsigned long attribute;
- unsigned long form;
+add_abbrev_attr (unsigned long attribute, unsigned long form)
{
abbrev_attr *attr;
- attr = (abbrev_attr *) malloc (sizeof (*attr));
+ attr = malloc (sizeof (*attr));
if (attr == NULL)
/* ugg */
an abbreviation set was found. */
static unsigned char *
-process_abbrev_section (start, end)
- unsigned char *start;
- unsigned char *end;
+process_abbrev_section (unsigned char *start, unsigned char *end)
{
if (first_abbrev != NULL)
return NULL;
static int
-display_debug_macinfo (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_macinfo (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
{
unsigned char *end = start + section->sh_size;
unsigned char *curr = start;
static int
-display_debug_abbrev (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_abbrev (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
{
abbrev_entry *entry;
unsigned char *end = start + section->sh_size;
static unsigned char *
-display_block (data, length)
- unsigned char *data;
- unsigned long length;
+display_block (unsigned char *data, unsigned long length)
{
printf (_(" %lu byte block: "), length);
}
static void
-decode_location_expression (data, pointer_size, length)
- unsigned char * data;
- unsigned int pointer_size;
- unsigned long length;
+decode_location_expression (unsigned char * data,
+ unsigned int pointer_size,
+ unsigned long length)
{
unsigned op;
int bytes_read;
}
/* Separate the ops. */
- printf ("; ");
+ if (data < end)
+ printf ("; ");
}
}
static bfd_vma debug_loc_size;
static void
-load_debug_loc (file)
- FILE *file;
+load_debug_loc (FILE *file)
{
Elf_Internal_Shdr *sec;
unsigned int i;
debug_loc_size = sec->sh_size;
- debug_loc_contents = ((char *)
- get_data (NULL, file, sec->sh_offset, sec->sh_size,
- _("debug_loc section data")));
+ debug_loc_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+ _("debug_loc section data"));
}
static void
-free_debug_loc ()
+free_debug_loc (void)
{
if (debug_loc_contents == NULL)
return;
static int
-display_debug_loc (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_loc (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
{
unsigned char *section_end;
unsigned long bytes;
/* 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
+ separately 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);
static bfd_vma debug_str_size;
static void
-load_debug_str (file)
- FILE *file;
+load_debug_str (FILE *file)
{
Elf_Internal_Shdr *sec;
unsigned int i;
debug_str_size = sec->sh_size;
- debug_str_contents = ((char *)
- get_data (NULL, file, sec->sh_offset, sec->sh_size,
- _("debug_str section data")));
+ debug_str_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+ _("debug_str section data"));
}
static void
-free_debug_str ()
+free_debug_str (void)
{
if (debug_str_contents == NULL)
return;
}
static const char *
-fetch_indirect_string (offset)
- unsigned long offset;
+fetch_indirect_string (unsigned long offset)
{
if (debug_str_contents == NULL)
return _("<no .debug_str section>");
}
static int
-display_debug_str (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_str (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
{
unsigned long bytes;
bfd_vma addr;
}
static unsigned char *
-read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
- unsigned long attribute;
- unsigned long form;
- unsigned char *data;
- unsigned long cu_offset;
- unsigned long pointer_size;
+read_and_display_attr_value (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)
break;
}
- /* For some attributes we can display futher information. */
+ /* For some attributes we can display further information. */
printf ("\t");
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)
- unsigned long attribute;
- unsigned long form;
- unsigned char *data;
- unsigned long cu_offset;
- unsigned long pointer_size;
+read_and_display_attr (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;
}
static int
-display_debug_info (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start;
- FILE *file;
+display_debug_info (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file)
{
unsigned char *end = start + section->sh_size;
unsigned char *section_begin = start;
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;
}
return 0;
}
- begin = ((unsigned char *)
- get_data (NULL, file, sec->sh_offset, sec->sh_size,
- _("debug_abbrev section data")));
+ begin = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+ _("debug_abbrev section data"));
if (!begin)
return 0;
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;
}
static int
-display_debug_aranges (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_aranges (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
{
unsigned char *end = start + section->sh_size;
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;
in the frame info. */
#define DW_CFA_unreferenced (-1)
-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 void
-frame_need_space (fc, reg)
- Frame_Chunk *fc;
- int reg;
+frame_need_space (Frame_Chunk *fc, int reg)
{
int prev = fc->ncols;
return;
fc->ncols = reg + 1;
- fc->col_type = (short int *) xrealloc (fc->col_type,
- fc->ncols * sizeof (short int));
- fc->col_offset = (int *) xrealloc (fc->col_offset,
- fc->ncols * sizeof (int));
+ fc->col_type = xrealloc (fc->col_type, fc->ncols * sizeof (short int));
+ fc->col_offset = xrealloc (fc->col_offset, fc->ncols * sizeof (int));
while (prev < fc->ncols)
{
}
static void
-frame_display_row (fc, need_col_headers, max_regs)
- Frame_Chunk *fc;
- int *need_col_headers;
- int *max_regs;
+frame_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs)
{
int r;
char tmp[100];
}
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 int
-size_of_encoded_value (encoding)
- int encoding;
+size_of_encoded_value (int encoding)
{
switch (encoding & 0x7)
{
}
}
+static bfd_vma
+get_encoded_value (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
static int
-display_debug_frames (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_frames (Elf_Internal_Shdr *section,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
{
unsigned char *end = start + section->sh_size;
unsigned char *section_start = start;
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))
{
int version;
- fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
+ fc = xmalloc (sizeof (Frame_Chunk));
memset (fc, 0, sizeof (Frame_Chunk));
fc->next = chunks;
chunks = fc;
fc->chunk_start = saved_start;
fc->ncols = 0;
- fc->col_type = (short int *) xmalloc (sizeof (short int));
- fc->col_offset = (int *) xmalloc (sizeof (int));
+ fc->col_type = xmalloc (sizeof (short int));
+ fc->col_offset = xmalloc (sizeof (int));
frame_need_space (fc, max_regs-1);
version = *start++;
cie_id, saved_start);
start = block_end;
fc->ncols = 0;
- fc->col_type = (short int *) xmalloc (sizeof (short int));
- fc->col_offset = (int *) xmalloc (sizeof (int));
+ fc->col_type = xmalloc (sizeof (short int));
+ fc->col_offset = xmalloc (sizeof (int));
frame_need_space (fc, max_regs - 1);
cie = fc;
fc->augmentation = "";
else
{
fc->ncols = cie->ncols;
- fc->col_type = (short int *) xmalloc (fc->ncols * sizeof (short int));
- fc->col_offset = (int *) xmalloc (fc->ncols * sizeof (int));
+ fc->col_type = xmalloc (fc->ncols * sizeof (short int));
+ fc->col_offset = xmalloc (fc->ncols * sizeof (int));
memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
fc->augmentation = cie->augmentation;
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_remember_state:
if (! do_debug_frames_interp)
printf (" DW_CFA_remember_state\n");
- rs = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
+ rs = xmalloc (sizeof (Frame_Chunk));
rs->ncols = fc->ncols;
- rs->col_type = (short int *) xmalloc (rs->ncols * sizeof (short int));
- rs->col_offset = (int *) xmalloc (rs->ncols * sizeof (int));
+ rs->col_type = xmalloc (rs->ncols * sizeof (short int));
+ rs->col_offset = xmalloc (rs->ncols * sizeof (int));
memcpy (rs->col_type, fc->col_type, rs->ncols);
memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
rs->next = remembered_state;
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;
#undef SLEB
static int
-display_debug_not_supported (section, start, file)
- Elf_Internal_Shdr *section;
- unsigned char *start ATTRIBUTE_UNUSED;
- FILE *file ATTRIBUTE_UNUSED;
+display_debug_not_supported (Elf_Internal_Shdr *section,
+ unsigned char *start ATTRIBUTE_UNUSED,
+ FILE *file ATTRIBUTE_UNUSED)
{
printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
SECTION_NAME (section));
When dumping the .debug_line, we use that size information, assuming
that all compilation units have the same address size. */
static int
-prescan_debug_info (section, start, file)
- Elf_Internal_Shdr *section ATTRIBUTE_UNUSED;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
+prescan_debug_info (Elf_Internal_Shdr *section ATTRIBUTE_UNUSED,
+ unsigned char *start,
+ FILE *file ATTRIBUTE_UNUSED)
{
- DWARF2_External_CompUnit *external;
+ unsigned long length;
+
+ /* 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);
+
+ 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:
- external = (DWARF2_External_CompUnit *) start;
+ unit_length: 12 bytes
+ version: 2 bytes
+ debug_abbrev_offset: 8 bytes
+ -----------------------------
+ Total: 22 bytes */
- debug_line_pointer_size = BYTE_GET (external->cu_pointer_size);
+ 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;
}
struct
{
const char *const name;
- int (*display) PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
- int (*prescan) PARAMS ((Elf_Internal_Shdr *, unsigned char *, FILE *));
+ int (*display) (Elf_Internal_Shdr *, unsigned char *, FILE *);
+ int (*prescan) (Elf_Internal_Shdr *, unsigned char *, FILE *);
}
debug_displays[] =
{
};
static int
-display_debug_section (section, file)
- Elf_Internal_Shdr *section;
- FILE *file;
+display_debug_section (Elf_Internal_Shdr *section, FILE *file)
{
char *name = SECTION_NAME (section);
bfd_size_type length;
return 0;
}
- start = (unsigned char *) get_data (NULL, file, section->sh_offset, length,
- _("debug section data"));
+ start = get_data (NULL, file, section->sh_offset, length,
+ _("debug section data"));
if (!start)
return 0;
}
static int
-process_section_contents (file)
- FILE *file;
+process_section_contents (FILE *file)
{
Elf_Internal_Shdr *section;
unsigned int i;
unsigned char *start;
length = section->sh_size;
- start = ((unsigned char *)
- get_data (NULL, file, section->sh_offset, length,
- _("debug section data")));
+ start = get_data (NULL, file, section->sh_offset, length,
+ _("debug section data"));
if (!start)
return 0;
}
static void
-process_mips_fpe_exception (mask)
- int mask;
+process_mips_fpe_exception (int mask)
{
if (mask)
{
}
static int
-process_mips_specific (file)
- FILE *file;
+process_mips_specific (FILE *file)
{
Elf_Internal_Dyn *entry;
size_t liblist_offset = 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;
Elf32_External_Lib *elib;
size_t cnt;
- elib = ((Elf32_External_Lib *)
- get_data (NULL, file, liblist_offset,
- liblistno * sizeof (Elf32_External_Lib),
- _("liblist")));
+ elib = get_data (NULL, file, liblist_offset,
+ liblistno * sizeof (Elf32_External_Lib),
+ _("liblist"));
if (elib)
{
printf ("\nSection '.liblist' contains %lu entries:\n",
while (sect->sh_type != SHT_MIPS_OPTIONS)
++sect;
- eopt = (Elf_External_Options *) get_data (NULL, file, options_offset,
- sect->sh_size, _("options"));
+ eopt = get_data (NULL, file, options_offset, sect->sh_size,
+ _("options"));
if (eopt)
{
- iopt = ((Elf_Internal_Options *)
- malloc ((sect->sh_size / sizeof (eopt)) * sizeof (*iopt)));
+ iopt = malloc ((sect->sh_size / sizeof (eopt)) * sizeof (*iopt));
if (iopt == NULL)
{
error (_("Out of memory"));
return 0;
}
- iconf = (Elf32_Conflict *) malloc (conflictsno * sizeof (*iconf));
+ iconf = malloc (conflictsno * sizeof (*iconf));
if (iconf == NULL)
{
error (_("Out of memory"));
{
Elf32_External_Conflict *econf32;
- econf32 = ((Elf32_External_Conflict *)
- get_data (NULL, file, conflicts_offset,
- conflictsno * sizeof (*econf32),
- _("conflict")));
+ econf32 = get_data (NULL, file, conflicts_offset,
+ conflictsno * sizeof (*econf32), _("conflict"));
if (!econf32)
return 0;
{
Elf64_External_Conflict *econf64;
- econf64 = ((Elf64_External_Conflict *)
- get_data (NULL, file, conflicts_offset,
- conflictsno * sizeof (*econf64),
- _("conflict")));
+ econf64 = get_data (NULL, file, conflicts_offset,
+ conflictsno * sizeof (*econf64), _("conflict"));
if (!econf64)
return 0;
}
static int
-process_gnu_liblist (file)
- FILE *file;
+process_gnu_liblist (FILE *file)
{
Elf_Internal_Shdr *section, *string_sec;
Elf32_External_Lib *elib;
switch (section->sh_type)
{
case SHT_GNU_LIBLIST:
- elib = ((Elf32_External_Lib *)
- get_data (NULL, file, section->sh_offset, section->sh_size,
- _("liblist")));
+ elib = get_data (NULL, file, section->sh_offset, section->sh_size,
+ _("liblist"));
if (elib == NULL)
break;
string_sec = SECTION_HEADER (section->sh_link);
- strtab = (char *) get_data (NULL, file, string_sec->sh_offset,
- string_sec->sh_size,
- _("liblist string table"));
+ strtab = get_data (NULL, file, string_sec->sh_offset,
+ string_sec->sh_size, _("liblist string table"));
if (strtab == NULL
|| section->sh_entsize != sizeof (Elf32_External_Lib))
}
static const char *
-get_note_type (e_type)
- unsigned e_type;
+get_note_type (unsigned e_type)
{
static char buff[64];
}
static const char *
-get_netbsd_elfcore_note_type (e_type)
- unsigned e_type;
+get_netbsd_elfcore_note_type (unsigned e_type)
{
static char buff[64];
If the value of namesz is zero, there is no name present. */
static int
-process_note (pnote)
- Elf_Internal_Note *pnote;
+process_note (Elf_Internal_Note *pnote)
{
const char *nt;
static int
-process_corefile_note_segment (file, offset, length)
- FILE *file;
- bfd_vma offset;
- bfd_vma length;
+process_corefile_note_segment (FILE *file, bfd_vma offset, bfd_vma length)
{
Elf_External_Note *pnotes;
Elf_External_Note *external;
if (length <= 0)
return 0;
- pnotes = (Elf_External_Note *) get_data (NULL, file, offset, length,
- _("notes"));
+ pnotes = get_data (NULL, file, offset, length, _("notes"));
if (!pnotes)
return 0;
}
static int
-process_corefile_note_segments (file)
- FILE *file;
+process_corefile_note_segments (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;
}
static int
-process_corefile_contents (file)
- FILE *file;
+process_corefile_contents (FILE *file)
{
/* If we have not been asked to display the notes then do nothing. */
if (! do_notes)
}
static int
-process_arch_specific (file)
- FILE *file;
+process_arch_specific (FILE *file)
{
if (! do_arch)
return 1;
}
static int
-get_file_header (file)
- FILE *file;
+get_file_header (FILE *file)
{
/* Read in the identity array. */
if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
{
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. */
/* If we have been compiled with sizeof (bfd_vma) == 4, then
we will not be able to cope with the 64bit data found in
64 ELF files. Detect this now and abort before we start
- overwritting things. */
+ overwriting things. */
if (sizeof (bfd_vma) < 8)
{
error (_("This instance of readelf has been built without support for a\n\
return 1;
}
+/* Process one ELF object file according to the command line options.
+ This file may actually be stored in an archive. The file is
+ positioned at the start of the ELF object. */
+
static int
-process_file (file_name)
- char *file_name;
+process_object (char *file_name, FILE *file)
{
- FILE *file;
- struct stat statbuf;
unsigned int i;
- if (stat (file_name, & statbuf) < 0)
- {
- error (_("Cannot stat input file %s.\n"), file_name);
- return 1;
- }
-
- file = fopen (file_name, "rb");
- if (file == NULL)
- {
- error (_("Input file %s not found.\n"), file_name);
- return 1;
- }
-
if (! get_file_header (file))
{
error (_("%s: Failed to read file header\n"), file_name);
- fclose (file);
return 1;
}
printf (_("\nFile: %s\n"), file_name);
if (! process_file_header ())
- {
- fclose (file);
- return 1;
- }
+ return 1;
if (! process_section_headers (file))
{
process_arch_specific (file);
- fclose (file);
+ if (program_headers)
+ {
+ free (program_headers);
+ program_headers = NULL;
+ }
if (section_headers)
{
return 0;
}
+/* Process an ELF archive. The file is positioned just after the
+ ARMAG string. */
+
+static int
+process_archive (char *file_name, FILE *file)
+{
+ struct ar_hdr arhdr;
+ size_t got;
+ unsigned long size;
+ char *longnames = NULL;
+ unsigned long longnames_size = 0;
+ size_t file_name_size;
+ int ret;
+
+ show_name = 1;
+
+ got = fread (&arhdr, 1, sizeof arhdr, file);
+ if (got != sizeof arhdr)
+ {
+ if (got == 0)
+ return 0;
+
+ error (_("%s: failed to read archive header\n"), file_name);
+ return 1;
+ }
+
+ if (memcmp (arhdr.ar_name, "/ ", 16) == 0)
+ {
+ /* This is the archive symbol table. Skip it.
+ FIXME: We should have an option to dump it. */
+ size = strtoul (arhdr.ar_size, NULL, 10);
+ if (fseek (file, size + (size & 1), SEEK_CUR) != 0)
+ {
+ error (_("%s: failed to skip archive symbol table\n"), file_name);
+ return 1;
+ }
+
+ got = fread (&arhdr, 1, sizeof arhdr, file);
+ if (got != sizeof arhdr)
+ {
+ if (got == 0)
+ return 0;
+
+ error (_("%s: failed to read archive header\n"), file_name);
+ return 1;
+ }
+ }
+
+ if (memcmp (arhdr.ar_name, "// ", 16) == 0)
+ {
+ /* This is the archive string table holding long member
+ names. */
+
+ longnames_size = strtoul (arhdr.ar_size, NULL, 10);
+
+ longnames = malloc (longnames_size);
+ if (longnames == NULL)
+ {
+ error (_("Out of memory\n"));
+ return 1;
+ }
+
+ if (fread (longnames, longnames_size, 1, file) != 1)
+ {
+ free (longnames);
+ error(_("%s: failed to read string table\n"), file_name);
+ return 1;
+ }
+
+ if ((longnames_size & 1) != 0)
+ getc (file);
+
+ got = fread (&arhdr, 1, sizeof arhdr, file);
+ if (got != sizeof arhdr)
+ {
+ free (longnames);
+
+ if (got == 0)
+ return 0;
+
+ error (_("%s: failed to read archive header\n"), file_name);
+ return 1;
+ }
+ }
+
+ file_name_size = strlen (file_name);
+ ret = 0;
+
+ while (1)
+ {
+ char *name;
+ char *nameend;
+ char *namealc;
+
+ if (arhdr.ar_name[0] == '/')
+ {
+ unsigned long off;
+
+ off = strtoul (arhdr.ar_name + 1, NULL, 10);
+ if (off >= longnames_size)
+ {
+ error (_("%s: invalid archive string table offset %lu\n"), off);
+ ret = 1;
+ break;
+ }
+
+ name = longnames + off;
+ nameend = memchr (name, '/', longnames_size - off);
+ }
+ else
+ {
+ name = arhdr.ar_name;
+ nameend = memchr (name, '/', 16);
+ }
+
+ if (nameend == NULL)
+ {
+ error (_("%s: bad archive file name\n"));
+ ret = 1;
+ break;
+ }
+
+ namealc = malloc (file_name_size + (nameend - name) + 3);
+ if (namealc == NULL)
+ {
+ error (_("Out of memory\n"));
+ ret = 1;
+ break;
+ }
+
+ memcpy (namealc, file_name, file_name_size);
+ namealc[file_name_size] = '(';
+ memcpy (namealc + file_name_size + 1, name, nameend - name);
+ namealc[file_name_size + 1 + (nameend - name)] = ')';
+ namealc[file_name_size + 2 + (nameend - name)] = '\0';
+
+ archive_file_offset = ftell (file);
+ archive_file_size = strtoul (arhdr.ar_size, NULL, 10);
+
+ ret |= process_object (namealc, file);
+
+ free (namealc);
+
+ if (fseek (file,
+ (archive_file_offset
+ + archive_file_size
+ + (archive_file_size & 1)),
+ SEEK_SET) != 0)
+ {
+ error (_("%s: failed to seek to next archive header\n"), file_name);
+ ret = 1;
+ break;
+ }
+
+ got = fread (&arhdr, 1, sizeof arhdr, file);
+ if (got != sizeof arhdr)
+ {
+ if (got == 0)
+ break;
+
+ error (_("%s: failed to read archive header\n"), file_name);
+ ret = 1;
+ break;
+ }
+ }
+
+ if (longnames != 0)
+ free (longnames);
+
+ return ret;
+}
+
+static int
+process_file (char *file_name)
+{
+ FILE *file;
+ struct stat statbuf;
+ char armag[SARMAG];
+ int ret;
+
+ if (stat (file_name, &statbuf) < 0)
+ {
+ error (_("Cannot stat input file %s.\n"), file_name);
+ return 1;
+ }
+
+ file = fopen (file_name, "rb");
+ if (file == NULL)
+ {
+ error (_("Input file %s not found.\n"), file_name);
+ return 1;
+ }
+
+ if (fread (armag, SARMAG, 1, file) != 1)
+ {
+ error (_("%s: Failed to read file header\n"), file_name);
+ fclose (file);
+ return 1;
+ }
+
+ if (memcmp (armag, ARMAG, SARMAG) == 0)
+ ret = process_archive (file_name, file);
+ else
+ {
+ rewind (file);
+ archive_file_size = archive_file_offset = 0;
+ ret = process_object (file_name, file);
+ }
+
+ fclose (file);
+
+ return ret;
+}
+
#ifdef SUPPORT_DISASSEMBLY
/* Needed by the i386 disassembler. For extra credit, someone could
fix this so that we insert symbolic addresses here, esp for GOT/PLT
}
#endif
-int main PARAMS ((int, char **));
-
int
-main (argc, argv)
- int argc;
- char **argv;
+main (int argc, char **argv)
{
int err;
char *cmdline_dump_sects = NULL;