diff options
author | Mark Wielaard <mjw@redhat.com> | 2013-12-09 16:33:26 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2013-12-13 14:23:02 +0100 |
commit | 3951f2ec0aaca021c77a2c7a464dcf43433261c3 (patch) | |
tree | ae53cf11004fbb40596d7ccde179100b52f3fa20 /libdw | |
parent | 8b10aaa3dd3db1981aee29cf8f88411707172295 (diff) | |
download | elfutils-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/ChangeLog | 11 | ||||
-rw-r--r-- | libdw/dwarf_getlocation.c | 11 | ||||
-rw-r--r-- | libdw/dwarf_getlocation_attr.c | 8 | ||||
-rw-r--r-- | libdw/dwarf_getlocation_implicit_pointer.c | 16 | ||||
-rw-r--r-- | libdw/libdwP.h | 4 |
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) |