summaryrefslogtreecommitdiff
path: root/elfutils/src/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'elfutils/src/readelf.c')
-rw-r--r--elfutils/src/readelf.c422
1 files changed, 306 insertions, 116 deletions
diff --git a/elfutils/src/readelf.c b/elfutils/src/readelf.c
index 52558602..dbc84998 100644
--- a/elfutils/src/readelf.c
+++ b/elfutils/src/readelf.c
@@ -180,7 +180,8 @@ static enum section_e
section_abbrev = 1, /* .debug_abbrev */
section_aranges = 2, /* .debug_aranges */
section_frame = 4, /* .debug_frame or .eh_frame & al. */
- section_info = 8, /* .debug_info */
+ section_info = 8, /* .debug_info, .debug_types */
+ section_types = section_info,
section_line = 16, /* .debug_line */
section_loc = 32, /* .debug_loc */
section_pubnames = 64, /* .debug_pubnames */
@@ -2167,7 +2168,7 @@ get_ver_flags (unsigned int flags)
if (flags & VER_FLG_WEAK)
{
if (endp != buf)
- endp = stpcpy (endp, "| ");
+ endp = stpcpy (endp, "| ");
endp = stpcpy (endp, "WEAK ");
}
@@ -2657,7 +2658,7 @@ print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
printf (gettext ("\
Average number of tests: successful lookup: %f\n\
- unsuccessful lookup: %f\n"),
+ unsuccessful lookup: %f\n"),
(double) success / (double) nzero_counts,
(double) nzero_counts / (double) nbucket);
}
@@ -3226,6 +3227,9 @@ dwarf_tag_string (unsigned int tag)
[DW_TAG_mutable_type] = "mutable_type",
[DW_TAG_condition] = "condition",
[DW_TAG_shared_type] = "shared_type",
+ [DW_TAG_type_unit] = "type_unit",
+ [DW_TAG_rvalue_reference_type] = "rvalue_reference_type",
+ [DW_TAG_template_alias] = "template_alias",
};
const unsigned int nknown_tags = (sizeof (known_tags)
/ sizeof (known_tags[0]));
@@ -3255,6 +3259,26 @@ dwarf_tag_string (unsigned int tag)
result = "class_template";
break;
+ case DW_TAG_GNU_BINCL:
+ result = "GNU_BINCL";
+ break;
+
+ case DW_TAG_GNU_EINCL:
+ result = "GNU_EINCL";
+ break;
+
+ case DW_TAG_GNU_template_template_param:
+ result = "GNU_template_template_param";
+ break;
+
+ case DW_TAG_GNU_template_parameter_pack:
+ result = "GNU_template_parameter_pack";
+ break;
+
+ case DW_TAG_GNU_formal_parameter_pack:
+ result = "GNU_formal_parameter_pack";
+ break;
+
default:
if (tag < DW_TAG_lo_user)
snprintf (buf, sizeof buf, gettext ("unknown tag %hx"), tag);
@@ -3362,6 +3386,12 @@ dwarf_attr_string (unsigned int attrnum)
[DW_AT_elemental] = "elemental",
[DW_AT_pure] = "pure",
[DW_AT_recursive] = "recursive",
+ [DW_AT_signature] = "signature",
+ [DW_AT_main_subprogram] = "main_subprogram",
+ [DW_AT_data_bit_offset] = "data_bit_offset",
+ [DW_AT_const_expr] = "const_expr",
+ [DW_AT_enum_class] = "enum_class",
+ [DW_AT_linkage_name] = "linkage_name",
};
const unsigned int nknown_attrs = (sizeof (known_attrs)
/ sizeof (known_attrs[0]));
@@ -3515,7 +3545,11 @@ dwarf_form_string (unsigned int form)
[DW_FORM_ref4] = "ref4",
[DW_FORM_ref8] = "ref8",
[DW_FORM_ref_udata] = "ref_udata",
- [DW_FORM_indirect] = "indirect"
+ [DW_FORM_indirect] = "indirect",
+ [DW_FORM_sec_offset] = "sec_offset",
+ [DW_FORM_exprloc] = "exprloc",
+ [DW_FORM_flag_present] = "flag_present",
+ [DW_FORM_ref_sig8] = "ref_sig8"
};
const unsigned int nknown_forms = (sizeof (known_forms)
/ sizeof (known_forms[0]));
@@ -3774,7 +3808,8 @@ print_block (size_t n, const void *block)
static void
print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
- unsigned int addrsize, Dwarf_Word len, const unsigned char *data)
+ unsigned int addrsize, unsigned int offset_size,
+ Dwarf_Word len, const unsigned char *data)
{
static const char *const known[] =
{
@@ -3949,7 +3984,6 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
switch (op)
{
- case DW_OP_call_ref:
case DW_OP_addr:;
/* Address operand. */
Dwarf_Word addr;
@@ -3964,18 +3998,31 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
data += addrsize;
len -= addrsize;
- 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);
+
+ offset += 1 + addrsize;
+ break;
+
+ case DW_OP_call_ref:
+ /* Offset operand. */
+ NEED (offset_size);
+ if (offset_size == 4)
+ addr = read_4ubyte_unaligned (dbg, data);
+ else
{
- char *a = format_dwarf_addr (dwflmod, 0, addr);
- printf ("%*s[%4" PRIuMAX "] %s %s\n",
- indent, "", (uintmax_t) offset, known[op], a);
- free (a);
+ assert (offset_size == 8);
+ addr = read_8ubyte_unaligned (dbg, data);
}
- else
- printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
- indent, "", (uintmax_t) offset,
- known[op], (uintmax_t) addr);
- offset += 1 + addrsize;
+ data += offset_size;
+ len -= offset_size;
+
+ printf ("%*s[%4" PRIuMAX "] %s %#" PRIxMAX "\n",
+ indent, "", (uintmax_t) offset,
+ known[op], (uintmax_t) addr);
+ offset += 1 + offset_size;
break;
case DW_OP_deref_size:
@@ -4074,9 +4121,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_plus_uconst:
case DW_OP_constu:;
const unsigned char *start = data;
- unsigned int uleb;
+ uint64_t uleb;
get_uleb128 (uleb, data); /* XXX check overrun */
- printf ("%*s[%4" PRIuMAX "] %s %u\n",
+ printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
indent, "", (uintmax_t) offset, known[op], uleb);
len -= data - start;
offset += 1 + (data - start);
@@ -4084,10 +4131,10 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_bit_piece:
start = data;
- unsigned int uleb2;
+ uint64_t uleb2;
get_uleb128 (uleb, data); /* XXX check overrun */
get_uleb128 (uleb2, data); /* XXX check overrun */
- printf ("%*s[%4" PRIuMAX "] %s %u, %u\n",
+ printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
len -= data - start;
offset += 1 + (data - start);
@@ -4097,9 +4144,9 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_breg0 ... DW_OP_breg31:
case DW_OP_consts:
start = data;
- unsigned int sleb;
+ int64_t sleb;
get_sleb128 (sleb, data); /* XXX check overrun */
- printf ("%*s[%4" PRIuMAX "] %s %d\n",
+ printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
indent, "", (uintmax_t) offset, known[op], sleb);
len -= data - start;
offset += 1 + (data - start);
@@ -4109,7 +4156,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
start = data;
get_uleb128 (uleb, data); /* XXX check overrun */
get_sleb128 (sleb, data); /* XXX check overrun */
- printf ("%*s[%4" PRIuMAX "] %s %u %d\n",
+ printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
indent, "", (uintmax_t) offset, known[op], uleb, sleb);
len -= data - start;
offset += 1 + (data - start);
@@ -4520,7 +4567,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
// XXX overflow check
get_uleb128 (op1, readp); /* Length of DW_FORM_block. */
printf (" def_cfa_expression %" PRIu64 "\n", op1);
- print_ops (dwflmod, dbg, 10, 10, ptr_size, op1, readp);
+ print_ops (dwflmod, dbg, 10, 10, ptr_size, 0, op1, readp);
readp += op1;
break;
case DW_CFA_expression:
@@ -4529,7 +4576,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
get_uleb128 (op2, readp); /* Length of DW_FORM_block. */
printf (" expression r%" PRIu64 " (%s) \n",
op1, regname (op1));
- print_ops (dwflmod, dbg, 10, 10, ptr_size, op2, readp);
+ print_ops (dwflmod, dbg, 10, 10, ptr_size, 0, op2, readp);
readp += op2;
break;
case DW_CFA_offset_extended_sf:
@@ -4572,7 +4619,7 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
get_uleb128 (op2, readp); /* Length of DW_FORM_block. */
printf (" val_expression r%" PRIu64 " (%s)\n",
op1, regname (op1));
- print_ops (dwflmod, dbg, 10, 10, ptr_size, op2, readp);
+ print_ops (dwflmod, dbg, 10, 10, ptr_size, 0, op2, readp);
readp += op2;
break;
case DW_CFA_MIPS_advance_loc8:
@@ -4597,10 +4644,10 @@ print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
else if (opcode < DW_CFA_restore)
{
- unsigned int offset;
+ uint64_t offset;
// XXX overflow check
get_uleb128 (offset, readp);
- printf (" offset r%u (%s) at cfa%+d\n",
+ printf (" offset r%u (%s) at cfa%+" PRId64 "\n",
opcode & 0x3f, regname (opcode & 0x3f), offset * data_align);
}
else
@@ -4817,8 +4864,9 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
const char *augmentation;
unsigned int code_alignment_factor;
unsigned int data_alignment_factor;
- unsigned int fde_encoding;
- unsigned int lsda_encoding;
+ uint8_t address_size;
+ uint8_t fde_encoding;
+ uint8_t lsda_encoding;
struct cieinfo *next;
} *cies = NULL;
@@ -4888,6 +4936,16 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
if (unlikely (readp == NULL))
goto invalid_data;
++readp;
+
+ uint_fast8_t segment_size = 0;
+ if (version >= 4)
+ {
+ if (cieend - readp < 5)
+ goto invalid_data;
+ ptr_size = *readp++;
+ segment_size = *readp++;
+ }
+
// XXX Check overflow
get_uleb128 (code_alignment_factor, readp);
// XXX Check overflow
@@ -4907,12 +4965,17 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
" CIE_id: %" PRIu64 "\n"
" version: %u\n"
- " augmentation: \"%s\"\n"
- " code_alignment_factor: %u\n"
+ " augmentation: \"%s\"\n",
+ offset, (uint64_t) unit_length, (uint64_t) cie_id,
+ version, augmentation);
+ if (version >= 4)
+ printf (" address_size: %u\n"
+ " segment_size: %u\n",
+ ptr_size, segment_size);
+ printf (" code_alignment_factor: %u\n"
" data_alignment_factor: %d\n"
" return_address_register: %u\n",
- offset, (uint64_t) unit_length, (uint64_t) cie_id,
- version, augmentation, code_alignment_factor,
+ code_alignment_factor,
data_alignment_factor, return_address_register);
if (augmentation[0] == 'z')
@@ -4978,15 +5041,19 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
}
}
- struct cieinfo *newp = alloca (sizeof (*newp));
- newp->cie_offset = offset;
- newp->augmentation = augmentation;
- newp->fde_encoding = fde_encoding;
- newp->lsda_encoding = lsda_encoding;
- newp->code_alignment_factor = code_alignment_factor;
- newp->data_alignment_factor = data_alignment_factor;
- newp->next = cies;
- cies = newp;
+ if (likely (ptr_size == 4 || ptr_size == 8))
+ {
+ struct cieinfo *newp = alloca (sizeof (*newp));
+ newp->cie_offset = offset;
+ newp->augmentation = augmentation;
+ newp->fde_encoding = fde_encoding;
+ newp->lsda_encoding = lsda_encoding;
+ newp->address_size = ptr_size;
+ newp->code_alignment_factor = code_alignment_factor;
+ newp->data_alignment_factor = data_alignment_factor;
+ newp->next = cies;
+ cies = newp;
+ }
}
else
{
@@ -5007,7 +5074,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
/* Initialize from CIE data. */
fde_encoding = cie->fde_encoding;
lsda_encoding = cie->lsda_encoding;
- ptr_size = encoded_ptr_size (fde_encoding, ptr_size);
+ ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
code_alignment_factor = cie->code_alignment_factor;
data_alignment_factor = cie->data_alignment_factor;
@@ -5098,6 +5165,7 @@ struct attrcb_args
Dwarf *dbg;
int level;
unsigned int addrsize;
+ unsigned int offset_size;
Dwarf_Off cu_offset;
};
@@ -5137,8 +5205,9 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
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);
+ printf (" %*s%-20s (%s) %s\n",
+ (int) (level * 2), "", dwarf_attr_string (attr),
+ dwarf_form_string (form), a);
free (a);
}
break;
@@ -5149,8 +5218,9 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
const char *str = dwarf_formstring (attrp);
if (unlikely (str == NULL))
goto attrval_out;
- printf (" %*s%-20s \"%s\"\n",
- (int) (level * 2), "", dwarf_attr_string (attr), str);
+ printf (" %*s%-20s (%s) \"%s\"\n",
+ (int) (level * 2), "", dwarf_attr_string (attr),
+ dwarf_form_string (form), str);
break;
case DW_FORM_ref_addr:
@@ -5163,11 +5233,22 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
goto attrval_out;
- printf (" %*s%-20s [%6" PRIxMAX "]\n",
+ printf (" %*s%-20s (%s) [%6" PRIxMAX "]\n",
(int) (level * 2), "", dwarf_attr_string (attr),
- (uintmax_t) dwarf_dieoffset (&ref));
+ dwarf_form_string (form), (uintmax_t) dwarf_dieoffset (&ref));
break;
+ case DW_FORM_ref_sig8:
+ printf (" %*s%-20s (%s) {%6" PRIx64 "}\n",
+ (int) (level * 2), "", dwarf_attr_string (attr),
+ dwarf_form_string (form),
+ read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
+ break;
+
+ case DW_FORM_sec_offset:
+ attrp->form = cbargs->offset_size == 8 ? DW_FORM_data8 : DW_FORM_data4;
+ /* Fall through. */
+
case DW_FORM_udata:
case DW_FORM_sdata:
case DW_FORM_data8:
@@ -5183,11 +5264,12 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
{
/* This case can take either a constant or a loclistptr. */
case DW_AT_data_member_location:
- if (form != DW_FORM_data4 && form != DW_FORM_data8)
+ if (form != DW_FORM_data4 && form != DW_FORM_data8
+ && form != DW_FORM_sec_offset) /* XXX not data[48] if CU v4! */
{
- printf (" %*s%-20s %" PRIxMAX "\n",
+ printf (" %*s%-20s (%s) %" PRIxMAX "\n",
(int) (level * 2), "", dwarf_attr_string (attr),
- (uintmax_t) num);
+ dwarf_form_string (form), (uintmax_t) num);
return DWARF_CB_OK;
}
/* else fallthrough */
@@ -5201,15 +5283,15 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
case DW_AT_frame_base:
case DW_AT_return_addr:
case DW_AT_static_link:
- printf (" %*s%-20s location list [%6" PRIxMAX "]\n",
+ printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]\n",
(int) (level * 2), "", dwarf_attr_string (attr),
- (uintmax_t) num);
+ dwarf_form_string (form), (uintmax_t) num);
return DWARF_CB_OK;
case DW_AT_ranges:
- printf (" %*s%-20s range list [%6" PRIxMAX "]\n",
+ printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]\n",
(int) (level * 2), "", dwarf_attr_string (attr),
- (uintmax_t) num);
+ dwarf_form_string (form), (uintmax_t) num);
return DWARF_CB_OK;
case DW_AT_language:
@@ -5248,13 +5330,13 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
}
if (valuestr == NULL)
- printf (" %*s%-20s %" PRIuMAX "\n",
+ printf (" %*s%-20s (%s) %" PRIuMAX "\n",
(int) (level * 2), "", dwarf_attr_string (attr),
- (uintmax_t) num);
+ dwarf_form_string (form), (uintmax_t) num);
else
- printf (" %*s%-20s %s (%" PRIuMAX ")\n",
+ printf (" %*s%-20s (%s) %s (%" PRIuMAX ")\n",
(int) (level * 2), "", dwarf_attr_string (attr),
- valuestr, (uintmax_t) num);
+ dwarf_form_string (form), valuestr, (uintmax_t) num);
break;
case DW_FORM_flag:;
@@ -5262,11 +5344,18 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
if (unlikely (dwarf_formflag (attrp, &flag) != 0))
goto attrval_out;
- printf (" %*s%-20s %s\n",
+ printf (" %*s%-20s (%s) %s\n",
+ (int) (level * 2), "", dwarf_attr_string (attr),
+ dwarf_form_string (form), nl_langinfo (flag ? YESSTR : NOSTR));
+ break;
+
+ case DW_FORM_flag_present:
+ printf (" %*s%-20s (%s) %s\n",
(int) (level * 2), "", dwarf_attr_string (attr),
- nl_langinfo (flag ? YESSTR : NOSTR));
+ dwarf_form_string (form), nl_langinfo (YESSTR));
break;
+ case DW_FORM_exprloc:
case DW_FORM_block4:
case DW_FORM_block2:
case DW_FORM_block1:
@@ -5275,11 +5364,20 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
if (unlikely (dwarf_formblock (attrp, &block) != 0))
goto attrval_out;
- printf (" %*s%-20s ",
- (int) (level * 2), "", dwarf_attr_string (attr));
+ printf (" %*s%-20s (%s) ",
+ (int) (level * 2), "", dwarf_attr_string (attr),
+ dwarf_form_string (form));
switch (attr)
{
+ default:
+ if (form != DW_FORM_exprloc)
+ {
+ print_block (block.length, block.data);
+ break;
+ }
+ /* Fall through. */
+
case DW_AT_location:
case DW_AT_data_location:
case DW_AT_data_member_location:
@@ -5301,17 +5399,14 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
case DW_AT_upper_bound:
print_ops (cbargs->dwflmod, cbargs->dbg,
12 + level * 2, 12 + level * 2,
- cbargs->addrsize, block.length, block.data);
- break;
-
- default:
- print_block (block.length, block.data);
+ cbargs->addrsize, cbargs->offset_size,
+ block.length, block.data);
break;
}
break;
default:
- printf (" %*s%-20s [form: %d] ???\n",
+ printf (" %*s%-20s (form: %#x) ???\n",
(int) (level * 2), "", dwarf_attr_string (attr),
(int) form);
break;
@@ -5320,17 +5415,19 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
return DWARF_CB_OK;
}
-
static void
-print_debug_info_section (Dwfl_Module *dwflmod,
- Ebl *ebl __attribute__ ((unused)),
- GElf_Ehdr *ehdr __attribute__ ((unused)),
- Elf_Scn *scn,
- GElf_Shdr *shdr, Dwarf *dbg)
+print_debug_units (Dwfl_Module *dwflmod,
+ Ebl *ebl __attribute__ ((unused)),
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
+ Elf_Scn *scn,
+ GElf_Shdr *shdr, Dwarf *dbg,
+ bool debug_types)
{
+ const char *secname = debug_types ? ".debug_types" : ".debug_info";
+
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
- elf_ndxscn (scn), ".debug_info", (uint64_t) shdr->sh_offset);
+ elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
/* If the section is empty we don't have to do anything. */
if (shdr->sh_size == 0)
@@ -5343,37 +5440,55 @@ print_debug_info_section (Dwfl_Module *dwflmod,
/* New compilation unit. */
size_t cuhl;
- //Dwarf_Half version;
+ Dwarf_Half version;
Dwarf_Off abbroffset;
uint8_t addrsize;
uint8_t offsize;
Dwarf_Off nextcu;
+ uint64_t typesig;
+ Dwarf_Off typeoff;
next_cu:
- if (dwarf_nextcu (dbg, offset, &nextcu, &cuhl, &abbroffset, &addrsize,
- &offsize) != 0)
+ if (dwarf_next_unit (dbg, offset, &nextcu, &cuhl, &version,
+ &abbroffset, &addrsize, &offsize,
+ debug_types ? &typesig : NULL,
+ debug_types ? &typeoff : NULL) != 0)
goto do_return;
- printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
- " Version: %" PRIu16 ", Abbreviation section offset: %"
- PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8 "\n"),
- (uint64_t) offset, /*version*/2, abbroffset, addrsize, offsize);
+ if (debug_types)
+ printf (gettext (" Type unit at offset %" PRIu64 ":\n"
+ " Version: %" PRIu16 ", Abbreviation section offset: %"
+ PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8
+ "\n Type signature: %#" PRIx64
+ ", Type offset: %#" PRIx64 "\n"),
+ (uint64_t) offset, version, abbroffset, addrsize, offsize,
+ typesig, (uint64_t) typeoff);
+ else
+ printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
+ " Version: %" PRIu16 ", Abbreviation section offset: %"
+ PRIu64 ", Address size: %" PRIu8 ", Offset size: %" PRIu8
+ "\n"),
+ (uint64_t) offset, version, abbroffset, addrsize, offsize);
- struct attrcb_args args;
- args.dwflmod = dwflmod;
- args.dbg = dbg;
- args.addrsize = addrsize;
- args.cu_offset = offset;
+ struct attrcb_args args =
+ {
+ .dwflmod = dwflmod,
+ .dbg = dbg,
+ .addrsize = addrsize,
+ .offset_size = offsize,
+ .cu_offset = offset
+ };
offset += cuhl;
int level = 0;
- if (unlikely (dwarf_offdie (dbg, offset, &dies[level]) == NULL))
+ if (unlikely ((debug_types ? dwarf_offdie_types : dwarf_offdie)
+ (dbg, offset, &dies[level]) == NULL))
{
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, secname, dwarf_errmsg (-1));
goto do_return;
}
@@ -5392,7 +5507,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, secname, dwarf_errmsg (-1));
goto do_return;
}
@@ -5443,6 +5558,20 @@ print_debug_info_section (Dwfl_Module *dwflmod,
free (dies);
}
+static void
+print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+ Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+ print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
+}
+
+static void
+print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+ Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+ print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
+}
+
static void
print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
@@ -5511,7 +5640,10 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
/* Next the minimum instruction length. */
uint_fast8_t minimum_instr_len = *linep++;
- /* Then the flag determining the default value of the is_stmt
+ /* Next the maximum operations per instruction, in version 4 format. */
+ uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++;
+
+ /* Then the flag determining the default value of the is_stmt
register. */
uint_fast8_t default_is_stmt = *linep++;
@@ -5531,6 +5663,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
" DWARF version: %" PRIuFAST16 "\n"
" Prologue length: %" PRIu64 "\n"
" Minimum instruction length: %" PRIuFAST8 "\n"
+ " Maximum operations per instruction: %" PRIuFAST8 "\n"
" Initial value if '%s': %" PRIuFAST8 "\n"
" Line base: %" PRIdFAST8 "\n"
" Line range: %" PRIuFAST8 "\n"
@@ -5538,7 +5671,8 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
"\n"
"Opcodes:\n"),
(uint64_t) unit_length, version, (uint64_t) header_length,
- minimum_instr_len, "is_stmt", default_is_stmt, line_base,
+ minimum_instr_len, max_ops_per_instr,
+ "is_stmt", default_is_stmt, line_base,
line_range, opcode_base);
if (unlikely (linep + opcode_base - 1 >= lineendp))
@@ -5615,6 +5749,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
puts (gettext ("\nLine number statements:"));
Dwarf_Word address = 0;
+ unsigned int op_index = 0;
size_t line = 1;
uint_fast8_t is_stmt = default_is_stmt;
@@ -5646,6 +5781,20 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
}
}
+ /* Apply the "operation advance" from a special opcode
+ or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */
+ unsigned int op_addr_advance;
+ bool show_op_index;
+ inline void advance_pc (unsigned int op_advance)
+ {
+ op_addr_advance = minimum_instr_len * ((op_index + op_advance)
+ / max_ops_per_instr);
+ address += op_advance;
+ show_op_index = (op_index > 0 ||
+ (op_index + op_advance) % max_ops_per_instr > 0);
+ op_index = (op_index + op_advance) % max_ops_per_instr;
+ }
+
while (linep < lineendp)
{
unsigned int u128;
@@ -5661,22 +5810,25 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
is computed with
opcode = (desired line increment - line_base)
- + (line_range * address advance) + opcode_base
+ + (line_range * address advance) + opcode_base
*/
int line_increment = (line_base
+ (opcode - opcode_base) % line_range);
- unsigned int address_increment = (minimum_instr_len
- * ((opcode - opcode_base)
- / line_range));
/* Perform the increments. */
line += line_increment;
- address += address_increment;
+ advance_pc ((opcode - opcode_base) / line_range);
char *a = format_dwarf_addr (dwflmod, 0, address);
- printf (gettext ("\
+ if (show_op_index)
+ printf (gettext ("\
+ special opcode %u: address+%u = %s, op_index = %u, line%+d = %zu\n"),
+ opcode, op_addr_advance, a, op_index,
+ line_increment, line);
+ else
+ printf (gettext ("\
special opcode %u: address+%u = %s, line%+d = %zu\n"),
- opcode, address_increment, a, line_increment, line);
+ opcode, op_addr_advance, a, line_increment, line);
free (a);
}
else if (opcode == 0)
@@ -5703,11 +5855,13 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
/* Reset the registers we care about. */
address = 0;
+ op_index = 0;
line = 1;
is_stmt = default_is_stmt;
break;
case DW_LNE_set_address:
+ op_index = 0;
if (address_size == 4)
address = read_4ubyte_unaligned_inc (dbg, linep);
else
@@ -5742,6 +5896,15 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
}
break;
+ case DW_LNE_set_discriminator:
+ /* Takes one ULEB128 parameter, the discriminator. */
+ if (unlikely (standard_opcode_lengths[opcode] != 1))
+ goto invalid_unit;
+
+ get_uleb128 (u128, linep);
+ printf (gettext (" set discriminator to %u\n"), u128);
+ break;
+
default:
/* Unknown, ignore it. */
puts (gettext ("unknown opcode"));
@@ -5749,7 +5912,7 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
break;
}
}
- else if (opcode <= DW_LNS_set_epilogue_begin)
+ else if (opcode <= DW_LNS_set_isa)
{
/* This is a known standard opcode. */
switch (opcode)
@@ -5763,11 +5926,16 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
/* Takes one uleb128 parameter which is added to the
address. */
get_uleb128 (u128, linep);
- address += minimum_instr_len * u128;
+ advance_pc (u128);
{
char *a = format_dwarf_addr (dwflmod, 0, address);
- printf (gettext ("advance address by %u to %s\n"),
- u128, a);
+ if (show_op_index)
+ printf (gettext ("\
+advance address by %u to %s, op_index to %u\n"),
+ op_addr_advance, a, op_index);
+ else
+ printf (gettext ("advance address by %u to %s\n"),
+ op_addr_advance, a);
free (a);
}
break;
@@ -5813,13 +5981,17 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
case DW_LNS_const_add_pc:
/* Takes no argument. */
- u128 = (minimum_instr_len
- * ((255 - opcode_base) / line_range));
- address += u128;
+ advance_pc ((255 - opcode_base) / line_range);
{
char *a = format_dwarf_addr (dwflmod, 0, address);
- printf (gettext ("advance address by constant %u to %s\n"),
- u128, a);
+ if (show_op_index)
+ printf (gettext ("\
+advance address by constant %u to %s, op_index to %u\n"),
+ op_addr_advance, a, op_index);
+ else
+ printf (gettext ("\
+advance address by constant %u to %s\n"),
+ op_addr_advance, a);
free (a);
}
break;
@@ -5832,6 +6004,7 @@ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
u128 = read_2ubyte_unaligned_inc (dbg, linep);
address += u128;
+ op_index = 0;
{
char *a = format_dwarf_addr (dwflmod, 0, address);
printf (gettext ("\
@@ -5850,6 +6023,15 @@ advance address by fixed value %u to %s\n"),
/* Takes no argument. */
puts (gettext (" set epilogue begin flag"));
break;
+
+ case DW_LNS_set_isa:
+ /* Takes one uleb128 parameter which is stored in isa. */
+ if (unlikely (standard_opcode_lengths[opcode] != 1))
+ goto invalid_unit;
+
+ get_uleb128 (u128, linep);
+ printf (gettext (" set isa to %u\n"), u128);
+ break;
}
}
else
@@ -5900,6 +6082,10 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
size_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+ /* XXX This is wrong! We can only know the right size given the CU that
+ points to this location list. */
+ size_t offset_size = 4;
+
bool first = true;
unsigned char *readp = data->d_buf;
while (readp < (unsigned char *) data->d_buf + data->d_size)
@@ -5952,7 +6138,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
free (e);
print_ops (dwflmod, dbg, 1, 18 + (address_size * 4),
- address_size, len, readp);
+ address_size, offset_size, len, readp);
first = false;
readp += len;
@@ -6069,9 +6255,9 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
case DW_MACINFO_undef:
case DW_MACINFO_vendor_ext:
/* For the first two opcodes the parameters are
- line, string
+ line, string
For the latter
- number, string.
+ number, string.
We can treat these cases together. */
get_uleb128 (u128, readp);
@@ -6478,12 +6664,15 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
/* Before we start the real work get a debug context descriptor. */
Dwarf_Addr dwbias;
Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
+ Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA] };
if (dbg == NULL)
{
- if (print_debug_sections != 0)
+ if ((print_debug_sections & ~section_exception) != 0)
error (0, 0, gettext ("cannot get debug context descriptor: %s"),
dwfl_errmsg (-1));
- return;
+ if ((print_debug_sections & section_exception) == 0)
+ return;
+ dbg = &dummy_dbg;
}
/* Get the section header string table index. */
@@ -6515,6 +6704,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
NEW_SECTION (aranges),
NEW_SECTION (frame),
NEW_SECTION (info),
+ NEW_SECTION (types),
NEW_SECTION (line),
NEW_SECTION (loc),
NEW_SECTION (pubnames),