summaryrefslogtreecommitdiffstats
path: root/src/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/readelf.c')
-rw-r--r--src/readelf.c486
1 files changed, 317 insertions, 169 deletions
diff --git a/src/readelf.c b/src/readelf.c
index ffcb0a1c..c591b322 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -39,6 +39,7 @@
#include <inttypes.h>
#include <langinfo.h>
#include <libdw.h>
+#include <libdwfl.h>
#include <libintl.h>
#include <locale.h>
#include <stdarg.h>
@@ -198,11 +199,8 @@ static size_t shnum;
/* Declarations of local functions. */
-static void process_file (int fd, Elf *elf, const char *prefix,
- const char *fname, bool only_one,
- bool will_print_archive_index);
-static void process_elf_file (Elf *elf, const char *prefix, const char *fname,
- bool only_one);
+static void process_file (int fd, const char *fname, bool only_one);
+static void process_elf_file (Dwfl_Module *dwflmod);
static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
@@ -218,7 +216,7 @@ static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
static void handle_versym (Ebl *ebl, Elf_Scn *scn,
GElf_Shdr *shdr);
-static void print_debug (Ebl *ebl, GElf_Ehdr *ehdr);
+static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
static void handle_hash (Ebl *ebl);
static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
static void print_liblist (Ebl *ebl);
@@ -256,21 +254,7 @@ main (int argc, char *argv[])
continue;
}
- /* Create an `Elf' descriptor. */
- Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
- if (elf == NULL)
- error (0, 0, gettext ("cannot generate Elf descriptor: %s\n"),
- elf_errmsg (-1));
- else
- {
- process_file (fd, elf, NULL, argv[remaining], only_one,
- print_archive_index);
-
- /* Now we can close the descriptor. */
- if (elf_end (elf) != 0)
- error (0, 0, gettext ("error while closing Elf descriptor: %s"),
- elf_errmsg (-1));
- }
+ process_file (fd, argv[remaining], only_one);
close (fd);
}
@@ -435,103 +419,138 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
}
-/* Process one file. */
+/* Check if the file is an archive, and if so dump its index. */
static void
-process_file (int fd, Elf *elf, const char *prefix, const char *fname,
- bool only_one, bool will_print_archive_index)
+check_archive_index (int fd, const char *fname, bool only_one)
{
- /* We can handle two types of files: ELF files and archives. */
- Elf_Kind kind = elf_kind (elf);
- struct stat64 st;
-
- switch (kind)
+ /* Create an `Elf' descriptor. */
+ Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+ if (elf == NULL)
+ error (0, 0, gettext ("cannot generate Elf descriptor: %s"),
+ elf_errmsg (-1));
+ else
{
- case ELF_K_ELF:
- if (unlikely (will_print_archive_index))
+ if (elf_kind (elf) == ELF_K_AR)
+ {
+ if (!only_one)
+ printf ("\n%s:\n\n", fname);
+ dump_archive_index (elf, fname);
+ }
+ else
error (0, 0,
gettext ("'%s' is not an archive, cannot print archive index"),
fname);
- /* Yes! It's an ELF file. */
- if (any_control_option)
- process_elf_file (elf, prefix, fname, only_one);
- break;
- case ELF_K_AR:
- {
- size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
- size_t fname_len = strlen (fname) + 1;
- char new_prefix[prefix_len + 1 + fname_len];
- char *cp = new_prefix;
+ /* Now we can close the descriptor. */
+ if (elf_end (elf) != 0)
+ error (0, 0, gettext ("error while closing Elf descriptor: %s"),
+ elf_errmsg (-1));
+ }
+}
- /* Create the full name of the file. */
- if (prefix != NULL)
- {
- cp = mempcpy (cp, prefix, prefix_len);
- *cp++ = ':';
- }
- memcpy (cp, fname, fname_len);
+/* Trivial callback used for checking if we opened an archive. */
+static int
+count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ void **userdata __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)),
+ Dwarf_Addr base __attribute__ ((unused)),
+ void *arg)
+{
+ *(bool *) arg = false;
+ return DWARF_CB_ABORT;
+}
- if (will_print_archive_index)
- dump_archive_index (elf, new_prefix);
+static int
+process_dwflmod (Dwfl_Module *dwflmod,
+ void **userdata __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)),
+ Dwarf_Addr base __attribute__ ((unused)),
+ void *arg)
+{
+ bool only_one = *(bool *) arg;
- /* It's an archive. We process each file in it. */
- Elf *subelf;
- Elf_Cmd cmd = ELF_C_READ_MMAP;
- while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
- {
- kind = elf_kind (subelf);
+ /* Print the file name. */
+ if (!only_one)
+ {
+ const char *fname;
+ dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
- /* Call this function recursively. */
- if (kind == ELF_K_ELF || kind == ELF_K_AR)
- {
- Elf_Arhdr *arhdr = elf_getarhdr (subelf);
- assert (arhdr != NULL);
+ printf ("\n%s:\n\n", fname);
+ }
- process_file (fd, subelf, new_prefix, arhdr->ar_name, false,
- kind == ELF_K_AR && will_print_archive_index);
- }
+ process_elf_file (dwflmod);
- /* Get next archive element. */
- cmd = elf_next (subelf);
- if (elf_end (subelf) != 0)
- error (0, 0,
- gettext (" error while freeing sub-ELF descriptor: %s\n"),
- elf_errmsg (-1));
- }
- }
- break;
+ return DWARF_CB_OK;
+}
- default:
+/* Stub libdwfl callback, only the ELF handle already open is ever used. */
+static int
+find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
+ void **userdata __attribute__ ((unused)),
+ const char *modname __attribute__ ((unused)),
+ Dwarf_Addr base __attribute__ ((unused)),
+ const char *file_name __attribute__ ((unused)),
+ const char *debuglink_file __attribute__ ((unused)),
+ GElf_Word debuglink_crc __attribute__ ((unused)),
+ char **debuginfo_file_name __attribute__ ((unused)))
+{
+ return -1;
+}
+
+/* Process one input file. */
+static void
+process_file (int fd, const char *fname, bool only_one)
+{
+ if (print_archive_index)
+ check_archive_index (fd, fname, only_one);
+
+ if (!any_control_option)
+ return;
+
+ /* Use libdwfl in a trivial way to open the libdw handle for us.
+ This takes care of applying relocations to DWARF data in ET_REL files. */
+ static const Dwfl_Callbacks callbacks =
+ {
+ .section_address = dwfl_offline_section_address,
+ .find_debuginfo = find_no_debuginfo
+ };
+ Dwfl *dwfl = dwfl_begin (&callbacks);
+ if (dwfl_report_offline (dwfl, fname, fname, fd) == NULL)
+ {
+ struct stat64 st;
if (fstat64 (fd, &st) != 0)
error (0, errno, gettext ("cannot stat input file"));
else if (st.st_size == 0)
error (0, 0, gettext ("input file is empty"));
else
- /* We cannot do anything. */
- error (0, 0, gettext ("\
-Not an ELF file - it has the wrong magic bytes at the start"));
- break;
+ error (0, 0, gettext ("failed reading '%s': %s"),
+ fname, dwfl_errmsg (-1));
+ }
+ else
+ {
+ dwfl_report_end (dwfl, NULL, NULL);
+
+ if (only_one)
+ /* Clear ONLY_ONE if we have multiple modules, from an archive. */
+ dwfl_getmodules (dwfl, &count_dwflmod, &only_one, 1);
+
+ /* Process the one or more modules gleaned from this file. */
+ dwfl_getmodules (dwfl, &process_dwflmod, &only_one, 0);
}
+ dwfl_end (dwfl);
}
-/* Process one file. */
+/* Process one ELF file. */
static void
-process_elf_file (Elf *elf, const char *prefix, const char *fname,
- bool only_one)
+process_elf_file (Dwfl_Module *dwflmod)
{
+ GElf_Addr dwflbias;
+ Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
+
GElf_Ehdr ehdr_mem;
GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
- /* Print the file name. */
- if (!only_one)
- {
- if (prefix != NULL)
- printf ("\n%s(%s):\n\n", prefix, fname);
- else
- printf ("\n%s:\n\n", fname);
- }
-
if (ehdr == NULL)
{
error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
@@ -578,7 +597,7 @@ process_elf_file (Elf *elf, const char *prefix, const char *fname,
if (string_sections != NULL)
dump_strings (ebl);
if (print_debug_sections != 0)
- print_debug (ebl, ehdr);
+ print_debug (dwflmod, ebl, ehdr);
if (print_notes)
handle_notes (ebl, ehdr);
if (print_string_sections)
@@ -2721,6 +2740,79 @@ print_liblist (Ebl *ebl)
}
+static char *
+format_dwarf_addr (Dwfl_Module *dwflmod,
+ int address_size, Dwarf_Addr address)
+{
+ /* See if there is a name we can give for this address. */
+ GElf_Sym sym;
+ const char *name = dwfl_module_addrsym (dwflmod, address, &sym, NULL);
+ if (name != NULL)
+ sym.st_value = address - sym.st_value;
+
+ /* Relativize the address. */
+ int n = dwfl_module_relocations (dwflmod);
+ int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
+
+ /* In an ET_REL file there is a section name to refer to. */
+ const char *scn = (i < 0 ? NULL
+ : dwfl_module_relocation_info (dwflmod, i, NULL));
+
+ char *result;
+ if ((name != NULL
+ ? (sym.st_value != 0
+ ? (scn != NULL
+ ? (address_size == 0
+ ? asprintf (&result,
+ gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
+ scn, address, name, sym.st_value)
+ : asprintf (&result,
+ gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
+ scn, 2 + address_size * 2, address,
+ name, sym.st_value))
+ : (address_size == 0
+ ? asprintf (&result,
+ gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
+ address, name, sym.st_value)
+ : asprintf (&result,
+ gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
+ 2 + address_size * 2, address,
+ name, sym.st_value)))
+ : (scn != NULL
+ ? (address_size == 0
+ ? asprintf (&result,
+ gettext ("%s+%#" PRIx64 " <%s>"),
+ scn, address, name)
+ : asprintf (&result,
+ gettext ("%s+%#0*" PRIx64 " <%s>"),
+ scn, 2 + address_size * 2, address, name))
+ : (address_size == 0
+ ? asprintf (&result,
+ gettext ("%#" PRIx64 " <%s>"),
+ address, name)
+ : asprintf (&result,
+ gettext ("%#0*" PRIx64 " <%s>"),
+ 2 + address_size * 2, address, name))))
+ : (scn != NULL
+ ? (address_size == 0
+ ? asprintf (&result,
+ gettext ("%s+%#" PRIx64),
+ scn, address)
+ : asprintf (&result,
+ gettext ("%s+%#0*" PRIx64),
+ scn, 2 + address_size * 2, address))
+ : (address_size == 0
+ ? asprintf (&result,
+ "%#" PRIx64,
+ address)
+ : asprintf (&result,
+ "%#0*" PRIx64,
+ 2 + address_size * 2, address)))) < 0)
+ error (EXIT_FAILURE, 0, _("memory exhausted"));
+
+ return result;
+}
+
static const char *
dwarf_tag_string (unsigned int tag)
{
@@ -3307,7 +3399,7 @@ dwarf_discr_list_string (unsigned int code)
static void
-print_ops (Dwarf *dbg, int indent, int indentrest,
+print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
unsigned int addrsize, Dwarf_Word len, const unsigned char *data)
{
static const char *const known[] =
@@ -3487,9 +3579,18 @@ print_ops (Dwarf *dbg, int indent, int indentrest,
data += addrsize;
len -= addrsize;
- printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
- indent, "", (uintmax_t) offset,
- known[op] ?: "???", (uintmax_t) addr);
+ if (op == DW_OP_addr)
+ {
+ char *a = format_dwarf_addr (dwflmod, 0, addr);
+ printf ("%*s[%4" PRIuMAX "] %s %s\n",
+ indent, "", (uintmax_t) offset,
+ known[op] ?: "???", a);
+ free (a);
+ }
+ else
+ printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
+ indent, "", (uintmax_t) offset,
+ known[op] ?: "???", (uintmax_t) addr);
offset += 1 + addrsize;
break;
@@ -3646,7 +3747,8 @@ print_ops (Dwarf *dbg, int indent, int indentrest,
static void
-print_debug_abbrev_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
GElf_Shdr *shdr, Dwarf *dbg)
@@ -3717,7 +3819,8 @@ print_debug_abbrev_section (Ebl *ebl __attribute__ ((unused)),
not have to know a bit about the structure of the section, libdwarf
takes care of it. */
static void
-print_debug_aranges_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
GElf_Shdr *shdr, Dwarf *dbg)
@@ -3773,7 +3876,8 @@ print_debug_aranges_section (Ebl *ebl __attribute__ ((unused)),
/* Print content of DWARF .debug_ranges section. */
static void
-print_debug_ranges_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_ranges_section (Dwfl_Module *dwflmod,
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg)
{
@@ -3800,7 +3904,7 @@ print_debug_ranges_section (Ebl *ebl __attribute__ ((unused)),
if (data->d_size - offset < address_size * 2)
{
- printf (" [%6tx] <INVALID DATA>\n", offset);
+ printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
break;
}
@@ -3820,21 +3924,24 @@ print_debug_ranges_section (Ebl *ebl __attribute__ ((unused)),
}
if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
- printf (" [%6tx] base address %#0*" PRIxMAX "\n", offset,
- 2 + (int) (address_size * 2), (uintmax_t) end);
+ {
+ char *b = format_dwarf_addr (dwflmod, address_size, end);
+ printf (gettext (" [%6tx] base address %s\n"), offset, b);
+ free (b);
+ }
else if (begin == 0 && end == 0) /* End of list entry. */
first = true;
else
{
+ char *b = format_dwarf_addr (dwflmod, address_size, begin);
+ char *e = format_dwarf_addr (dwflmod, address_size, end);
/* We have an address range entry. */
if (first) /* First address range entry in a list. */
- printf (" [%6tx] %#0*" PRIxMAX "..%#0*" PRIxMAX "\n", offset,
- 2 + (int) (address_size * 2), (uintmax_t) begin,
- 2 + (int) (address_size * 2), (uintmax_t) end);
+ printf (gettext (" [%6tx] %s..%s\n"), offset, b, e);
else
- printf (" %#0*" PRIxMAX "..%#0*" PRIxMAX "\n",
- 2 + (int) (address_size * 2), (uintmax_t) begin,
- 2 + (int) (address_size * 2), (uintmax_t) end);
+ printf (gettext (" %s..%s\n"), b, e);
+ free (b);
+ free (e);
first = false;
}
@@ -3843,7 +3950,8 @@ print_debug_ranges_section (Ebl *ebl __attribute__ ((unused)),
static void
-print_debug_frame_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_frame_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
GElf_Shdr *shdr __attribute__ ((unused)),
@@ -3854,6 +3962,7 @@ print_debug_frame_section (Ebl *ebl __attribute__ ((unused)),
struct attrcb_args
{
+ Dwfl_Module *dwflmod;
Dwarf *dbg;
int level;
unsigned int addrsize;
@@ -3885,18 +3994,21 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
switch (form)
{
- case DW_FORM_addr:;
- Dwarf_Addr addr;
- if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
- {
- attrval_out:
- error (0, 0, gettext ("cannot get attribute value: %s"),
- dwarf_errmsg (-1));
- return DWARF_CB_ABORT;
- }
- printf (" %*s%-20s %#0*" PRIxMAX "\n",
- (int) (level * 2), "", dwarf_attr_string (attr),
- 2 + (int) (cbargs->addrsize * 2), (uintmax_t) addr);
+ case DW_FORM_addr:
+ {
+ Dwarf_Addr addr;
+ if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
+ {
+ attrval_out:
+ error (0, 0, gettext ("cannot get attribute value: %s"),
+ dwarf_errmsg (-1));
+ return DWARF_CB_ABORT;
+ }
+ char *a = format_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr);
+ printf (" %*s%-20s %s\n",
+ (int) (level * 2), "", dwarf_attr_string (attr), a);
+ free (a);
+ }
break;
case DW_FORM_indirect:
@@ -4033,7 +4145,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
case DW_AT_frame_base:
case DW_AT_return_addr:
case DW_AT_static_link:
- print_ops (cbargs->dbg, 12 + level * 2, 12 + level * 2,
+ print_ops (cbargs->dwflmod, cbargs->dbg,
+ 12 + level * 2, 12 + level * 2,
cbargs->addrsize, block.length, block.data);
break;
}
@@ -4051,7 +4164,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
static void
-print_debug_info_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_info_section (Dwfl_Module *dwflmod,
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
GElf_Shdr *shdr, Dwarf *dbg)
@@ -4088,6 +4202,7 @@ print_debug_info_section (Ebl *ebl __attribute__ ((unused)),
struct attrcb_args args;
+ args.dwflmod = dwflmod;
args.dbg = dbg;
args.addrsize = addrsize;
args.cu_offset = offset;
@@ -4172,7 +4287,8 @@ print_debug_info_section (Ebl *ebl __attribute__ ((unused)),
static void
-print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
+print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\
@@ -4391,10 +4507,11 @@ print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
line += line_increment;
address += address_increment;
+ char *a = format_dwarf_addr (dwflmod, 0, address);
printf (gettext ("\
- special opcode %u: address+%u = %#" PRIx64 ", line%+d = %zu\n"),
- opcode, address_increment, (uint64_t) address,
- line_increment, line);
+ special opcode %u: address+%u = %s, line%+d = %zu\n"),
+ opcode, address_increment, a, line_increment, line);
+ free (a);
}
else if (opcode == 0)
{
@@ -4429,8 +4546,11 @@ print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
address = read_4ubyte_unaligned_inc (dbg, linep);
else
address = read_8ubyte_unaligned_inc (dbg, linep);
- printf (gettext ("set address to %#" PRIx64 "\n"),
- (uint64_t) address);
+ {
+ char *a = format_dwarf_addr (dwflmod, 0, address);
+ printf (gettext ("set address to %s\n"), a);
+ free (a);
+ }
break;
case DW_LNE_define_file:
@@ -4478,9 +4598,12 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
address. */
get_uleb128 (u128, linep);
address += minimum_instr_len * u128;
- printf (gettext ("\
- advance address by %u to %#" PRIx64 "\n"),
- u128, (uint64_t) address);
+ {
+ char *a = format_dwarf_addr (dwflmod, 0, address);
+ printf (gettext ("advance address by %u to %s\n"),
+ u128, a);
+ free (a);
+ }
break;
case DW_LNS_advance_line:
@@ -4527,9 +4650,12 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
u128 = (minimum_instr_len
* ((255 - opcode_base) / line_range));
address += u128;
- printf (gettext ("\
- advance address by constant %u to %#" PRIx64 "\n"),
- u128, (uint64_t) address);
+ {
+ char *a = format_dwarf_addr (dwflmod, 0, address);
+ printf (gettext ("advance address by constant %u to %s\n"),
+ u128, a);
+ free (a);
+ }
break;
case DW_LNS_fixed_advance_pc:
@@ -4540,9 +4666,13 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
u128 = read_2ubyte_unaligned_inc (dbg, linep);
address += u128;
- printf (gettext ("\
- advance address by fixed value %u to %#" PRIx64 "\n"),
- u128, (uint64_t) address);
+ {
+ char *a = format_dwarf_addr (dwflmod, 0, address);
+ printf (gettext ("\
+advance address by fixed value %u to %s\n"),
+ u128, a);
+ free (a);
+ }
break;
case DW_LNS_set_prologue_end:
@@ -4585,7 +4715,8 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
static void
-print_debug_loc_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_loc_section (Dwfl_Module *dwflmod,
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
GElf_Shdr *shdr,
@@ -4614,7 +4745,7 @@ print_debug_loc_section (Ebl *ebl __attribute__ ((unused)),
if (data->d_size - offset < address_size * 2)
{
- printf (" [%6tx] <INVALID DATA>\n", offset);
+ printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
break;
}
@@ -4634,8 +4765,11 @@ print_debug_loc_section (Ebl *ebl __attribute__ ((unused)),
}
if (begin == (Dwarf_Addr) -1l) /* Base address entry. */
- printf (" [%6tx] base address %#0*" PRIxMAX "\n", offset,
- 2 + (int) (address_size * 2), (uintmax_t) end);
+ {
+ char *b = format_dwarf_addr (dwflmod, address_size, end);
+ printf (gettext (" [%6tx] base address %s\n"), offset, b);
+ free (b);
+ }
else if (begin == 0 && end == 0) /* End of list entry. */
first = true;
else
@@ -4643,17 +4777,18 @@ print_debug_loc_section (Ebl *ebl __attribute__ ((unused)),
/* We have a location expression entry. */
uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
+ char *b = format_dwarf_addr (dwflmod, address_size, begin);
+ char *e = format_dwarf_addr (dwflmod, address_size, end);
+
if (first) /* First entry in a list. */
- printf (" [%6tx] %#0*" PRIxMAX "..%#0*" PRIxMAX,
- offset,
- 2 + (int) (address_size * 2), (uintmax_t) begin,
- 2 + (int) (address_size * 2), (uintmax_t) end);
+ printf (gettext (" [%6tx] %s..%s"), offset, b, e);
else
- printf (" %#0*" PRIxMAX "..%#0*" PRIxMAX,
- 2 + (int) (address_size * 2), (uintmax_t) begin,
- 2 + (int) (address_size * 2), (uintmax_t) end);
+ printf (gettext (" %s..%s"), b, e);
- print_ops (dbg, 1, 18 + (address_size * 4),
+ free (b);
+ free (e);
+
+ print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
address_size, len, readp);
first = false;
@@ -4686,7 +4821,8 @@ mac_compare (const void *p1, const void *p2)
static void
-print_debug_macinfo_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
@@ -4857,7 +4993,8 @@ print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
/* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
static void
-print_debug_pubnames_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
GElf_Shdr *shdr, Dwarf *dbg)
@@ -4871,7 +5008,8 @@ print_debug_pubnames_section (Ebl *ebl __attribute__ ((unused)),
/* Print the content of the DWARF string section '.debug_str'. */
static void
-print_debug_str_section (Ebl *ebl __attribute__ ((unused)),
+print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+ Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
GElf_Shdr *shdr, Dwarf *dbg)
@@ -4910,34 +5048,29 @@ print_debug_str_section (Ebl *ebl __attribute__ ((unused)),
}
}
-
static void
-print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
+print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
{
- /* Find the version information sections. For this we have to
- search through the section table. */
- Dwarf *dbg;
- Elf_Scn *scn;
- size_t shstrndx;
-
/* Before we start the real work get a debug context descriptor. */
- dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
+ Dwarf_Addr dwbias;
+ Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
if (dbg == NULL)
{
error (0, 0, gettext ("cannot get debug context descriptor: %s"),
- dwarf_errmsg (-1));
+ dwfl_errmsg (-1));
return;
}
/* Get the section header string table index. */
+ size_t shstrndx;
if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
error (EXIT_FAILURE, 0,
gettext ("cannot get section header string table index"));
- scn = NULL;
+ /* Look through all the sections for the debugging sections to print. */
+ Elf_Scn *scn = NULL;
while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
{
- /* Handle the section if it is part of the versioning handling. */
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
@@ -4947,7 +5080,8 @@ print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
{
const char *name;
enum section_e bitmask;
- void (*fp) (Ebl *, GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
+ void (*fp) (Dwfl_Module *, Ebl *,
+ GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
} debug_sections[] =
{
#define NEW_SECTION(name) \
@@ -4974,14 +5108,11 @@ print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
if (strcmp (name, debug_sections[n].name) == 0)
{
if (print_debug_sections & debug_sections[n].bitmask)
- debug_sections[n].fp (ebl, ehdr, scn, shdr, dbg);
+ debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
break;
}
}
}
-
- /* We are done with the DWARF handling. */
- dwarf_end (dbg);
}
@@ -5144,6 +5275,7 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
break;
case 'T':
+ case (char) ('T'|0x80):
assert (count == 2);
Dwarf_Word sec;
Dwarf_Word usec;
@@ -5161,6 +5293,22 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
default:
abort ();
}
+ if (unlikely (item->format == (char) ('T'|0x80)))
+ {
+ /* This is a hack for an ill-considered 64-bit ABI where
+ tv_usec is actually a 32-bit field with 32 bits of padding
+ rounding out struct timeval. We've already converted it as
+ a 64-bit field. For little-endian, this just means the
+ high half is the padding; it's presumably zero, but should
+ be ignored anyway. For big-endian, it means the 32-bit
+ field went into the high half of USEC. */
+ GElf_Ehdr ehdr_mem;
+ GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
+ if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
+ usec >>= 32;
+ else
+ usec &= UINT32_MAX;
+ }
colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
break;