diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -39,6 +39,12 @@ StringRef(reinterpret_cast(Data.data()), Data.size()), IsLittleEndian, AddressSize) {} + /// Truncating constructor + DWARFDataExtractor(const DWARFDataExtractor &Other, size_t Length) + : DataExtractor(Other.getData().substr(0, Length), Other.isLittleEndian(), + Other.getAddressSize()), + Obj(Other.Obj), Section(Other.Section) {} + /// Extracts the DWARF "initial length" field, which can either be a 32-bit /// value smaller than 0xfffffff0, or the value 0xffffffff followed by a /// 64-bit length. Returns the actual length, and the DWARF format which is diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDataExtractorTest.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" @@ -95,4 +97,57 @@ std::make_tuple(0x0001020304050607, dwarf::DWARF64, 12)); } +TEST(DWARFDataExtractorTest, Truncation) { + StringRef Yaml = R"( +!ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_386 +Sections: + - Name: .text + Type: SHT_PROGBITS + Size: 0x80 + - Name: .debug_line + Type: SHT_PROGBITS + Content: '616263640000000065666768' + - Name: .rel.debug_line + Type: SHT_REL + Info: .debug_line + Relocations: + - Offset: 4 + Symbol: f + Type: R_386_32 +Symbols: + - Name: f + Type: STT_SECTION + Section: .text + Value: 0x42 +)"; + SmallString<0> Storage; + std::unique_ptr Obj = + yaml::yaml2ObjectFile(Storage, Yaml, [](Twine Err) { errs() << Err; }); + ASSERT_TRUE(Obj); + std::unique_ptr Ctx = DWARFContext::create(*Obj); + const DWARFObject &DObj = Ctx->getDWARFObj(); + ASSERT_EQ(12u, DObj.getLineSection().Data.size()); + + DWARFDataExtractor Data(DObj, DObj.getLineSection(), Obj->isLittleEndian(), + Obj->getBytesInAddress()); + DataExtractor::Cursor C(0); + EXPECT_EQ(0x64636261u, Data.getRelocatedAddress(C)); + EXPECT_EQ(0x42u, Data.getRelocatedAddress(C)); + EXPECT_EQ(0x68676665u, Data.getRelocatedAddress(C)); + EXPECT_THAT_ERROR(C.takeError(), Succeeded()); + + C = DataExtractor::Cursor{0}; + DWARFDataExtractor Truncated(Data, 8); + EXPECT_EQ(0x64636261u, Truncated.getRelocatedAddress(C)); + EXPECT_EQ(0x42u, Truncated.getRelocatedAddress(C)); + EXPECT_EQ(0x0u, Truncated.getRelocatedAddress(C)); + EXPECT_THAT_ERROR(C.takeError(), + FailedWithMessage("unexpected end of data at offset 0x8")); +} + } // namespace