diff --git a/level_zero/core/source/kernel/kernel.h b/level_zero/core/source/kernel/kernel.h index a8b880e9ab..a1a90a2ff6 100644 --- a/level_zero/core/source/kernel/kernel.h +++ b/level_zero/core/source/kernel/kernel.h @@ -63,6 +63,9 @@ struct KernelImmutableData { const NEO::KernelInfo *getKernelInfo() const { return kernelInfo; } protected: + MOCKABLE_VIRTUAL void createRelocatedDebugData(NEO::GraphicsAllocation *globalConstBuffer, + NEO::GraphicsAllocation *globalVarBuffer); + Device *device = nullptr; NEO::KernelInfo *kernelInfo = nullptr; NEO::KernelDescriptor *kernelDescriptor = nullptr; diff --git a/level_zero/core/source/kernel/kernel_imp.cpp b/level_zero/core/source/kernel/kernel_imp.cpp index 41ed6a3a24..cbc702e9fa 100644 --- a/level_zero/core/source/kernel/kernel_imp.cpp +++ b/level_zero/core/source/kernel/kernel_imp.cpp @@ -121,8 +121,12 @@ void KernelImmutableData::initialize(NEO::KernelInfo *kernelInfo, Device *device } isaGraphicsAllocation.reset(allocation); - if (device->getL0Debugger() && kernelInfo->kernelDescriptor.external.debugData.get()) { - device->getL0Debugger()->registerElf(kernelInfo->kernelDescriptor.external.debugData.get(), allocation); + + if (neoDevice->getDebugger() && kernelInfo->kernelDescriptor.external.debugData.get()) { + createRelocatedDebugData(globalConstBuffer, globalVarBuffer); + if (device->getL0Debugger()) { + device->getL0Debugger()->registerElf(kernelInfo->kernelDescriptor.external.debugData.get(), allocation); + } } this->crossThreadDataSize = this->kernelDescriptor->kernelAttributes.crossThreadDataSize; @@ -185,6 +189,41 @@ void KernelImmutableData::initialize(NEO::KernelInfo *kernelInfo, Device *device } } +void KernelImmutableData::createRelocatedDebugData(NEO::GraphicsAllocation *globalConstBuffer, + NEO::GraphicsAllocation *globalVarBuffer) { + NEO::Linker::SegmentInfo globalData; + NEO::Linker::SegmentInfo constData; + if (globalVarBuffer) { + globalData.gpuAddress = globalVarBuffer->getGpuAddress(); + globalData.segmentSize = globalVarBuffer->getUnderlyingBufferSize(); + } + if (globalConstBuffer) { + constData.gpuAddress = globalConstBuffer->getGpuAddress(); + constData.segmentSize = globalConstBuffer->getUnderlyingBufferSize(); + } + + if (kernelInfo->kernelDescriptor.external.debugData.get()) { + std::string outErrReason; + std::string outWarning; + auto decodedElf = NEO::Elf::decodeElf(ArrayRef(reinterpret_cast(kernelInfo->kernelDescriptor.external.debugData->vIsa), + kernelInfo->kernelDescriptor.external.debugData->vIsaSize), + outErrReason, outWarning); + + if (decodedElf.getDebugInfoRelocations().size() > 1) { + auto size = kernelInfo->kernelDescriptor.external.debugData->vIsaSize; + kernelInfo->kernelDescriptor.external.relocatedDebugData = std::make_unique(size); + + memcpy_s(kernelInfo->kernelDescriptor.external.relocatedDebugData.get(), size, kernelInfo->kernelDescriptor.external.debugData->vIsa, kernelInfo->kernelDescriptor.external.debugData->vIsaSize); + + NEO::Linker::SegmentInfo textSegment = {getIsaGraphicsAllocation()->getGpuAddress(), + getIsaGraphicsAllocation()->getUnderlyingBufferSize()}; + + NEO::Linker::applyDebugDataRelocations(decodedElf, ArrayRef(kernelInfo->kernelDescriptor.external.relocatedDebugData.get(), size), + textSegment, globalData, constData); + } + } +} + uint32_t KernelImmutableData::getIsaSize() const { return static_cast(isaGraphicsAllocation->getUnderlyingBufferSize()); } diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index d382665548..6c7c1088d7 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -353,14 +353,6 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) verifyDebugCapabilities(); this->updateBuildLog(neoDevice); - if (debugEnabled && device->getSourceLevelDebugger()) { - for (auto kernelInfo : this->translationUnit->programInfo.kernelInfos) { - device->getSourceLevelDebugger()->notifyKernelDebugData(kernelInfo->kernelDescriptor.external.debugData.get(), - kernelInfo->kernelDescriptor.kernelMetadata.kernelName, - kernelInfo->heapInfo.pKernelHeap, - kernelInfo->heapInfo.KernelHeapSize); - } - } if (false == success) { return false; @@ -376,6 +368,28 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) } this->maxGroupSize = static_cast(this->translationUnit->device->getNEODevice()->getDeviceInfo().maxWorkGroupSize); + if (debugEnabled) { + if (device->getSourceLevelDebugger()) { + for (auto kernelInfo : this->translationUnit->programInfo.kernelInfos) { + NEO::DebugData *notifyDebugData = kernelInfo->kernelDescriptor.external.debugData.get(); + NEO::DebugData relocatedDebugData; + + if (kernelInfo->kernelDescriptor.external.relocatedDebugData.get()) { + relocatedDebugData.genIsa = kernelInfo->kernelDescriptor.external.debugData->genIsa; + relocatedDebugData.genIsaSize = kernelInfo->kernelDescriptor.external.debugData->genIsaSize; + relocatedDebugData.vIsa = reinterpret_cast(kernelInfo->kernelDescriptor.external.relocatedDebugData.get()); + relocatedDebugData.vIsaSize = kernelInfo->kernelDescriptor.external.debugData->vIsaSize; + notifyDebugData = &relocatedDebugData; + } + + device->getSourceLevelDebugger()->notifyKernelDebugData(notifyDebugData, + kernelInfo->kernelDescriptor.kernelMetadata.kernelName, + kernelInfo->heapInfo.pKernelHeap, + kernelInfo->heapInfo.KernelHeapSize); + } + } + } + return this->linkBinary(); } diff --git a/level_zero/core/source/module/module_imp.h b/level_zero/core/source/module/module_imp.h index fcafe87318..6e7c5929f9 100644 --- a/level_zero/core/source/module/module_imp.h +++ b/level_zero/core/source/module/module_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -120,6 +120,7 @@ struct ModuleImp : public Module { protected: void copyPatchedSegments(const NEO::Linker::PatchableSegments &isaSegmentsForPatching); void verifyDebugCapabilities(); + Device *device = nullptr; PRODUCT_FAMILY productFamily{}; std::unique_ptr translationUnit; diff --git a/level_zero/core/test/unit_tests/mocks/mock_kernel.h b/level_zero/core/test/unit_tests/mocks/mock_kernel.h index 0ccb5a2942..d3e1acba3f 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_kernel.h +++ b/level_zero/core/test/unit_tests/mocks/mock_kernel.h @@ -21,6 +21,7 @@ namespace ult { template <> struct WhiteBox<::L0::KernelImmutableData> : public ::L0::KernelImmutableData { using BaseClass = ::L0::KernelImmutableData; + using ::L0::KernelImmutableData::createRelocatedDebugData; using ::L0::KernelImmutableData::crossThreadDataSize; using ::L0::KernelImmutableData::crossThreadDataTemplate; using ::L0::KernelImmutableData::device; diff --git a/level_zero/core/test/unit_tests/mocks/mock_module.h b/level_zero/core/test/unit_tests/mocks/mock_module.h index d56d3de08b..d4d39d285b 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_module.h +++ b/level_zero/core/test/unit_tests/mocks/mock_module.h @@ -65,6 +65,8 @@ struct MockModuleTranslationUnit : public L0::ModuleTranslationUnit { struct MockModule : public L0::ModuleImp { using ModuleImp::debugEnabled; + using ModuleImp::kernelImmDatas; + using ModuleImp::translationUnit; MockModule(L0::Device *device, L0::ModuleBuildLog *moduleBuildLog, @@ -77,6 +79,7 @@ struct MockModule : public L0::ModuleImp { const KernelImmutableData *getKernelImmutableData(const char *functionName) const override { return kernelImmData; } + KernelImmutableData *kernelImmData = nullptr; }; 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 0f9c49d906..c066d0f913 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 @@ -7,6 +7,7 @@ #include "shared/source/device_binary_format/patchtokens_decoder.h" #include "shared/source/kernel/kernel_descriptor_from_patchtokens.h" +#include "shared/test/common/mocks/mock_elf.h" #include "opencl/source/program/kernel_info.h" #include "opencl/source/program/kernel_info_from_patchtokens.h" @@ -106,6 +107,140 @@ TEST_F(DeviceWithDebuggerEnabledTest, GivenNonDebuggeableKernelWhenModuleIsIniti EXPECT_FALSE(module->isDebugEnabled()); } +using ModuleWithSLDTest = Test; + +TEST_F(ModuleWithSLDTest, GivenNoDebugDataWhenInitializingModuleThenRelocatedDebugDataIsNotCreated) { + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto debugger = new MockActiveSourceLevelDebugger(new MockOsLibrary); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(debugger); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + ModuleBuildLog *moduleBuildLog = nullptr; + + std::unique_ptr module = std::make_unique(device, + moduleBuildLog, + ModuleType::User); + module->translationUnit = std::make_unique(device); + + uint32_t kernelHeap = 0; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + Mock<::L0::Kernel> kernel; + kernel.module = module.get(); + kernel.immutableData.kernelInfo = kernelInfo; + + kernel.immutableData.surfaceStateHeapSize = 64; + kernel.immutableData.surfaceStateHeapTemplate.reset(new uint8_t[64]); + kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0; + + module->kernelImmData = &kernel.immutableData; + module->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + + EXPECT_EQ(nullptr, module->translationUnit->debugData.get()); + auto result = module->initialize(&moduleDesc, neoDevice); + EXPECT_TRUE(result); + + EXPECT_EQ(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData); +} + +TEST_F(ModuleWithSLDTest, GivenDebugDataWithSingleRelocationWhenInitializingModuleThenRelocatedDebugDataIsNotCreated) { + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto debugger = new MockActiveSourceLevelDebugger(new MockOsLibrary); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(debugger); + + createKernel(); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + ModuleBuildLog *moduleBuildLog = nullptr; + + std::unique_ptr moduleMock = std::make_unique(device, moduleBuildLog, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + + uint32_t kernelHeap = 0; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + Mock<::L0::Kernel> kernelMock; + kernelMock.module = moduleMock.get(); + kernelMock.immutableData.kernelInfo = kernelInfo; + + kernelMock.immutableData.surfaceStateHeapSize = 64; + kernelMock.immutableData.surfaceStateHeapTemplate.reset(new uint8_t[64]); + kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0; + + moduleMock->kernelImmData = &kernelMock.immutableData; + moduleMock->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + + kernelInfo->kernelDescriptor.external.debugData = std::make_unique(); + kernelInfo->kernelDescriptor.external.debugData->vIsa = kernel->getKernelDescriptor().external.debugData->vIsa; + kernelInfo->kernelDescriptor.external.debugData->vIsaSize = kernel->getKernelDescriptor().external.debugData->vIsaSize; + kernelInfo->kernelDescriptor.external.debugData->genIsa = nullptr; + kernelInfo->kernelDescriptor.external.debugData->genIsaSize = 0; + + auto result = moduleMock->initialize(&moduleDesc, neoDevice); + EXPECT_TRUE(result); + + EXPECT_EQ(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData); +} + +TEST_F(ModuleWithSLDTest, GivenDebugDataWithMultipleRelocationsWhenInitializingModuleThenRelocatedDebugDataIsCreated) { + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + auto debugger = new MockActiveSourceLevelDebugger(new MockOsLibrary); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0]->debugger.reset(debugger); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + ModuleBuildLog *moduleBuildLog = nullptr; + + std::unique_ptr moduleMock = std::make_unique(device, moduleBuildLog, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + + uint32_t kernelHeap = 0; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + Mock<::L0::Kernel> kernelMock; + kernelMock.module = moduleMock.get(); + kernelMock.immutableData.kernelInfo = kernelInfo; + kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0; + + moduleMock->kernelImmData = &kernelMock.immutableData; + moduleMock->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + + kernelInfo->kernelDescriptor.external.debugData = std::make_unique(); + + auto debugData = MockElfEncoder<>::createRelocateableDebugDataElf(); + kernelInfo->kernelDescriptor.external.debugData->vIsaSize = static_cast(debugData.size()); + kernelInfo->kernelDescriptor.external.debugData->vIsa = reinterpret_cast(debugData.data()); + kernelInfo->kernelDescriptor.external.debugData->genIsa = nullptr; + kernelInfo->kernelDescriptor.external.debugData->genIsaSize = 0; + + EXPECT_EQ(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData); + + auto result = moduleMock->initialize(&moduleDesc, neoDevice); + EXPECT_TRUE(result); + + EXPECT_NE(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData); +} + 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 9283649ffe..75887c15ad 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 @@ -8,6 +8,7 @@ #include "shared/source/gmm_helper/gmm.h" #include "shared/source/gmm_helper/gmm_helper.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" +#include "shared/test/common/mocks/mock_elf.h" #include "shared/test/common/mocks/mock_graphics_allocation.h" #include "shared/test/unit_test/compiler_interface/linker_mock.h" #include "shared/test/unit_test/device_binary_format/zebin_tests.h" @@ -857,5 +858,56 @@ TEST_F(ModuleTest, givenInternalOptionsWhenBindlessDisabledThenBindlesOptionsNot EXPECT_FALSE(NEO::CompilerOptions::contains(internalBuildOptions, NEO::CompilerOptions::bindlessMode)); } +using ModuleDebugDataTest = Test; +TEST_F(ModuleDebugDataTest, GivenDebugDataWithRelocationsWhenCreatingRelocatedDebugDataThenRelocationsAreApplied) { + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + + uint8_t binary[10]; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + ModuleBuildLog *moduleBuildLog = nullptr; + + std::unique_ptr module = std::make_unique(device, + moduleBuildLog, + ModuleType::User); + module->translationUnit = std::make_unique(device); + + module->translationUnit->globalVarBuffer = neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties( + {device->getRootDeviceIndex(), MemoryConstants::pageSize, NEO::GraphicsAllocation::AllocationType::BUFFER, neoDevice->getDeviceBitfield()}); + module->translationUnit->globalConstBuffer = neoDevice->getMemoryManager()->allocateGraphicsMemoryWithProperties( + {device->getRootDeviceIndex(), MemoryConstants::pageSize, NEO::GraphicsAllocation::AllocationType::BUFFER, neoDevice->getDeviceBitfield()}); + + uint32_t kernelHeap = 0; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0; + kernelInfo->kernelDescriptor.external.debugData = std::make_unique(); + + auto debugData = MockElfEncoder<>::createRelocateableDebugDataElf(); + + kernelInfo->kernelDescriptor.external.debugData->vIsaSize = static_cast(debugData.size()); + kernelInfo->kernelDescriptor.external.debugData->vIsa = reinterpret_cast(debugData.data()); + + // pass kernelInfo ownership to programInfo + module->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + + std::unique_ptr> kernelImmData{new WhiteBox<::L0::KernelImmutableData>(this->device)}; + kernelImmData->initialize(kernelInfo, device, 0, module->translationUnit->globalConstBuffer, module->translationUnit->globalVarBuffer, false); + kernelImmData->createRelocatedDebugData(module->translationUnit->globalConstBuffer, module->translationUnit->globalVarBuffer); + + module->kernelImmDatas.push_back(std::move(kernelImmData)); + + EXPECT_NE(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData); + + uint64_t *relocAddress = reinterpret_cast(kernelInfo->kernelDescriptor.external.relocatedDebugData.get() + 600); + auto expectedValue = module->kernelImmDatas[0]->getIsaGraphicsAllocation()->getGpuAddress() + 0x1a8; + EXPECT_EQ(expectedValue, *relocAddress); +} + } // namespace ult } // namespace L0 diff --git a/shared/source/compiler_interface/linker.cpp b/shared/source/compiler_interface/linker.cpp index 1cba1b414f..4afc510390 100644 --- a/shared/source/compiler_interface/linker.cpp +++ b/shared/source/compiler_interface/linker.cpp @@ -433,4 +433,32 @@ std::string constructRelocationsDebugMessage(const Linker::RelocatedSymbolsMap & return stream.str(); } +void Linker::applyDebugDataRelocations(const NEO::Elf::Elf &decodedElf, ArrayRef inputOutputElf, const SegmentInfo &text, const SegmentInfo &globalData, const SegmentInfo &constData) { + + for (auto &reloc : decodedElf.getDebugInfoRelocations()) { + auto targetSectionName = decodedElf.getSectionName(reloc.targetSectionIndex); + auto sectionName = decodedElf.getSectionName(reloc.symbolSectionIndex); + auto symbolAddress = decodedElf.getSymbolAddress(reloc.symbolTableIndex); + + if (sectionName == Elf::SpecialSectionNames::text) { + symbolAddress += text.gpuAddress; + } else if (ConstStringRef(sectionName.c_str()).startsWith(Elf::SpecialSectionNames::debug.data())) { + symbolAddress += reinterpret_cast(inputOutputElf.begin() + decodedElf.sectionHeaders[reloc.symbolSectionIndex].header->offset); + } else { + continue; + } + + symbolAddress += reloc.addend; + + auto targetSectionOffset = decodedElf.sectionHeaders[reloc.targetSectionIndex].header->offset; + auto relocLocation = reinterpret_cast(inputOutputElf.begin()) + targetSectionOffset + reloc.offset; + + if (static_cast(reloc.relocType) == Elf::RELOCATION_X8664_TYPE::R_X8664_64) { + *reinterpret_cast(relocLocation) = symbolAddress; + } else if (static_cast(reloc.relocType) == Elf::RELOCATION_X8664_TYPE::R_X8664_32) { + *reinterpret_cast(relocLocation) = static_cast(symbolAddress & uint32_t(-1)); + } + } +} + } // namespace NEO diff --git a/shared/source/compiler_interface/linker.h b/shared/source/compiler_interface/linker.h index 7fcfdc4928..5689a9be81 100644 --- a/shared/source/compiler_interface/linker.h +++ b/shared/source/compiler_interface/linker.h @@ -198,6 +198,11 @@ struct Linker { return RelocatedSymbolsMap(std::move(relocatedSymbols)); } + static void applyDebugDataRelocations(const NEO::Elf::Elf &decodedElf, ArrayRef inputOutputElf, + const SegmentInfo &text, + const SegmentInfo &globalData, + const SegmentInfo &constData); + protected: const LinkerInput &data; RelocatedSymbolsMap relocatedSymbols; diff --git a/shared/source/device_binary_format/elf/elf.h b/shared/source/device_binary_format/elf/elf.h index 6f138a62c3..a2cb9e811d 100644 --- a/shared/source/device_binary_format/elf/elf.h +++ b/shared/source/device_binary_format/elf/elf.h @@ -408,6 +408,7 @@ static constexpr ConstStringRef comment = ".comment"; // version cont static constexpr ConstStringRef data = ".data"; // initialized memory static constexpr ConstStringRef data1 = ".data1"; // initialized memory static constexpr ConstStringRef debug = ".debug"; // debug symbols +static constexpr ConstStringRef debugInfo = ".debug_info"; // debug info static constexpr ConstStringRef dynamic = ".dynamic"; // dynamic linking information static constexpr ConstStringRef dynstr = ".dynstr"; // strings for dynamic linking static constexpr ConstStringRef dynsym = ".dynsym"; // dynamic linking symbol table diff --git a/shared/source/device_binary_format/elf/elf_decoder.cpp b/shared/source/device_binary_format/elf/elf_decoder.cpp index 39dd7322b6..e24475a066 100644 --- a/shared/source/device_binary_format/elf/elf_decoder.cpp +++ b/shared/source/device_binary_format/elf/elf_decoder.cpp @@ -115,15 +115,18 @@ bool Elf::decodeRelocations(SectionHeaderAndData §ionHeaderData, st return false; } size_t numberOfEntries = static_cast(sectionHeaderData.header->size / sectionHeaderData.header->entsize); + auto sectionHeaderNamesData = sectionHeaders[elfFileHeader->shStrNdx].data; + int targetSectionIndex = sectionHeaderData.header->info; + auto sectionName = getSectionName(targetSectionIndex); + auto debugDataRelocation = isDebugDataRelocation(ConstStringRef(sectionName.c_str())); + Relocations &relocs = debugDataRelocation ? debugInfoRelocations : relocations; + auto rela = reinterpret_cast *>(sectionHeaderData.data.begin()); // there may be multiple rela sections, reserve additional size auto previousEntries = relocations.size(); auto allEntries = previousEntries + numberOfEntries; - relocations.reserve(allEntries); - - int targetSectionIndex = sectionHeaderData.header->info; - auto sectionHeaderNamesData = sectionHeaders[elfFileHeader->shStrNdx].data; + relocs.reserve(allEntries); for (auto i = previousEntries; i < allEntries; i++) { @@ -134,7 +137,7 @@ bool Elf::decodeRelocations(SectionHeaderAndData §ionHeaderData, st RelocationInfo relocInfo = {symbolSectionIndex, symbolIndex, targetSectionIndex, rela->addend, rela->offset, relocType, name}; - relocations.push_back(relocInfo); + relocs.push_back(relocInfo); rela++; } } @@ -146,15 +149,19 @@ bool Elf::decodeRelocations(SectionHeaderAndData §ionHeaderData, st return false; } auto numberOfEntries = static_cast(sectionHeaderData.header->size / sectionHeaderData.header->entsize); + + auto sectionHeaderNamesData = sectionHeaders[elfFileHeader->shStrNdx].data; + int targetSectionIndex = sectionHeaderData.header->info; + auto sectionName = getSectionName(targetSectionIndex); + auto debugDataRelocation = isDebugDataRelocation(ConstStringRef(sectionName.c_str())); + Relocations &relocs = debugDataRelocation ? debugInfoRelocations : relocations; + auto reloc = reinterpret_cast *>(sectionHeaderData.data.begin()); // there may be multiple rel sections, reserve additional size auto previousEntries = relocations.size(); auto allEntries = previousEntries + numberOfEntries; - relocations.reserve(allEntries); - - int targetSectionIndex = sectionHeaderData.header->info; - auto sectionHeaderNamesData = sectionHeaders[elfFileHeader->shStrNdx].data; + relocs.reserve(allEntries); for (auto i = previousEntries; i < allEntries; i++) { int symbolIndex = extractSymbolIndex>(*reloc); @@ -164,7 +171,7 @@ bool Elf::decodeRelocations(SectionHeaderAndData §ionHeaderData, st RelocationInfo relocInfo = {symbolSectionIndex, symbolIndex, targetSectionIndex, 0, reloc->offset, relocType, name}; - relocations.push_back(relocInfo); + relocs.push_back(relocInfo); reloc++; } } @@ -187,6 +194,14 @@ bool Elf::decodeSections(std::string &outError) { return success; } +template +bool Elf::isDebugDataRelocation(ConstStringRef sectionName) { + if (sectionName.startsWith(NEO::Elf::SpecialSectionNames::debug.data())) { + return true; + } + return false; +} + template <> template int Elf::extractSymbolIndex(const ElfReloc &elfReloc) const { diff --git a/shared/source/device_binary_format/elf/elf_decoder.h b/shared/source/device_binary_format/elf/elf_decoder.h index ae5a5da965..3e004154fd 100644 --- a/shared/source/device_binary_format/elf/elf_decoder.h +++ b/shared/source/device_binary_format/elf/elf_decoder.h @@ -77,11 +77,15 @@ struct Elf { return symbolTable[idx].value; } - const Relocations &getRelocations() { + const Relocations &getRelocations() const { return relocations; } - const SymbolsTable &getSymbols() { + const Relocations &getDebugInfoRelocations() const { + return debugInfoRelocations; + } + + const SymbolsTable &getSymbols() const { return symbolTable; } @@ -92,9 +96,11 @@ struct Elf { protected: bool decodeSymTab(SectionHeaderAndData §ionHeaderData, std::string &outError); bool decodeRelocations(SectionHeaderAndData §ionHeaderData, std::string &outError); + bool isDebugDataRelocation(ConstStringRef sectionName); SymbolsTable symbolTable; Relocations relocations; + Relocations debugInfoRelocations; }; template diff --git a/shared/source/kernel/kernel_descriptor.h b/shared/source/kernel/kernel_descriptor.h index 847b80697e..e985c620a7 100644 --- a/shared/source/kernel/kernel_descriptor.h +++ b/shared/source/kernel/kernel_descriptor.h @@ -177,6 +177,7 @@ struct KernelDescriptor final { struct { std::unique_ptr debugData; + std::unique_ptr relocatedDebugData; const void *igcInfoForGtpin = nullptr; } external; diff --git a/shared/test/common/mocks/mock_elf.h b/shared/test/common/mocks/mock_elf.h index 454f58d922..52c1c81446 100644 --- a/shared/test/common/mocks/mock_elf.h +++ b/shared/test/common/mocks/mock_elf.h @@ -13,6 +13,7 @@ template struct MockElf : public NEO::Elf::Elf { using BaseClass = NEO::Elf::Elf; + using BaseClass::debugInfoRelocations; using BaseClass::relocations; using BaseClass::symbolTable; @@ -51,4 +52,71 @@ struct MockElfEncoder : public NEO::Elf::ElfEncoder { NEO::Elf::ElfSectionHeader *getSectionHeader(uint32_t idx) { return sectionHeaders.data() + idx; } + + static std::vector createRelocateableDebugDataElf() { + MockElfEncoder<> elfEncoder; + + elfEncoder.getElfFileHeader().type = NEO::Elf::ELF_TYPE::ET_REL; + elfEncoder.getElfFileHeader().machine = NEO::Elf::ELF_MACHINE::EM_NONE; + + uint8_t dummyData[16]; + elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SpecialSectionNames::text.str(), ArrayRef(dummyData, sizeof(dummyData))); + auto textSectionIndex = elfEncoder.getLastSectionHeaderIndex(); + + NEO::Elf::ElfRela relocationsWithAddend; + relocationsWithAddend.addend = 0x1a8; + relocationsWithAddend.info = static_cast(textSectionIndex) << 32 | uint32_t(NEO::Elf::RELOCATION_X8664_TYPE::R_X8664_64); + relocationsWithAddend.offset = 8; + + elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SpecialSectionNames::debugInfo, ArrayRef(dummyData, sizeof(dummyData))); + auto debugSectionIndex = elfEncoder.getLastSectionHeaderIndex(); + + elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::ConstStringRef(NEO::Elf::SpecialSectionNames::debug.str() + "_line"), ArrayRef(dummyData, sizeof(dummyData))); + auto debugLineSectionIndex = elfEncoder.getLastSectionHeaderIndex(); + + elfEncoder.appendSection(NEO::Elf::SHT_RELA, NEO::Elf::SpecialSectionNames::relaPrefix.str() + NEO::Elf::SpecialSectionNames::debugInfo.str(), + ArrayRef(reinterpret_cast(&relocationsWithAddend), sizeof(relocationsWithAddend))); + auto relaDebugSectionIndex = elfEncoder.getLastSectionHeaderIndex(); + + auto relaDebugSection = elfEncoder.getSectionHeader(relaDebugSectionIndex); + relaDebugSection->info = debugSectionIndex; + + relocationsWithAddend.addend = 0; + relocationsWithAddend.info = static_cast(textSectionIndex) << 32 | uint32_t(NEO::Elf::RELOCATION_X8664_TYPE::R_X8664_64); + relocationsWithAddend.offset = 0; + + elfEncoder.appendSection(NEO::Elf::SHT_RELA, NEO::Elf::SpecialSectionNames::relaPrefix.str() + NEO::Elf::SpecialSectionNames::debug.str() + "_line", + ArrayRef(reinterpret_cast(&relocationsWithAddend), sizeof(relocationsWithAddend))); + relaDebugSectionIndex = elfEncoder.getLastSectionHeaderIndex(); + auto relaDebugLineSection = elfEncoder.getSectionHeader(relaDebugSectionIndex); + relaDebugLineSection->info = debugLineSectionIndex; + + std::vector symbolTable; + symbolTable.resize(2 * sizeof(NEO::Elf::ElfSymbolEntry)); + + auto symbols = reinterpret_cast *>(symbolTable.data()); + symbols[0].name = 0; // undef + symbols[0].info = 0; + symbols[0].shndx = 0; + symbols[0].size = 0; + symbols[0].value = 0; + + symbols[1].name = elfEncoder.appendSectionName(NEO::ConstStringRef(".text")); + symbols[1].info = NEO::Elf::SYMBOL_TABLE_TYPE::STT_SECTION | NEO::Elf::SYMBOL_TABLE_BIND::STB_LOCAL << 4; + symbols[1].shndx = static_cast(textSectionIndex); + symbols[1].size = 0; + symbols[1].value = 0; + symbols[1].other = 0; + + elfEncoder.appendSection(NEO::Elf::SHT_SYMTAB, NEO::Elf::SpecialSectionNames::symtab.str(), ArrayRef(symbolTable.data(), symbolTable.size())); + auto symTabSectionIndex = elfEncoder.getLastSectionHeaderIndex(); + + relaDebugSection->link = symTabSectionIndex; + relaDebugLineSection->link = symTabSectionIndex; + + auto symTabSectionHeader = elfEncoder.getSectionHeader(symTabSectionIndex); + symTabSectionHeader->info = 2; + symTabSectionHeader->link = elfEncoder.getLastSectionHeaderIndex() + 1; //strtab section added as last + return elfEncoder.encode(); + } }; diff --git a/shared/test/unit_test/compiler_interface/linker_tests.cpp b/shared/test/unit_test/compiler_interface/linker_tests.cpp index 53301ec450..2759a4c24f 100644 --- a/shared/test/unit_test/compiler_interface/linker_tests.cpp +++ b/shared/test/unit_test/compiler_interface/linker_tests.cpp @@ -1734,3 +1734,138 @@ TEST(RelocationsDebugMessageTests, givenListOfRelocatedSymbolsThenReturnProperDe } EXPECT_STREQ(expected.str().c_str(), message.c_str()); } + +TEST(LinkerTests, GivenDebugDataWhenApplyingDebugDataRelocationsThenRelocationsAreAppliedInMemory) { + NEO::Elf::ElfFileHeader header; + header.shOff = header.ehSize; + header.shNum = 4; + header.shStrNdx = 0; + + NEO::Elf::ElfSectionHeader sectionHeader0; + sectionHeader0.size = 80; + sectionHeader0.offset = 80; + + NEO::Elf::ElfSectionHeader sectionHeader1; + sectionHeader1.size = 80; + sectionHeader1.offset = 160; + + NEO::Elf::ElfSectionHeader sectionHeader2; + sectionHeader2.size = 80; + sectionHeader2.offset = 240; + + NEO::Elf::ElfSectionHeader sectionHeader3; + sectionHeader3.size = 80; + sectionHeader3.offset = 320; + + NEO::Elf::ElfSectionHeader sectionHeader4; + sectionHeader4.size = 80; + sectionHeader4.offset = 400; + + MockElf elf64; + elf64.elfFileHeader = &header; + + uint64_t dummyData[100]; + uint8_t *storage = reinterpret_cast(dummyData); + + elf64.sectionHeaders.push_back({§ionHeader0, {&storage[80], 80}}); + elf64.sectionHeaders.push_back({§ionHeader1, {&storage[160], 80}}); + elf64.sectionHeaders.push_back({§ionHeader2, {&storage[240], 80}}); + elf64.sectionHeaders.push_back({§ionHeader3, {&storage[320], 80}}); + elf64.sectionHeaders.push_back({§ionHeader4, {&storage[400], 80}}); + + std::unordered_map sectionNames; + sectionNames[0] = ".text"; + sectionNames[1] = ".data.global"; + sectionNames[2] = ".debug_info"; + sectionNames[3] = ".debug_abbrev"; + sectionNames[4] = ".debug_line"; + + elf64.setupSecionNames(std::move(sectionNames)); + + NEO::Elf::Elf::RelocationInfo reloc0 = {}; + reloc0.offset = 64; + reloc0.relocType = static_cast(Elf::RELOCATION_X8664_TYPE::R_X8664_64); + reloc0.symbolName = ".debug_abbrev"; + reloc0.symbolSectionIndex = 3; + reloc0.symbolTableIndex = 0; + reloc0.targetSectionIndex = 2; + reloc0.addend = 0; + + elf64.debugInfoRelocations.emplace_back(reloc0); + + NEO::Elf::Elf::RelocationInfo reloc1 = {}; + reloc1.offset = 32; + reloc1.relocType = static_cast(Elf::RELOCATION_X8664_TYPE::R_X8664_32); + reloc1.symbolName = ".debug_line"; + reloc1.symbolSectionIndex = 4; + reloc1.symbolTableIndex = 0; + reloc1.targetSectionIndex = 2; + reloc1.addend = 4; + + elf64.debugInfoRelocations.emplace_back(reloc1); + + NEO::Elf::Elf::RelocationInfo reloc2 = {}; + reloc2.offset = 32; + reloc2.relocType = static_cast(Elf::RELOCATION_X8664_TYPE::R_X8664_64); + reloc2.symbolName = ".text"; + reloc2.symbolSectionIndex = 0; + reloc2.symbolTableIndex = 0; + reloc2.targetSectionIndex = 4; + reloc2.addend = 18; + + elf64.debugInfoRelocations.emplace_back(reloc2); + + NEO::Elf::Elf::RelocationInfo reloc3 = {}; + reloc3.offset = 0; + reloc3.relocType = static_cast(Elf::RELOCATION_X8664_TYPE::R_X8664_64); + reloc3.symbolName = ".data"; + reloc3.symbolSectionIndex = 1; + reloc3.symbolTableIndex = 0; + reloc3.targetSectionIndex = 4; + reloc3.addend = 55; + + elf64.debugInfoRelocations.emplace_back(reloc3); + + NEO::Elf::Elf::RelocationInfo reloc4 = {}; + reloc4.offset = 8; + reloc4.relocType = static_cast(0); + reloc4.symbolName = ".text"; + reloc4.symbolSectionIndex = 0; + reloc4.symbolTableIndex = 0; + reloc4.targetSectionIndex = 4; + reloc4.addend = 77; + + elf64.debugInfoRelocations.emplace_back(reloc4); + + uint64_t *relocInDebugLine = reinterpret_cast(&storage[400]); + *relocInDebugLine = 0; + uint64_t *relocInDebugLine2 = reinterpret_cast(&storage[408]); + *relocInDebugLine2 = 0; + + NEO::Elf::ElfSymbolEntry symbol; + symbol.value = 0; + elf64.symbolTable.push_back(symbol); + + NEO::Linker::SegmentInfo text = {static_cast(0x80001000), 0x10000}; + NEO::Linker::SegmentInfo dataGlobal = {static_cast(0x123000), 0x10000}; + NEO::Linker::SegmentInfo dataConst = {static_cast(0xabc000), 0x10000}; + + NEO::Linker::applyDebugDataRelocations(elf64, {storage, sizeof(dummyData)}, text, dataGlobal, dataConst); + + auto reloc0Location = reinterpret_cast(&elf64.sectionHeaders[reloc0.targetSectionIndex].data[static_cast(reloc0.offset)]); + auto reloc1Location = reinterpret_cast(&elf64.sectionHeaders[reloc1.targetSectionIndex].data[static_cast(reloc1.offset)]); + auto reloc2Location = reinterpret_cast(&elf64.sectionHeaders[reloc2.targetSectionIndex].data[static_cast(reloc2.offset)]); + auto reloc3Location = reinterpret_cast(&elf64.sectionHeaders[reloc3.targetSectionIndex].data[static_cast(reloc3.offset)]); + auto reloc4Location = reinterpret_cast(&elf64.sectionHeaders[reloc4.targetSectionIndex].data[static_cast(reloc4.offset)]); + + auto expectedValue0 = reinterpret_cast(&elf64.sectionHeaders[reloc0.symbolSectionIndex].data[0]) + reloc0.addend; + auto expectedValue1 = static_cast(reinterpret_cast(&elf64.sectionHeaders[reloc1.symbolSectionIndex].data[0]) + reloc1.addend); + auto expectedValue2 = uint64_t(0x80001000) + reloc2.addend; + uint64_t expectedValue3 = 0; // skip relocation from .data + + EXPECT_EQ(expectedValue0, *reloc0Location); + EXPECT_EQ(expectedValue1, *reloc1Location); + EXPECT_EQ(expectedValue2, *reloc2Location); + EXPECT_EQ(expectedValue3, *reloc3Location); + EXPECT_EQ(0u, *reloc4Location); +} \ No newline at end of file diff --git a/shared/test/unit_test/device_binary_format/elf/elf_decoder_tests.cpp b/shared/test/unit_test/device_binary_format/elf/elf_decoder_tests.cpp index 376ae4f225..63e0e412c8 100644 --- a/shared/test/unit_test/device_binary_format/elf/elf_decoder_tests.cpp +++ b/shared/test/unit_test/device_binary_format/elf/elf_decoder_tests.cpp @@ -54,20 +54,30 @@ class TestElf { auto relaDebugSection = elfEncoder.getSectionHeader(relaDebugSectionIndex); relaDebugSection->info = debugSectionIndex; - ElfRel relocation; - relocation.info = relSymbolIndex << 32 | uint64_t(RELOCATION_X8664_TYPE::R_X8664_64); - relocation.offset = relOffset; + ElfRel relocations[2]; + relocations[0].info = relSymbolIndex << 32 | uint64_t(RELOCATION_X8664_TYPE::R_X8664_64); + relocations[0].offset = relOffsets[0]; + + relocations[1].info = relSymbolIndex << 32 | uint64_t(RELOCATION_X8664_TYPE::R_X8664_64); + relocations[1].offset = relOffsets[1]; elfEncoder.appendSection(SHT_PROGBITS, SpecialSectionNames::line, std::string{"dummy_line_data______________________"}); auto lineSectionIndex = elfEncoder.getLastSectionHeaderIndex(); elfEncoder.appendSection(SHT_REL, SpecialSectionNames::relPrefix.str() + SpecialSectionNames::line.str(), - ArrayRef(reinterpret_cast(&relocation), sizeof(relocation))); + ArrayRef(reinterpret_cast(&relocations[0]), sizeof(relocations[0]))); auto relLineSectionIndex = elfEncoder.getLastSectionHeaderIndex(); auto relLineSection = elfEncoder.getSectionHeader(relLineSectionIndex); relLineSection->info = lineSectionIndex; + elfEncoder.appendSection(SHT_REL, SpecialSectionNames::relPrefix.str() + SpecialSectionNames::debug.str(), + ArrayRef(reinterpret_cast(&relocations[1]), sizeof(relocations[1]))); + auto relDebugSectionIndex = elfEncoder.getLastSectionHeaderIndex(); + + auto relDebugSection = elfEncoder.getSectionHeader(relDebugSectionIndex); + relDebugSection->info = debugSectionIndex; + elfEncoder.appendSection(SHT_PROGBITS, SpecialSectionNames::data, std::string{"global_data_memory"}); auto dataSectionIndex = elfEncoder.getLastSectionHeaderIndex(); @@ -106,6 +116,7 @@ class TestElf { relaDebugSection->link = symTabSectionIndex; relLineSection->link = symTabSectionIndex; + relDebugSection->link = symTabSectionIndex; auto symTabSectionHeader = elfEncoder.getSectionHeader(symTabSectionIndex); symTabSectionHeader->info = 4; // one greater than last LOCAL symbol @@ -117,7 +128,7 @@ class TestElf { const uint64_t relaOffsets[2] = {8, 24}; const uint64_t relSymbolIndex = 2; - const uint64_t relOffset = 16; + const uint64_t relOffsets[2] = {16, 32}; uint8_t dummyData[8 * 10]; std::vector symbolTable; @@ -676,31 +687,41 @@ TEST(ElfDecoder, GivenElfWithRelocationsWhenDecodedThenCorrectRelocationsAndSymo EXPECT_NE(nullptr, elf64.elfFileHeader); auto relocations = elf64.getRelocations(); - ASSERT_EQ(3u, relocations.size()); + auto debugRelocations = elf64.getDebugInfoRelocations(); + ASSERT_EQ(1u, relocations.size()); + ASSERT_EQ(3u, debugRelocations.size()); - EXPECT_EQ(testElf.relaAddend, relocations[0].addend); - EXPECT_EQ(testElf.relaOffsets[0], relocations[0].offset); + EXPECT_EQ(testElf.relaAddend, debugRelocations[0].addend); + EXPECT_EQ(testElf.relaOffsets[0], debugRelocations[0].offset); + EXPECT_EQ(uint32_t(RELOCATION_X8664_TYPE::R_X8664_64), debugRelocations[0].relocType); + EXPECT_STREQ("global_object_symbol_0", debugRelocations[0].symbolName.c_str()); + EXPECT_EQ(7, debugRelocations[0].symbolSectionIndex); + EXPECT_EQ(3, debugRelocations[0].symbolTableIndex); + EXPECT_EQ(2, debugRelocations[0].targetSectionIndex); + + EXPECT_EQ(testElf.relaAddend, debugRelocations[1].addend); + EXPECT_EQ(testElf.relaOffsets[1], debugRelocations[1].offset); + EXPECT_EQ(uint32_t(RELOCATION_X8664_TYPE::R_X8664_32), debugRelocations[1].relocType); + EXPECT_STREQ("local_function_symbol_1", debugRelocations[1].symbolName.c_str()); + EXPECT_EQ(1, debugRelocations[1].symbolSectionIndex); + EXPECT_EQ(1, debugRelocations[1].symbolTableIndex); + EXPECT_EQ(2, debugRelocations[1].targetSectionIndex); + + EXPECT_EQ(0u, debugRelocations[2].addend); + EXPECT_EQ(testElf.relOffsets[1], debugRelocations[2].offset); + EXPECT_EQ(uint32_t(RELOCATION_X8664_TYPE::R_X8664_64), debugRelocations[2].relocType); + EXPECT_STREQ("section_symbol_2", debugRelocations[2].symbolName.c_str()); + EXPECT_EQ(1, debugRelocations[2].symbolSectionIndex); + EXPECT_EQ(2, debugRelocations[2].symbolTableIndex); + EXPECT_EQ(2, debugRelocations[2].targetSectionIndex); + + EXPECT_EQ(0u, relocations[0].addend); + EXPECT_EQ(testElf.relOffsets[0], relocations[0].offset); EXPECT_EQ(uint32_t(RELOCATION_X8664_TYPE::R_X8664_64), relocations[0].relocType); - EXPECT_STREQ("global_object_symbol_0", relocations[0].symbolName.c_str()); - EXPECT_EQ(6, relocations[0].symbolSectionIndex); - EXPECT_EQ(3, relocations[0].symbolTableIndex); - EXPECT_EQ(2, relocations[0].targetSectionIndex); - - EXPECT_EQ(testElf.relaAddend, relocations[1].addend); - EXPECT_EQ(testElf.relaOffsets[1], relocations[1].offset); - EXPECT_EQ(uint32_t(RELOCATION_X8664_TYPE::R_X8664_32), relocations[1].relocType); - EXPECT_STREQ("local_function_symbol_1", relocations[1].symbolName.c_str()); - EXPECT_EQ(1, relocations[1].symbolSectionIndex); - EXPECT_EQ(1, relocations[1].symbolTableIndex); - EXPECT_EQ(2, relocations[1].targetSectionIndex); - - EXPECT_EQ(0u, relocations[2].addend); - EXPECT_EQ(testElf.relOffset, relocations[2].offset); - EXPECT_EQ(uint32_t(RELOCATION_X8664_TYPE::R_X8664_64), relocations[2].relocType); - EXPECT_STREQ("section_symbol_2", relocations[2].symbolName.c_str()); - EXPECT_EQ(1, relocations[2].symbolSectionIndex); - EXPECT_EQ(2, relocations[2].symbolTableIndex); - EXPECT_EQ(4, relocations[2].targetSectionIndex); + EXPECT_STREQ("section_symbol_2", relocations[0].symbolName.c_str()); + EXPECT_EQ(1, relocations[0].symbolSectionIndex); + EXPECT_EQ(2, relocations[0].symbolTableIndex); + EXPECT_EQ(4, relocations[0].targetSectionIndex); auto symbolTable = elf64.getSymbols(); ASSERT_EQ(4u, symbolTable.size());