Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
\f
+/* The difference between readelf and objdump:
+ Both programs are capabale of displaying the contents of ELF format files,
+ so why does the binutils project have two file dumpers ?
+
+ The reason is that objdump sees an ELF file through a BFD filter of the
+ world; if BFD has a bug where, say, it disagrees about a machine constant
+ in e_flags, then the odds are good that it will remain internally
+ consistent. The linker sees it the BFD way, objdump sees it the BFD way,
+ GAS sees it the BFD way. There was need for a tool to go find out what
+ the file actually says.
+
+ This is why the readelf program does not link against the BFD library - it
+ exists as an independent program to help verify the correct working of BFD.
+
+ There is also the case that readelf can provide more information about an
+ ELF file than is provided by objdump. In particular it can display DWARF
+ debugging information which (at the moment) objdump cannot. */
+\f
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.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 void (*byte_put)
- PARAMS ((unsigned char *, bfd_vma, int));
-static void byte_put_little_endian
- PARAMS ((unsigned char *, bfd_vma, int));
-static void byte_put_big_endian
- PARAMS ((unsigned char *, bfd_vma, int));
-static const char *get_mips_dynamic_type
- PARAMS ((unsigned long));
-static const char *get_sparc64_dynamic_type
- PARAMS ((unsigned long));
-static const char *get_ppc64_dynamic_type
- PARAMS ((unsigned long));
-static const char *get_parisc_dynamic_type
- PARAMS ((unsigned long));
-static const char *get_ia64_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 void dynamic_segment_ia64_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, unsigned long, int));
-static unsigned char *read_and_display_attr_value
- PARAMS ((unsigned long, unsigned long, unsigned char *, unsigned long,
- unsigned long, unsigned long, int));
-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;
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 (field, value, size)
- unsigned char * field;
- bfd_vma value;
- int size;
+byte_put_little_endian (unsigned char *field, bfd_vma value, int size)
{
switch (size)
{
/* 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 (field, value, size)
- unsigned char * field;
- bfd_vma value;
- int size;
+byte_put_big_endian (unsigned char *field, bfd_vma value, int size)
{
switch (size)
{
/* 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_DLX:
case EM_OPENRISC:
case EM_OR32:
- case EM_M32R:
case EM_CYGNUS_M32R:
case EM_D10V:
case EM_CYGNUS_D10V:
case EM_IQ2000:
case EM_XTENSA:
case EM_XTENSA_OLD:
+ case EM_M32R:
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;
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_ia64_dynamic_type (type)
- unsigned long type;
+get_ia64_dynamic_type (unsigned long type)
{
switch (type)
{
}
static const char *
-get_dynamic_type (type)
- unsigned long type;
+get_dynamic_type (unsigned long type)
{
static char buff[32];
}
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 "Renesas 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";
}
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;
}
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";
}
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;
}
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)
{
/* Process the reloc section. */
static int
-process_relocs (file)
- FILE *file;
+process_relocs (FILE *file)
{
unsigned long rel_size;
unsigned long rel_offset;
const char *name;
int has_dynamic_reloc;
unsigned int i;
-
+
has_dynamic_reloc = 0;
for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++)
(_("\n'%s' relocation section at offset 0x%lx contains %ld bytes:\n"),
name, rel_offset, rel_size);
- dump_relocations (file, rel_offset - loadaddr, rel_size,
+ dump_relocations (file,
+ offset_from_vma (file, rel_offset, rel_size),
+ rel_size,
dynamic_symbols, num_dynamic_syms,
dynamic_strings, is_rela);
}
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)
{
}
static void
-dynamic_segment_ia64_val (entry)
- Elf_Internal_Dyn *entry;
+dynamic_segment_ia64_val (Elf_Internal_Dyn *entry)
{
switch (entry->d_tag)
{
- case DT_IA_64_PLT_RESERVE:
- /* First 3 bytes reserved. */
+ 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);
- printf ("\n");
+ 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"));
}
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;
return len;
}
+/* Finds section NAME inside FILE and returns a
+ pointer to it, or NULL upon failure. */
+
+static Elf_Internal_Shdr *
+find_section (const char * name)
+{
+ Elf_Internal_Shdr *sec;
+ unsigned int i;
+
+ for (i = elf_header.e_shnum, sec = section_headers + i - 1;
+ i; --i, --sec)
+ if (strcmp (SECTION_NAME (sec), name) == 0)
+ break;
+
+ if (i && sec && sec->sh_size != 0)
+ return sec;
+
+ return NULL;
+}
+
/* Size of pointers in the .debug_line section. This information is not
really present in that section. It's obtained before dumping the debug
sections by doing some pre-scan of the .debug_info section. */
-static int debug_line_pointer_size = 4;
+static unsigned int * debug_line_pointer_sizes = NULL;
+static unsigned int num_debug_line_pointer_sizes = 0;
+
+/* Locate and scan the .debug_info section in the file and record the pointer
+ sizes for the compilation units in it. Usually an executable will have
+ just one pointer size, but this is not guaranteed, and so we try not to
+ make any assumptions. Returns zero upon failure, or the number of
+ compilation units upon success. */
+
+static unsigned int
+get_debug_line_pointer_sizes (FILE * file)
+{
+ Elf_Internal_Shdr * section;
+ unsigned char * start;
+ unsigned char * end;
+ unsigned char * begin;
+ unsigned long length;
+ unsigned int num_units;
+ unsigned int unit;
+
+ section = find_section (".debug_info");
+ if (section == NULL)
+ return 0;
+
+ length = section->sh_size;
+ start = get_data (NULL, file, section->sh_offset, section->sh_size,
+ _("extracting pointer sizes from .debug_info section"));
+ if (start == NULL)
+ return 0;
+
+ end = start + section->sh_size;
+ /* First scan the section to get the number of comp units. */
+ for (begin = start, num_units = 0; begin < end; num_units++)
+ {
+ /* 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. */
+ length = byte_get (begin, 4);
+
+ if (length == 0xffffffff)
+ {
+ length = byte_get (begin + 4, 8);
+ begin += length + 12;
+ }
+ else
+ begin += length + 4;
+ }
+
+ if (num_units == 0)
+ {
+ error (_("No comp units in .debug_info section ?"));
+ free (start);
+ return 0;
+ }
+
+ /* Then allocate an array to hold the pointer sizes. */
+ debug_line_pointer_sizes = malloc (num_units * sizeof * debug_line_pointer_sizes);
+ if (debug_line_pointer_sizes == NULL)
+ {
+ error (_("Not enough memory for a pointer size array of %u entries"),
+ num_units);
+ free (start);
+ return 0;
+ }
+
+ /* Populate the array. */
+ for (begin = start, unit = 0; begin < end; unit++)
+ {
+ length = byte_get (begin, 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:
+
+ unit_length: 12 bytes
+ version: 2 bytes
+ debug_abbrev_offset: 8 bytes
+ -----------------------------
+ Total: 22 bytes */
+
+ debug_line_pointer_sizes [unit] = byte_get (begin + 22, 1);
+ length = byte_get (begin + 4, 8);
+ begin += length + 12;
+ }
+ 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_sizes [unit] = byte_get (begin + 10, 1);
+ begin += length + 4;
+ }
+ }
+
+ free (start);
+ num_debug_line_pointer_sizes = num_units;
+ return num_units;
+}
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)
{
unsigned char *hdrptr;
DWARF2_Internal_LineInfo info;
int i;
int offset_size;
int initial_length_size;
+ unsigned int comp_unit = 0;
printf (_("\nDump of debug contents of section %s:\n\n"),
SECTION_NAME (section));
+ if (num_debug_line_pointer_sizes == 0)
+ get_debug_line_pointer_sizes (file);
+
while (data < end)
{
+ unsigned int pointer_size;
+
hdrptr = data;
/* Check the length of the block. */
info.li_line_base <<= 24;
info.li_line_base >>= 24;
+ /* Get the pointer size from the comp unit associated
+ with this block of line number information. */
+ if (comp_unit >= num_debug_line_pointer_sizes)
+ {
+ error (_("Not enough comp units for .debug_lines section\n"));
+ return 0;
+ }
+ else
+ {
+ pointer_size = debug_line_pointer_sizes [comp_unit];
+ comp_unit ++;
+ }
+
printf (_(" Length: %ld\n"), info.li_length);
printf (_(" DWARF Version: %d\n"), info.li_version);
printf (_(" Prologue Length: %d\n"), info.li_prologue_length);
printf (_(" Line Base: %d\n"), info.li_line_base);
printf (_(" Line Range: %d\n"), info.li_line_range);
printf (_(" Opcode Base: %d\n"), info.li_opcode_base);
+ printf (_(" (Pointer size: %u)\n"), pointer_size);
end_of_sequence = data + info.li_length + initial_length_size;
{
case DW_LNS_extended_op:
data += process_extended_line_op (data, info.li_default_is_stmt,
- debug_line_pointer_size);
+ pointer_size);
break;
case DW_LNS_copy:
}
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_Internal_PubNames pubnames;
unsigned char *end;
}
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;
/* If it is already loaded, do nothing. */
if (debug_loc_contents != NULL)
return;
/* Locate the .debug_loc section. */
- for (i = 0, sec = section_headers;
- i < elf_header.e_shnum;
- i++, sec++)
- if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0)
- break;
-
- if (i == elf_header.e_shnum || sec->sh_size == 0)
+ sec = find_section (".debug_loc");
+ if (sec == NULL)
return;
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)
{
unsigned char *section_end;
unsigned long bytes;
unsigned char *section_begin = start;
bfd_vma addr;
+ unsigned int comp_unit = 0;
addr = section->sh_addr;
bytes = section->sh_size;
return 0;
}
+ if (num_debug_line_pointer_sizes == 0)
+ get_debug_line_pointer_sizes (file);
+
printf (_("Contents of the .debug_loc section:\n\n"));
printf (_("\n Offset Begin End Expression\n"));
unsigned long end;
unsigned short length;
unsigned long offset;
+ unsigned int pointer_size;
offset = start - section_begin;
+ /* Get the pointer size from the comp unit associated
+ with this block of location information. */
+ if (comp_unit >= num_debug_line_pointer_sizes)
+ {
+ error (_("Not enough comp units for .debug_loc section\n"));
+ return 0;
+ }
+ else
+ {
+ pointer_size = debug_line_pointer_sizes [comp_unit];
+ comp_unit ++;
+ }
+
while (1)
{
- /* Normally, the lists in the debug_loc section are related to a
- given compilation unit, and thus, we would use the pointer size
- of that compilation unit. However, since we are displaying it
- seperately here, we either have to store pointer sizes of all
- compilation units, or assume they don't change. We assume,
- like the debug_line display, that it doesn't change. */
- begin = byte_get (start, debug_line_pointer_size);
- start += debug_line_pointer_size;
- end = byte_get (start, debug_line_pointer_size);
- start += debug_line_pointer_size;
+ begin = byte_get (start, pointer_size);
+ start += pointer_size;
+ end = byte_get (start, pointer_size);
+ start += pointer_size;
if (begin == 0 && end == 0)
break;
start += 2;
printf (" %8.8lx %8.8lx %8.8lx (", offset, begin, end);
- decode_location_expression (start, debug_line_pointer_size, length);
+ decode_location_expression (start, pointer_size, length);
printf (")\n");
start += length;
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;
/* If it is already loaded, do nothing. */
if (debug_str_contents != NULL)
return;
/* Locate the .debug_str section. */
- for (i = 0, sec = section_headers;
- i < elf_header.e_shnum;
- i++, sec++)
- if (strcmp (SECTION_NAME (sec), ".debug_str") == 0)
- break;
-
- if (i == elf_header.e_shnum || sec->sh_size == 0)
+ sec = find_section (".debug_str");
+ if (sec == NULL)
return;
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,
- offset_size, dwarf_version)
- unsigned long attribute;
- unsigned long form;
- unsigned char *data;
- unsigned long cu_offset;
- unsigned long pointer_size;
- unsigned long offset_size;
- int dwarf_version;
+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;
}
- /* For some attributes we can display futher information. */
+ /* For some attributes we can display further information. */
printf ("\t");
}
static unsigned char *
-read_and_display_attr (attribute, form, data, cu_offset, pointer_size,
- offset_size, dwarf_version)
- unsigned long attribute;
- unsigned long form;
- unsigned char *data;
- unsigned long cu_offset;
- unsigned long pointer_size;
- unsigned long offset_size;
- int dwarf_version;
+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,
}
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;
unsigned char *hdrptr;
unsigned char *cu_abbrev_offset_ptr;
unsigned char *tags;
- unsigned int i;
int level;
unsigned long cu_offset;
int offset_size;
unsigned char *begin;
/* Locate the .debug_abbrev section and process it. */
- for (i = 0, sec = section_headers;
- i < elf_header.e_shnum;
- i++, sec++)
- if (strcmp (SECTION_NAME (sec), ".debug_abbrev") == 0)
- break;
-
- if (i == elf_header.e_shnum || sec->sh_size == 0)
+ sec = find_section (".debug_abbrev");
+ if (sec == NULL)
{
warn (_("Unable to locate .debug_abbrev section!\n"));
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;
}
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;
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;
{
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));
return 1;
}
-/* Pre-scan the .debug_info section to record the size of address.
- When dumping the .debug_line, we use that size information, assuming
- that all compilation units have the same address size. */
-static int
-prescan_debug_info (section, start, file)
- Elf_Internal_Shdr *section ATTRIBUTE_UNUSED;
- unsigned char *start;
- FILE *file ATTRIBUTE_UNUSED;
-{
- 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:
-
- unit_length: 12 bytes
- version: 2 bytes
- debug_abbrev_offset: 8 bytes
- -----------------------------
- Total: 22 bytes */
-
- debug_line_pointer_size = byte_get (start + 22, 1);
- }
- else
- {
- /* For 32-bit DWARF, the 1-byte address_size field is 10 bytes from
- the start of the section:
- unit_length: 4 bytes
- version: 2 bytes
- debug_abbrev_offset: 4 bytes
- -----------------------------
- Total: 10 bytes */
-
- debug_line_pointer_size = byte_get (start + 10, 1);
- }
- return 0;
-}
-
- /* A structure containing the name of a debug section and a pointer
- to a function that can decode it. The third field is a prescan
- function to be run over the section before displaying any of the
- sections. */
+/* A structure containing the name of a debug section
+ and a pointer to a function that can decode it. */
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 *);
}
debug_displays[] =
{
- { ".debug_abbrev", display_debug_abbrev, NULL },
- { ".debug_aranges", display_debug_aranges, NULL },
- { ".debug_frame", display_debug_frames, NULL },
- { ".debug_info", display_debug_info, prescan_debug_info },
- { ".debug_line", display_debug_lines, NULL },
- { ".debug_pubnames", display_debug_pubnames, NULL },
- { ".eh_frame", display_debug_frames, NULL },
- { ".debug_macinfo", display_debug_macinfo, NULL },
- { ".debug_str", display_debug_str, NULL },
- { ".debug_loc", display_debug_loc, NULL },
- { ".debug_pubtypes", display_debug_not_supported, NULL },
- { ".debug_ranges", display_debug_not_supported, NULL },
- { ".debug_static_func", display_debug_not_supported, NULL },
- { ".debug_static_vars", display_debug_not_supported, NULL },
- { ".debug_types", display_debug_not_supported, NULL },
- { ".debug_weaknames", display_debug_not_supported, NULL }
+ { ".debug_abbrev", display_debug_abbrev },
+ { ".debug_aranges", display_debug_aranges },
+ { ".debug_frame", display_debug_frames },
+ { ".debug_info", display_debug_info },
+ { ".debug_line", display_debug_lines },
+ { ".debug_pubnames", display_debug_pubnames },
+ { ".eh_frame", display_debug_frames },
+ { ".debug_macinfo", display_debug_macinfo },
+ { ".debug_str", display_debug_str },
+ { ".debug_loc", display_debug_loc },
+ { ".debug_pubtypes", display_debug_not_supported },
+ { ".debug_ranges", display_debug_not_supported },
+ { ".debug_static_func", display_debug_not_supported },
+ { ".debug_static_vars", display_debug_not_supported },
+ { ".debug_types", display_debug_not_supported },
+ { ".debug_weaknames", display_debug_not_supported }
};
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;
if (! do_dump)
return 1;
- /* Pre-scan the debug sections to find some debug information not
- present in some of them. For the .debug_line, we must find out the
- size of address (specified in .debug_info and .debug_aranges). */
- for (i = 0, section = section_headers;
- i < elf_header.e_shnum && i < num_dump_sects;
- i++, section++)
- {
- char *name = SECTION_NAME (section);
- int j;
-
- if (section->sh_size == 0)
- continue;
-
- /* See if there is some pre-scan operation for this section. */
- for (j = NUM_ELEM (debug_displays); j--;)
- if (strcmp (debug_displays[j].name, name) == 0)
- {
- if (debug_displays[j].prescan != NULL)
- {
- bfd_size_type length;
- unsigned char *start;
-
- length = section->sh_size;
- start = ((unsigned char *)
- get_data (NULL, file, section->sh_offset, length,
- _("debug section data")));
- if (!start)
- return 0;
-
- debug_displays[j].prescan (section, start, file);
- free (start);
- }
-
- break;
- }
- }
-
for (i = 0, section = section_headers;
i < elf_header.e_shnum && i < num_dump_sects;
i++, section++)
}
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];
switch (e_type)
{
+ case NT_AUXV: return _("NT_AUXV (auxiliary vector)");
case NT_PRSTATUS: return _("NT_PRSTATUS (prstatus structure)");
case NT_FPREGSET: return _("NT_FPREGSET (floating point registers)");
case NT_PRPSINFO: return _("NT_PRPSINFO (prpsinfo structure)");
}
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)
/* 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)
+ {
+ if (errno == ENOENT)
+ error (_("'%s': No such file\n"), file_name);
+ else
+ error (_("Could not locate '%s'. System error message: %s\n"),
+ file_name, strerror (errno));
+ return 1;
+ }
+
+ if (! S_ISREG (statbuf.st_mode))
+ {
+ error (_("'%s' is not an ordinary file\n"), file_name);
+ return 1;
+ }
+
+ file = fopen (file_name, "rb");
+ if (file == NULL)
+ {
+ error (_("Input file '%s' is not readable.\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;