Return debug ZeBin on getDebugInfo in Level Zero

Signed-off-by: Kacper Nowak <kacper.nowak@intel.com>
This commit is contained in:
Kacper Nowak 2021-12-08 14:25:03 +00:00 committed by Compute-Runtime-Automation
parent 59bf2e02ff
commit 80ed37faf6
4 changed files with 57 additions and 14 deletions

View File

@ -555,21 +555,25 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice)
return success;
}
void ModuleImp::createDebugZebin() {
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize);
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());
}
void ModuleImp::passDebugData() {
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize);
if (NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(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());
createDebugZebin();
if (device->getSourceLevelDebugger()) {
NEO::DebugData debugData; // pass debug zebin in vIsa field
debugData.vIsa = reinterpret_cast<const char *>(debugZebin.data());
debugData.vIsaSize = static_cast<uint32_t>(debugZebin.size());
debugData.vIsa = reinterpret_cast<const char *>(translationUnit->debugData.get());
debugData.vIsaSize = static_cast<uint32_t>(translationUnit->debugDataSize);
device->getSourceLevelDebugger()->notifyKernelDebugData(&debugData, "debug_zebin", nullptr, 0);
}
} else {
@ -656,11 +660,17 @@ ze_result_t ModuleImp::getDebugInfo(size_t *pDebugDataSize, uint8_t *pDebugData)
if (translationUnit == nullptr) {
return ZE_RESULT_ERROR_UNINITIALIZED;
}
if (pDebugData == nullptr) {
*pDebugDataSize = translationUnit->debugDataSize;
return ZE_RESULT_SUCCESS;
auto refBin = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize);
if (nullptr == translationUnit->debugData.get() && NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Zebin>(refBin)) {
createDebugZebin();
}
memcpy_s(pDebugData, *pDebugDataSize, translationUnit->debugData.get(), translationUnit->debugDataSize);
if (pDebugData != nullptr) {
if (*pDebugDataSize < translationUnit->debugDataSize) {
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
}
memcpy_s(pDebugData, *pDebugDataSize, translationUnit->debugData.get(), translationUnit->debugDataSize);
}
*pDebugDataSize = translationUnit->debugDataSize;
return ZE_RESULT_SUCCESS;
}

View File

@ -139,6 +139,7 @@ struct ModuleImp : public Module {
void checkIfPrivateMemoryPerDispatchIsNeeded() override;
NEO::Debug::Segments getZebinSegments();
void passDebugData();
void createDebugZebin();
Device *device = nullptr;
PRODUCT_FAMILY productFamily{};

View File

@ -315,6 +315,7 @@ struct ModuleWithZebinFixture : public DeviceFixture {
};
struct MockModuleWithZebin : public L0::ModuleImp {
using ModuleImp::getDebugInfo;
using ModuleImp::getZebinSegments;
using ModuleImp::kernelImmDatas;
using ModuleImp::passDebugData;

View File

@ -2088,5 +2088,36 @@ TEST_F(ModuleWithZebinTest, givenZebinSegmentsThenSegmentsArePopulated) {
EXPECT_EQ(module->translationUnit->programInfo.globalStrings.size, segments.stringData.data.size());
}
TEST_F(ModuleWithZebinTest, givenValidZebinWhenGettingDebugInfoThenDebugZebinIsCreatedAndReturned) {
module->addEmptyZebin();
size_t debugDataSize;
module->getDebugInfo(&debugDataSize, nullptr);
auto debugData = std::make_unique<uint8_t[]>(debugDataSize);
ze_result_t retCode = module->getDebugInfo(&debugDataSize, debugData.get());
ASSERT_NE(nullptr, module->translationUnit->debugData.get());
EXPECT_EQ(0, memcmp(module->translationUnit->debugData.get(), debugData.get(), debugDataSize));
EXPECT_EQ(retCode, ZE_RESULT_SUCCESS);
}
TEST_F(ModuleWithZebinTest, givenValidZebinAndPassedDataSmallerThanDebugDataThenErrorIsReturned) {
module->addEmptyZebin();
size_t debugDataSize;
module->getDebugInfo(&debugDataSize, nullptr);
auto debugData = std::make_unique<uint8_t[]>(debugDataSize);
debugDataSize = 0;
ze_result_t errorCode = module->getDebugInfo(&debugDataSize, debugData.get());
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, errorCode);
}
TEST_F(ModuleWithZebinTest, givenNonZebinaryFormatWhenGettingDebugInfoThenDebugZebinIsNotCreated) {
size_t mockProgramSize = sizeof(Elf::ElfFileHeader<Elf::EI_CLASS_64>);
module->translationUnit->unpackedDeviceBinary = std::make_unique<char[]>(mockProgramSize);
module->translationUnit->unpackedDeviceBinarySize = mockProgramSize;
size_t debugDataSize;
ze_result_t retCode = module->getDebugInfo(&debugDataSize, nullptr);
EXPECT_EQ(debugDataSize, 0u);
EXPECT_EQ(retCode, ZE_RESULT_SUCCESS);
}
} // namespace ult
} // namespace L0