summaryrefslogtreecommitdiff
path: root/unittests/DebugInfo/DWARF
diff options
context:
space:
mode:
authorVictor Leschuk <vleschuk@accesssoftek.com>2017-03-01 22:13:42 +0000
committerVictor Leschuk <vleschuk@accesssoftek.com>2017-03-01 22:13:42 +0000
commitea1f54828a74359b91947bafbe9c1c69756a5290 (patch)
tree47c8f23b1de1576f44d68bce1b1bcb60ddb89278 /unittests/DebugInfo/DWARF
parentabd2baf2076e22632d03746a234098b53eebc1cb (diff)
[DebugInfo] [DWARFv5] Unique abbrevs for DIEs with different implicit_const values
Take DW_FORM_implicit_const attribute value into account when profiling DIEAbbrevData. Currently if we have two similar types with implicit_const attributes and different values we end up with only one abbrev in .debug_abbrev section. For example consider two structures: S1 with implicit_const attribute ATTR and value VAL1 and S2 with implicit_const ATTR and value VAL2. The .debug_abbrev section will contain only 1 related record: [N] DW_TAG_structure_type DW_CHILDREN_yes DW_AT_ATTR DW_FORM_implicit_const VAL1 // .... This is incorrect as struct S2 (with VAL2) will use abbrev record with VAL1. With this patch we will have two different abbreviations here: [N] DW_TAG_structure_type DW_CHILDREN_yes DW_AT_ATTR DW_FORM_implicit_const VAL1 // .... [M] DW_TAG_structure_type DW_CHILDREN_yes DW_AT_ATTR DW_FORM_implicit_const VAL2 // .... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296691 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/DebugInfo/DWARF')
-rw-r--r--unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp117
1 files changed, 117 insertions, 0 deletions
diff --git a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
index dafa77bff16..90dd688d51f 100644
--- a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
+++ b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
@@ -1543,4 +1543,121 @@ TEST(DWARFDebugInfo, TestFindAttrs) {
EXPECT_EQ(DieMangled, toString(NameOpt, ""));
}
+TEST(DWARFDebugInfo, TestImplicitConstAbbrevs) {
+ uint16_t Version = 5;
+
+ const uint8_t AddrSize = sizeof(void *);
+ initLLVMIfNeeded();
+ Triple Triple = getHostTripleForAddrSize(AddrSize);
+ auto ExpectedDG = dwarfgen::Generator::create(Triple, Version);
+ if (HandleExpectedError(ExpectedDG))
+ return;
+ dwarfgen::Generator *DG = ExpectedDG.get().get();
+ dwarfgen::CompileUnit &CU = DG->addCompileUnit();
+ dwarfgen::DIE CUDie = CU.getUnitDIE();
+ const dwarf::Attribute Attr = DW_AT_lo_user;
+ const int64_t Val1 = 42;
+ const int64_t Val2 = 43;
+
+ auto FirstVal1DIE = CUDie.addChild(DW_TAG_class_type);
+ FirstVal1DIE.addAttribute(Attr, DW_FORM_implicit_const, Val1);
+
+ auto SecondVal1DIE = CUDie.addChild(DW_TAG_class_type);
+ SecondVal1DIE.addAttribute(Attr, DW_FORM_implicit_const, Val1);
+
+ auto Val2DIE = CUDie.addChild(DW_TAG_class_type);
+ Val2DIE.addAttribute(Attr, DW_FORM_implicit_const, Val2);
+
+ MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
+ auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
+ EXPECT_TRUE((bool)Obj);
+ DWARFContextInMemory DwarfContext(*Obj.get());
+ DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+ EXPECT_TRUE((bool)U);
+
+ const auto *Abbrevs = U->getAbbreviations();
+ EXPECT_TRUE((bool)Abbrevs);
+
+ // Let's find implicit_const abbrevs and verify,
+ // that there are exactly two of them and both of them
+ // can be dumped correctly.
+ typedef decltype(Abbrevs->begin()) AbbrevIt;
+ AbbrevIt Val1Abbrev = Abbrevs->end();
+ AbbrevIt Val2Abbrev = Abbrevs->end();
+ for(auto it = Abbrevs->begin(); it != Abbrevs->end(); ++it) {
+ if (it->getNumAttributes() == 0)
+ continue; // root abbrev for DW_TAG_compile_unit
+
+ auto A = it->getAttrByIndex(0);
+ EXPECT_EQ(A, Attr);
+
+ auto FormValue = it->getAttributeValue(/* offset */ 0, A, *U);
+ EXPECT_TRUE((bool)FormValue);
+ EXPECT_EQ(FormValue->getForm(), dwarf::DW_FORM_implicit_const);
+
+ const auto V = FormValue->getAsSignedConstant();
+ EXPECT_TRUE((bool)V);
+
+ auto VerifyAbbrevDump = [&V](AbbrevIt it) {
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ it->dump(OS);
+ auto FormPos = OS.str().find("DW_FORM_implicit_const");
+ EXPECT_NE(FormPos, std::string::npos);
+ auto ValPos = S.find_first_of("-0123456789", FormPos);
+ EXPECT_NE(ValPos, std::string::npos);
+ int64_t Val = std::atoll(S.substr(ValPos).c_str());
+ EXPECT_EQ(Val, *V);
+ };
+
+ switch(*V) {
+ case Val1:
+ EXPECT_EQ(Val1Abbrev, Abbrevs->end());
+ Val1Abbrev = it;
+ VerifyAbbrevDump(it);
+ break;
+ case Val2:
+ EXPECT_EQ(Val2Abbrev, Abbrevs->end());
+ Val2Abbrev = it;
+ VerifyAbbrevDump(it);
+ break;
+ default:
+ FAIL() << "Unexpected attribute value: " << *V;
+ }
+ }
+
+ // Now let's make sure that two Val1-DIEs refer to the same abbrev,
+ // and Val2-DIE refers to another one.
+ auto DieDG = U->getUnitDIE(false);
+ auto it = DieDG.begin();
+ std::multimap<int64_t, decltype(it->getAbbreviationDeclarationPtr())> DIEs;
+ const DWARFAbbreviationDeclaration *AbbrevPtrVal1 = nullptr;
+ const DWARFAbbreviationDeclaration *AbbrevPtrVal2 = nullptr;
+ for (; it != DieDG.end(); ++it) {
+ const auto *AbbrevPtr = it->getAbbreviationDeclarationPtr();
+ EXPECT_TRUE((bool)AbbrevPtr);
+ auto FormValue = it->find(Attr);
+ EXPECT_TRUE((bool)FormValue);
+ const auto V = FormValue->getAsSignedConstant();
+ EXPECT_TRUE((bool)V);
+ switch(*V) {
+ case Val1:
+ AbbrevPtrVal1 = AbbrevPtr;
+ break;
+ case Val2:
+ AbbrevPtrVal2 = AbbrevPtr;
+ break;
+ default:
+ FAIL() << "Unexpected attribute value: " << *V;
+ }
+ DIEs.insert(std::make_pair(*V, AbbrevPtr));
+ }
+ EXPECT_EQ(DIEs.count(Val1), 2u);
+ EXPECT_EQ(DIEs.count(Val2), 1u);
+ auto Val1Range = DIEs.equal_range(Val1);
+ for (auto it = Val1Range.first; it != Val1Range.second; ++it)
+ EXPECT_EQ(it->second, AbbrevPtrVal1);
+ EXPECT_EQ(DIEs.find(Val2)->second, AbbrevPtrVal2);
+}
+
} // end anonymous namespace