From: Mark Wielaard Date: Mon, 9 Dec 2013 15:33:26 +0000 (+0100) Subject: libdw: Handle empty location expression for (indirect) DIE locations. X-Git-Tag: elfutils-0.158~45 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3951f2ec0aaca021c77a2c7a464dcf43433261c3;p=thirdparty%2Felfutils.git 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 --- diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 91e108335..79bb4b57f 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,14 @@ +2013-12-09 Mark Wielaard + + * 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 * libdw.map (ELFUTILS_0.158): Add dwfl_module_addrsym_elf and diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index ff25fc7cd..4124ae36b 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 bf1558409..cb290456b 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 322fdb8a8..f93d17ec8 100644 --- a/libdw/dwarf_getlocation_implicit_pointer.c +++ b/libdw/dwarf_getlocation_implicit_pointer.c @@ -34,6 +34,18 @@ #include +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 f02a5bf2d..35ab6e79c 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) diff --git a/tests/ChangeLog b/tests/ChangeLog index 9e4cd9afc..31638d3c4 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2013-12-09 Mark Wielaard + + * varlocs.c (print_expr): Update comment to explain empty location + associated with DW_OP_GNU_implicit_pointer. + 2013-12-05 Jan Kratochvil Fix test FAIL with -O2. diff --git a/tests/varlocs.c b/tests/varlocs.c index 6f4d4901a..04f17ff27 100644 --- a/tests/varlocs.c +++ b/tests/varlocs.c @@ -404,7 +404,7 @@ print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr) int locs = dwarf_getlocation_addr (&attrval, addr, &exprval, &exprval_len, 1); if (locs == 0) - printf (""); // XXX should that be flagged? + printf (""); // This means "optimized out". else if (locs == 1) print_expr_block (&attrval, exprval, exprval_len, addr); else