diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp --- a/lldb/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFUnitTest.cpp @@ -84,3 +84,75 @@ EXPECT_EQ(die_first->GetFirstChild(), nullptr); EXPECT_EQ(die_first->GetSibling(), nullptr); } + +TEST(DWARFUnitTest, Elf64RnglistsAddressSize64) { + // Test parsing .debug_rnglists with address size matching its ELF size. + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x401020 +Sections: + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '09000000050001080000000001' + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '011100000000' + - Name: .debug_rnglists + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 1A0000000500080000000000060706050403020100878685848382818000 +)"; + + YAMLModuleTester t(yamldata); + ASSERT_TRUE((bool)t.GetDwarfUnit()); + + DWARFUnit *unit = t.GetDwarfUnit(); + llvm::Expected Rnglist = unit->FindRnglistFromOffset(12); + ASSERT_TRUE(!!Rnglist); + ASSERT_EQ(Rnglist->GetSize(), 1U); + ASSERT_EQ(Rnglist->GetEntryRef(0).base, 0x0001020304050607U); + ASSERT_EQ(Rnglist->GetEntryRef(0).size, 0x8080808080808080U); +} + +TEST(DWARFUnitTest, Elf64RnglistsAddressSize32) { + // Test parsing .debug_rnglists with address size different than its ELF size. + const char *yamldata = R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x401020 +Sections: + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '09000000050001040000000001' + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: '011100000000' + - Name: .debug_rnglists + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 12000000050004000000000006030201008382818000 +)"; + + YAMLModuleTester t(yamldata); + ASSERT_TRUE((bool)t.GetDwarfUnit()); + + DWARFUnit *unit = t.GetDwarfUnit(); + llvm::Expected Rnglist = unit->FindRnglistFromOffset(12); + ASSERT_TRUE(!!Rnglist); + ASSERT_EQ(Rnglist->GetSize(), 1U); + ASSERT_EQ(Rnglist->GetEntryRef(0).base, 0x00010203U); + ASSERT_EQ(Rnglist->GetEntryRef(0).size, 0x80808080U); +} diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -170,7 +170,8 @@ /// Extract an entire table, including all list entries. Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr); /// Look up a list based on a given offset. Extract it and enter it into the - /// list map if necessary. + /// list map if necessary. \a Data setAddressSize needs to be set iff + /// neither extractHeaderAndOffsets nor extract were called. Expected findList(DWARFDataExtractor Data, uint64_t Offset) const; @@ -281,8 +282,10 @@ uint64_t Offset) const { // Extract the list from the section and enter it into the list map. DWARFListType List; - if (Header.length()) + if (Header.length()) { Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length()); + Data.setAddressSize(Header.getAddrSize()); + } if (Error E = List.extract(Data, Header.length() ? getHeaderOffset() : 0, &Offset, Header.getSectionName(), Header.getListTypeString())) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -70,7 +70,6 @@ "%s table at offset 0x%" PRIx64 " has more offset entries (%" PRIu32 ") than there is space for", SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount); - Data.setAddressSize(HeaderData.AddrSize); *OffsetPtr += HeaderData.OffsetEntryCount * OffsetByteSize; return Error::success(); } diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -2103,4 +2103,74 @@ }); } +TEST(DWARFDebugInfo, TestRnglistsAddressSize) { + static const char DebugInfoSecRaw[] = + "\x09\x00\x00\x00" // Length + "\x05\x00" // Version + "\x01" // DW_UT_compile + "\x08" // Address size + "\x00\x00\x00\x00" // Offset Into Abbrev. Sec. + "\x01"; // Abbreviation 1 + static const char DebugAbbrevSecRaw[] = "\x01" // Abbreviation Code + "\x11" // DW_TAG_compile_unit + "\x00" // DW_CHILDREN_no + "\x00\x00" // End of Abbreviation 1 + "\x00"; // End of Abbreviations + static const char DebugRnglistsSecRaw[] = + "\x1A\x00\x00\x00" // Length + "\x05\x00" // Version + "\x08" // Address Size + "\x00" // Segment Selector Size + "\x00\x00\x00\x00" // Offset Entry Count + "\x06" // DW_RLE_start_end + "\x07\x06\x05\x04\x03\x02\x01\x00" // Start Address + "\x87\x86\x85\x84\x83\x82\x81\x80" // End Address + "\x00"; // DW_RLE_end_of_list + + StringMap> Sections; + Sections.insert(std::make_pair( + "debug_info", MemoryBuffer::getMemBuffer(StringRef( + DebugInfoSecRaw, sizeof(DebugInfoSecRaw) - 1)))); + Sections.insert(std::make_pair( + "debug_abbrev", MemoryBuffer::getMemBuffer(StringRef( + DebugAbbrevSecRaw, sizeof(DebugAbbrevSecRaw) - 1)))); + Sections.insert(std::make_pair( + "debug_rnglists", + MemoryBuffer::getMemBuffer( + StringRef(DebugRnglistsSecRaw, sizeof(DebugRnglistsSecRaw) - 1)))); + auto Context = DWARFContext::create(Sections, /* AddrSize = */ 8, + /* isLittleEndian = */ true); + const auto &Obj = Context->getDWARFObj(); + Obj.forEachInfoSections([&](const DWARFSection &Sec) { + DWARFUnitHeader Header; + DWARFDataExtractor Data(Obj, Sec, /* IsLittleEndian = */ true, + /* AddressSize = */ 4); + uint64_t Offset = 0; + EXPECT_TRUE(Header.extract(*Context, Data, &Offset, DW_SECT_INFO)); + ASSERT_EQ(8, Header.getAddressByteSize()); + + // Check that the length can be correctly read in the unit class. + DWARFUnitVector DummyUnitVector; + DWARFSection DummySec; + DWARFDataExtractor AbbrevData(Obj.getAbbrevSection(), + /* IsLittleEndian = */ true, + /* AddressSize = */ 4); + DWARFDebugAbbrev Abbrev; + Abbrev.extract(AbbrevData); + Abbrev.parse(); + DWARFCompileUnit CU(*Context, Sec, Header, /* DA = */ &Abbrev, + /* RS = */ &Obj.getRnglistsSection(), + /* LocSection = */ 0, /* SS = */ StringRef(), + /* SOS = */ DummySec, /* AOS = */ 0, + /* LS = */ DummySec, /* LE = */ true, + /* isDWO= */ false, DummyUnitVector); + llvm::Expected Rnglist = + CU.findRnglistFromOffset(12); + ASSERT_TRUE(!!Rnglist); + ASSERT_EQ(Rnglist->size(), 1U); + ASSERT_EQ(Rnglist->at(0).LowPC, 0x0001020304050607U); + ASSERT_EQ(Rnglist->at(0).HighPC, 0x8081828384858687U); + }); +} + } // end anonymous namespace diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFListTableTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFListTableTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFListTableTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFListTableTest.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFListTable.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" @@ -99,4 +100,136 @@ EXPECT_EQ(Header.length(), sizeof(SecData) - 1); } +TEST(DWARFListTableHeader, AddressSize64Header) { + static const char SecData[] = "\x1a\x00\x00\x00" // Length + "\x05\x00" // Version + "\x08" // Address size + "\x00" // Segment selector size + "\x00\x00\x00\x00" // Offset entry count + "\x06" // DW_RLE_start_end + "\x07\x06\x05\x04" // 64-bit starting address + "\x03\x02\x01\x00" // 64-bit starting address + "\x87\x86\x85\x84" // 64-bit ending address + "\x83\x82\x81\x80" // 64-bit ending address + "\x00"; // DW_RLE_end_of_list + DWARFDataExtractor Extractor(StringRef(SecData, sizeof(SecData) - 1), + /*isLittleEndian=*/true, + /*AddrSize=*/4); + DWARFListTableHeader Header(/*SectionName=*/".debug_rnglists", + /*ListTypeString=*/"range"); + uint64_t Offset = 0; + llvm::DWARFDebugRnglistTable Table; + llvm::Error E = Table.extractHeaderAndOffsets(Extractor, &Offset); + ASSERT_FALSE(!!E); + EXPECT_EQ(Offset, 12U); + EXPECT_EQ(Table.length(), sizeof(SecData) - 1); + EXPECT_EQ(Extractor.getAddressSize(), 4U); + EXPECT_EQ(Table.getAddrSize(), 8U); + Expected List = Table.findList(Extractor, Offset); + ASSERT_THAT_EXPECTED(List, Succeeded()); + ASSERT_EQ(List->getEntries().size(), 2U); + EXPECT_EQ(List->getEntries()[0].Offset, 12 + 0U); + EXPECT_EQ(List->getEntries()[0].EntryKind, dwarf::DW_RLE_start_end); + EXPECT_EQ(List->getEntries()[0].Value0, 0x0001020304050607U); + EXPECT_EQ(List->getEntries()[0].Value1, 0x8081828384858687U); + EXPECT_EQ(List->getEntries()[1].Offset, 12 + 17U); + EXPECT_EQ(List->getEntries()[1].EntryKind, dwarf::DW_RLE_end_of_list); +} + +TEST(DWARFListTableHeader, AddressSize64Offset) { + static const char SecData[] = "\x1a\x00\x00\x00" // Length + "\x05\x00" // Version + "\x08" // Address size + "\x00" // Segment selector size + "\x00\x00\x00\x00" // Offset entry count + "\x06" // DW_RLE_start_end + "\x07\x06\x05\x04" // 64-bit starting address + "\x03\x02\x01\x00" // 64-bit starting address + "\x87\x86\x85\x84" // 64-bit ending address + "\x83\x82\x81\x80" // 64-bit ending address + "\x00"; // DW_RLE_end_of_list + DWARFDataExtractor Extractor(StringRef(SecData, sizeof(SecData) - 1), + /*isLittleEndian=*/true, + /*AddrSize=*/4); + DWARFListTableHeader Header(/*SectionName=*/".debug_rnglists", + /*ListTypeString=*/"range"); + llvm::DWARFDebugRnglistTable Table; + // Table.getAddrSize() is uninitialized. + EXPECT_EQ(Extractor.getAddressSize(), 4U); + Extractor.setAddressSize(8); + Expected List = Table.findList(Extractor, 12); + ASSERT_THAT_EXPECTED(List, Succeeded()); + ASSERT_EQ(List->getEntries().size(), 2U); + EXPECT_EQ(List->getEntries()[0].Offset, 12 + 0U); + EXPECT_EQ(List->getEntries()[0].EntryKind, dwarf::DW_RLE_start_end); + EXPECT_EQ(List->getEntries()[0].Value0, 0x0001020304050607U); + EXPECT_EQ(List->getEntries()[0].Value1, 0x8081828384858687U); + EXPECT_EQ(List->getEntries()[1].Offset, 12 + 17U); + EXPECT_EQ(List->getEntries()[1].EntryKind, dwarf::DW_RLE_end_of_list); +} + +TEST(DWARFListTableHeader, AddressSize32Header) { + static const char SecData[] = "\x12\x00\x00\x00" // Length + "\x05\x00" // Version + "\x04" // Address size + "\x00" // Segment selector size + "\x00\x00\x00\x00" // Offset entry count + "\x06" // DW_RLE_start_end + "\x03\x02\x01\x00" // 32-bit starting address + "\x83\x82\x81\x80" // 32-bit ending address + "\x00"; // DW_RLE_end_of_list + DWARFDataExtractor Extractor(StringRef(SecData, sizeof(SecData) - 1), + /*isLittleEndian=*/true, + /*AddrSize=*/8); + DWARFListTableHeader Header(/*SectionName=*/".debug_rnglists", + /*ListTypeString=*/"range"); + uint64_t Offset = 0; + llvm::DWARFDebugRnglistTable Table; + llvm::Error E = Table.extractHeaderAndOffsets(Extractor, &Offset); + ASSERT_FALSE(!!E); + EXPECT_EQ(Offset, 12U); + EXPECT_EQ(Table.length(), sizeof(SecData) - 1); + EXPECT_EQ(Extractor.getAddressSize(), 8U); + EXPECT_EQ(Table.getAddrSize(), 4U); + Expected List = Table.findList(Extractor, Offset); + ASSERT_THAT_EXPECTED(List, Succeeded()); + ASSERT_EQ(List->getEntries().size(), 2U); + EXPECT_EQ(List->getEntries()[0].Offset, 12 + 0U); + EXPECT_EQ(List->getEntries()[0].EntryKind, dwarf::DW_RLE_start_end); + EXPECT_EQ(List->getEntries()[0].Value0, 0x00010203U); + EXPECT_EQ(List->getEntries()[0].Value1, 0x80818283U); + EXPECT_EQ(List->getEntries()[1].Offset, 12 + 9U); + EXPECT_EQ(List->getEntries()[1].EntryKind, dwarf::DW_RLE_end_of_list); +} + +TEST(DWARFListTableHeader, AddressSize32Offset) { + static const char SecData[] = "\x12\x00\x00\x00" // Length + "\x05\x00" // Version + "\x04" // Address size + "\x00" // Segment selector size + "\x00\x00\x00\x00" // Offset entry count + "\x06" // DW_RLE_start_end + "\x03\x02\x01\x00" // 32-bit starting address + "\x83\x82\x81\x80" // 32-bit ending address + "\x00"; // DW_RLE_end_of_list + DWARFDataExtractor Extractor(StringRef(SecData, sizeof(SecData) - 1), + /*isLittleEndian=*/true, + /*AddrSize=*/8); + DWARFListTableHeader Header(/*SectionName=*/".debug_rnglists", + /*ListTypeString=*/"range"); + llvm::DWARFDebugRnglistTable Table; + // Table.getAddrSize() is uninitialized. + EXPECT_EQ(Extractor.getAddressSize(), 8U); + Extractor.setAddressSize(4); + Expected List = Table.findList(Extractor, 12); + ASSERT_THAT_EXPECTED(List, Succeeded()); + ASSERT_EQ(List->getEntries().size(), 2U); + EXPECT_EQ(List->getEntries()[0].Offset, 12 + 0U); + EXPECT_EQ(List->getEntries()[0].EntryKind, dwarf::DW_RLE_start_end); + EXPECT_EQ(List->getEntries()[0].Value0, 0x00010203U); + EXPECT_EQ(List->getEntries()[0].Value1, 0x80818283U); + EXPECT_EQ(List->getEntries()[1].Offset, 12 + 9U); + EXPECT_EQ(List->getEntries()[1].EntryKind, dwarf::DW_RLE_end_of_list); +} + } // end anonymous namespace