summaryrefslogtreecommitdiff
path: root/libdw
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2013-12-09 16:33:26 +0100
committerMark Wielaard <mjw@redhat.com>2013-12-13 14:23:02 +0100
commit3951f2ec0aaca021c77a2c7a464dcf43433261c3 (patch)
treeae53cf11004fbb40596d7ccde179100b52f3fa20 /libdw
parent8b10aaa3dd3db1981aee29cf8f88411707172295 (diff)
downloadelfutils-3951f2ec0aaca021c77a2c7a464dcf43433261c3.tar.gz
libdw: Handle empty location expression for (indirect) DIE locations.
When dwarf_getlocation_implicit_pointer and dwarf_getlocation_attr refer to a DIE that doesn't contain a DW_AT_location then don't generate an error, but return an empty location expression to signal the actual value pointed to is not available. This isn't invalid DWARF. Also make sure that __libdw_intern_expression handles empty location expressions. Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libdw')
-rw-r--r--libdw/ChangeLog11
-rw-r--r--libdw/dwarf_getlocation.c11
-rw-r--r--libdw/dwarf_getlocation_attr.c8
-rw-r--r--libdw/dwarf_getlocation_implicit_pointer.c16
-rw-r--r--libdw/libdwP.h4
5 files changed, 42 insertions, 8 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 91e10833..79bb4b57 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,14 @@
+2013-12-09 Mark Wielaard <mjw@redhat.com>
+
+ * dwarf_getlocation.c (__libdw_intern_expression): Handle empty
+ location expressions.
+ * dwarf_getlocation_attr.c (dwarf_getlocation_attr): When no
+ location found, return empty location expression.
+ * dwarf_getlocation_implicit_pointer.c
+ (dwarf_getlocation_implicit_pointer): Likewise.
+ (__libdw_empty_loc_attr): New internal function.
+ * libdwP.h (__libdw_empty_loc_attr): Define.
+
2013-11-27 Mark Wielaard <mjw@redhat.com>
* libdw.map (ELFUTILS_0.158): Add dwfl_module_addrsym_elf and
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index ff25fc7c..4124ae36 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -202,6 +202,13 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
bool cfap, bool valuep,
Dwarf_Op **llbuf, size_t *listlen, int sec_index)
{
+ /* Empty location expressions don't have any ops to intern. */
+ if (block->length == 0)
+ {
+ *listlen = 0;
+ return 0;
+ }
+
/* Check whether we already looked at this list. */
struct loc_s fake = { .addr = block->data };
struct loc_s **found = tfind (&fake, cache, loc_compare);
@@ -465,8 +472,8 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
if (unlikely (n == 0))
{
/* This is not allowed.
-
- XXX Is it? */
+ It would mean an empty location expression, which we handled
+ already as a special case above. */
goto invalid;
}
diff --git a/libdw/dwarf_getlocation_attr.c b/libdw/dwarf_getlocation_attr.c
index bf155840..cb290456 100644
--- a/libdw/dwarf_getlocation_attr.c
+++ b/libdw/dwarf_getlocation_attr.c
@@ -74,8 +74,8 @@ dwarf_getlocation_attr (attr, op, result)
return -1;
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
}
break;
@@ -88,8 +88,8 @@ dwarf_getlocation_attr (attr, op, result)
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
&& INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
}
break;
diff --git a/libdw/dwarf_getlocation_implicit_pointer.c b/libdw/dwarf_getlocation_implicit_pointer.c
index 322fdb8a..f93d17ec 100644
--- a/libdw/dwarf_getlocation_implicit_pointer.c
+++ b/libdw/dwarf_getlocation_implicit_pointer.c
@@ -34,6 +34,18 @@
#include <dwarf.h>
+static unsigned char empty_exprloc = 0;
+
+void
+internal_function
+__libdw_empty_loc_attr (Dwarf_Attribute *attr, struct Dwarf_CU *cu )
+{
+ attr->code = DW_AT_location;
+ attr->form = DW_FORM_exprloc;
+ attr->valp = &empty_exprloc;
+ attr->cu = cu;
+}
+
int
dwarf_getlocation_implicit_pointer (attr, op, result)
Dwarf_Attribute *attr;
@@ -57,8 +69,8 @@ dwarf_getlocation_implicit_pointer (attr, op, result)
if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
&& INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
{
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
+ __libdw_empty_loc_attr (result, attr->cu);
+ return 0;
}
return 0;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index f02a5bf2..35ab6e79 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -632,6 +632,10 @@ int __check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len)
internal_function;
#endif /* ENABLE_DWZ */
+/* Fills in the given attribute to point at an empty location expression. */
+void __libdw_empty_loc_attr (Dwarf_Attribute *attr, struct Dwarf_CU *cu)
+ internal_function;
+
/* Aliases to avoid PLTs. */
INTDECL (dwarf_aggregate_size)