Skip to content

Commit 6dd0f0c

Browse files
Relocate debug data
Related-To: NEO-4769 Signed-off-by: Mateusz Hoppe <[email protected]>
1 parent a0d3e8b commit 6dd0f0c

File tree

17 files changed

+580
-52
lines changed

17 files changed

+580
-52
lines changed

level_zero/core/source/kernel/kernel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ struct KernelImmutableData {
6363
const NEO::KernelInfo *getKernelInfo() const { return kernelInfo; }
6464

6565
protected:
66+
MOCKABLE_VIRTUAL void createRelocatedDebugData(NEO::GraphicsAllocation *globalConstBuffer,
67+
NEO::GraphicsAllocation *globalVarBuffer);
68+
6669
Device *device = nullptr;
6770
NEO::KernelInfo *kernelInfo = nullptr;
6871
NEO::KernelDescriptor *kernelDescriptor = nullptr;

level_zero/core/source/kernel/kernel_imp.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,12 @@ void KernelImmutableData::initialize(NEO::KernelInfo *kernelInfo, Device *device
121121
}
122122

123123
isaGraphicsAllocation.reset(allocation);
124-
if (device->getL0Debugger() && kernelInfo->kernelDescriptor.external.debugData.get()) {
125-
device->getL0Debugger()->registerElf(kernelInfo->kernelDescriptor.external.debugData.get(), allocation);
124+
125+
if (neoDevice->getDebugger() && kernelInfo->kernelDescriptor.external.debugData.get()) {
126+
createRelocatedDebugData(globalConstBuffer, globalVarBuffer);
127+
if (device->getL0Debugger()) {
128+
device->getL0Debugger()->registerElf(kernelInfo->kernelDescriptor.external.debugData.get(), allocation);
129+
}
126130
}
127131

128132
this->crossThreadDataSize = this->kernelDescriptor->kernelAttributes.crossThreadDataSize;
@@ -185,6 +189,41 @@ void KernelImmutableData::initialize(NEO::KernelInfo *kernelInfo, Device *device
185189
}
186190
}
187191

192+
void KernelImmutableData::createRelocatedDebugData(NEO::GraphicsAllocation *globalConstBuffer,
193+
NEO::GraphicsAllocation *globalVarBuffer) {
194+
NEO::Linker::SegmentInfo globalData;
195+
NEO::Linker::SegmentInfo constData;
196+
if (globalVarBuffer) {
197+
globalData.gpuAddress = globalVarBuffer->getGpuAddress();
198+
globalData.segmentSize = globalVarBuffer->getUnderlyingBufferSize();
199+
}
200+
if (globalConstBuffer) {
201+
constData.gpuAddress = globalConstBuffer->getGpuAddress();
202+
constData.segmentSize = globalConstBuffer->getUnderlyingBufferSize();
203+
}
204+
205+
if (kernelInfo->kernelDescriptor.external.debugData.get()) {
206+
std::string outErrReason;
207+
std::string outWarning;
208+
auto decodedElf = NEO::Elf::decodeElf<NEO::Elf::EI_CLASS_64>(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(kernelInfo->kernelDescriptor.external.debugData->vIsa),
209+
kernelInfo->kernelDescriptor.external.debugData->vIsaSize),
210+
outErrReason, outWarning);
211+
212+
if (decodedElf.getDebugInfoRelocations().size() > 1) {
213+
auto size = kernelInfo->kernelDescriptor.external.debugData->vIsaSize;
214+
kernelInfo->kernelDescriptor.external.relocatedDebugData = std::make_unique<uint8_t[]>(size);
215+
216+
memcpy_s(kernelInfo->kernelDescriptor.external.relocatedDebugData.get(), size, kernelInfo->kernelDescriptor.external.debugData->vIsa, kernelInfo->kernelDescriptor.external.debugData->vIsaSize);
217+
218+
NEO::Linker::SegmentInfo textSegment = {getIsaGraphicsAllocation()->getGpuAddress(),
219+
getIsaGraphicsAllocation()->getUnderlyingBufferSize()};
220+
221+
NEO::Linker::applyDebugDataRelocations(decodedElf, ArrayRef<uint8_t>(kernelInfo->kernelDescriptor.external.relocatedDebugData.get(), size),
222+
textSegment, globalData, constData);
223+
}
224+
}
225+
}
226+
188227
uint32_t KernelImmutableData::getIsaSize() const {
189228
return static_cast<uint32_t>(isaGraphicsAllocation->getUnderlyingBufferSize());
190229
}

level_zero/core/source/module/module_imp.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -353,14 +353,6 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice)
353353
verifyDebugCapabilities();
354354

355355
this->updateBuildLog(neoDevice);
356-
if (debugEnabled && device->getSourceLevelDebugger()) {
357-
for (auto kernelInfo : this->translationUnit->programInfo.kernelInfos) {
358-
device->getSourceLevelDebugger()->notifyKernelDebugData(kernelInfo->kernelDescriptor.external.debugData.get(),
359-
kernelInfo->kernelDescriptor.kernelMetadata.kernelName,
360-
kernelInfo->heapInfo.pKernelHeap,
361-
kernelInfo->heapInfo.KernelHeapSize);
362-
}
363-
}
364356

365357
if (false == success) {
366358
return false;
@@ -376,6 +368,28 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice)
376368
}
377369
this->maxGroupSize = static_cast<uint32_t>(this->translationUnit->device->getNEODevice()->getDeviceInfo().maxWorkGroupSize);
378370

371+
if (debugEnabled) {
372+
if (device->getSourceLevelDebugger()) {
373+
for (auto kernelInfo : this->translationUnit->programInfo.kernelInfos) {
374+
NEO::DebugData *notifyDebugData = kernelInfo->kernelDescriptor.external.debugData.get();
375+
NEO::DebugData relocatedDebugData;
376+
377+
if (kernelInfo->kernelDescriptor.external.relocatedDebugData.get()) {
378+
relocatedDebugData.genIsa = kernelInfo->kernelDescriptor.external.debugData->genIsa;
379+
relocatedDebugData.genIsaSize = kernelInfo->kernelDescriptor.external.debugData->genIsaSize;
380+
relocatedDebugData.vIsa = reinterpret_cast<char *>(kernelInfo->kernelDescriptor.external.relocatedDebugData.get());
381+
relocatedDebugData.vIsaSize = kernelInfo->kernelDescriptor.external.debugData->vIsaSize;
382+
notifyDebugData = &relocatedDebugData;
383+
}
384+
385+
device->getSourceLevelDebugger()->notifyKernelDebugData(notifyDebugData,
386+
kernelInfo->kernelDescriptor.kernelMetadata.kernelName,
387+
kernelInfo->heapInfo.pKernelHeap,
388+
kernelInfo->heapInfo.KernelHeapSize);
389+
}
390+
}
391+
}
392+
379393
return this->linkBinary();
380394
}
381395

level_zero/core/source/module/module_imp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2019-2020 Intel Corporation
2+
* Copyright (C) 2019-2021 Intel Corporation
33
*
44
* SPDX-License-Identifier: MIT
55
*
@@ -120,6 +120,7 @@ struct ModuleImp : public Module {
120120
protected:
121121
void copyPatchedSegments(const NEO::Linker::PatchableSegments &isaSegmentsForPatching);
122122
void verifyDebugCapabilities();
123+
123124
Device *device = nullptr;
124125
PRODUCT_FAMILY productFamily{};
125126
std::unique_ptr<ModuleTranslationUnit> translationUnit;

level_zero/core/test/unit_tests/mocks/mock_kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace ult {
2121
template <>
2222
struct WhiteBox<::L0::KernelImmutableData> : public ::L0::KernelImmutableData {
2323
using BaseClass = ::L0::KernelImmutableData;
24+
using ::L0::KernelImmutableData::createRelocatedDebugData;
2425
using ::L0::KernelImmutableData::crossThreadDataSize;
2526
using ::L0::KernelImmutableData::crossThreadDataTemplate;
2627
using ::L0::KernelImmutableData::device;

level_zero/core/test/unit_tests/mocks/mock_module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ struct MockModuleTranslationUnit : public L0::ModuleTranslationUnit {
6565

6666
struct MockModule : public L0::ModuleImp {
6767
using ModuleImp::debugEnabled;
68+
using ModuleImp::kernelImmDatas;
69+
using ModuleImp::translationUnit;
6870

6971
MockModule(L0::Device *device,
7072
L0::ModuleBuildLog *moduleBuildLog,
@@ -77,6 +79,7 @@ struct MockModule : public L0::ModuleImp {
7779
const KernelImmutableData *getKernelImmutableData(const char *functionName) const override {
7880
return kernelImmData;
7981
}
82+
8083
KernelImmutableData *kernelImmData = nullptr;
8184
};
8285

level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "shared/source/device_binary_format/patchtokens_decoder.h"
99
#include "shared/source/kernel/kernel_descriptor_from_patchtokens.h"
10+
#include "shared/test/common/mocks/mock_elf.h"
1011

1112
#include "opencl/source/program/kernel_info.h"
1213
#include "opencl/source/program/kernel_info_from_patchtokens.h"
@@ -106,6 +107,140 @@ TEST_F(DeviceWithDebuggerEnabledTest, GivenNonDebuggeableKernelWhenModuleIsIniti
106107
EXPECT_FALSE(module->isDebugEnabled());
107108
}
108109

110+
using ModuleWithSLDTest = Test<ModuleFixture>;
111+
112+
TEST_F(ModuleWithSLDTest, GivenNoDebugDataWhenInitializingModuleThenRelocatedDebugDataIsNotCreated) {
113+
auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions();
114+
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip);
115+
auto debugger = new MockActiveSourceLevelDebugger(new MockOsLibrary);
116+
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(debugger);
117+
118+
uint8_t binary[10];
119+
ze_module_desc_t moduleDesc = {};
120+
moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
121+
moduleDesc.pInputModule = binary;
122+
moduleDesc.inputSize = 10;
123+
ModuleBuildLog *moduleBuildLog = nullptr;
124+
125+
std::unique_ptr<MockModule> module = std::make_unique<MockModule>(device,
126+
moduleBuildLog,
127+
ModuleType::User);
128+
module->translationUnit = std::make_unique<MockModuleTranslationUnit>(device);
129+
130+
uint32_t kernelHeap = 0;
131+
auto kernelInfo = new KernelInfo();
132+
kernelInfo->heapInfo.KernelHeapSize = 1;
133+
kernelInfo->heapInfo.pKernelHeap = &kernelHeap;
134+
135+
Mock<::L0::Kernel> kernel;
136+
kernel.module = module.get();
137+
kernel.immutableData.kernelInfo = kernelInfo;
138+
139+
kernel.immutableData.surfaceStateHeapSize = 64;
140+
kernel.immutableData.surfaceStateHeapTemplate.reset(new uint8_t[64]);
141+
kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0;
142+
143+
module->kernelImmData = &kernel.immutableData;
144+
module->translationUnit->programInfo.kernelInfos.push_back(kernelInfo);
145+
146+
EXPECT_EQ(nullptr, module->translationUnit->debugData.get());
147+
auto result = module->initialize(&moduleDesc, neoDevice);
148+
EXPECT_TRUE(result);
149+
150+
EXPECT_EQ(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData);
151+
}
152+
153+
TEST_F(ModuleWithSLDTest, GivenDebugDataWithSingleRelocationWhenInitializingModuleThenRelocatedDebugDataIsNotCreated) {
154+
auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions();
155+
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip);
156+
auto debugger = new MockActiveSourceLevelDebugger(new MockOsLibrary);
157+
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(debugger);
158+
159+
createKernel();
160+
161+
uint8_t binary[10];
162+
ze_module_desc_t moduleDesc = {};
163+
moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
164+
moduleDesc.pInputModule = binary;
165+
moduleDesc.inputSize = 10;
166+
ModuleBuildLog *moduleBuildLog = nullptr;
167+
168+
std::unique_ptr<MockModule> moduleMock = std::make_unique<MockModule>(device, moduleBuildLog, ModuleType::User);
169+
moduleMock->translationUnit = std::make_unique<MockModuleTranslationUnit>(device);
170+
171+
uint32_t kernelHeap = 0;
172+
auto kernelInfo = new KernelInfo();
173+
kernelInfo->heapInfo.KernelHeapSize = 1;
174+
kernelInfo->heapInfo.pKernelHeap = &kernelHeap;
175+
176+
Mock<::L0::Kernel> kernelMock;
177+
kernelMock.module = moduleMock.get();
178+
kernelMock.immutableData.kernelInfo = kernelInfo;
179+
180+
kernelMock.immutableData.surfaceStateHeapSize = 64;
181+
kernelMock.immutableData.surfaceStateHeapTemplate.reset(new uint8_t[64]);
182+
kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0;
183+
184+
moduleMock->kernelImmData = &kernelMock.immutableData;
185+
moduleMock->translationUnit->programInfo.kernelInfos.push_back(kernelInfo);
186+
187+
kernelInfo->kernelDescriptor.external.debugData = std::make_unique<NEO::DebugData>();
188+
kernelInfo->kernelDescriptor.external.debugData->vIsa = kernel->getKernelDescriptor().external.debugData->vIsa;
189+
kernelInfo->kernelDescriptor.external.debugData->vIsaSize = kernel->getKernelDescriptor().external.debugData->vIsaSize;
190+
kernelInfo->kernelDescriptor.external.debugData->genIsa = nullptr;
191+
kernelInfo->kernelDescriptor.external.debugData->genIsaSize = 0;
192+
193+
auto result = moduleMock->initialize(&moduleDesc, neoDevice);
194+
EXPECT_TRUE(result);
195+
196+
EXPECT_EQ(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData);
197+
}
198+
199+
TEST_F(ModuleWithSLDTest, GivenDebugDataWithMultipleRelocationsWhenInitializingModuleThenRelocatedDebugDataIsCreated) {
200+
auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions();
201+
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip);
202+
auto debugger = new MockActiveSourceLevelDebugger(new MockOsLibrary);
203+
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(debugger);
204+
205+
uint8_t binary[10];
206+
ze_module_desc_t moduleDesc = {};
207+
moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
208+
moduleDesc.pInputModule = binary;
209+
moduleDesc.inputSize = 10;
210+
ModuleBuildLog *moduleBuildLog = nullptr;
211+
212+
std::unique_ptr<MockModule> moduleMock = std::make_unique<MockModule>(device, moduleBuildLog, ModuleType::User);
213+
moduleMock->translationUnit = std::make_unique<MockModuleTranslationUnit>(device);
214+
215+
uint32_t kernelHeap = 0;
216+
auto kernelInfo = new KernelInfo();
217+
kernelInfo->heapInfo.KernelHeapSize = 1;
218+
kernelInfo->heapInfo.pKernelHeap = &kernelHeap;
219+
220+
Mock<::L0::Kernel> kernelMock;
221+
kernelMock.module = moduleMock.get();
222+
kernelMock.immutableData.kernelInfo = kernelInfo;
223+
kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0;
224+
225+
moduleMock->kernelImmData = &kernelMock.immutableData;
226+
moduleMock->translationUnit->programInfo.kernelInfos.push_back(kernelInfo);
227+
228+
kernelInfo->kernelDescriptor.external.debugData = std::make_unique<NEO::DebugData>();
229+
230+
auto debugData = MockElfEncoder<>::createRelocateableDebugDataElf();
231+
kernelInfo->kernelDescriptor.external.debugData->vIsaSize = static_cast<uint32_t>(debugData.size());
232+
kernelInfo->kernelDescriptor.external.debugData->vIsa = reinterpret_cast<char *>(debugData.data());
233+
kernelInfo->kernelDescriptor.external.debugData->genIsa = nullptr;
234+
kernelInfo->kernelDescriptor.external.debugData->genIsaSize = 0;
235+
236+
EXPECT_EQ(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData);
237+
238+
auto result = moduleMock->initialize(&moduleDesc, neoDevice);
239+
EXPECT_TRUE(result);
240+
241+
EXPECT_NE(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData);
242+
}
243+
109244
using KernelDebugSurfaceTest = Test<ModuleFixture>;
110245

111246
HWTEST_F(KernelDebugSurfaceTest, givenDebuggerAndBindfulKernelWhenAppendingKernelToCommandListThenBindfulSurfaceStateForDebugSurfaceIsProgrammed) {

level_zero/core/test/unit_tests/sources/module/test_module.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "shared/source/gmm_helper/gmm.h"
99
#include "shared/source/gmm_helper/gmm_helper.h"
1010
#include "shared/test/common/helpers/debug_manager_state_restore.h"
11+
#include "shared/test/common/mocks/mock_elf.h"
1112
#include "shared/test/common/mocks/mock_graphics_allocation.h"
1213
#include "shared/test/unit_test/compiler_interface/linker_mock.h"
1314
#include "shared/test/unit_test/device_binary_format/zebin_tests.h"
@@ -857,5 +858,56 @@ TEST_F(ModuleTest, givenInternalOptionsWhenBindlessDisabledThenBindlesOptionsNot
857858
EXPECT_FALSE(NEO::CompilerOptions::contains(internalBuildOptions, NEO::CompilerOptions::bindlessMode));
858859
}
859860

861+
using ModuleDebugDataTest = Test<DeviceFixture>;
862+
TEST_F(ModuleDebugDataTest, GivenDebugDataWithRelocationsWhenCreatingRelocatedDebugDataThenRelocationsAreApplied) {
863+
auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions();
864+
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip);
865+
866+
uint8_t binary[10];
867+
ze_module_desc_t moduleDesc = {};
868+
moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
869+
moduleDesc.pInputModule = binary;
870+
moduleDesc.inputSize = 10;
871+
ModuleBuildLog *moduleBuildLog = nullptr;
872+
873+
std::unique_ptr<MockModule> module = std::make_unique<MockModule>(device,
874+
moduleBuildLog,
875+
ModuleType::User);
876+
module->translationUnit = std::make_unique<MockModuleTranslationUnit>(device);
877+
878+
module->translationUnit->globalVarBuffer = neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
879+
{device->getRootDeviceIndex(), MemoryConstants::pageSize, NEO::GraphicsAllocation::AllocationType::BUFFER, neoDevice->getDeviceBitfield()});
880+
module->translationUnit->globalConstBuffer = neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties(
881+
{device->getRootDeviceIndex(), MemoryConstants::pageSize, NEO::GraphicsAllocation::AllocationType::BUFFER, neoDevice->getDeviceBitfield()});
882+
883+
uint32_t kernelHeap = 0;
884+
auto kernelInfo = new KernelInfo();
885+
kernelInfo->heapInfo.KernelHeapSize = 1;
886+
kernelInfo->heapInfo.pKernelHeap = &kernelHeap;
887+
888+
kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0;
889+
kernelInfo->kernelDescriptor.external.debugData = std::make_unique<NEO::DebugData>();
890+
891+
auto debugData = MockElfEncoder<>::createRelocateableDebugDataElf();
892+
893+
kernelInfo->kernelDescriptor.external.debugData->vIsaSize = static_cast<uint32_t>(debugData.size());
894+
kernelInfo->kernelDescriptor.external.debugData->vIsa = reinterpret_cast<char *>(debugData.data());
895+
896+
// pass kernelInfo ownership to programInfo
897+
module->translationUnit->programInfo.kernelInfos.push_back(kernelInfo);
898+
899+
std::unique_ptr<WhiteBox<::L0::KernelImmutableData>> kernelImmData{new WhiteBox<::L0::KernelImmutableData>(this->device)};
900+
kernelImmData->initialize(kernelInfo, device, 0, module->translationUnit->globalConstBuffer, module->translationUnit->globalVarBuffer, false);
901+
kernelImmData->createRelocatedDebugData(module->translationUnit->globalConstBuffer, module->translationUnit->globalVarBuffer);
902+
903+
module->kernelImmDatas.push_back(std::move(kernelImmData));
904+
905+
EXPECT_NE(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData);
906+
907+
uint64_t *relocAddress = reinterpret_cast<uint64_t *>(kernelInfo->kernelDescriptor.external.relocatedDebugData.get() + 600);
908+
auto expectedValue = module->kernelImmDatas[0]->getIsaGraphicsAllocation()->getGpuAddress() + 0x1a8;
909+
EXPECT_EQ(expectedValue, *relocAddress);
910+
}
911+
860912
} // namespace ult
861913
} // namespace L0

0 commit comments

Comments
 (0)