mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-03 06:49:52 +08:00
feat(dbg zebin): set sym value to absolute address
GDB requires debug zebin to be an absolute ELF. This change adds setting symbols values to absolute addresses allowing GDB to work correctly. Resolves: NEO-7097 Signed-off-by: Krystian Chmielewski <krystian.chmielewski@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
5dc14eb46a
commit
adfc3a1e7a
@@ -12,6 +12,7 @@
|
||||
#include "shared/test/common/test_macros/test.h"
|
||||
#include "shared/test/unit_test/device_binary_format/zebin_tests.h"
|
||||
|
||||
using namespace NEO::Elf;
|
||||
TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
|
||||
MockElfEncoder<> elfEncoder;
|
||||
|
||||
@@ -25,93 +26,100 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
|
||||
|
||||
using Segment = NEO::Debug::Segments::Segment;
|
||||
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "kernel", ArrayRef<const uint8_t>(kernelISA, sizeof(kernelISA)));
|
||||
elfEncoder.appendSection(SHT_PROGBITS, SectionsNamesZebin::textPrefix.str() + "kernel", ArrayRef<const uint8_t>(kernelISA, sizeof(kernelISA)));
|
||||
auto kernelSectionIndex = elfEncoder.getLastSectionHeaderIndex();
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataConst, ArrayRef<const uint8_t>(constData, sizeof(constData)));
|
||||
elfEncoder.appendSection(SHT_PROGBITS, SectionsNamesZebin::dataConst, ArrayRef<const uint8_t>(constData, sizeof(constData)));
|
||||
auto constDataSectionIndex = elfEncoder.getLastSectionHeaderIndex();
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataGlobal, ArrayRef<const uint8_t>(varData, sizeof(varData)));
|
||||
elfEncoder.appendSection(SHT_PROGBITS, SectionsNamesZebin::dataGlobal, ArrayRef<const uint8_t>(varData, sizeof(varData)));
|
||||
auto varDataSectionIndex = elfEncoder.getLastSectionHeaderIndex();
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataConstString, ArrayRef<const uint8_t>(stringData, sizeof(stringData)));
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::debugInfo, ArrayRef<const uint8_t>(debugInfo, sizeof(debugInfo)));
|
||||
elfEncoder.appendSection(SHT_PROGBITS, SectionsNamesZebin::dataConstString, ArrayRef<const uint8_t>(stringData, sizeof(stringData)));
|
||||
elfEncoder.appendSection(SHT_PROGBITS, SectionsNamesZebin::debugInfo, ArrayRef<const uint8_t>(debugInfo, sizeof(debugInfo)));
|
||||
auto debugInfoSectionIndex = elfEncoder.getLastSectionHeaderIndex();
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::debugAbbrev, ArrayRef<const uint8_t>(debugAbbrev, sizeof(debugAbbrev)));
|
||||
elfEncoder.appendSection(SHT_PROGBITS, SectionsNamesZebin::debugAbbrev, ArrayRef<const uint8_t>(debugAbbrev, sizeof(debugAbbrev)));
|
||||
auto debugAbbrevSectionIndex = elfEncoder.getLastSectionHeaderIndex();
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, std::string{});
|
||||
elfEncoder.appendSection(SHT_ZEBIN_ZEINFO, SectionsNamesZebin::zeInfo, std::string{});
|
||||
auto zeInfoSectionIndex = elfEncoder.getLastSectionHeaderIndex();
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_SPIRV, NEO::Elf::SectionsNamesZebin::spv, std::string{});
|
||||
elfEncoder.appendSection(SHT_ZEBIN_SPIRV, SectionsNamesZebin::spv, std::string{});
|
||||
|
||||
typedef NEO::Elf::ElfSymbolEntry<NEO::Elf::ELF_IDENTIFIER_CLASS::EI_CLASS_64> SymbolEntry;
|
||||
typedef NEO::Elf::ElfRela<NEO::Elf::ELF_IDENTIFIER_CLASS::EI_CLASS_64> Relocation;
|
||||
using SymbolEntry = ElfSymbolEntry<ELF_IDENTIFIER_CLASS::EI_CLASS_64>;
|
||||
using Relocation = ElfRela<ELF_IDENTIFIER_CLASS::EI_CLASS_64>;
|
||||
|
||||
SymbolEntry symbols[7]{};
|
||||
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].info = SYMBOL_TABLE_TYPE::STT_SECTION | SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[0].shndx = static_cast<decltype(SymbolEntry::shndx)>(kernelSectionIndex);
|
||||
symbols[0].value = 0U;
|
||||
|
||||
symbols[1].name = elfEncoder.appendSectionName("constData");
|
||||
symbols[1].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_SECTION | NEO::Elf::SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[1].info = SYMBOL_TABLE_TYPE::STT_SECTION | SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[1].shndx = static_cast<decltype(SymbolEntry::shndx)>(constDataSectionIndex);
|
||||
symbols[1].value = 0U;
|
||||
|
||||
symbols[2].name = elfEncoder.appendSectionName("varData");
|
||||
symbols[2].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_SECTION | NEO::Elf::SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[2].info = SYMBOL_TABLE_TYPE::STT_SECTION | SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[2].shndx = static_cast<decltype(SymbolEntry::shndx)>(varDataSectionIndex);
|
||||
symbols[2].value = 0U;
|
||||
|
||||
symbols[3].name = elfEncoder.appendSectionName("debugInfo");
|
||||
symbols[3].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_SECTION | NEO::Elf::SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[3].info = SYMBOL_TABLE_TYPE::STT_SECTION | SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[3].shndx = static_cast<decltype(SymbolEntry::shndx)>(debugAbbrevSectionIndex);
|
||||
symbols[3].value = 0x1U;
|
||||
|
||||
symbols[4].name = elfEncoder.appendSectionName("zeInfo");
|
||||
symbols[4].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_SECTION | NEO::Elf::SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[4].info = SYMBOL_TABLE_TYPE::STT_SECTION | SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[4].shndx = static_cast<decltype(SymbolEntry::shndx)>(zeInfoSectionIndex);
|
||||
symbols[4].value = 0U;
|
||||
|
||||
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].name = elfEncoder.appendSectionName(SectionsNamesZebin::textPrefix.str() + "kernel");
|
||||
symbols[5].info = SYMBOL_TABLE_TYPE::STT_SECTION | SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[5].shndx = static_cast<decltype(SymbolEntry::shndx)>(debugInfoSectionIndex);
|
||||
symbols[5].value = 0U;
|
||||
|
||||
symbols[6].name = elfEncoder.appendSectionName("kernel_payload_offset");
|
||||
symbols[6].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_SECTION | NEO::Elf::SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[6].info = SYMBOL_TABLE_TYPE::STT_SECTION | SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbols[6].shndx = static_cast<decltype(SymbolEntry::shndx)>(kernelSectionIndex);
|
||||
symbols[6].value = 0x10U;
|
||||
|
||||
Relocation debugRelocations[7]{};
|
||||
debugRelocations[0].addend = 0xabc;
|
||||
debugRelocations[0].offset = 0x0;
|
||||
debugRelocations[0].info = (uint64_t(0) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR;
|
||||
debugRelocations[0].setSymbolTableIndex(0);
|
||||
debugRelocations[0].setRelocationType(RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR);
|
||||
|
||||
debugRelocations[1].addend = 0x0;
|
||||
debugRelocations[1].offset = 0x8U;
|
||||
debugRelocations[1].info = (uint64_t(1) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR_32;
|
||||
debugRelocations[1].setSymbolTableIndex(1);
|
||||
debugRelocations[1].setRelocationType(RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR_32);
|
||||
|
||||
debugRelocations[2].addend = 0x0;
|
||||
debugRelocations[2].offset = 0xCU;
|
||||
debugRelocations[2].info = (uint64_t(2) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR_32_HI;
|
||||
debugRelocations[2].setSymbolTableIndex(2);
|
||||
debugRelocations[2].setRelocationType(RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR_32_HI);
|
||||
|
||||
debugRelocations[3].addend = -0xa;
|
||||
debugRelocations[3].offset = 0x10U;
|
||||
debugRelocations[3].info = (uint64_t(3) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR;
|
||||
debugRelocations[3].setSymbolTableIndex(3);
|
||||
debugRelocations[3].setRelocationType(RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR);
|
||||
|
||||
// Will be ignored
|
||||
debugRelocations[4].addend = 0x0;
|
||||
debugRelocations[4].offset = 0x18U;
|
||||
debugRelocations[4].info = (uint64_t(4) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR;
|
||||
debugRelocations[4].setSymbolTableIndex(4);
|
||||
debugRelocations[4].setRelocationType(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;
|
||||
debugRelocations[5].setSymbolTableIndex(5);
|
||||
debugRelocations[5].setRelocationType(RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR);
|
||||
|
||||
// Will be ignored due to reloc type
|
||||
debugRelocations[6].addend = 0x0;
|
||||
debugRelocations[6].offset = 0x28;
|
||||
debugRelocations[6].info = (uint64_t(6) << 32) | NEO::Elf::RELOC_TYPE_ZEBIN::R_PER_THREAD_PAYLOAD_OFFSET;
|
||||
debugRelocations[6].setSymbolTableIndex(6);
|
||||
debugRelocations[6].setRelocationType(RELOC_TYPE_ZEBIN::R_PER_THREAD_PAYLOAD_OFFSET);
|
||||
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_SYMTAB, NEO::Elf::SectionsNamesZebin::symtab, ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(symbols), sizeof(symbols)));
|
||||
auto &relaHeader = elfEncoder.appendSection(NEO::Elf::SHT_RELA, NEO::Elf::SpecialSectionNames::relaPrefix.str() + NEO::Elf::SectionsNamesZebin::debugInfo.str(), ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(debugRelocations), sizeof(debugRelocations)));
|
||||
elfEncoder.appendSection(SHT_SYMTAB, SectionsNamesZebin::symtab, ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(symbols), sizeof(symbols)));
|
||||
auto &relaHeader = elfEncoder.appendSection(SHT_RELA, SpecialSectionNames::relaPrefix.str() + SectionsNamesZebin::debugInfo.str(), ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(debugRelocations), sizeof(debugRelocations)));
|
||||
relaHeader.info = debugInfoSectionIndex;
|
||||
|
||||
NEO::Debug::Segments segments;
|
||||
@@ -123,18 +131,18 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
|
||||
auto zebinBin = elfEncoder.encode();
|
||||
|
||||
std::string warning, error;
|
||||
auto zebin = NEO::Elf::decodeElf(zebinBin, error, warning);
|
||||
auto zebin = decodeElf(zebinBin, error, warning);
|
||||
ASSERT_TRUE(error.empty());
|
||||
ASSERT_TRUE(warning.empty());
|
||||
|
||||
auto debugZebinBin = NEO::Debug::createDebugZebin(zebinBin, segments);
|
||||
auto debugZebin = NEO::Elf::decodeElf(debugZebinBin, error, warning);
|
||||
auto debugZebin = decodeElf(debugZebinBin, error, warning);
|
||||
ASSERT_TRUE(error.empty());
|
||||
ASSERT_TRUE(warning.empty());
|
||||
|
||||
EXPECT_EQ(zebin.elfFileHeader->machine, debugZebin.elfFileHeader->machine);
|
||||
EXPECT_EQ(zebin.elfFileHeader->flags, debugZebin.elfFileHeader->flags);
|
||||
EXPECT_EQ(NEO::Elf::ET_EXEC, debugZebin.elfFileHeader->type);
|
||||
EXPECT_EQ(ET_EXEC, debugZebin.elfFileHeader->type);
|
||||
EXPECT_EQ(zebin.elfFileHeader->version, debugZebin.elfFileHeader->version);
|
||||
EXPECT_EQ(zebin.elfFileHeader->shStrNdx, debugZebin.elfFileHeader->shStrNdx);
|
||||
|
||||
@@ -155,23 +163,23 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
|
||||
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())) {
|
||||
if (refSectionName.startsWith(SectionsNamesZebin::textPrefix.data())) {
|
||||
offsetKernel = sectionHeader->offset;
|
||||
fileSzKernel = sectionHeader->size;
|
||||
EXPECT_EQ(segments.nameToSegMap["kernel"].address, sectionHeader->addr);
|
||||
} else if (refSectionName == NEO::Elf::SectionsNamesZebin::dataConst) {
|
||||
} else if (refSectionName == SectionsNamesZebin::dataConst) {
|
||||
offsetConstData = sectionHeader->offset;
|
||||
fileSzConstData = sectionHeader->size;
|
||||
EXPECT_EQ(segments.constData.address, sectionHeader->addr);
|
||||
} else if (refSectionName == NEO::Elf::SectionsNamesZebin::dataGlobal) {
|
||||
} else if (refSectionName == SectionsNamesZebin::dataGlobal) {
|
||||
offsetVarData = sectionHeader->offset;
|
||||
fileSzVarData = sectionHeader->size;
|
||||
EXPECT_EQ(segments.varData.address, sectionHeader->addr);
|
||||
} else if (refSectionName == NEO::Elf::SectionsNamesZebin::dataConstString) {
|
||||
} else if (refSectionName == SectionsNamesZebin::dataConstString) {
|
||||
offsetStringData = sectionHeader->offset;
|
||||
fileSzStringData = sectionHeader->size;
|
||||
EXPECT_EQ(segments.stringData.address, sectionHeader->addr);
|
||||
} else if (refSectionName == NEO::Elf::SectionsNamesZebin::debugInfo) {
|
||||
} else if (refSectionName == SectionsNamesZebin::debugInfo) {
|
||||
auto ptrDebugInfo = sectionData.begin();
|
||||
EXPECT_EQ(segments.nameToSegMap["kernel"].address + symbols[0].value + debugRelocations[0].addend,
|
||||
*reinterpret_cast<const uint64_t *>(ptrDebugInfo + debugRelocations[0].offset));
|
||||
@@ -196,6 +204,20 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) {
|
||||
|
||||
EXPECT_EQ(*reinterpret_cast<uint64_t *>(debugInfo + debugRelocations[6].offset),
|
||||
*reinterpret_cast<const uint64_t *>(ptrDebugInfo + debugRelocations[6].offset));
|
||||
} else if (refSectionName == SectionsNamesZebin::symtab) {
|
||||
using ElfSymbolT = ElfSymbolEntry<EI_CLASS_64>;
|
||||
size_t symbolCount = static_cast<size_t>(sectionHeader->size) / static_cast<size_t>(sectionHeader->entsize);
|
||||
ArrayRef<const ElfSymbolT> debugSymbols = {reinterpret_cast<const ElfSymbolT *>(sectionData.begin()), symbolCount};
|
||||
|
||||
EXPECT_EQ(7U, debugSymbols.size());
|
||||
EXPECT_EQ(segments.nameToSegMap["kernel"].address + symbols[0].value, debugSymbols[0].value);
|
||||
EXPECT_EQ(segments.constData.address + symbols[1].value, debugSymbols[1].value);
|
||||
EXPECT_EQ(segments.varData.address + symbols[2].value, debugSymbols[2].value);
|
||||
EXPECT_EQ(symbols[3].value, debugSymbols[3].value);
|
||||
EXPECT_EQ(symbols[4].value, debugSymbols[4].value);
|
||||
EXPECT_EQ(segments.nameToSegMap["kernel"].address + symbols[5].value, debugSymbols[5].value);
|
||||
EXPECT_EQ(segments.nameToSegMap["kernel"].address + symbols[6].value, debugSymbols[6].value);
|
||||
|
||||
} else {
|
||||
EXPECT_EQ(zebin.sectionHeaders[i].header->size, sectionHeader->size);
|
||||
if (sectionHeader->size > 0U) {
|
||||
@@ -234,3 +256,50 @@ TEST(DebugZebinTest, givenInvalidZebinThenDebugZebinIsNotGenerated) {
|
||||
auto debugZebin = NEO::Debug::createDebugZebin(ArrayRef<const uint8_t>(notZebin, sizeof(notZebin)), {});
|
||||
EXPECT_EQ(0U, debugZebin.size());
|
||||
}
|
||||
|
||||
TEST(DebugZebinTest, givenSymTabShndxUndefinedThenDoNotApplyRelocations) {
|
||||
MockElfEncoder<> elfEncoder;
|
||||
|
||||
uint8_t kernelISA[8] = {0U};
|
||||
elfEncoder.appendSection(SHT_PROGBITS, SectionsNamesZebin::textPrefix.str() + "kernel", ArrayRef<const uint8_t>(kernelISA, sizeof(kernelISA)));
|
||||
auto kernelSectionIndex = elfEncoder.getLastSectionHeaderIndex();
|
||||
|
||||
using SymbolEntry = ElfSymbolEntry<ELF_IDENTIFIER_CLASS::EI_CLASS_64>;
|
||||
using Relocation = ElfRela<ELF_IDENTIFIER_CLASS::EI_CLASS_64>;
|
||||
|
||||
SymbolEntry symbol{};
|
||||
symbol.name = elfEncoder.appendSectionName("kernel");
|
||||
symbol.info = SYMBOL_TABLE_TYPE::STT_SECTION | SYMBOL_TABLE_BIND::STB_LOCAL << 4;
|
||||
symbol.shndx = static_cast<decltype(SymbolEntry::shndx)>(kernelSectionIndex);
|
||||
symbol.value = 0xAU;
|
||||
|
||||
Relocation relocation{};
|
||||
relocation.addend = 0x0;
|
||||
relocation.offset = 0x0;
|
||||
relocation.setSymbolTableIndex(0);
|
||||
relocation.setRelocationType(RELOC_TYPE_ZEBIN::R_ZE_SYM_ADDR);
|
||||
|
||||
elfEncoder.appendSection(SHT_SYMTAB, SectionsNamesZebin::symtab, ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(&symbol), sizeof(symbol)));
|
||||
auto &relaHeader = elfEncoder.appendSection(SHT_RELA, SpecialSectionNames::relaPrefix.str() + SectionsNamesZebin::textPrefix.str() + "kernel", ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(&relocation), sizeof(relocation)));
|
||||
relaHeader.info = kernelSectionIndex;
|
||||
|
||||
auto zebin = elfEncoder.encode();
|
||||
std::string errors, warnings;
|
||||
auto zebinElf = decodeElf(zebin, errors, warnings);
|
||||
ASSERT_TRUE(errors.empty());
|
||||
ASSERT_TRUE(warnings.empty());
|
||||
|
||||
class MockDebugZebinCreator : public NEO::Debug::DebugZebinCreator {
|
||||
public:
|
||||
using Base = NEO::Debug::DebugZebinCreator;
|
||||
using Base::Base;
|
||||
using Base::debugZebin;
|
||||
using Base::symTabShndx;
|
||||
};
|
||||
NEO::Debug::Segments segments;
|
||||
MockDebugZebinCreator dzc(zebinElf, segments);
|
||||
dzc.debugZebin = zebin;
|
||||
dzc.symTabShndx = std::numeric_limits<uint32_t>::max();
|
||||
dzc.applyRelocations();
|
||||
EXPECT_EQ(0U, *reinterpret_cast<uint64_t *>(zebin.data() + zebinElf.sectionHeaders[1].header->offset + relocation.offset));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user