diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -251,9 +251,6 @@ protected: const DWARFUnitHeader &getHeader() const { return Header; } - /// Size in bytes of the parsed unit header. - uint32_t getHeaderSize() const { return Header.getSize(); } - /// Find the unit's contribution to the string offsets table and determine its /// length and form. The given offset is expected to be derived from the unit /// DIE's DW_AT_str_offsets_base attribute. @@ -290,6 +287,8 @@ uint8_t getDwarfOffsetByteSize() const { return Header.getDwarfOffsetByteSize(); } + /// Size in bytes of the parsed unit header. + uint32_t getHeaderSize() const { return Header.getSize(); } uint64_t getLength() const { return Header.getLength(); } dwarf::DwarfFormat getFormat() const { return Header.getFormat(); } uint8_t getUnitType() const { return Header.getUnitType(); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -635,14 +635,14 @@ for (const DWARFAttribute &AttrValue : attributes()) dumpAttribute(OS, *this, AttrValue, Indent, DumpOpts); - DWARFDie child = getFirstChild(); - if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0 && child) { + if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 0) { + DWARFDie Child = getFirstChild(); DumpOpts.ChildRecurseDepth--; DIDumpOptions ChildDumpOpts = DumpOpts; ChildDumpOpts.ShowParents = false; - while (child) { - child.dump(OS, Indent + 2, ChildDumpOpts); - child = child.getSibling(); + while (Child) { + Child.dump(OS, Indent + 2, ChildDumpOpts); + Child = Child.getSibling(); } } } else { diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt --- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -19,6 +19,7 @@ DWARFDebugInfoTest.cpp DWARFDebugLineTest.cpp DWARFDieTest.cpp + DWARFDieManualExtractTest.cpp DWARFExpressionCompactPrinterTest.cpp DWARFFormValueTest.cpp DWARFListTableTest.cpp diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDieManualExtractTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDieManualExtractTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDieManualExtractTest.cpp @@ -0,0 +1,81 @@ +//===-llvm/unittest/DebugInfo/DWARFDieManualExtractTest.cpp---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "DwarfGenerator.h" +#include "DwarfUtils.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/ObjectYAML/DWARFEmitter.h" +#include "llvm/Testing/Support/Error.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::dwarf; +using namespace utils; + +namespace { + +TEST(DWARFDie, manualExtractDump) { + typedef uint32_t AddrType; + uint16_t Version = 4; + Triple Triple = getDefaultTargetTripleForAddrSize(sizeof(AddrType)); + if (!isObjectEmissionSupported(Triple)) + return; + + auto ExpectedDG = dwarfgen::Generator::create(Triple, Version); + ASSERT_THAT_EXPECTED(ExpectedDG, Succeeded()); + dwarfgen::Generator *DG = ExpectedDG.get().get(); + dwarfgen::CompileUnit &DGCU = DG->addCompileUnit(); + dwarfgen::DIE CUDie = DGCU.getUnitDIE(); + + CUDie.addAttribute(DW_AT_name, DW_FORM_strp, "/tmp/main.c"); + CUDie.addAttribute(DW_AT_language, DW_FORM_data2, DW_LANG_C); + + dwarfgen::DIE SubprogramDie = CUDie.addChild(DW_TAG_subprogram); + SubprogramDie.addAttribute(DW_AT_name, DW_FORM_strp, "main"); + SubprogramDie.addAttribute(DW_AT_low_pc, DW_FORM_addr, 0x1000U); + SubprogramDie.addAttribute(DW_AT_high_pc, DW_FORM_addr, 0x2000U); + + StringRef FileBytes = DG->generate(); + MemoryBufferRef FileBuffer(FileBytes, "dwarf"); + auto Obj = object::ObjectFile::createObjectFile(FileBuffer); + EXPECT_TRUE((bool)Obj); + std::unique_ptr Ctx = DWARFContext::create(**Obj); + + DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); + ASSERT_NE(nullptr, CU); + // Manually extracting DWARF DIE. + uint64_t DIEOffset = CU->getOffset() + CU->getHeaderSize(); + uint64_t NextCUOffset = CU->getNextUnitOffset(); + DWARFDebugInfoEntry DieInfo; + DWARFDataExtractor DebugInfoData = CU->getDebugInfoExtractor(); + uint32_t Depth = 0; + ASSERT_TRUE( + DieInfo.extractFast(*CU, &DIEOffset, DebugInfoData, NextCUOffset, Depth)); + DWARFDie Die(CU, &DieInfo); + ASSERT_TRUE(Die.isValid()); + ASSERT_TRUE(Die.hasChildren()); + // Since we have extracted manually DieArray is empty. + // Dump function should respect the default flags and print just current DIE, + // and not explore children. + SmallString<512> Output; + raw_svector_ostream OS(Output); + Die.dump(OS); + constexpr size_t NumOfLines = 3; + SmallVector Strings; + SmallVector ValidStrings = { + "0x0000000b: DW_TAG_compile_unit", + " DW_AT_name (\"/tmp/main.c\")", + " DW_AT_language (DW_LANG_C)"}; + StringRef(Output).split(Strings, '\n', -1, false); + ASSERT_EQ(Strings.size(), NumOfLines); + for (size_t I = 0; I < NumOfLines; ++I) + EXPECT_EQ(ValidStrings[I], Strings[I]); +} + +} // end anonymous namespace