diff options
author | Victor Leschuk <vleschuk@accesssoftek.com> | 2017-03-01 22:13:42 +0000 |
---|---|---|
committer | Victor Leschuk <vleschuk@accesssoftek.com> | 2017-03-01 22:13:42 +0000 |
commit | ea1f54828a74359b91947bafbe9c1c69756a5290 (patch) | |
tree | 47c8f23b1de1576f44d68bce1b1bcb60ddb89278 /unittests/DebugInfo/DWARF | |
parent | abd2baf2076e22632d03746a234098b53eebc1cb (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.cpp | 117 |
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 |