<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 16, 2015 at 4:16 PM, Frederic Riss <span dir="ltr"><<a href="mailto:friss@apple.com" target="_blank">friss@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi samsonov, dblaikie,<br>
<br>
The DIE representation of libDebugInfo is designed to be minimal<br>
(as the class name implies). The information that's there allows<br>
to walk the DIE tree down, but you can't get back to the root<br>
from an arbitrary node.<br>
<br>
This patch adds this ability with the goal of using it in<br>
llvm-dsymutil. I could also use this information in dwarfdump<br>
itself to easily support dumping the full DIE hierarchy of a<br>
selected DIE when I finally implement a search option.<br>
<br>
The added information definitely has a cost: the size of<br>
the structure is increased by 8 bytes on 64 bits archs<br>
due to padding and this combined to the added logic makes<br>
the raw parsing between 5 and 10% slower.<br>
<br>
Just for llvm-dsymutil, this is optional. I can gather the<br>
parent chains in a separate path and store them, but I think<br>
that the performance/aded functionality benefit is worth<br>
it. WDYT?<br></blockquote><div><br>I doubt the performance of dwarfdump is terribly important - but I would imagine the performance of dsymutil will be/is, so it might be worth looking at the alternatives that don't increase the memory cost of all DIEs?<br><br>(I imagine a search query that responds with a path, rather than a node, would be a reasonable API, for example - but I dunno)<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
<a href="http://reviews.llvm.org/D7025" target="_blank">http://reviews.llvm.org/D7025</a><br>
<br>
Files:<br>
  include/llvm/DebugInfo/DWARFDebugInfoEntry.h<br>
  lib/DebugInfo/DWARFUnit.cpp<br>
<br>
Index: include/llvm/DebugInfo/DWARFDebugInfoEntry.h<br>
===================================================================<br>
--- include/llvm/DebugInfo/DWARFDebugInfoEntry.h<br>
+++ include/llvm/DebugInfo/DWARFDebugInfoEntry.h<br>
@@ -30,13 +30,16 @@<br>
   /// Offset within the .debug_info of the start of this entry.<br>
   uint32_t Offset;<br>
<br>
+  /// How many to substract to "this" to get the parent.<br>
+  uint32_t ParentIdx;<br>
+<br>
   /// How many to add to "this" to get the sibling.<br>
   uint32_t SiblingIdx;<br>
<br>
   const DWARFAbbreviationDeclaration *AbbrevDecl;<br>
 public:<br>
   DWARFDebugInfoEntryMinimal()<br>
-    : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {}<br>
+    : Offset(0), ParentIdx(0), SiblingIdx(0), AbbrevDecl(nullptr) {}<br>
<br>
   void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth,<br>
             unsigned indent = 0) const;<br>
@@ -66,6 +69,11 @@<br>
     return SiblingIdx > 0 ? this + SiblingIdx : nullptr;<br>
   }<br>
<br>
+  // Returns the parent DIE or null if this is the root DIE.<br>
+  const DWARFDebugInfoEntryMinimal *getParent() const {<br>
+    return ParentIdx ? this - ParentIdx : nullptr;<br>
+  }<br>
+<br>
   // We know we are kept in a vector of contiguous entries, so we know<br>
   // we don't need to store our child pointer, if we have a child it will<br>
   // be the next entry in the list...<br>
@@ -82,6 +90,15 @@<br>
       SiblingIdx = 0;<br>
   }<br>
<br>
+  void setParent(const DWARFDebugInfoEntryMinimal *Parent) {<br>
+    if (Parent) {<br>
+      // We know we are kept in a vector of contiguous entries, so we know<br>
+      // our parent will be soewhere before "this".<br>
+      ParentIdx = this - Parent;<br>
+    } else<br>
+      ParentIdx = 0;<br>
+  }<br>
+<br>
   const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {<br>
     return AbbrevDecl;<br>
   }<br>
Index: lib/DebugInfo/DWARFUnit.cpp<br>
===================================================================<br>
--- lib/DebugInfo/DWARFUnit.cpp<br>
+++ lib/DebugInfo/DWARFUnit.cpp<br>
@@ -143,12 +143,18 @@<br>
   if (DieArray.size() <= 1)<br>
     return;<br>
<br>
-  std::vector<DWARFDebugInfoEntryMinimal *> ParentChain;<br>
+  // Make sure the vector is never empty so that we don't have to<br>
+  // check for emptyness inside the loop bellow.<br>
+  std::vector<DWARFDebugInfoEntryMinimal *> ParentChain(1,&DieArray[0]);<br>
   DWARFDebugInfoEntryMinimal *SiblingChain = nullptr;<br>
   for (auto &DIE : DieArray) {<br>
     if (SiblingChain) {<br>
       SiblingChain->setSibling(&DIE);<br>
     }<br>
+    // Note that this will call setParent with itself on the root<br>
+    // node. This will result in a null offset which is handled as 'no<br>
+    // parent'.<br>
+    DIE.setParent(ParentChain.back());<br>
     if (const DWARFAbbreviationDeclaration *AbbrDecl =<br>
             DIE.getAbbreviationDeclarationPtr()) {<br>
       // Normal DIE.<br>
@@ -165,7 +171,7 @@<br>
     }<br>
   }<br>
   assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]);<br>
-  assert(ParentChain.empty());<br>
+  assert(ParentChain.size() == 1 && ParentChain[0] == &DieArray[0]);<br>
 }<br>
<br>
 void DWARFUnit::extractDIEsToVector(<br>
<br>
EMAIL PREFERENCES<br>
  <a href="http://reviews.llvm.org/settings/panel/emailpreferences/" target="_blank">http://reviews.llvm.org/settings/panel/emailpreferences/</a><br>
</blockquote></div><br></div></div>