[DWARF] Fix crash for DWARFDie::dump.

When DIE is extracted manually, the DieArray is empty. When dump is invoked on aforementioned DIE it tries to extract child, even if Dump options say otherwise. Resulting in crash.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D99698
This commit is contained in:
Alexander Yermolovich 2021-04-14 17:04:19 -07:00 committed by Rafael Auler
parent 8f9477b067
commit b7459a10da
4 changed files with 89 additions and 8 deletions

View File

@ -251,9 +251,6 @@ class DWARFUnit {
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 @@ public:
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(); }

View File

@ -635,14 +635,14 @@ void DWARFDie::dump(raw_ostream &OS, unsigned Indent,
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 {

View File

@ -19,6 +19,7 @@ add_llvm_unittest(DebugInfoDWARFTests
DWARFDebugInfoTest.cpp
DWARFDebugLineTest.cpp
DWARFDieTest.cpp
DWARFDieManualExtractTest.cpp
DWARFExpressionCompactPrinterTest.cpp
DWARFFormValueTest.cpp
DWARFListTableTest.cpp

View File

@ -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<DWARFContext> 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<StringRef, NumOfLines> Strings;
SmallVector<StringRef, NumOfLines> 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