summaryrefslogtreecommitdiffstats
path: root/src/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/readelf.c')
-rw-r--r--src/readelf.c481
1 files changed, 449 insertions, 32 deletions
diff --git a/src/readelf.c b/src/readelf.c
index 2797a849..101f7ae3 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -57,6 +57,8 @@
#include "../libdw/libdwP.h"
#include "../libdwfl/libdwflP.h"
#include "../libdw/memory-access.h"
+#include "../libdw/unwindP.h"
+#include "../libdw/encoded-value.h"
/* Name and version of program. */
@@ -344,7 +346,7 @@ parse_opt (int key, char *arg,
print_debug_sections |= section_aranges;
else if (strcmp (arg, "ranges") == 0)
print_debug_sections |= section_ranges;
- else if (strcmp (arg, "frame") == 0)
+ else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
print_debug_sections |= section_frame;
else if (strcmp (arg, "info") == 0)
print_debug_sections |= section_info;
@@ -3961,11 +3963,11 @@ 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)
+ GElf_Shdr *shdr, const char *secname, Dwarf *dbg)
{
printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
" [ Code]\n"),
- ".debug_abbrev", (uint64_t) shdr->sh_offset);
+ secname, (uint64_t) shdr->sh_offset);
Dwarf_Off offset = 0;
while (offset < shdr->sh_size)
@@ -4033,14 +4035,14 @@ 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)
+ GElf_Shdr *shdr, const char *name, Dwarf *dbg)
{
Dwarf_Aranges *aranges;
size_t cnt;
if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
{
- error (0, 0, gettext ("cannot get .debug_aranges content: %s"),
- dwarf_errmsg (-1));
+ error (0, 0, gettext ("cannot get %s content: %s"),
+ name, dwarf_errmsg (-1));
return;
}
@@ -4049,7 +4051,7 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
"\
\nDWARF section '%s' at offset %#" PRIx64 " contains %zu entries:\n",
cnt),
- ".debug_aranges", (uint64_t) shdr->sh_offset, cnt);
+ name, (uint64_t) shdr->sh_offset, cnt);
/* Compute floor(log16(cnt)). */
size_t tmp = cnt;
@@ -4089,20 +4091,20 @@ static void
print_debug_ranges_section (Dwfl_Module *dwflmod,
Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr,
- Dwarf *dbg)
+ const char *name, Dwarf *dbg)
{
Elf_Data *data = elf_rawdata (scn, NULL);
if (unlikely (data == NULL))
{
- error (0, 0, gettext ("cannot get .debug_ranges content: %s"),
- elf_errmsg (-1));
+ error (0, 0, gettext ("cannot get %s content: %s"),
+ name, elf_errmsg (-1));
return;
}
printf (gettext ("\
\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_ranges", (uint64_t) shdr->sh_offset);
+ name, (uint64_t) shdr->sh_offset);
size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
@@ -4158,6 +4160,271 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
}
}
+static void
+print_cfi (unsigned int indent, Dwarf *dbg, Dwarf_CFI *cfi,
+ unsigned int addrsize, uint8_t fde_encoding,
+ const uint8_t *program, const uint8_t *program_end,
+ Dwarf_Addr loc)
+{
+ static const char *cfi_extended[] =
+ {
+ [DW_CFA_nop] = "nop",
+ [DW_CFA_set_loc] = "set_loc",
+ [DW_CFA_advance_loc1] = "advance_loc1",
+ [DW_CFA_advance_loc2] = "advance_loc2",
+ [DW_CFA_advance_loc4] = "advance_loc4",
+ [DW_CFA_offset_extended] = "offset_extended",
+ [DW_CFA_restore_extended] = "restore_extended",
+ [DW_CFA_undefined] = "undefined",
+ [DW_CFA_same_value] = "same_value",
+ [DW_CFA_register] = "register",
+ [DW_CFA_remember_state] = "remember_state",
+ [DW_CFA_restore_state] = "restore_state",
+ [DW_CFA_def_cfa] = "def_cfa",
+ [DW_CFA_def_cfa_register] = "def_cfa_register",
+ [DW_CFA_def_cfa_offset] = "def_cfa_offset",
+ [DW_CFA_def_cfa_expression] = "def_cfa_expression",
+ [DW_CFA_expression] = "expression",
+ [DW_CFA_offset_extended_sf] = "offset_extended_sf",
+ [DW_CFA_def_cfa_sf] = "def_cfa_sf",
+ [DW_CFA_def_cfa_offset_sf] = "def_cfa_offset_sf",
+ [DW_CFA_val_offset] = "val_offset",
+ [DW_CFA_val_offset_sf] = "val_offset_sf",
+ [DW_CFA_val_expression] = "val_expression",
+
+ [DW_CFA_lo_user] = "lo_user",
+ [DW_CFA_MIPS_advance_loc8] = "MIPS_advance_loc8",
+ [DW_CFA_GNU_window_save] = "GNU_window_save",
+ [DW_CFA_GNU_args_size] = "GNU_args_size",
+ [DW_CFA_hi_user] = "hi_user"
+ };
+
+#define REGFMT "r%" PRIu64
+
+ while (program < program_end)
+ {
+ uint8_t opcode = *program++;
+ uint8_t ophi = opcode & 0xc0;
+ uint8_t oplo = opcode & 0x3f;
+ Dwarf_Word operand = oplo;
+
+ switch (ophi)
+ {
+ case DW_CFA_advance_loc:
+ printf ("%*s%s + %#x", indent, "", "advance_loc", oplo);
+ goto advance_loc;
+ case DW_CFA_offset:
+ printf ("%*s%s + %#x", indent, "", "offset", oplo);
+ goto offset;
+ case DW_CFA_restore:
+ printf ("%*s%s + %#x", indent, "", "restore", oplo);
+ goto restore;
+ case DW_CFA_extended:
+ break;
+ }
+
+ if (cfi_extended[oplo] != NULL)
+ printf ("%*s%s", indent, "", cfi_extended[oplo]);
+ else if (oplo >= DW_CFA_lo_user && oplo < DW_CFA_hi_user)
+ printf ("%*s%s + %#x", indent, "", "lo_user", oplo);
+ else
+ printf ("%*s??? %#x", indent, "", oplo);
+
+ Dwarf_Word offset;
+ Dwarf_Sword sf_offset;
+ Dwarf_Word regno;
+ switch (opcode)
+ {
+ case DW_CFA_advance_loc1:
+ operand = *program++;
+ advance_loc:
+ printf (gettext (": advance location %" PRIu64
+ " * code_alignment_factor\n"),
+ operand);
+ break;
+
+ case DW_CFA_advance_loc2:
+ operand = read_2ubyte_unaligned_inc (dbg, program);
+ goto advance_loc;
+ case DW_CFA_advance_loc4:
+ operand = read_4ubyte_unaligned_inc (dbg, program);
+ goto advance_loc;
+ case DW_CFA_MIPS_advance_loc8:
+ operand = read_8ubyte_unaligned_inc (dbg, program);
+ goto advance_loc;
+
+ case DW_CFA_set_loc:
+ if (cfi == NULL)
+ {
+ puts (gettext (": invalid in CIE initial instructions"));
+ program += addrsize;
+ }
+ else
+ {
+ loc = read_encoded_value (cfi, fde_encoding, &program);
+ printf (gettext (": set location to %#" PRIx64 "\n"), loc);
+ }
+ break;
+
+ case DW_CFA_def_cfa:
+ get_uleb128 (operand, program);
+ get_uleb128 (offset, program);
+ printf (gettext (": CFA is " REGFMT " + %#" PRIx64 "\n"),
+ operand, offset);
+ break;
+
+ case DW_CFA_def_cfa_register:
+ get_uleb128 (regno, program);
+ printf (gettext (": CFA is " REGFMT " + old offset\n"), regno);
+ break;
+
+ case DW_CFA_def_cfa_sf:
+ get_uleb128 (operand, program);
+ get_sleb128 (sf_offset, program);
+ printf (gettext (": CFA is " REGFMT
+ " + %" PRId64 " * data_alignment_factor\n"),
+ operand, sf_offset);
+ break;
+
+ case DW_CFA_def_cfa_offset:
+ get_uleb128 (offset, program);
+ printf (gettext (": CFA is old register + %#" PRIx64 "\n"), offset);
+ break;
+
+ case DW_CFA_def_cfa_offset_sf:
+ get_sleb128 (sf_offset, program);
+ printf (gettext (": CFA is old register"
+ " + %" PRId64 " * data_alignment_factor\n"),
+ sf_offset);
+ break;
+
+ case DW_CFA_def_cfa_expression:
+ /* DW_FORM_block is a ULEB128 length followed by that many bytes. */
+ get_uleb128 (operand, program);
+ if ((Dwarf_Word) (program_end - program) < operand)
+ {
+ printf (gettext (": invalid expression length %" PRIu64
+ " (> %tu)\n"), operand, program_end - program);
+ program = program_end;
+ }
+ else
+ {
+ size_t len = indent + printf (gettext (": CFA computed by:\n"));
+ print_ops (dbg, len, len, addrsize, operand, program);
+ program += operand;
+ }
+ break;
+
+ case DW_CFA_undefined:
+ get_uleb128 (operand, program);
+ printf (gettext (": " REGFMT " is undefined\n"), operand);
+ break;
+
+ case DW_CFA_same_value:
+ get_uleb128 (operand, program);
+ printf (gettext (": " REGFMT " has caller's value\n"), operand);
+ break;
+
+ case DW_CFA_offset_extended:
+ get_uleb128 (operand, program);
+ offset:
+ get_uleb128 (offset, program);
+ printf (gettext (": " REGFMT " at CFA"
+ " + %" PRId64 " * data_alignment_factor\n"),
+ operand, offset);
+ break;
+
+ case DW_CFA_offset_extended_sf:
+ get_uleb128 (operand, program);
+ get_sleb128 (sf_offset, program);
+ printf (gettext (": " REGFMT " saved at CFA"
+ " + %" PRId64 " * data_alignment_factor\n"),
+ operand, sf_offset);
+ break;
+
+ case DW_CFA_val_offset:
+ get_uleb128 (operand, program);
+ get_uleb128 (offset, program);
+ printf (gettext (": " REGFMT " has value CFA"
+ " + %" PRIu64 " * data_alignment_factor\n"),
+ operand, offset);
+ break;
+
+ case DW_CFA_val_offset_sf:
+ get_uleb128 (operand, program);
+ get_sleb128 (sf_offset, program);
+ printf (gettext (": " REGFMT " has value CFA"
+ " + %" PRId64 " * data_alignment_factor\n"),
+ operand, sf_offset);
+ break;
+
+ case DW_CFA_register:
+ get_uleb128 (regno, program);
+ get_uleb128 (operand, program);
+ printf (gettext (": " REGFMT " saved in " REGFMT "\n"),
+ regno, operand);
+ break;
+
+ case DW_CFA_expression:
+ get_uleb128 (regno, program);
+ /* DW_FORM_block is a ULEB128 length followed by that many bytes. */
+ get_uleb128 (operand, program);
+ if ((Dwarf_Word) (program_end - program) < operand)
+ {
+ printf (gettext (": invalid expression length %" PRIu64
+ " (> %tu)\n"), operand, program_end - program);
+ program = program_end;
+ }
+ else
+ {
+ size_t len = indent + printf (gettext (": " REGFMT
+ " saved at:\n"), regno);
+ print_ops (dbg, len, len, addrsize, operand, program);
+ program += operand;
+ }
+ break;
+
+ case DW_CFA_val_expression:
+ get_uleb128 (regno, program);
+ /* DW_FORM_block is a ULEB128 length followed by that many bytes. */
+ get_uleb128 (operand, program);
+ if ((Dwarf_Word) (program_end - program) < operand)
+ {
+ printf (gettext (": invalid expression length %" PRIu64
+ " (> %tu)\n"), operand, program_end - program);
+ program = program_end;
+ }
+ else
+ {
+ size_t len = indent + printf (gettext (": " REGFMT
+ " value is:\n"), regno);
+ print_ops (dbg, len, len, addrsize, operand, program);
+ program += operand;
+ }
+ break;
+
+ case DW_CFA_restore_extended:
+ get_uleb128 (operand, program);
+ restore:
+ printf (gettext ("restore " REGFMT " to CIE initial state\n"),
+ operand);
+ break;
+
+ case DW_CFA_GNU_args_size:
+ get_uleb128 (operand, program);
+ printf (gettext ("argument size %" PRIu64 "\n"), operand);
+ break;
+
+ case DW_CFA_GNU_window_save:
+ case DW_CFA_remember_state:
+ case DW_CFA_restore_state:
+ case DW_CFA_nop:
+ default:
+ puts ("");
+ break;
+ }
+ }
+}
static void
print_debug_frame_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
@@ -4165,8 +4432,143 @@ print_debug_frame_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
GElf_Shdr *shdr __attribute__ ((unused)),
+ const char *name,
Dwarf *dbg __attribute__ ((unused)))
{
+ Elf_Data *data = elf_rawdata (scn, NULL);
+
+ if (data == NULL)
+ {
+ error (0, 0, gettext ("cannot get %s content: %s"),
+ name, elf_errmsg (-1));
+ return;
+ }
+
+ printf (gettext ("\
+\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
+ name, (uint64_t) shdr->sh_offset);
+
+ bool eh_frame_p = !strcmp (name, ".eh_frame");
+
+ /* Dummy struct for memory-access.h macros. */
+ Dwarf dw =
+ {
+ .other_byte_order = ((BYTE_ORDER == LITTLE_ENDIAN
+ && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+ || (BYTE_ORDER == BIG_ENDIAN
+ && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
+ };
+ if (dbg == NULL)
+ dbg = &dw;
+ else
+ assert (dw.other_byte_order == dbg->other_byte_order);
+
+ unsigned int addrsize = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+
+ Dwarf_Off last_offset;
+ Dwarf_Off offset = 0;
+ uint8_t fde_encoding = DW_EH_PE_omit;
+ size_t fde_augmentation_size = 0;
+ Dwarf_Off last_cie = CIE_ID;
+ do
+ {
+ last_offset = offset;
+ Dwarf_CFI_Entry entry;
+ int result = dwarf_next_cfi (ehdr->e_ident, data, eh_frame_p,
+ offset, &offset, &entry);
+ if (result > 0)
+ /* No more entries. */
+ break;
+ if (result < 0)
+ printf ("cannot read CFI at offset %#" PRIx64 ": %s\n",
+ (uint64_t) last_offset, dwarf_errmsg (-1));
+ else if (dwarf_cfi_cie_p (&entry))
+ { /* CIE */
+ printf (gettext (" [%6" PRIx64 "] CIE, augmentation: \"%s\""
+ " (data bytes: %zu)\n"),
+ last_offset, entry.cie.augmentation,
+ entry.cie.augmentation_data_size);
+ printf (gettext (" code_alignment_factor: %" PRIu64 ", "
+ "data_alignment_factor: %" PRId64 "\n"),
+ entry.cie.code_alignment_factor,
+ entry.cie.data_alignment_factor);
+ printf (gettext (" return_address_register: %" PRIu64 "\n"),
+ entry.cie.return_address_register);
+ printf (gettext (" initial_instructions:\n"));
+ print_cfi (12, dbg, NULL, addrsize, DW_EH_PE_omit,
+ entry.cie.initial_instructions,
+ entry.cie.initial_instructions_end,
+ 0);
+ }
+ else
+ { /* FDE */
+ printf (gettext (" [%6" PRIx64 "] FDE, "
+ "CIE_pointer: [%6" PRIx64 "]\n"),
+ last_offset, entry.fde.CIE_pointer);
+
+ if (entry.fde.CIE_pointer != last_cie
+ || fde_encoding == DW_EH_PE_omit)
+ {
+ /* We have to go find the referenced CIE to be sure of the
+ encodings used in this FDE. */
+
+ Dwarf_CFI_Entry cie_entry;
+ Dwarf_Off next;
+ result = dwarf_next_cfi (ehdr->e_ident, data, eh_frame_p,
+ entry.fde.CIE_pointer,
+ &next, &cie_entry);
+ if (result != 0 || !dwarf_cfi_cie_p (&cie_entry))
+ continue;
+
+ last_cie = entry.fde.CIE_pointer;
+ fde_encoding = DW_EH_PE_absptr;
+ const char *p = cie_entry.cie.augmentation;
+ const uint8_t *dp = cie_entry.cie.augmentation_data;
+ while (*p != '\0')
+ {
+ switch (*p++)
+ {
+ case 'R':
+ fde_encoding = *dp++;
+ break;
+ case 'L': /* Skip LSDA pointer encoding byte. */
+ ++dp;
+ continue;
+ case 'P': /* Skip encoded personality routine pointer. */
+ dp += 1 + encoded_value_size (data, ehdr->e_ident,
+ *dp, dp + 1);
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+
+ fde_augmentation_size = cie_entry.cie.fde_augmentation_data_size;
+ }
+
+ Dwarf_CFI *cfi = (eh_frame_p ? dwarf_getcfi_elf (ebl->elf)
+ : dwarf_getcfi (dbg));
+ if (cfi == NULL)
+ continue;
+
+ Dwarf_Addr initial_location = read_encoded_value (cfi,
+ fde_encoding,
+ &entry.fde.start);
+ Dwarf_Addr address_range = read_encoded_value (cfi,
+ fde_encoding & 0x0f,
+ &entry.fde.start);
+ entry.fde.start += fde_augmentation_size;
+
+ printf (gettext (" initial_location: %#" PRIx64 ", "
+ "address_range: %#" PRIx64 "\n"),
+ initial_location, address_range);
+
+ printf (gettext (" instructions:\n"));
+ print_cfi (12, dbg, cfi, addrsize, fde_encoding,
+ entry.fde.start, entry.fde.end, initial_location);
+ }
+ } while (offset != last_offset);
}
@@ -4390,11 +4792,11 @@ 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)
+ GElf_Shdr *shdr, const char *name, Dwarf *dbg)
{
printf (gettext ("\
\nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
- ".debug_info", (uint64_t) shdr->sh_offset);
+ name, (uint64_t) shdr->sh_offset);
/* If the section is empty we don't have to do anything. */
if (shdr->sh_size == 0)
@@ -4437,7 +4839,7 @@ print_debug_info_section (Dwfl_Module *dwflmod,
{
error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
" in section '%s': %s"),
- (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
+ (uint64_t) offset, name, dwarf_errmsg (-1));
goto do_return;
}
@@ -4456,7 +4858,7 @@ print_debug_info_section (Dwfl_Module *dwflmod,
{
error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
" in section '%s': %s"),
- (uint64_t) offset, ".debug_info", dwarf_errmsg (-1));
+ (uint64_t) offset, name, dwarf_errmsg (-1));
goto do_return;
}
@@ -4511,11 +4913,12 @@ print_debug_info_section (Dwfl_Module *dwflmod,
static void
print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+ Elf_Scn *scn, GElf_Shdr *shdr, const char *name,
+ Dwarf *dbg)
{
printf (gettext ("\
\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_line", (uint64_t) shdr->sh_offset);
+ name, (uint64_t) shdr->sh_offset);
if (shdr->sh_size == 0)
return;
@@ -4548,7 +4951,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
{
invalid_data:
error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
- elf_ndxscn (scn), ".debug_line");
+ elf_ndxscn (scn), name);
return;
}
unit_length = read_8ubyte_unaligned_inc (dbg, linep);
@@ -4949,21 +5352,21 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
Ebl *ebl __attribute__ ((unused)),
GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn __attribute__ ((unused)),
- GElf_Shdr *shdr,
+ GElf_Shdr *shdr, const char *name,
Dwarf *dbg __attribute__ ((unused)))
{
Elf_Data *data = elf_rawdata (scn, NULL);
if (unlikely (data == NULL))
{
- error (0, 0, gettext ("cannot get .debug_loc content: %s"),
- elf_errmsg (-1));
+ error (0, 0, gettext ("cannot get %s content: %s"),
+ name, elf_errmsg (-1));
return;
}
printf (gettext ("\
\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_loc", (uint64_t) shdr->sh_offset);
+ name, (uint64_t) shdr->sh_offset);
size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
@@ -5054,11 +5457,12 @@ static void
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)
+ Elf_Scn *scn, GElf_Shdr *shdr, const char *name,
+ Dwarf *dbg)
{
printf (gettext ("\
\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_macinfo", (uint64_t) shdr->sh_offset);
+ name, (uint64_t) shdr->sh_offset);
putc_unlocked ('\n', stdout);
/* There is no function in libdw to iterate over the raw content of
@@ -5227,10 +5631,10 @@ 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)
+ GElf_Shdr *shdr, const char *name, Dwarf *dbg)
{
printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
- ".debug_pubnames", (uint64_t) shdr->sh_offset);
+ name, (uint64_t) shdr->sh_offset);
int n = 0;
(void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
@@ -5242,7 +5646,7 @@ 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)
+ GElf_Shdr *shdr, const char *name, Dwarf *dbg)
{
/* Compute floor(log16(shdr->sh_size)). */
GElf_Addr tmp = shdr->sh_size;
@@ -5256,7 +5660,7 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
printf (gettext ("\nDWARF section '%s' at offset %#" PRIx64 ":\n"
" %*s String\n"),
- ".debug_str", (uint64_t) shdr->sh_offset,
+ name, (uint64_t) shdr->sh_offset,
/* TRANS: the debugstr| prefix makes the string unique. */
digits + 2, sgettext ("debugstr|Offset"));
@@ -5281,6 +5685,12 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
static void
print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
{
+ /* Find the debug 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. */
Dwarf_Addr dwbias;
Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
@@ -5310,8 +5720,8 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
{
const char *name;
enum section_e bitmask;
- void (*fp) (Dwfl_Module *, Ebl *,
- GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
+ void (*fp) (Dwfl_Module *, Ebl *, GElf_Ehdr *,
+ Elf_Scn *, GElf_Shdr *, const char *, Dwarf *);
} debug_sections[] =
{
#define NEW_SECTION(name) \
@@ -5326,7 +5736,6 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
NEW_SECTION (str),
NEW_SECTION (macinfo),
NEW_SECTION (ranges),
- { ".eh_frame", section_frame, print_debug_frame_section }
};
const int ndebug_sections = (sizeof (debug_sections)
/ sizeof (debug_sections[0]));
@@ -5334,11 +5743,19 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
shdr->sh_name);
int n;
+ if (strcmp (name, ".eh_frame") == 0)
+ {
+ if (print_debug_sections & section_frame)
+ print_debug_frame_section (ebl, ehdr, scn, shdr, name, dbg);
+ continue;
+ }
+
for (n = 0; n < ndebug_sections; ++n)
if (strcmp (name, debug_sections[n].name) == 0)
{
if (print_debug_sections & debug_sections[n].bitmask)
- debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
+ debug_sections[n].fp (dwflmod, ebl, ehdr,
+ scn, shdr, name, dbg);
break;
}
}