From 8e57e48695c38aa98eda1d5cd4c5d768603717be Mon Sep 17 00:00:00 2001 From: Krystian Chmielewski Date: Thu, 28 Oct 2021 15:54:45 +0000 Subject: [PATCH] L0: Pass debug zebin to SLD Added passing debug zebin to SLD. Added support for .const.data.strings section in debug zebin creation. Refactored debug zebin creation code. Resolves: NEO-6246 Signed-off-by: Krystian Chmielewski --- level_zero/core/source/module/module_imp.cpp | 60 ++++++++++++- level_zero/core/source/module/module_imp.h | 7 ++ .../test/unit_tests/fixtures/module_fixture.h | 83 ++++++++++++++++++ .../debugger/test_module_with_debug.cpp | 10 +++ .../unit_tests/sources/module/test_module.cpp | 35 ++++++++ .../device_binary_format/debug_zebin.cpp | 85 +++++++++---------- .../source/device_binary_format/debug_zebin.h | 43 +++++++--- shared/source/utilities/const_stringref.h | 6 +- .../zebin_debug_binary_tests.cpp | 47 ++++++---- 9 files changed, 294 insertions(+), 82 deletions(-) diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 13e4c71d81..0a44b87c82 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -10,6 +10,7 @@ #include "shared/source/compiler_interface/intermediate_representations.h" #include "shared/source/compiler_interface/linker.h" #include "shared/source/device/device.h" +#include "shared/source/device_binary_format/debug_zebin.h" #include "shared/source/device_binary_format/device_binary_formats.h" #include "shared/source/device_binary_format/elf/elf.h" #include "shared/source/device_binary_format/elf/elf_encoder.h" @@ -431,6 +432,34 @@ ModuleImp::~ModuleImp() { kernelImmDatas.clear(); } +NEO::Debug::Segments ModuleImp::getZebinSegments() { + NEO::Debug::Segments segments; + + auto varBuffer = translationUnit->globalVarBuffer; + if (varBuffer) { + segments.varData = {varBuffer->getGpuAddressToPatch(), {reinterpret_cast(varBuffer->getUnderlyingBuffer()), varBuffer->getUnderlyingBufferSize()}}; + } + + auto constBuffer = translationUnit->globalConstBuffer; + if (constBuffer) { + segments.constData = {constBuffer->getGpuAddressToPatch(), {reinterpret_cast(constBuffer->getUnderlyingBuffer()), constBuffer->getUnderlyingBufferSize()}}; + } + + auto stringBuffer = translationUnit->programInfo.globalStrings; + if (stringBuffer.initData) { + segments.stringData = {reinterpret_cast(stringBuffer.initData), + {reinterpret_cast(stringBuffer.initData), stringBuffer.size}}; + } + + for (auto &kernImmData : this->kernelImmDatas) { + const auto &isa = kernImmData->getIsaGraphicsAllocation(); + NEO::Debug::Segments::Segment kernelSegment = {isa->getGpuAddressToPatch(), {reinterpret_cast(isa->getUnderlyingBuffer()), isa->getUnderlyingBufferSize()}}; + segments.nameToSegMap.insert(std::pair(kernImmData->getDescriptor().kernelMetadata.kernelName, kernelSegment)); + } + + return segments; +} + bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) { bool success = true; @@ -493,9 +522,8 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) } } - verifyDebugCapabilities(); - this->updateBuildLog(neoDevice); + verifyDebugCapabilities(); if (false == success) { return false; @@ -513,7 +541,33 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) checkIfPrivateMemoryPerDispatchIsNeeded(); + success = this->linkBinary(); + if (debugEnabled) { + passDebugData(); + } + + return success; +} + +void ModuleImp::passDebugData() { + auto refBin = ArrayRef(reinterpret_cast(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize); + if (NEO::isDeviceBinaryFormat(refBin)) { + auto segments = getZebinSegments(); + auto debugZebin = NEO::Debug::createDebugZebin(refBin, segments); + + translationUnit->debugDataSize = debugZebin.size(); + translationUnit->debugData.reset(new char[translationUnit->debugDataSize]); + memcpy_s(translationUnit->debugData.get(), translationUnit->debugDataSize, + debugZebin.data(), debugZebin.size()); + + if (device->getSourceLevelDebugger()) { + NEO::DebugData debugData; // pass debug zebin in vIsa field + debugData.vIsa = reinterpret_cast(debugZebin.data()); + debugData.vIsaSize = static_cast(debugZebin.size()); + device->getSourceLevelDebugger()->notifyKernelDebugData(&debugData, "debug_zebin", nullptr, 0); + } + } else { if (device->getSourceLevelDebugger()) { for (auto kernelInfo : this->translationUnit->programInfo.kernelInfos) { NEO::DebugData *notifyDebugData = kernelInfo->kernelDescriptor.external.debugData.get(); @@ -534,8 +588,6 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) } } } - - return this->linkBinary(); } const KernelImmutableData *ModuleImp::getKernelImmutableData(const char *functionName) const { diff --git a/level_zero/core/source/module/module_imp.h b/level_zero/core/source/module/module_imp.h index 104b1515d7..8bfc19638e 100644 --- a/level_zero/core/source/module/module_imp.h +++ b/level_zero/core/source/module/module_imp.h @@ -20,6 +20,11 @@ #include #include +namespace NEO { +namespace Debug { +struct Segments; +} +} // namespace NEO namespace L0 { namespace BuildOptions { @@ -132,6 +137,8 @@ struct ModuleImp : public Module { void copyPatchedSegments(const NEO::Linker::PatchableSegments &isaSegmentsForPatching); void verifyDebugCapabilities(); void checkIfPrivateMemoryPerDispatchIsNeeded() override; + NEO::Debug::Segments getZebinSegments(); + void passDebugData(); Device *device = nullptr; PRODUCT_FAMILY productFamily{}; diff --git a/level_zero/core/test/unit_tests/fixtures/module_fixture.h b/level_zero/core/test/unit_tests/fixtures/module_fixture.h index 3ef53d42ed..298086e5b9 100644 --- a/level_zero/core/test/unit_tests/fixtures/module_fixture.h +++ b/level_zero/core/test/unit_tests/fixtures/module_fixture.h @@ -15,6 +15,7 @@ #include "shared/test/common/mocks/mock_compilers.h" #include "shared/test/common/mocks/mock_graphics_allocation.h" #include "shared/test/common/mocks/mock_memory_manager.h" +#include "shared/test/unit_test/device_binary_format/zebin_tests.h" #include "level_zero/core/source/module/module.h" #include "level_zero/core/source/module/module_imp.h" @@ -288,6 +289,88 @@ struct MultiDeviceModuleFixture : public MultiDeviceFixture { std::unique_ptr> kernel; }; +struct ModuleWithZebinFixture : public DeviceFixture { + struct MockImmutableData : public KernelImmutableData { + using KernelImmutableData::device; + using KernelImmutableData::isaGraphicsAllocation; + using KernelImmutableData::kernelDescriptor; + MockImmutableData(L0::Device *device) { + + auto mockKernelDescriptor = new NEO::KernelDescriptor; + mockKernelDescriptor->kernelMetadata.kernelName = "kernel"; + kernelDescriptor = mockKernelDescriptor; + this->device = device; + isaGraphicsAllocation.reset(new NEO::MockGraphicsAllocation(0, + NEO::GraphicsAllocation::AllocationType::KERNEL_ISA, + reinterpret_cast(0x1234), + 0x1000, + 0, + sizeof(uint32_t), + MemoryPool::System4KBPages)); + } + + ~MockImmutableData() { + delete kernelDescriptor; + } + }; + + struct MockModuleWithZebin : public L0::ModuleImp { + using ModuleImp::getZebinSegments; + using ModuleImp::kernelImmDatas; + using ModuleImp::passDebugData; + using ModuleImp::translationUnit; + MockModuleWithZebin(L0::Device *device) : ModuleImp(device, nullptr, ModuleType::User) {} + + void addSegments() { + kernelImmDatas.push_back(std::make_unique(device)); + translationUnit->globalVarBuffer = new NEO::MockGraphicsAllocation(0, + NEO::GraphicsAllocation::AllocationType::GLOBAL_SURFACE, + reinterpret_cast(0x1234), + 0x1000, + 0, + sizeof(uint32_t), + MemoryPool::System4KBPages); + translationUnit->globalConstBuffer = new NEO::MockGraphicsAllocation(0, + NEO::GraphicsAllocation::AllocationType::GLOBAL_SURFACE, + reinterpret_cast(0x1234), + 0x1000, + 0, + sizeof(uint32_t), + MemoryPool::System4KBPages); + + translationUnit->programInfo.globalStrings.initData = &strings; + translationUnit->programInfo.globalStrings.size = sizeof(strings); + } + + void addKernelSegment() { + } + + void addEmptyZebin() { + auto zebin = ZebinTestData::ValidEmptyProgram(); + + translationUnit->unpackedDeviceBinarySize = zebin.storage.size(); + translationUnit->unpackedDeviceBinary.reset(new char[zebin.storage.size()]); + memcpy_s(translationUnit->unpackedDeviceBinary.get(), translationUnit->unpackedDeviceBinarySize, + zebin.storage.data(), zebin.storage.size()); + } + + ~MockModuleWithZebin() { + } + + const char strings[12] = "Hello olleH"; + }; + void SetUp() { + NEO::MockCompilerEnableGuard mock(true); + DeviceFixture::SetUp(); + module = std::make_unique(device); + } + + void TearDown() { + DeviceFixture::TearDown(); + } + std::unique_ptr module; +}; + struct ImportHostPointerModuleFixture : public ModuleFixture { void SetUp() { DebugManager.flags.EnableHostPointerImport.set(1); diff --git a/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp b/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp index 3033d8755d..d42b303a0d 100644 --- a/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp +++ b/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp @@ -297,6 +297,16 @@ TEST_F(ModuleWithSLDTest, GivenDebugDataWithMultipleRelocationsWhenInitializingM EXPECT_NE(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData); } +using ModuleWithZebinAndSLDTest = Test; +TEST_F(ModuleWithZebinAndSLDTest, GivenZebinThenCreateDebugZebinAndPassToSLD) { + module->addEmptyZebin(); + + auto debugger = new MockActiveSourceLevelDebugger(new MockOsLibrary); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(debugger); + module->passDebugData(); + + EXPECT_TRUE(module->translationUnit->debugData); +} using KernelDebugSurfaceTest = Test; HWTEST_F(KernelDebugSurfaceTest, givenDebuggerAndBindfulKernelWhenAppendingKernelToCommandListThenBindfulSurfaceStateForDebugSurfaceIsProgrammed) { diff --git a/level_zero/core/test/unit_tests/sources/module/test_module.cpp b/level_zero/core/test/unit_tests/sources/module/test_module.cpp index a1fb479e72..3af73bca84 100644 --- a/level_zero/core/test/unit_tests/sources/module/test_module.cpp +++ b/level_zero/core/test/unit_tests/sources/module/test_module.cpp @@ -5,6 +5,7 @@ * */ +#include "shared/source/device_binary_format/debug_zebin.h" #include "shared/source/gmm_helper/gmm.h" #include "shared/source/gmm_helper/gmm_helper.h" #include "shared/source/kernel/implicit_args.h" @@ -1958,5 +1959,39 @@ TEST_F(ModuleTests, givenImplicitArgsRelocationWhenLinkingModuleThenSegmentIsPat EXPECT_TRUE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); } +using ModuleWithZebinTest = Test; +TEST_F(ModuleWithZebinTest, givenNoZebinThenSegmentsAreEmpty) { + auto segments = module->getZebinSegments(); + + EXPECT_EQ(std::numeric_limits::max(), segments.constData.address); + EXPECT_TRUE(segments.constData.data.empty()); + + EXPECT_EQ(std::numeric_limits::max(), segments.varData.address); + EXPECT_TRUE(segments.varData.data.empty()); + + EXPECT_EQ(std::numeric_limits::max(), segments.stringData.address); + EXPECT_TRUE(segments.stringData.data.empty()); + + EXPECT_TRUE(segments.nameToSegMap.empty()); +} + +TEST_F(ModuleWithZebinTest, givenZebinSegmentsThenSegmentsArePopulated) { + module->addSegments(); + auto segments = module->getZebinSegments(); + + auto checkGPUSeg = [](NEO::GraphicsAllocation *alloc, NEO::Debug::Segments::Segment segment) { + EXPECT_EQ(static_cast(alloc->getGpuAddressToPatch()), segment.address); + EXPECT_EQ(reinterpret_cast(alloc->getUnderlyingBuffer()), segment.data.begin()); + EXPECT_EQ(static_cast(alloc->getUnderlyingBufferSize()), segment.data.size()); + }; + checkGPUSeg(module->translationUnit->globalConstBuffer, segments.constData); + checkGPUSeg(module->translationUnit->globalConstBuffer, segments.varData); + checkGPUSeg(module->kernelImmDatas[0]->getIsaGraphicsAllocation(), segments.nameToSegMap["kernel"]); + + EXPECT_EQ(reinterpret_cast(module->translationUnit->programInfo.globalStrings.initData), segments.stringData.address); + EXPECT_EQ(reinterpret_cast(module->translationUnit->programInfo.globalStrings.initData), segments.stringData.data.begin()); + EXPECT_EQ(module->translationUnit->programInfo.globalStrings.size, segments.stringData.data.size()); +} + } // namespace ult } // namespace L0 diff --git a/shared/source/device_binary_format/debug_zebin.cpp b/shared/source/device_binary_format/debug_zebin.cpp index a36420b822..e0a68c5020 100644 --- a/shared/source/device_binary_format/debug_zebin.cpp +++ b/shared/source/device_binary_format/debug_zebin.cpp @@ -14,7 +14,7 @@ namespace NEO { namespace Debug { using namespace Elf; -std::vector createDebugZebin(NEO::Elf::Elf &zebin, const GPUSegments &gpuSegments) { +void DebugZebinCreator::createDebugZebin() { ElfEncoder elfEncoder(false, false); auto &header = elfEncoder.getElfFileHeader(); header.machine = zebin.elfFileHeader->machine; @@ -26,41 +26,24 @@ std::vector createDebugZebin(NEO::Elf::Elf &zebin, const G for (uint32_t i = 0; i < zebin.sectionHeaders.size(); i++) { const auto §ion = zebin.sectionHeaders[i]; auto sectionName = zebin.getSectionName(i); - auto refSectionName = ConstStringRef(sectionName); + ArrayRef sectionData; - uint64_t segGpuAddr = 0U; - ArrayRef data; - - if (refSectionName.startsWith(SectionsNamesZebin::textPrefix.data())) { - auto kernelName = sectionName.substr(SectionsNamesZebin::textPrefix.length()); - auto segmentIdIter = gpuSegments.nameToSectIdMap.find(kernelName); - UNRECOVERABLE_IF(segmentIdIter == gpuSegments.nameToSectIdMap.end()); - const auto &kernel = gpuSegments.kernels[segmentIdIter->second]; - segGpuAddr = kernel.gpuAddress; - data = kernel.data; - } else if (refSectionName == SectionsNamesZebin::dataConst) { - segGpuAddr = gpuSegments.constData.gpuAddress; - data = gpuSegments.constData.data; - } else if (refSectionName == SectionsNamesZebin::dataGlobal) { - segGpuAddr = gpuSegments.varData.gpuAddress; - data = gpuSegments.varData.data; + if (auto segment = getSegmentByName(sectionName)) { + sectionData = segment->data; + elfEncoder.appendProgramHeaderLoad(i, segment->address, sectionData.size()); } else { - data = section.data; + sectionData = section.data; } - if (segGpuAddr != 0U) { - elfEncoder.appendProgramHeaderLoad(i, segGpuAddr, data.size()); - } - - auto §ionHeader = elfEncoder.appendSection(section.header->type, refSectionName, data); + auto §ionHeader = elfEncoder.appendSection(section.header->type, sectionName, sectionData); sectionHeader.link = section.header->link; sectionHeader.info = section.header->info; sectionHeader.name = section.header->name; } - return elfEncoder.encode(); + debugZebin = elfEncoder.encode(); } -void patch(uint64_t addr, uint64_t value, RELOC_TYPE_ZEBIN type) { +void DebugZebinCreator::applyRelocation(uint64_t addr, uint64_t value, RELOC_TYPE_ZEBIN type) { switch (type) { default: UNRECOVERABLE_IF(type != R_ZE_SYM_ADDR) @@ -75,47 +58,57 @@ void patch(uint64_t addr, uint64_t value, RELOC_TYPE_ZEBIN type) { } } -void patchDebugZebin(std::vector &debugZebin, const GPUSegments &gpuSegments) { +void DebugZebinCreator::applyDebugRelocations() { std::string errors, warnings; auto elf = decodeElf(debugZebin, errors, warnings); for (const auto &reloc : elf.getDebugInfoRelocations()) { + auto sectionName = elf.getSectionName(reloc.symbolSectionIndex); - auto refSectionName = ConstStringRef(sectionName); uint64_t sectionAddress = 0U; - if (refSectionName.startsWith(SectionsNamesZebin::textPrefix.data())) { - auto kernelName = sectionName.substr(SectionsNamesZebin::textPrefix.length()); - auto segmentIdIter = gpuSegments.nameToSectIdMap.find(kernelName); - UNRECOVERABLE_IF(segmentIdIter == gpuSegments.nameToSectIdMap.end()); - sectionAddress = gpuSegments.kernels[segmentIdIter->second].gpuAddress; - } else if (refSectionName.startsWith(SectionsNamesZebin::dataConst.data())) { - sectionAddress = gpuSegments.constData.gpuAddress; - } else if (refSectionName.startsWith(SectionsNamesZebin::dataGlobal.data())) { - sectionAddress = gpuSegments.varData.gpuAddress; - } else if (refSectionName.startsWith(SectionsNamesZebin::debugPrefix.data())) { + if (auto segment = getSegmentByName(sectionName)) { + sectionAddress = segment->address; + } else if (ConstStringRef(sectionName).startsWith(SectionsNamesZebin::debugPrefix.data())) { // do not offset debug symbols } else { DEBUG_BREAK_IF(true); continue; } - auto patchValue = sectionAddress + elf.getSymbolValue(reloc.symbolTableIndex) + reloc.addend; - auto patchLocation = reinterpret_cast(debugZebin.data()) + elf.getSectionOffset(reloc.targetSectionIndex) + reloc.offset; - - patch(patchLocation, patchValue, static_cast(reloc.relocType)); + auto value = sectionAddress + elf.getSymbolValue(reloc.symbolTableIndex) + reloc.addend; + auto address = reinterpret_cast(debugZebin.data()) + elf.getSectionOffset(reloc.targetSectionIndex) + reloc.offset; + auto type = static_cast(reloc.relocType); + applyRelocation(address, value, type); } } -std::vector getDebugZebin(ArrayRef zebinBin, const GPUSegments &gpuSegments) { +std::vector createDebugZebin(ArrayRef zebinBin, const Segments &gpuSegments) { std::string errors, warnings; auto zebin = decodeElf(zebinBin, errors, warnings); if (false == errors.empty()) { return {}; } - auto debugZebin = createDebugZebin(zebin, gpuSegments); - patchDebugZebin(debugZebin, gpuSegments); - return debugZebin; + auto dzc = DebugZebinCreator(zebin, gpuSegments); + dzc.createDebugZebin(); + dzc.applyDebugRelocations(); + return dzc.getDebugZebin(); +} + +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; + } else if (sectionName == SectionsNamesZebin::dataConst) { + return &segments.constData; + } else if (sectionName == SectionsNamesZebin::dataGlobal) { + return &segments.varData; + } else if (sectionName == SectionsNamesZebin::dataConstString) { + return &segments.stringData; + } + return nullptr; } } // namespace Debug diff --git a/shared/source/device_binary_format/debug_zebin.h b/shared/source/device_binary_format/debug_zebin.h index 1cf3d182d5..eb5f5a19c1 100644 --- a/shared/source/device_binary_format/debug_zebin.h +++ b/shared/source/device_binary_format/debug_zebin.h @@ -16,21 +16,40 @@ namespace NEO { namespace Debug { -struct GPUSegments { +struct Segments { struct Segment { - uintptr_t gpuAddress = std::numeric_limits::max(); + uintptr_t address = std::numeric_limits::max(); ArrayRef data; }; - using KernelNameToSectionIdMap = std::unordered_map; - Segment varData; - Segment constData; - StackVec kernels; - KernelNameToSectionIdMap nameToSectIdMap; -}; -void patch(uint64_t addr, uint64_t value, NEO::Elf::RELOC_TYPE_ZEBIN type); -void patchDebugZebin(std::vector &debugZebin, const GPUSegments &segmentData); -std::vector createDebugZebin(ArrayRef zebin, const GPUSegments &segmentData); + using CPUSegment = Segment; + using GPUSegment = Segment; + using KernelNameToSegmentMap = std::unordered_map; -std::vector getDebugZebin(ArrayRef zebin, const GPUSegments &segmentData); + GPUSegment varData; + GPUSegment constData; + CPUSegment stringData; + KernelNameToSegmentMap nameToSegMap; +}; + +class DebugZebinCreator { + public: + using Elf = NEO::Elf::Elf; + DebugZebinCreator() = delete; + DebugZebinCreator(Elf &zebin, const Segments &segments) : segments(segments), zebin(zebin) {} + + void applyDebugRelocations(); + void createDebugZebin(); + inline std::vector getDebugZebin() { return debugZebin; } + + protected: + void applyRelocation(uint64_t addr, uint64_t value, NEO::Elf::RELOC_TYPE_ZEBIN type); + const Segments::Segment *getSegmentByName(ConstStringRef sectionName); + + std::vector debugZebin; + const Segments &segments; + Elf &zebin; +}; + +std::vector createDebugZebin(ArrayRef zebin, const Segments &segmentData); } // namespace Debug } // namespace NEO diff --git a/shared/source/utilities/const_stringref.h b/shared/source/utilities/const_stringref.h index b3837c588e..4d6c84323a 100644 --- a/shared/source/utilities/const_stringref.h +++ b/shared/source/utilities/const_stringref.h @@ -59,7 +59,8 @@ class ConstStringRef { : ptr(str.data()), len(str.length()) { } - constexpr ConstStringRef substr(int offset, int len) const noexcept { + template + constexpr ConstStringRef substr(SizeT offset, SizeT len) const noexcept { if (len >= 0) { return ConstStringRef(this->ptr + offset, len); } else { @@ -67,7 +68,8 @@ class ConstStringRef { } } - constexpr ConstStringRef substr(int offset) const noexcept { + template + constexpr ConstStringRef substr(SizeT offset) const noexcept { return ConstStringRef(this->ptr + offset, this->len - offset); } 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 8a5b30f582..0905b1771b 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 @@ -16,10 +16,11 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { MockElfEncoder<> elfEncoder; - NEO::Debug::GPUSegments segments; + NEO::Debug::Segments segments; uint8_t constData[8] = {0x1}; uint8_t varData[8] = {0x2}; uint8_t kernelISA[8] = {0x3}; + uint8_t stringData[8] = {0x4}; uint8_t debugInfo[0x20] = {0x0}; uint8_t debugAbbrev[8] = {0x0}; @@ -30,6 +31,7 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { auto constDataSectionIndex = elfEncoder.getLastSectionHeaderIndex(); elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataGlobal, ArrayRef(varData, sizeof(varData))); auto varDataSectionIndex = elfEncoder.getLastSectionHeaderIndex(); + elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::dataConstString, ArrayRef(stringData, sizeof(stringData))); elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::debugInfo, ArrayRef(debugInfo, sizeof(debugInfo))); auto debugInfoSectionIndex = elfEncoder.getLastSectionHeaderIndex(); elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::debugAbbrev, ArrayRef(debugAbbrev, sizeof(debugAbbrev))); @@ -95,8 +97,8 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { segments.constData = {reinterpret_cast(constData), {constData, sizeof(constData)}}; segments.varData = {reinterpret_cast(varData), {varData, sizeof(varData)}}; - segments.kernels.push_back({reinterpret_cast(kernelISA), {kernelISA, sizeof(kernelISA)}}); - segments.nameToSectIdMap["kernel"] = 0; + segments.stringData = {reinterpret_cast(stringData), {stringData, sizeof(stringData)}}; + segments.nameToSegMap["kernel"] = {reinterpret_cast(kernelISA), {kernelISA, sizeof(kernelISA)}}; auto zebinBin = elfEncoder.encode(); std::string warning, error; @@ -104,7 +106,7 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { ASSERT_TRUE(error.empty()); ASSERT_TRUE(warning.empty()); - auto debugZebinBin = NEO::Debug::getDebugZebin(zebinBin, segments); + auto debugZebinBin = NEO::Debug::createDebugZebin(zebinBin, segments); auto debugZebin = NEO::Elf::decodeElf(debugZebinBin, error, warning); ASSERT_TRUE(error.empty()); ASSERT_TRUE(warning.empty()); @@ -117,7 +119,7 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { EXPECT_EQ(zebin.sectionHeaders.size(), debugZebin.sectionHeaders.size()); - uint64_t offsetKernel, offsetConstData, offsetVarData; + uint64_t offsetKernel, offsetConstData, offsetVarData, offsetStringData; offsetKernel = offsetConstData = offsetVarData = std::numeric_limits::max(); for (uint32_t i = 0; i < zebin.sectionHeaders.size(); ++i) { EXPECT_EQ(zebin.sectionHeaders[i].header->type, debugZebin.sectionHeaders[i].header->type); @@ -129,9 +131,9 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { auto refSectionName = NEO::ConstStringRef(sectionName); if (refSectionName.startsWith(NEO::Elf::SectionsNamesZebin::textPrefix.data())) { auto kernelName = sectionName.substr(NEO::Elf::SectionsNamesZebin::textPrefix.length()); - auto segmentIdIter = segments.nameToSectIdMap.find(kernelName); - ASSERT_TRUE(segmentIdIter != segments.nameToSectIdMap.end()); - const auto &kernel = segments.kernels[segmentIdIter->second]; + auto segmentIdIter = segments.nameToSegMap.find(kernelName); + ASSERT_TRUE(segmentIdIter != segments.nameToSegMap.end()); + const auto &kernel = segmentIdIter->second; EXPECT_EQ(kernel.data.size(), debugZebin.sectionHeaders[i].header->size); EXPECT_TRUE(memcmp(kernel.data.begin(), debugZebin.sectionHeaders[i].data.begin(), kernel.data.size()) == 0); @@ -144,18 +146,22 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { EXPECT_EQ(segments.varData.data.size(), debugZebin.sectionHeaders[i].header->size); EXPECT_TRUE(memcmp(segments.varData.data.begin(), debugZebin.sectionHeaders[i].data.begin(), segments.varData.data.size()) == 0); offsetVarData = debugZebin.sectionHeaders[i].header->offset; + } else if (refSectionName == NEO::Elf::SectionsNamesZebin::dataConstString) { + EXPECT_EQ(segments.stringData.data.size(), debugZebin.sectionHeaders[i].header->size); + EXPECT_TRUE(memcmp(segments.stringData.data.begin(), debugZebin.sectionHeaders[i].data.begin(), segments.stringData.data.size()) == 0); + offsetStringData = debugZebin.sectionHeaders[i].header->offset; } else if (refSectionName == NEO::Elf::SectionsNamesZebin::debugInfo) { EXPECT_EQ(zebin.sectionHeaders[i].header->size, debugZebin.sectionHeaders[i].header->size); auto ptrDebugInfo = debugZebin.sectionHeaders[i].data.begin(); EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[0].offset), - segments.kernels[0].gpuAddress + symbols[0].value + debugRelocations[0].addend); + segments.nameToSegMap["kernel"].address + symbols[0].value + debugRelocations[0].addend); EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[1].offset), - static_cast((segments.constData.gpuAddress + symbols[1].value + debugRelocations[1].addend) & 0xffffffff)); + static_cast((segments.constData.address + symbols[1].value + debugRelocations[1].addend) & 0xffffffff)); EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[2].offset), - static_cast(((segments.varData.gpuAddress + symbols[2].value + debugRelocations[2].addend) >> 32) & 0xffffffff)); + static_cast(((segments.varData.address + symbols[2].value + debugRelocations[2].addend) >> 32) & 0xffffffff)); // debug symbols are not offseted EXPECT_EQ(*reinterpret_cast(ptrDebugInfo + debugRelocations[3].offset), @@ -171,21 +177,26 @@ TEST(DebugZebinTest, givenValidZebinThenDebugZebinIsGenerated) { } } - EXPECT_EQ(3U, debugZebin.programHeaders.size()); - EXPECT_EQ(segments.kernels[0].gpuAddress, static_cast(debugZebin.programHeaders[0].header->vAddr)); - EXPECT_EQ(segments.kernels[0].data.size(), static_cast(debugZebin.programHeaders[0].header->fileSz)); - EXPECT_EQ(segments.kernels[0].data.size(), static_cast(debugZebin.programHeaders[0].header->memSz)); + EXPECT_EQ(4U, debugZebin.programHeaders.size()); + EXPECT_EQ(segments.nameToSegMap["kernel"].address, static_cast(debugZebin.programHeaders[0].header->vAddr)); + EXPECT_EQ(segments.nameToSegMap["kernel"].data.size(), static_cast(debugZebin.programHeaders[0].header->fileSz)); + EXPECT_EQ(segments.nameToSegMap["kernel"].data.size(), static_cast(debugZebin.programHeaders[0].header->memSz)); EXPECT_EQ(offsetKernel, static_cast(debugZebin.programHeaders[0].header->offset)); - EXPECT_EQ(segments.constData.gpuAddress, static_cast(debugZebin.programHeaders[1].header->vAddr)); + EXPECT_EQ(segments.constData.address, static_cast(debugZebin.programHeaders[1].header->vAddr)); EXPECT_EQ(segments.constData.data.size(), static_cast(debugZebin.programHeaders[1].header->fileSz)); EXPECT_EQ(segments.constData.data.size(), static_cast(debugZebin.programHeaders[1].header->memSz)); EXPECT_EQ(offsetConstData, static_cast(debugZebin.programHeaders[1].header->offset)); - EXPECT_EQ(segments.varData.gpuAddress, static_cast(debugZebin.programHeaders[2].header->vAddr)); + EXPECT_EQ(segments.varData.address, static_cast(debugZebin.programHeaders[2].header->vAddr)); EXPECT_EQ(segments.varData.data.size(), static_cast(debugZebin.programHeaders[2].header->fileSz)); EXPECT_EQ(segments.varData.data.size(), static_cast(debugZebin.programHeaders[2].header->memSz)); EXPECT_EQ(offsetVarData, static_cast(debugZebin.programHeaders[2].header->offset)); + + EXPECT_EQ(segments.stringData.address, static_cast(debugZebin.programHeaders[3].header->vAddr)); + EXPECT_EQ(segments.stringData.data.size(), static_cast(debugZebin.programHeaders[3].header->fileSz)); + EXPECT_EQ(segments.stringData.data.size(), static_cast(debugZebin.programHeaders[3].header->memSz)); + EXPECT_EQ(offsetStringData, static_cast(debugZebin.programHeaders[3].header->offset)); } TEST(DebugZebinTest, givenInvalidZebinThenDebugZebinIsNotGenerated) { @@ -195,6 +206,6 @@ TEST(DebugZebinTest, givenInvalidZebinThenDebugZebinIsNotGenerated) { 'E', 'L', 'F'}; - auto debugZebin = NEO::Debug::getDebugZebin(ArrayRef(notZebin, sizeof(notZebin)), {}); + auto debugZebin = NEO::Debug::createDebugZebin(ArrayRef(notZebin, sizeof(notZebin)), {}); EXPECT_EQ(0U, debugZebin.size()); }