diff options
author | Aleksei Vetrov <vvvvvv@google.com> | 2023-12-12 22:04:40 +0000 |
---|---|---|
committer | Giuliano Procida <gprocida@google.com> | 2023-12-13 11:25:58 +0000 |
commit | 7979d57ad006d679c8ad6dcee1b9a9d31a3ff8d3 (patch) | |
tree | 888ca6b24fd50016311990d7143fd857a122a511 | |
parent | 20fb84fcd511d8f92e27444f4357334d5d55d05e (diff) | |
download | stg-7979d57ad006d679c8ad6dcee1b9a9d31a3ff8d3.tar.gz |
DWARF processor: treat empty location expression as no location
Change `GetExpression` to `MaybeGetExpression`, which returns an empty
optional if the expression is empty. Handle this the same as "attribute
is not present" in `MaybeGetExpression` callers.
According to the DWARF 5 standard:
> If no location attribute is present in a variable entry representing
> the definition of a variable (that is, with no DW_AT_declaration
> attribute), or if the location attribute is present but has an empty
> location description (as described in Section 2.6 on page 38), the
> variable is assumed to exist in the source code but not in the
> executable program.
So according to the standard, an empty DWARF location expression is
equivalent to "no location attribute is present".
PiperOrigin-RevId: 590329297
Change-Id: Ia09b078d1a4acaa93e50c3ab9f9b0985b1598043
-rw-r--r-- | dwarf_wrappers.cc | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/dwarf_wrappers.cc b/dwarf_wrappers.cc index e5780eb..d13d7b8 100644 --- a/dwarf_wrappers.cc +++ b/dwarf_wrappers.cc @@ -129,13 +129,19 @@ struct Expression { size_t length = 0; }; -Expression GetExpression(Dwarf_Attribute& attribute) { +std::optional<Expression> MaybeGetExpression(Dwarf_Attribute& attribute) { Expression result; Check(dwarf_getlocation(&attribute, &result.atoms, &result.length) == kReturnOk) << "dwarf_getlocation returned error"; - Check(result.atoms != nullptr && result.length > 0) - << "dwarf_getlocation returned empty expression"; + // If no location attribute is present or has an empty location description, + // the variable is present in the source but not in the object code. + // So zero length expression is equivalent of no location attribute. + if (result.length == 0) { + return std::nullopt; + } + Check(result.atoms != nullptr) + << "dwarf_getlocation returned non-empty expression with NULL atoms"; return result; } @@ -298,7 +304,11 @@ std::optional<Entry> Entry::MaybeGetReference(uint32_t attribute) { namespace { std::optional<Address> GetAddressFromLocation(Dwarf_Attribute& attribute) { - const auto expression = GetExpression(attribute); + const auto expression_opt = MaybeGetExpression(attribute); + if (!expression_opt) { + return {}; + } + const Expression& expression = *expression_opt; Dwarf_Attribute result_attribute; if (dwarf_getlocation_attr(&attribute, expression.atoms, &result_attribute) == @@ -360,7 +370,11 @@ std::optional<uint64_t> Entry::MaybeGetMemberByteOffset() { } // Parse location expression - const auto expression = GetExpression(attribute.value()); + const auto expression_opt = MaybeGetExpression(attribute.value()); + if (!expression_opt) { + return {}; + } + const Expression& expression = *expression_opt; // Parse virtual base classes offset, which looks like this: // [0] = DW_OP_dup @@ -394,7 +408,11 @@ std::optional<uint64_t> Entry::MaybeGetVtableOffset() { } // Parse location expression - const Expression expression = GetExpression(attribute.value()); + const auto expression_opt = MaybeGetExpression(attribute.value()); + if (!expression_opt) { + return {}; + } + const Expression& expression = *expression_opt; // We expect compilers to produce expression with one constant operand if (expression.length == 1) { |