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);
 };