DWARF reading: fix getting of `DW_AT_declaration` flag
According to the DWARF standard, not all attributes of the debugging
information entry referenced by a DW_AT_specification attribute apply to the
referring debugging information entry. For example, DW_AT_declaration cannot
apply to a referring entry.
Add function `GetDirectAttribute`, which uses `dwarf_attr` instead of
`dwarf_attr_integrate`, and use it in `GetFlag` in case of getting
the `DW_AT_declaration` flag.
PiperOrigin-RevId: 500765025
Change-Id: I14737b342cb5bbcd1c313c1b1462d200df3d67ee
diff --git a/dwarf_wrappers.cc b/dwarf_wrappers.cc
index 91e0307..008d99c 100644
--- a/dwarf_wrappers.cc
+++ b/dwarf_wrappers.cc
@@ -19,6 +19,7 @@
#include "dwarf_wrappers.h"
+#include <dwarf.h>
#include <elf.h>
#include <elfutils/libdw.h>
#include <elfutils/libdwfl.h>
@@ -61,6 +62,18 @@
return result;
}
+// Get the attribute directly from DIE without following DW_AT_specification and
+// DW_AT_abstract_origin references.
+std::optional<Dwarf_Attribute> GetDirectAttribute(Dwarf_Die* die,
+ int attribute) {
+ // Create an optional with default-initialized value already inside
+ std::optional<Dwarf_Attribute> result(std::in_place);
+ if (!dwarf_attr(die, attribute, &result.value())) {
+ result.reset();
+ }
+ return result;
+}
+
void CheckOrDwflError(bool condition, const char* caller) {
if (!condition) {
int dwfl_error = dwfl_errno();
@@ -192,7 +205,9 @@
bool Entry::GetFlag(uint32_t attribute) {
bool result = false;
- auto dwarf_attribute = GetAttribute(&die, attribute);
+ auto dwarf_attribute = (attribute == DW_AT_declaration)
+ ? GetDirectAttribute(&die, attribute)
+ : GetAttribute(&die, attribute);
if (!dwarf_attribute) {
return result;
}
diff --git a/dwarf_wrappers.h b/dwarf_wrappers.h
index dfada89..7e4f86d 100644
--- a/dwarf_wrappers.h
+++ b/dwarf_wrappers.h
@@ -58,6 +58,8 @@
Dwarf_Off GetOffset();
std::optional<std::string> MaybeGetString(uint32_t attribute);
std::optional<uint64_t> MaybeGetUnsignedConstant(uint32_t attribute);
+ // If "direct" is true, get the flag directly from DIE without following
+ // DW_AT_specification and DW_AT_abstract_origin references.
bool GetFlag(uint32_t attribute);
std::optional<Entry> MaybeGetReference(uint32_t attribute);
};