summaryrefslogtreecommitdiff
path: root/libdw/dwarf_getlocation.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdw/dwarf_getlocation.c')
-rw-r--r--libdw/dwarf_getlocation.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index 6fb3ff3d..f2bad5a9 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -130,9 +130,8 @@ store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
sizeof (struct loc_block_s), 1);
const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
- uint64_t len = __libdw_get_uleb128 (&data, data + len_leb128 (Dwarf_Word));
- if (unlikely (len != op->number))
- return -1;
+ /* Skip the block length. */
+ __libdw_get_uleb128_unchecked (&data);
block->addr = op;
block->data = (unsigned char *) data;
block->length = op->number;
@@ -161,11 +160,14 @@ dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op,
return 0;
}
-/* DW_AT_data_member_location can be a constant as well as a loclistptr.
- Only data[48] indicate a loclistptr. */
+/* If the given attribute is DW_AT_data_member_location and it has constant
+ form then create a fake location using DW_OP_plus_uconst and the offset
+ value. On success returns zero and fills in llbuf (when not NULL) and
+ sets listlen to 1. Returns 1 when this isn't a DW_AT_data_member_location
+ offset. Returns -1 and sets dwarf_errno on failure (bad DWARF data). */
static int
-check_constant_offset (Dwarf_Attribute *attr,
- Dwarf_Op **llbuf, size_t *listlen)
+is_constant_offset (Dwarf_Attribute *attr,
+ Dwarf_Op **llbuf, size_t *listlen)
{
if (attr->code != DW_AT_data_member_location)
return 1;
@@ -665,9 +667,9 @@ dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
if (! attr_ok (attr))
return -1;
- int result = check_constant_offset (attr, llbuf, listlen);
+ int result = is_constant_offset (attr, llbuf, listlen);
if (result != 1)
- return result;
+ return result; /* Either success 0, or -1 to indicate error. */
/* If it has a block form, it's a single location expression.
Except for DW_FORM_data16, which is a 128bit constant. */
@@ -898,7 +900,8 @@ dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
}
}
- int result = check_constant_offset (attr, llbufs, listlens);
+ /* If is_constant_offset is successful, we are done with 1 result. */
+ int result = is_constant_offset (attr, llbufs, listlens);
if (result != 1)
return result ?: 1;
@@ -979,7 +982,7 @@ dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
}
}
- int result = check_constant_offset (attr, expr, exprlen);
+ int result = is_constant_offset (attr, expr, exprlen);
if (result != 1)
{
if (result == 0)
@@ -989,7 +992,7 @@ dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
*endp = -1;
return 1;
}
- return result;
+ return result; /* Something bad, dwarf_errno has been set. */
}
/* We must be looking at a true loclistptr, fetch the initial