10b57cec5SDimitry Andric //===-- llvm/CodeGen/DIEHash.cpp - Dwarf Hashing Framework ----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains support for DWARF4 hashing of DIEs.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "DIEHash.h"
140b57cec5SDimitry Andric #include "ByteStreamer.h"
15e8d8bef9SDimitry Andric #include "DwarfCompileUnit.h"
160b57cec5SDimitry Andric #include "DwarfDebug.h"
170b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
190b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
210b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric #define DEBUG_TYPE "dwarfdebug"
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric /// Grabs the string in whichever attribute is passed in and returns
290b57cec5SDimitry Andric /// a reference to it.
getDIEStringAttr(const DIE & Die,uint16_t Attr)300b57cec5SDimitry Andric static StringRef getDIEStringAttr(const DIE &Die, uint16_t Attr) {
310b57cec5SDimitry Andric // Iterate through all the attributes until we find the one we're
320b57cec5SDimitry Andric // looking for, if we can't find it return an empty string.
330b57cec5SDimitry Andric for (const auto &V : Die.values())
340b57cec5SDimitry Andric if (V.getAttribute() == Attr)
350b57cec5SDimitry Andric return V.getDIEString().getString();
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric return StringRef("");
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric /// Adds the string in \p Str to the hash. This also hashes
410b57cec5SDimitry Andric /// a trailing NULL with the string.
addString(StringRef Str)420b57cec5SDimitry Andric void DIEHash::addString(StringRef Str) {
430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Adding string " << Str << " to hash.\n");
440b57cec5SDimitry Andric Hash.update(Str);
45*bdd1243dSDimitry Andric Hash.update(ArrayRef((uint8_t)'\0'));
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric // FIXME: The LEB128 routines are copied and only slightly modified out of
490b57cec5SDimitry Andric // LEB128.h.
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric /// Adds the unsigned in \p Value to the hash encoded as a ULEB128.
addULEB128(uint64_t Value)520b57cec5SDimitry Andric void DIEHash::addULEB128(uint64_t Value) {
530b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
540b57cec5SDimitry Andric do {
550b57cec5SDimitry Andric uint8_t Byte = Value & 0x7f;
560b57cec5SDimitry Andric Value >>= 7;
570b57cec5SDimitry Andric if (Value != 0)
580b57cec5SDimitry Andric Byte |= 0x80; // Mark this byte to show that more bytes will follow.
590b57cec5SDimitry Andric Hash.update(Byte);
600b57cec5SDimitry Andric } while (Value != 0);
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric
addSLEB128(int64_t Value)630b57cec5SDimitry Andric void DIEHash::addSLEB128(int64_t Value) {
640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
650b57cec5SDimitry Andric bool More;
660b57cec5SDimitry Andric do {
670b57cec5SDimitry Andric uint8_t Byte = Value & 0x7f;
680b57cec5SDimitry Andric Value >>= 7;
690b57cec5SDimitry Andric More = !((((Value == 0) && ((Byte & 0x40) == 0)) ||
700b57cec5SDimitry Andric ((Value == -1) && ((Byte & 0x40) != 0))));
710b57cec5SDimitry Andric if (More)
720b57cec5SDimitry Andric Byte |= 0x80; // Mark this byte to show that more bytes will follow.
730b57cec5SDimitry Andric Hash.update(Byte);
740b57cec5SDimitry Andric } while (More);
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric /// Including \p Parent adds the context of Parent to the hash..
addParentContext(const DIE & Parent)780b57cec5SDimitry Andric void DIEHash::addParentContext(const DIE &Parent) {
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Adding parent context to hash...\n");
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric // [7.27.2] For each surrounding type or namespace beginning with the
830b57cec5SDimitry Andric // outermost such construct...
840b57cec5SDimitry Andric SmallVector<const DIE *, 1> Parents;
850b57cec5SDimitry Andric const DIE *Cur = &Parent;
860b57cec5SDimitry Andric while (Cur->getParent()) {
870b57cec5SDimitry Andric Parents.push_back(Cur);
880b57cec5SDimitry Andric Cur = Cur->getParent();
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric assert(Cur->getTag() == dwarf::DW_TAG_compile_unit ||
910b57cec5SDimitry Andric Cur->getTag() == dwarf::DW_TAG_type_unit);
920b57cec5SDimitry Andric
930b57cec5SDimitry Andric // Reverse iterate over our list to go from the outermost construct to the
940b57cec5SDimitry Andric // innermost.
95349cc55cSDimitry Andric for (const DIE *Die : llvm::reverse(Parents)) {
960b57cec5SDimitry Andric // ... Append the letter "C" to the sequence...
970b57cec5SDimitry Andric addULEB128('C');
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric // ... Followed by the DWARF tag of the construct...
100349cc55cSDimitry Andric addULEB128(Die->getTag());
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric // ... Then the name, taken from the DW_AT_name attribute.
103349cc55cSDimitry Andric StringRef Name = getDIEStringAttr(*Die, dwarf::DW_AT_name);
1040b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "... adding context: " << Name << "\n");
1050b57cec5SDimitry Andric if (!Name.empty())
1060b57cec5SDimitry Andric addString(Name);
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric // Collect all of the attributes for a particular DIE in single structure.
collectAttributes(const DIE & Die,DIEAttrs & Attrs)1110b57cec5SDimitry Andric void DIEHash::collectAttributes(const DIE &Die, DIEAttrs &Attrs) {
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric for (const auto &V : Die.values()) {
1140b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Attribute: "
1150b57cec5SDimitry Andric << dwarf::AttributeString(V.getAttribute())
1160b57cec5SDimitry Andric << " added.\n");
1170b57cec5SDimitry Andric switch (V.getAttribute()) {
1180b57cec5SDimitry Andric #define HANDLE_DIE_HASH_ATTR(NAME) \
1190b57cec5SDimitry Andric case dwarf::NAME: \
1200b57cec5SDimitry Andric Attrs.NAME = V; \
1210b57cec5SDimitry Andric break;
1220b57cec5SDimitry Andric #include "DIEHashAttributes.def"
1230b57cec5SDimitry Andric default:
1240b57cec5SDimitry Andric break;
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric
hashShallowTypeReference(dwarf::Attribute Attribute,const DIE & Entry,StringRef Name)1290b57cec5SDimitry Andric void DIEHash::hashShallowTypeReference(dwarf::Attribute Attribute,
1300b57cec5SDimitry Andric const DIE &Entry, StringRef Name) {
1310b57cec5SDimitry Andric // append the letter 'N'
1320b57cec5SDimitry Andric addULEB128('N');
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric // the DWARF attribute code (DW_AT_type or DW_AT_friend),
1350b57cec5SDimitry Andric addULEB128(Attribute);
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric // the context of the tag,
1380b57cec5SDimitry Andric if (const DIE *Parent = Entry.getParent())
1390b57cec5SDimitry Andric addParentContext(*Parent);
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric // the letter 'E',
1420b57cec5SDimitry Andric addULEB128('E');
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric // and the name of the type.
1450b57cec5SDimitry Andric addString(Name);
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric // Currently DW_TAG_friends are not used by Clang, but if they do become so,
1480b57cec5SDimitry Andric // here's the relevant spec text to implement:
1490b57cec5SDimitry Andric //
1500b57cec5SDimitry Andric // For DW_TAG_friend, if the referenced entry is the DW_TAG_subprogram,
1510b57cec5SDimitry Andric // the context is omitted and the name to be used is the ABI-specific name
1520b57cec5SDimitry Andric // of the subprogram (e.g., the mangled linker name).
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
hashRepeatedTypeReference(dwarf::Attribute Attribute,unsigned DieNumber)1550b57cec5SDimitry Andric void DIEHash::hashRepeatedTypeReference(dwarf::Attribute Attribute,
1560b57cec5SDimitry Andric unsigned DieNumber) {
1570b57cec5SDimitry Andric // a) If T is in the list of [previously hashed types], use the letter
1580b57cec5SDimitry Andric // 'R' as the marker
1590b57cec5SDimitry Andric addULEB128('R');
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric addULEB128(Attribute);
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric // and use the unsigned LEB128 encoding of [the index of T in the
1640b57cec5SDimitry Andric // list] as the attribute value;
1650b57cec5SDimitry Andric addULEB128(DieNumber);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
hashDIEEntry(dwarf::Attribute Attribute,dwarf::Tag Tag,const DIE & Entry)1680b57cec5SDimitry Andric void DIEHash::hashDIEEntry(dwarf::Attribute Attribute, dwarf::Tag Tag,
1690b57cec5SDimitry Andric const DIE &Entry) {
1700b57cec5SDimitry Andric assert(Tag != dwarf::DW_TAG_friend && "No current LLVM clients emit friend "
1710b57cec5SDimitry Andric "tags. Add support here when there's "
1720b57cec5SDimitry Andric "a use case");
1730b57cec5SDimitry Andric // Step 5
1740b57cec5SDimitry Andric // If the tag in Step 3 is one of [the below tags]
1750b57cec5SDimitry Andric if ((Tag == dwarf::DW_TAG_pointer_type ||
1760b57cec5SDimitry Andric Tag == dwarf::DW_TAG_reference_type ||
1770b57cec5SDimitry Andric Tag == dwarf::DW_TAG_rvalue_reference_type ||
1780b57cec5SDimitry Andric Tag == dwarf::DW_TAG_ptr_to_member_type) &&
1790b57cec5SDimitry Andric // and the referenced type (via the [below attributes])
1800b57cec5SDimitry Andric // FIXME: This seems overly restrictive, and causes hash mismatches
1810b57cec5SDimitry Andric // there's a decl/def difference in the containing type of a
1820b57cec5SDimitry Andric // ptr_to_member_type, but it's what DWARF says, for some reason.
1830b57cec5SDimitry Andric Attribute == dwarf::DW_AT_type) {
1840b57cec5SDimitry Andric // ... has a DW_AT_name attribute,
1850b57cec5SDimitry Andric StringRef Name = getDIEStringAttr(Entry, dwarf::DW_AT_name);
1860b57cec5SDimitry Andric if (!Name.empty()) {
1870b57cec5SDimitry Andric hashShallowTypeReference(Attribute, Entry, Name);
1880b57cec5SDimitry Andric return;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric unsigned &DieNumber = Numbering[&Entry];
1930b57cec5SDimitry Andric if (DieNumber) {
1940b57cec5SDimitry Andric hashRepeatedTypeReference(Attribute, DieNumber);
1950b57cec5SDimitry Andric return;
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric // otherwise, b) use the letter 'T' as the marker, ...
1990b57cec5SDimitry Andric addULEB128('T');
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric addULEB128(Attribute);
2020b57cec5SDimitry Andric
2030b57cec5SDimitry Andric // ... process the type T recursively by performing Steps 2 through 7, and
2040b57cec5SDimitry Andric // use the result as the attribute value.
2050b57cec5SDimitry Andric DieNumber = Numbering.size();
2060b57cec5SDimitry Andric computeHash(Entry);
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
hashRawTypeReference(const DIE & Entry)20904eeddc0SDimitry Andric void DIEHash::hashRawTypeReference(const DIE &Entry) {
21004eeddc0SDimitry Andric unsigned &DieNumber = Numbering[&Entry];
21104eeddc0SDimitry Andric if (DieNumber) {
21204eeddc0SDimitry Andric addULEB128('R');
21304eeddc0SDimitry Andric addULEB128(DieNumber);
21404eeddc0SDimitry Andric return;
21504eeddc0SDimitry Andric }
21604eeddc0SDimitry Andric DieNumber = Numbering.size();
21704eeddc0SDimitry Andric addULEB128('T');
21804eeddc0SDimitry Andric computeHash(Entry);
21904eeddc0SDimitry Andric }
22004eeddc0SDimitry Andric
2210b57cec5SDimitry Andric // Hash all of the values in a block like set of values. This assumes that
2220b57cec5SDimitry Andric // all of the data is going to be added as integers.
hashBlockData(const DIE::const_value_range & Values)2230b57cec5SDimitry Andric void DIEHash::hashBlockData(const DIE::const_value_range &Values) {
2240b57cec5SDimitry Andric for (const auto &V : Values)
225e8d8bef9SDimitry Andric if (V.getType() == DIEValue::isBaseTypeRef) {
226e8d8bef9SDimitry Andric const DIE &C =
227e8d8bef9SDimitry Andric *CU->ExprRefedBaseTypes[V.getDIEBaseTypeRef().getIndex()].Die;
228e8d8bef9SDimitry Andric StringRef Name = getDIEStringAttr(C, dwarf::DW_AT_name);
229e8d8bef9SDimitry Andric assert(!Name.empty() &&
230e8d8bef9SDimitry Andric "Base types referenced from DW_OP_convert should have a name");
231e8d8bef9SDimitry Andric hashNestedType(C, Name);
232e8d8bef9SDimitry Andric } else
2330b57cec5SDimitry Andric Hash.update((uint64_t)V.getDIEInteger().getValue());
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric // Hash the contents of a loclistptr class.
hashLocList(const DIELocList & LocList)2370b57cec5SDimitry Andric void DIEHash::hashLocList(const DIELocList &LocList) {
2380b57cec5SDimitry Andric HashingByteStreamer Streamer(*this);
2390b57cec5SDimitry Andric DwarfDebug &DD = *AP->getDwarfDebug();
2400b57cec5SDimitry Andric const DebugLocStream &Locs = DD.getDebugLocs();
2415ffd83dbSDimitry Andric const DebugLocStream::List &List = Locs.getList(LocList.getValue());
2425ffd83dbSDimitry Andric for (const DebugLocStream::Entry &Entry : Locs.getEntries(List))
2435ffd83dbSDimitry Andric DD.emitDebugLocEntry(Streamer, Entry, List.CU);
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric // Hash an individual attribute \param Attr based on the type of attribute and
2470b57cec5SDimitry Andric // the form.
hashAttribute(const DIEValue & Value,dwarf::Tag Tag)2480b57cec5SDimitry Andric void DIEHash::hashAttribute(const DIEValue &Value, dwarf::Tag Tag) {
2490b57cec5SDimitry Andric dwarf::Attribute Attribute = Value.getAttribute();
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric // Other attribute values use the letter 'A' as the marker, and the value
2520b57cec5SDimitry Andric // consists of the form code (encoded as an unsigned LEB128 value) followed by
2530b57cec5SDimitry Andric // the encoding of the value according to the form code. To ensure
2540b57cec5SDimitry Andric // reproducibility of the signature, the set of forms used in the signature
2550b57cec5SDimitry Andric // computation is limited to the following: DW_FORM_sdata, DW_FORM_flag,
2560b57cec5SDimitry Andric // DW_FORM_string, and DW_FORM_block.
2570b57cec5SDimitry Andric
2580b57cec5SDimitry Andric switch (Value.getType()) {
2590b57cec5SDimitry Andric case DIEValue::isNone:
2600b57cec5SDimitry Andric llvm_unreachable("Expected valid DIEValue");
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric // 7.27 Step 3
2630b57cec5SDimitry Andric // ... An attribute that refers to another type entry T is processed as
2640b57cec5SDimitry Andric // follows:
2650b57cec5SDimitry Andric case DIEValue::isEntry:
2660b57cec5SDimitry Andric hashDIEEntry(Attribute, Tag, Value.getDIEEntry().getEntry());
2670b57cec5SDimitry Andric break;
2680b57cec5SDimitry Andric case DIEValue::isInteger: {
2690b57cec5SDimitry Andric addULEB128('A');
2700b57cec5SDimitry Andric addULEB128(Attribute);
2710b57cec5SDimitry Andric switch (Value.getForm()) {
2720b57cec5SDimitry Andric case dwarf::DW_FORM_data1:
2730b57cec5SDimitry Andric case dwarf::DW_FORM_data2:
2740b57cec5SDimitry Andric case dwarf::DW_FORM_data4:
2750b57cec5SDimitry Andric case dwarf::DW_FORM_data8:
2760b57cec5SDimitry Andric case dwarf::DW_FORM_udata:
2770b57cec5SDimitry Andric case dwarf::DW_FORM_sdata:
2780b57cec5SDimitry Andric addULEB128(dwarf::DW_FORM_sdata);
2790b57cec5SDimitry Andric addSLEB128((int64_t)Value.getDIEInteger().getValue());
2800b57cec5SDimitry Andric break;
2810b57cec5SDimitry Andric // DW_FORM_flag_present is just flag with a value of one. We still give it a
2820b57cec5SDimitry Andric // value so just use the value.
2830b57cec5SDimitry Andric case dwarf::DW_FORM_flag_present:
2840b57cec5SDimitry Andric case dwarf::DW_FORM_flag:
2850b57cec5SDimitry Andric addULEB128(dwarf::DW_FORM_flag);
2860b57cec5SDimitry Andric addULEB128((int64_t)Value.getDIEInteger().getValue());
2870b57cec5SDimitry Andric break;
2880b57cec5SDimitry Andric default:
2890b57cec5SDimitry Andric llvm_unreachable("Unknown integer form!");
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric break;
2920b57cec5SDimitry Andric }
2930b57cec5SDimitry Andric case DIEValue::isString:
2940b57cec5SDimitry Andric addULEB128('A');
2950b57cec5SDimitry Andric addULEB128(Attribute);
2960b57cec5SDimitry Andric addULEB128(dwarf::DW_FORM_string);
2970b57cec5SDimitry Andric addString(Value.getDIEString().getString());
2980b57cec5SDimitry Andric break;
2990b57cec5SDimitry Andric case DIEValue::isInlineString:
3000b57cec5SDimitry Andric addULEB128('A');
3010b57cec5SDimitry Andric addULEB128(Attribute);
3020b57cec5SDimitry Andric addULEB128(dwarf::DW_FORM_string);
3030b57cec5SDimitry Andric addString(Value.getDIEInlineString().getString());
3040b57cec5SDimitry Andric break;
3050b57cec5SDimitry Andric case DIEValue::isBlock:
3060b57cec5SDimitry Andric case DIEValue::isLoc:
3070b57cec5SDimitry Andric case DIEValue::isLocList:
3080b57cec5SDimitry Andric addULEB128('A');
3090b57cec5SDimitry Andric addULEB128(Attribute);
3100b57cec5SDimitry Andric addULEB128(dwarf::DW_FORM_block);
3110b57cec5SDimitry Andric if (Value.getType() == DIEValue::isBlock) {
31204eeddc0SDimitry Andric addULEB128(Value.getDIEBlock().computeSize(AP->getDwarfFormParams()));
3130b57cec5SDimitry Andric hashBlockData(Value.getDIEBlock().values());
3140b57cec5SDimitry Andric } else if (Value.getType() == DIEValue::isLoc) {
31504eeddc0SDimitry Andric addULEB128(Value.getDIELoc().computeSize(AP->getDwarfFormParams()));
3160b57cec5SDimitry Andric hashBlockData(Value.getDIELoc().values());
3170b57cec5SDimitry Andric } else {
3180b57cec5SDimitry Andric // We could add the block length, but that would take
3190b57cec5SDimitry Andric // a bit of work and not add a lot of uniqueness
3200b57cec5SDimitry Andric // to the hash in some way we could test.
3210b57cec5SDimitry Andric hashLocList(Value.getDIELocList());
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric break;
3240b57cec5SDimitry Andric // FIXME: It's uncertain whether or not we should handle this at the moment.
3250b57cec5SDimitry Andric case DIEValue::isExpr:
3260b57cec5SDimitry Andric case DIEValue::isLabel:
3270b57cec5SDimitry Andric case DIEValue::isBaseTypeRef:
3280b57cec5SDimitry Andric case DIEValue::isDelta:
329fe6060f1SDimitry Andric case DIEValue::isAddrOffset:
3300b57cec5SDimitry Andric llvm_unreachable("Add support for additional value types.");
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric // Go through the attributes from \param Attrs in the order specified in 7.27.4
3350b57cec5SDimitry Andric // and hash them.
hashAttributes(const DIEAttrs & Attrs,dwarf::Tag Tag)3360b57cec5SDimitry Andric void DIEHash::hashAttributes(const DIEAttrs &Attrs, dwarf::Tag Tag) {
3370b57cec5SDimitry Andric #define HANDLE_DIE_HASH_ATTR(NAME) \
3380b57cec5SDimitry Andric { \
3390b57cec5SDimitry Andric if (Attrs.NAME) \
3400b57cec5SDimitry Andric hashAttribute(Attrs.NAME, Tag); \
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric #include "DIEHashAttributes.def"
3430b57cec5SDimitry Andric // FIXME: Add the extended attributes.
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric
3460b57cec5SDimitry Andric // Add all of the attributes for \param Die to the hash.
addAttributes(const DIE & Die)3470b57cec5SDimitry Andric void DIEHash::addAttributes(const DIE &Die) {
3480b57cec5SDimitry Andric DIEAttrs Attrs = {};
3490b57cec5SDimitry Andric collectAttributes(Die, Attrs);
3500b57cec5SDimitry Andric hashAttributes(Attrs, Die.getTag());
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric
hashNestedType(const DIE & Die,StringRef Name)3530b57cec5SDimitry Andric void DIEHash::hashNestedType(const DIE &Die, StringRef Name) {
3540b57cec5SDimitry Andric // 7.27 Step 7
3550b57cec5SDimitry Andric // ... append the letter 'S',
3560b57cec5SDimitry Andric addULEB128('S');
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric // the tag of C,
3590b57cec5SDimitry Andric addULEB128(Die.getTag());
3600b57cec5SDimitry Andric
3610b57cec5SDimitry Andric // and the name.
3620b57cec5SDimitry Andric addString(Name);
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andric // Compute the hash of a DIE. This is based on the type signature computation
3660b57cec5SDimitry Andric // given in section 7.27 of the DWARF4 standard. It is the md5 hash of a
3670b57cec5SDimitry Andric // flattened description of the DIE.
computeHash(const DIE & Die)3680b57cec5SDimitry Andric void DIEHash::computeHash(const DIE &Die) {
3690b57cec5SDimitry Andric // Append the letter 'D', followed by the DWARF tag of the DIE.
3700b57cec5SDimitry Andric addULEB128('D');
3710b57cec5SDimitry Andric addULEB128(Die.getTag());
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric // Add each of the attributes of the DIE.
3740b57cec5SDimitry Andric addAttributes(Die);
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andric // Then hash each of the children of the DIE.
377fcaf7f86SDimitry Andric for (const auto &C : Die.children()) {
3780b57cec5SDimitry Andric // 7.27 Step 7
3790b57cec5SDimitry Andric // If C is a nested type entry or a member function entry, ...
3805ffd83dbSDimitry Andric if (isType(C.getTag()) || (C.getTag() == dwarf::DW_TAG_subprogram && isType(C.getParent()->getTag()))) {
3810b57cec5SDimitry Andric StringRef Name = getDIEStringAttr(C, dwarf::DW_AT_name);
3820b57cec5SDimitry Andric // ... and has a DW_AT_name attribute
3830b57cec5SDimitry Andric if (!Name.empty()) {
3840b57cec5SDimitry Andric hashNestedType(C, Name);
3850b57cec5SDimitry Andric continue;
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric computeHash(C);
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric
3910b57cec5SDimitry Andric // Following the last (or if there are no children), append a zero byte.
392*bdd1243dSDimitry Andric Hash.update(ArrayRef((uint8_t)'\0'));
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andric /// This is based on the type signature computation given in section 7.27 of the
3960b57cec5SDimitry Andric /// DWARF4 standard. It is an md5 hash of the flattened description of the DIE
3970b57cec5SDimitry Andric /// with the inclusion of the full CU and all top level CU entities.
3980b57cec5SDimitry Andric // TODO: Initialize the type chain at 0 instead of 1 for CU signatures.
computeCUSignature(StringRef DWOName,const DIE & Die)3990b57cec5SDimitry Andric uint64_t DIEHash::computeCUSignature(StringRef DWOName, const DIE &Die) {
4000b57cec5SDimitry Andric Numbering.clear();
4010b57cec5SDimitry Andric Numbering[&Die] = 1;
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric if (!DWOName.empty())
4040b57cec5SDimitry Andric Hash.update(DWOName);
4050b57cec5SDimitry Andric // Hash the DIE.
4060b57cec5SDimitry Andric computeHash(Die);
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric // Now return the result.
4090b57cec5SDimitry Andric MD5::MD5Result Result;
4100b57cec5SDimitry Andric Hash.final(Result);
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric // ... take the least significant 8 bytes and return those. Our MD5
4130b57cec5SDimitry Andric // implementation always returns its results in little endian, so we actually
4140b57cec5SDimitry Andric // need the "high" word.
4150b57cec5SDimitry Andric return Result.high();
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric /// This is based on the type signature computation given in section 7.27 of the
4190b57cec5SDimitry Andric /// DWARF4 standard. It is an md5 hash of the flattened description of the DIE
4200b57cec5SDimitry Andric /// with the inclusion of additional forms not specifically called out in the
4210b57cec5SDimitry Andric /// standard.
computeTypeSignature(const DIE & Die)4220b57cec5SDimitry Andric uint64_t DIEHash::computeTypeSignature(const DIE &Die) {
4230b57cec5SDimitry Andric Numbering.clear();
4240b57cec5SDimitry Andric Numbering[&Die] = 1;
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric if (const DIE *Parent = Die.getParent())
4270b57cec5SDimitry Andric addParentContext(*Parent);
4280b57cec5SDimitry Andric
4290b57cec5SDimitry Andric // Hash the DIE.
4300b57cec5SDimitry Andric computeHash(Die);
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andric // Now return the result.
4330b57cec5SDimitry Andric MD5::MD5Result Result;
4340b57cec5SDimitry Andric Hash.final(Result);
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andric // ... take the least significant 8 bytes and return those. Our MD5
4370b57cec5SDimitry Andric // implementation always returns its results in little endian, so we actually
4380b57cec5SDimitry Andric // need the "high" word.
4390b57cec5SDimitry Andric return Result.high();
4400b57cec5SDimitry Andric }
441