diff --git a/shared/source/device_binary_format/debug_zebin.cpp b/shared/source/device_binary_format/debug_zebin.cpp index ed81585540..46b5ca869d 100644 --- a/shared/source/device_binary_format/debug_zebin.cpp +++ b/shared/source/device_binary_format/debug_zebin.cpp @@ -46,15 +46,16 @@ void DebugZebinCreator::createDebugZebin() { const auto §ion = zebin.sectionHeaders[i]; auto sectionName = zebin.getSectionName(i); - if (auto segment = getSegmentByName(sectionName)) { - elfEncoder.appendProgramHeaderLoad(i, segment->address, segment->size); - } - auto §ionHeader = elfEncoder.appendSection(section.header->type, sectionName, section.data); sectionHeader.link = section.header->link; sectionHeader.info = section.header->info; sectionHeader.name = section.header->name; sectionHeader.flags = section.header->flags; + + if (auto segment = getSegmentByName(sectionName)) { + elfEncoder.appendProgramHeaderLoad(i, segment->address, segment->size); + sectionHeader.addr = segment->address; + } } debugZebin = elfEncoder.encode(); } @@ -81,21 +82,23 @@ void DebugZebinCreator::applyRelocations() { for (const auto &relocations : {elf.getDebugInfoRelocations(), elf.getRelocations()}) { for (const auto &reloc : relocations) { - auto sectionName = elf.getSectionName(reloc.symbolSectionIndex); - uint64_t sectionAddress = 0U; - if (auto segment = getSegmentByName(sectionName)) { - sectionAddress = segment->address; - } else if (ConstStringRef(sectionName).startsWith(SectionsNamesZebin::debugPrefix.data())) { - // do not offset debug symbols + uint64_t symbolOffset = 0U; + auto symbolSectionName = elf.getSectionName(reloc.symbolSectionIndex); + if (auto segment = getSegmentByName(symbolSectionName)) { + symbolOffset = segment->address; + } else if (ConstStringRef(symbolSectionName).startsWith(SectionsNamesZebin::debugPrefix.data())) { + if (ConstStringRef(reloc.symbolName).startsWith(SectionsNamesZebin::textPrefix.data())) { + symbolOffset = getTextSegmentByName(reloc.symbolName)->address; + } } else { DEBUG_BREAK_IF(true); continue; } - auto value = sectionAddress + elf.getSymbolValue(reloc.symbolTableIndex) + reloc.addend; - auto address = reinterpret_cast(debugZebin.data()) + elf.getSectionOffset(reloc.targetSectionIndex) + reloc.offset; + uint64_t relocVal = symbolOffset + elf.getSymbolValue(reloc.symbolTableIndex) + reloc.addend; + auto relocAddr = reinterpret_cast(debugZebin.data()) + elf.getSectionOffset(reloc.targetSectionIndex) + reloc.offset; auto type = static_cast(reloc.relocType); - applyRelocation(address, value, type); + applyRelocation(relocAddr, relocVal, type); } } } @@ -115,10 +118,7 @@ std::vector createDebugZebin(ArrayRef zebinBin, const Se const Segments::Segment *DebugZebinCreator::getSegmentByName(ConstStringRef sectionName) { if (sectionName.startsWith(SectionsNamesZebin::textPrefix.data())) { - auto kernelName = sectionName.substr(SectionsNamesZebin::textPrefix.length()); - auto kernelSegmentIt = segments.nameToSegMap.find(kernelName.str()); - UNRECOVERABLE_IF(kernelSegmentIt == segments.nameToSegMap.end()); - return &kernelSegmentIt->second; + return getTextSegmentByName(sectionName); } else if (sectionName == SectionsNamesZebin::dataConst) { return &segments.constData; } else if (sectionName == SectionsNamesZebin::dataGlobal) { @@ -129,5 +129,12 @@ const Segments::Segment *DebugZebinCreator::getSegmentByName(ConstStringRef sect return nullptr; } +const Segments::Segment *DebugZebinCreator::getTextSegmentByName(ConstStringRef sectionName) { + auto kernelName = sectionName.substr(SectionsNamesZebin::textPrefix.length()); + auto kernelSegmentIt = segments.nameToSegMap.find(kernelName.str()); + UNRECOVERABLE_IF(kernelSegmentIt == segments.nameToSegMap.end()); + return &kernelSegmentIt->second; +} + } // namespace Debug } // namespace NEO diff --git a/shared/source/device_binary_format/debug_zebin.h b/shared/source/device_binary_format/debug_zebin.h index bb8e3a4454..e87cc609a4 100644 --- a/shared/source/device_binary_format/debug_zebin.h +++ b/shared/source/device_binary_format/debug_zebin.h @@ -48,6 +48,7 @@ class DebugZebinCreator { protected: void applyRelocation(uint64_t addr, uint64_t value, NEO::Elf::RELOC_TYPE_ZEBIN type); const Segments::Segment *getSegmentByName(ConstStringRef sectionName); + const Segments::Segment *getTextSegmentByName(ConstStringRef sectionName); std::vector debugZebin; const Segments &segments; diff --git a/shared/test/unit_test/device_binary_format/zebin_debug_binary_tests.cpp b/shared/test/unit_test/device_binary_format/zebin_debug_binary_tests.cpp index 7116d18d4e..8beaf6d881 100644 --- a/shared/test/unit_test/device_binary_format/zebin_debug_binary_tests.cpp +++ b/shared/test/unit_test/device_binary_format/zebin_debug_binary_tests.cpp @@ -20,7 +20,7 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { uint8_t kernelISA[8] = {0x3}; uint8_t stringData[8] = {0x4}; - uint8_t debugInfo[0x20] = {0x0}; + uint8_t debugInfo[0x28] = {0x0}; uint8_t debugAbbrev[8] = {0x0}; using Segment = NEO::Debug::Segments::Segment; @@ -43,7 +43,7 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { typedef NEO::Elf::ElfSymbolEntry SymbolEntry; typedef NEO::Elf::ElfRela Relocation; - SymbolEntry symbols[5]{}; + SymbolEntry symbols[6]{}; symbols[0].name = elfEncoder.appendSectionName("kernel"); symbols[0].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_SECTION | NEO::Elf::SYMBOL_TABLE_BIND::STB_LOCAL << 4; symbols[0].shndx = static_cast(kernelSectionIndex); @@ -69,7 +69,12 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { symbols[4].shndx = static_cast(zeInfoSectionIndex); symbols[4].value = 0U; - Relocation debugRelocations[5]{}; + symbols[5].name = elfEncoder.appendSectionName(NEO::Elf::SectionsNamesZebin::textPrefix.str() + "kernel"); + symbols[5].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_SECTION | NEO::Elf::SYMBOL_TABLE_BIND::STB_LOCAL << 4; + symbols[5].shndx = static_cast(debugInfoSectionIndex); + symbols[5].value = 0U; + + Relocation debugRelocations[6]{}; debugRelocations[0].addend = 0xabc; debugRelocations[0].offset = 0x0; debugRelocations[0].info = (uint64_t(0) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR; @@ -91,6 +96,10 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { debugRelocations[4].offset = 0x18U; debugRelocations[4].info = (uint64_t(4) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR; + debugRelocations[5].addend = 0x0; + debugRelocations[5].offset = 0x20U; + debugRelocations[5].info = (uint64_t(5) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR; + elfEncoder.appendSection(NEO::Elf::SHT_SYMTAB, NEO::Elf::SectionsNamesZebin::symtab, ArrayRef(reinterpret_cast(symbols), sizeof(symbols))); auto &relaHeader = elfEncoder.appendSection(NEO::Elf::SHT_RELA, NEO::Elf::SpecialSectionNames::relaPrefix.str() + NEO::Elf::SectionsNamesZebin::debugInfo.str(), ArrayRef(reinterpret_cast(debugRelocations), sizeof(debugRelocations))); relaHeader.info = debugInfoSectionIndex; @@ -132,41 +141,51 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { EXPECT_EQ(zebin.sectionHeaders[i].header->name, debugZebin.sectionHeaders[i].header->name); EXPECT_EQ(zebin.sectionHeaders[i].header->flags, debugZebin.sectionHeaders[i].header->flags); - auto sectionName = debugZebin.getSectionName(i); + const auto §ionHeader = debugZebin.sectionHeaders[i].header; + const auto §ionData = debugZebin.sectionHeaders[i].data; + const auto sectionName = debugZebin.getSectionName(i); auto refSectionName = NEO::ConstStringRef(sectionName); if (refSectionName.startsWith(NEO::Elf::SectionsNamesZebin::textPrefix.data())) { - offsetKernel = debugZebin.sectionHeaders[i].header->offset; - fileSzKernel = debugZebin.sectionHeaders[i].header->size; + offsetKernel = sectionHeader->offset; + fileSzKernel = sectionHeader->size; + EXPECT_EQ(segments.nameToSegMap["kernel"].address, sectionHeader->addr); } else if (refSectionName == NEO::Elf::SectionsNamesZebin::dataConst) { - offsetConstData = debugZebin.sectionHeaders[i].header->offset; - fileSzConstData = debugZebin.sectionHeaders[i].header->size; + offsetConstData = sectionHeader->offset; + fileSzConstData = sectionHeader->size; + EXPECT_EQ(segments.constData.address, sectionHeader->addr); } else if (refSectionName == NEO::Elf::SectionsNamesZebin::dataGlobal) { - offsetVarData = debugZebin.sectionHeaders[i].header->offset; - fileSzVarData = debugZebin.sectionHeaders[i].header->size; + offsetVarData = sectionHeader->offset; + fileSzVarData = sectionHeader->size; + EXPECT_EQ(segments.varData.address, sectionHeader->addr); } else if (refSectionName == NEO::Elf::SectionsNamesZebin::dataConstString) { - offsetStringData = debugZebin.sectionHeaders[i].header->offset; - fileSzStringData = debugZebin.sectionHeaders[i].header->size; + offsetStringData = sectionHeader->offset; + fileSzStringData = sectionHeader->size; + EXPECT_EQ(segments.stringData.address, sectionHeader->addr); } else if (refSectionName == NEO::Elf::SectionsNamesZebin::debugInfo) { - auto ptrDebugInfo = debugZebin.sectionHeaders[i].data.begin(); - EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[0].offset), - segments.nameToSegMap["kernel"].address + symbols[0].value + debugRelocations[0].addend); + auto ptrDebugInfo = sectionData.begin(); + EXPECT_EQ(segments.nameToSegMap["kernel"].address + symbols[0].value + debugRelocations[0].addend, + *reinterpret_cast(ptrDebugInfo + debugRelocations[0].offset)); - EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[1].offset), - static_cast((segments.constData.address + symbols[1].value + debugRelocations[1].addend) & 0xffffffff)); + EXPECT_EQ(static_cast((segments.constData.address + symbols[1].value + debugRelocations[1].addend) & 0xffffffff), + *reinterpret_cast(ptrDebugInfo + debugRelocations[1].offset)); - EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[2].offset), - static_cast(((segments.varData.address + symbols[2].value + debugRelocations[2].addend) >> 32) & 0xffffffff)); + EXPECT_EQ(static_cast(((segments.varData.address + symbols[2].value + debugRelocations[2].addend) >> 32) & 0xffffffff), + *reinterpret_cast(ptrDebugInfo + debugRelocations[2].offset)); - // debug symbols are not offseted - EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[3].offset), - symbols[3].value + debugRelocations[3].addend); + // debug symbols with name different than text segments are not offseted + EXPECT_EQ(symbols[3].value + debugRelocations[3].addend, + *reinterpret_cast(ptrDebugInfo + debugRelocations[3].offset)); - // if symbols points to other sections relocation is skipped - EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[4].offset), 0U); + // if symbols points to other sections relocation is skipped - not text, data, debug + EXPECT_EQ(0U, *reinterpret_cast(ptrDebugInfo + debugRelocations[4].offset)); + + // debug symbols with text segment name are offseted by corresponding segment's address + EXPECT_EQ(segments.nameToSegMap["kernel"].address, + *reinterpret_cast(ptrDebugInfo + debugRelocations[5].offset)); } else { - EXPECT_EQ(zebin.sectionHeaders[i].header->size, debugZebin.sectionHeaders[i].header->size); - if (debugZebin.sectionHeaders[i].header->size > 0U) { - EXPECT_TRUE(memcmp(zebin.sectionHeaders[i].data.begin(), debugZebin.sectionHeaders[i].data.begin(), debugZebin.sectionHeaders[i].data.size()) == 0); + EXPECT_EQ(zebin.sectionHeaders[i].header->size, sectionHeader->size); + if (sectionHeader->size > 0U) { + EXPECT_TRUE(memcmp(zebin.sectionHeaders[i].data.begin(), sectionData.begin(), sectionData.size()) == 0); } } }