Skip to content

Commit d29614f

Browse files
committed
Add the start of DIE hashing for DWARF4 type units and split dwarf
CUs. Currently only hashes the name of CUs and the names of any children, but it's an obvious first step to show the framework. The testcase should continue to be correct, however, as it's an empty TU. llvm-svn: 188243
1 parent 75f9aa9 commit d29614f

File tree

4 files changed

+164
-5
lines changed

4 files changed

+164
-5
lines changed

llvm/lib/CodeGen/AsmPrinter/DIEHash.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,92 @@ void DIEHash::addParentContext(DIE *Parent) {
102102
}
103103
}
104104

105+
// Collect all of the attributes for a particular DIE in single structure.
106+
void DIEHash::collectAttributes(DIE *Die, DIEAttrs Attrs) {
107+
const SmallVectorImpl<DIEValue *> &Values = Die->getValues();
108+
const DIEAbbrev &Abbrevs = Die->getAbbrev();
109+
110+
#define COLLECT_ATTR(NAME) \
111+
Attrs.NAME.Val = Values[i]; \
112+
Attrs.NAME.Desc = &Abbrevs.getData()[i];
113+
114+
for (size_t i = 0, e = Values.size(); i != e; ++i) {
115+
DEBUG(dbgs() << "Attribute: "
116+
<< dwarf::AttributeString(Abbrevs.getData()[i].getAttribute())
117+
<< " added.\n");
118+
switch (Abbrevs.getData()[i].getAttribute()) {
119+
case dwarf::DW_AT_name:
120+
COLLECT_ATTR(DW_AT_name);
121+
break;
122+
default:
123+
break;
124+
}
125+
}
126+
}
127+
128+
// Hash an individual attribute \param Attr based on the type of attribute and
129+
// the form.
130+
void DIEHash::hashAttribute(AttrEntry Attr) {
131+
const DIEValue *Value = Attr.Val;
132+
const DIEAbbrevData *Desc = Attr.Desc;
133+
134+
// TODO: Add support for types.
135+
136+
// Add the letter A to the hash.
137+
addULEB128('A');
138+
139+
// Then the attribute code and form.
140+
addULEB128(Desc->getAttribute());
141+
addULEB128(Desc->getForm());
142+
143+
// TODO: Add support for additional forms.
144+
switch (Desc->getForm()) {
145+
case dwarf::DW_FORM_strp:
146+
addString(cast<DIEString>(Value)->getString());
147+
break;
148+
}
149+
}
150+
151+
// Go through the attributes from \param Attrs in the order specified in 7.27.4
152+
// and hash them.
153+
void DIEHash::hashAttributes(DIEAttrs Attrs) {
154+
#define ADD_ATTR(ATTR) \
155+
{ \
156+
if (ATTR.Val != 0) \
157+
hashAttribute(ATTR); \
158+
}
159+
160+
// FIXME: Add the rest.
161+
ADD_ATTR(Attrs.DW_AT_name);
162+
}
163+
164+
// Add all of the attributes for \param Die to the hash.
165+
void DIEHash::addAttributes(DIE *Die) {
166+
DIEAttrs Attrs;
167+
memset(&Attrs, 0, sizeof(Attrs));
168+
collectAttributes(Die, Attrs);
169+
hashAttributes(Attrs);
170+
}
171+
172+
// Compute the hash of a DIE. This is based on the type signature computation
173+
// given in section 7.27 of the DWARF4 standard. It is the md5 hash of a
174+
// flattened description of the DIE.
175+
void DIEHash::computeHash(DIE *Die) {
176+
177+
// Append the letter 'D', followed by the DWARF tag of the DIE.
178+
addULEB128('D');
179+
addULEB128(Die->getTag());
180+
181+
// Add each of the attributes of the DIE.
182+
addAttributes(Die);
183+
184+
// Then hash each of the children of the DIE.
185+
for (std::vector<DIE *>::const_iterator I = Die->getChildren().begin(),
186+
E = Die->getChildren().end();
187+
I != E; ++I)
188+
computeHash(*I);
189+
}
190+
105191
/// This is based on the type signature computation given in section 7.27 of the
106192
/// DWARF4 standard. It is the md5 hash of a flattened description of the DIE
107193
/// with the exception that we are hashing only the context and the name of the
@@ -134,3 +220,21 @@ uint64_t DIEHash::computeDIEODRSignature(DIE *Die) {
134220
// appropriately.
135221
return *reinterpret_cast<support::ulittle64_t *>(Result + 8);
136222
}
223+
224+
/// This is based on the type signature computation given in section 7.27 of the
225+
/// DWARF4 standard. It is an md5 hash of the flattened description of the DIE
226+
/// with the inclusion of the full CU and all top level CU entities.
227+
uint64_t DIEHash::computeCUSignature(DIE *Die) {
228+
229+
// Hash the DIE.
230+
computeHash(Die);
231+
232+
// Now return the result.
233+
MD5::MD5Result Result;
234+
Hash.final(Result);
235+
236+
// ... take the least significant 8 bytes and return those. Our MD5
237+
// implementation always returns its results in little endian, swap bytes
238+
// appropriately.
239+
return *reinterpret_cast<support::ulittle64_t *>(Result + 8);
240+
}

llvm/lib/CodeGen/AsmPrinter/DIEHash.h

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,53 @@ class CompileUnit;
2020
/// \brief An object containing the capability of hashing and adding hash
2121
/// attributes onto a DIE.
2222
class DIEHash {
23+
// The entry for a particular attribute.
24+
struct AttrEntry {
25+
const DIEValue *Val;
26+
const DIEAbbrevData *Desc;
27+
};
28+
29+
// Collection of all attributes used in hashing a particular DIE.
30+
struct DIEAttrs {
31+
AttrEntry DW_AT_name;
32+
};
33+
2334
public:
2435
/// \brief Computes the ODR signature
2536
uint64_t computeDIEODRSignature(DIE *Die);
2637

38+
/// \brief Computes the CU signature
39+
uint64_t computeCUSignature(DIE *Die);
40+
2741
// Helper routines to process parts of a DIE.
28-
private:
42+
private:
2943
/// \brief Adds the parent context of \param Die to the hash.
3044
void addParentContext(DIE *Die);
31-
45+
46+
/// \brief Adds the attributes of \param Die to the hash.
47+
void addAttributes(DIE *Die);
48+
49+
/// \brief Computes the full DWARF4 7.27 hash of the DIE.
50+
void computeHash(DIE *Die);
51+
3252
// Routines that add DIEValues to the hash.
3353
private:
3454
/// \brief Encodes and adds \param Value to the hash as a ULEB128.
3555
void addULEB128(uint64_t Value);
3656

3757
/// \brief Adds \param Str to the hash and includes a NULL byte.
3858
void addString(StringRef Str);
39-
59+
60+
/// \brief Collects the attributes of DIE \param Die into the \param Attrs
61+
/// structure.
62+
void collectAttributes(DIE *Die, DIEAttrs Attrs);
63+
64+
/// \brief Hashes the attributes in \param Attrs in order.
65+
void hashAttributes(DIEAttrs Attrs);
66+
67+
/// \brief Hashes an individual attribute.
68+
void hashAttribute(AttrEntry Attr);
69+
4070
private:
4171
MD5 Hash;
4272
};

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ GenerateODRHash("generate-odr-hash", cl::Hidden,
6767
cl::desc("Add an ODR hash to external type DIEs."),
6868
cl::init(false));
6969

70+
static cl::opt<bool>
71+
GenerateCUHash("generate-cu-hash", cl::Hidden,
72+
cl::desc("Add the CU hash as the dwo_id."),
73+
cl::init(false));
74+
7075
namespace {
7176
enum DefaultOnOff {
7277
Default,
@@ -1024,14 +1029,19 @@ void DwarfDebug::finalizeModuleInfo() {
10241029
// If we're splitting the dwarf out now that we've got the entire
10251030
// CU then construct a skeleton CU based upon it.
10261031
if (useSplitDwarf()) {
1032+
uint64_t ID = 0;
1033+
if (GenerateCUHash) {
1034+
DIEHash CUHash;
1035+
ID = CUHash.computeCUSignature(TheCU->getCUDie());
1036+
}
10271037
// This should be a unique identifier when we want to build .dwp files.
10281038
TheCU->addUInt(TheCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
1029-
dwarf::DW_FORM_data8, 0);
1039+
dwarf::DW_FORM_data8, ID);
10301040
// Now construct the skeleton CU associated.
10311041
CompileUnit *SkCU = constructSkeletonCU(CUI->first);
10321042
// This should be a unique identifier when we want to build .dwp files.
10331043
SkCU->addUInt(SkCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
1034-
dwarf::DW_FORM_data8, 0);
1044+
dwarf::DW_FORM_data8, ID);
10351045
}
10361046
}
10371047

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; RUN: llc -split-dwarf=Enable -generate-cu-hash -O0 %s -mtriple=x86_64-unknown-linux-gnu -filetype=obj -o %t
2+
; RUN: llvm-dwarfdump -debug-dump=all %t | FileCheck %s
3+
4+
; The source is an empty file.
5+
6+
; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x356a7d50a77f5177)
7+
; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x356a7d50a77f5177)
8+
9+
!llvm.dbg.cu = !{!0}
10+
!llvm.module.flags = !{!3}
11+
12+
!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.4 (trunk 188230) (llvm/trunk 188234)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !2, metadata !2, metadata !2, metadata !"foo.dwo"} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/echristo/tmp/foo.c] [DW_LANG_C99]
13+
!1 = metadata !{metadata !"foo.c", metadata !"/usr/local/google/home/echristo/tmp"}
14+
!2 = metadata !{i32 0}
15+
!3 = metadata !{i32 2, metadata !"Dwarf Version", i32 3}

0 commit comments

Comments
 (0)