summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdw/ChangeLog6
-rw-r--r--libdw/dwarf.h2
-rw-r--r--libdw/dwarf_formudata.c1
-rw-r--r--src/ChangeLog15
-rw-r--r--src/readelf.c79
5 files changed, 96 insertions, 7 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index b86fb13f..4c3587b4 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,9 @@
+2018-03-01 Mark Wielaard <[email protected]>
+
+ * dwarf.h: Add DW_AT_GNU_locviews and DW_AT_GNU_entry_view.
+ * dwarf_formudata.c (dwarf_formudata): Handle DW_AT_GNU_locviews
+ as a loclistptr.
+
2018-02-09 Mark Wielaard <[email protected]>
* dwarf_formblock.c (dwarf_formblock): Handle DW_FORM_data16 as a
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index 4f362066..d53a30d8 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -339,6 +339,8 @@ enum
DW_AT_GNU_all_tail_call_sites = 0x2116,
DW_AT_GNU_all_call_sites = 0x2117,
DW_AT_GNU_all_source_call_sites = 0x2118,
+ DW_AT_GNU_locviews = 0x2137,
+ DW_AT_GNU_entry_view = 0x2138,
DW_AT_GNU_macros = 0x2119,
DW_AT_GNU_deleted = 0x211a,
diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c
index 9c1644ef..95872d6b 100644
--- a/libdw/dwarf_formudata.c
+++ b/libdw/dwarf_formudata.c
@@ -141,6 +141,7 @@ dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
case DW_AT_string_length:
case DW_AT_use_location:
case DW_AT_vtable_elem_location:
+ case DW_AT_GNU_locviews:
/* loclistptr */
if (__libdw_formptr (attr, IDX_debug_loc,
DWARF_E_NO_LOCLIST, NULL,
diff --git a/src/ChangeLog b/src/ChangeLog
index e73c6154..70a2d438 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
+2018-03-01 Mark Wielaard <[email protected]>
+
+ * readelf.c (struct listptr): Add attr field.
+ (compare_listptr): Warn when two listptrs for the same offset have
+ different attributes.
+ (notice_listptr): Take attr as argument and add it to listptr.
+ (skip_listptr_hole): New attr argument.
+ (next_listptr_offset): New function.
+ (print_debug_ranges_section): Pass NULL attr to skip_listptr_hole.
+ (attr_callback): Handle DW_AT_GNU_locviews. Call notice_listptr with
+ attr.
+ (print_debug_loc_section): Keep track of which attr is associated with
+ a listptr. If the attr is DW_AT_GNU_locview print view pairs till the
+ next listptr offset.
+
2018-02-09 Mark Wielaard <[email protected]>
* elflint.c (check_group): Make sure we can read a complete
diff --git a/src/readelf.c b/src/readelf.c
index 2d49af34..098209f0 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -4532,6 +4532,7 @@ struct listptr
bool dwarf64:1;
bool warned:1;
struct Dwarf_CU *cu;
+ unsigned int attr;
};
#define listptr_offset_size(p) ((p)->dwarf64 ? 8 : 4)
@@ -4592,6 +4593,15 @@ compare_listptr (const void *a, const void *b, void *arg)
gettext ("%s %#" PRIx64 " used with different base addresses"),
name, (uint64_t) p1->offset);
}
+ if (p1->attr != p2 ->attr)
+ {
+ p1->warned = p2->warned = true;
+ error (0, 0,
+ gettext ("%s %#" PRIx64
+ " used with different attribute %s and %s"),
+ name, (uint64_t) p1->offset, dwarf_attr_name (p2->attr),
+ dwarf_attr_name (p2->attr));
+ }
}
return 0;
@@ -4619,7 +4629,7 @@ reset_listptr (struct listptr_table *table)
static bool
notice_listptr (enum section_e section, struct listptr_table *table,
uint_fast8_t address_size, uint_fast8_t offset_size,
- struct Dwarf_CU *cu, Dwarf_Off offset)
+ struct Dwarf_CU *cu, Dwarf_Off offset, unsigned int attr)
{
if (print_debug_sections & section)
{
@@ -4640,7 +4650,8 @@ notice_listptr (enum section_e section, struct listptr_table *table,
.addr64 = address_size == 8,
.dwarf64 = offset_size == 8,
.offset = offset,
- .cu = cu
+ .cu = cu,
+ .attr = attr
};
if (p->offset != offset)
@@ -4664,7 +4675,8 @@ static bool
skip_listptr_hole (struct listptr_table *table, size_t *idxp,
uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
- unsigned char **readp, unsigned char *endp)
+ unsigned char **readp, unsigned char *endp,
+ unsigned int *attr)
{
if (table->n == 0)
return false;
@@ -4699,10 +4711,27 @@ skip_listptr_hole (struct listptr_table *table, size_t *idxp,
*base = listptr_base (p);
if (cu != NULL)
*cu = p->cu;
+ if (attr != NULL)
+ *attr = p->attr;
return false;
}
+static Dwarf_Off
+next_listptr_offset (struct listptr_table *table, size_t idx)
+{
+ /* Note that multiple attributes could in theory point to the same loclist
+ offset, so make sure we pick one that is bigger than the current one.
+ The table is sorted on offset. */
+ Dwarf_Off offset = table->table[idx].offset;
+ while (++idx < table->n)
+ {
+ Dwarf_Off next = table->table[idx].offset;
+ if (next > offset)
+ return next;
+ }
+ return 0;
+}
static void
print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
@@ -5042,7 +5071,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
&address_size, NULL, &base, &cu,
- offset, &readp, endp))
+ offset, &readp, endp, NULL))
continue;
if (last_cu != cu)
@@ -6121,10 +6150,11 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
case DW_AT_GNU_call_site_data_value:
case DW_AT_GNU_call_site_target:
case DW_AT_GNU_call_site_target_clobbered:
+ case DW_AT_GNU_locviews:
{
bool nlpt = notice_listptr (section_loc, &known_loclistptr,
cbargs->addrsize, cbargs->offset_size,
- cbargs->cu, num);
+ cbargs->cu, num, attr);
if (!cbargs->silent)
printf (" %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
(int) (level * 2), "", dwarf_attr_name (attr),
@@ -6137,7 +6167,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
{
bool nlpt = notice_listptr (section_ranges, &known_rangelistptr,
cbargs->addrsize, cbargs->offset_size,
- cbargs->cu, num);
+ cbargs->cu, num, attr);
if (!cbargs->silent)
printf (" %*s%-20s (%s) range list [%6" PRIxMAX "]%s\n",
(int) (level * 2), "", dwarf_attr_name (attr),
@@ -7215,10 +7245,11 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
{
ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
Dwarf_CU *cu = last_cu;
+ unsigned int attr = 0;
if (first && skip_listptr_hole (&known_loclistptr, &listptr_idx,
&address_size, &offset_size, &base,
- &cu, offset, &readp, endp))
+ &cu, offset, &readp, endp, &attr))
continue;
if (last_cu != cu)
@@ -7237,6 +7268,40 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
}
last_cu = cu;
+ if (attr == DW_AT_GNU_locviews)
+ {
+ Dwarf_Off next_off = next_listptr_offset (&known_loclistptr,
+ listptr_idx);
+ const unsigned char *locp = readp;
+ const unsigned char *locendp;
+ if (next_off == 0)
+ locendp = endp;
+ else
+ locendp = (const unsigned char *) data->d_buf + next_off;
+
+ while (locp < locendp)
+ {
+ uint64_t v1, v2;
+ get_uleb128 (v1, locp, locendp);
+ if (locp >= locendp)
+ {
+ printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);
+ break;
+ }
+ get_uleb128 (v2, locp, locendp);
+ if (first) /* First view pair in a list. */
+ printf (" [%6tx] ", offset);
+ else
+ printf (" ");
+ printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
+ first = false;
+ }
+
+ first = true;
+ readp = (unsigned char *) locendp;
+ continue;
+ }
+
if (unlikely (data->d_size - offset < (size_t) address_size * 2))
{
printf (gettext (" [%6tx] <INVALID DATA>\n"), offset);