From 34ebcc95204f3571686ba56af116041c28322494 Mon Sep 17 00:00:00 2001 From: Krystian Chmielewski Date: Fri, 15 Apr 2022 12:59:44 +0000 Subject: [PATCH] Zebin: Use addend in relocations feat(zebin): Use addend from RELA sections when performing relocations. Resolves: NEO-6898 Signed-off-by: Krystian Chmielewski --- level_zero/core/source/module/module_imp.cpp | 2 +- .../debugger/test_module_with_debug.cpp | 2 +- .../unit_tests/sources/module/test_module.cpp | 8 +- .../unit_test/program/program_data_tests.cpp | 22 ++--- shared/source/compiler_interface/linker.cpp | 35 +++---- shared/source/compiler_interface/linker.h | 7 +- .../compiler_interface/linker_mock.h | 5 +- .../compiler_interface/linker_tests.cpp | 94 ++++++++++++++++++- 8 files changed, 134 insertions(+), 41 deletions(-) diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 2a4ccb3154..32e568ecef 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -988,7 +988,7 @@ ze_result_t ModuleImp::performDynamicLink(uint32_t numModules, auto relocAddress = ptrOffset(isaSegmentsForPatching[unresolvedExternal.instructionsSegmentId].hostPointer, static_cast(unresolvedExternal.unresolvedRelocation.offset)); - NEO::Linker::patchAddress(relocAddress, symbolIt->second, unresolvedExternal.unresolvedRelocation); + NEO::Linker::patchAddress(relocAddress, symbolIt->second.gpuAddress, unresolvedExternal.unresolvedRelocation); numPatchedSymbols++; moduleId->importedSymbolAllocations.insert(moduleHandle->exportedFunctionsSurface); std::map::iterator it; 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 e9227a0159..86cd7334e1 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 @@ -840,7 +840,7 @@ HWTEST_F(NotifyModuleLoadTest, givenDebuggingEnabledWhenModuleWithUnresolvedSymb auto linkerInput = std::make_unique<::WhiteBox>(); linkerInput->traits.requiresPatchingOfInstructionSegments = true; - linkerInput->relocations.push_back({unresolvedRelocation}); + linkerInput->textRelocations.push_back({unresolvedRelocation}); module->getTranslationUnit()->programInfo.linkerInput = std::move(linkerInput); module->unresolvedExternalsInfo.push_back({unresolvedRelocation}); 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 6ac4073e99..d774d725d0 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 @@ -2399,7 +2399,7 @@ TEST_F(ModuleTests, givenConstDataStringSectionWhenLinkingModuleThenSegmentIsPat pModule->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); auto linkerInput = std::make_unique<::WhiteBox>(); - linkerInput->relocations.push_back({{".str", 0x8, LinkerInput::RelocationInfo::Type::Address, SegmentType::Instructions}}); + linkerInput->textRelocations.push_back({{".str", 0x8, LinkerInput::RelocationInfo::Type::Address, SegmentType::Instructions}}); linkerInput->symbols.insert({".str", {0x0, 0x8, SegmentType::GlobalStrings}}); linkerInput->traits.requiresPatchingOfInstructionSegments = true; pModule->translationUnit->programInfo.linkerInput = std::move(linkerInput); @@ -2431,7 +2431,7 @@ TEST_F(ModuleTests, givenImplicitArgsRelocationAndStackCallsWhenLinkingModuleThe pModule->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); auto linkerInput = std::make_unique<::WhiteBox>(); linkerInput->traits.requiresPatchingOfInstructionSegments = true; - linkerInput->relocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); + linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); pModule->translationUnit->programInfo.linkerInput = std::move(linkerInput); EXPECT_FALSE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); @@ -2468,7 +2468,7 @@ TEST_F(ModuleTests, givenImplicitArgsRelocationAndDebuggerEnabledWhenLinkingModu pModule->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); auto linkerInput = std::make_unique<::WhiteBox>(); linkerInput->traits.requiresPatchingOfInstructionSegments = true; - linkerInput->relocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); + linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); pModule->translationUnit->programInfo.linkerInput = std::move(linkerInput); EXPECT_FALSE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); @@ -2498,7 +2498,7 @@ TEST_F(ModuleTests, givenImplicitArgsRelocationAndNoDebuggerOrStackCallsWhenLink pModule->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); auto linkerInput = std::make_unique<::WhiteBox>(); linkerInput->traits.requiresPatchingOfInstructionSegments = true; - linkerInput->relocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); + linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); pModule->translationUnit->programInfo.linkerInput = std::move(linkerInput); EXPECT_FALSE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); diff --git a/opencl/test/unit_test/program/program_data_tests.cpp b/opencl/test/unit_test/program/program_data_tests.cpp index c59e6a509f..faab209799 100644 --- a/opencl/test/unit_test/program/program_data_tests.cpp +++ b/opencl/test/unit_test/program/program_data_tests.cpp @@ -571,7 +571,7 @@ TEST(ProgramLinkBinaryTest, whenLinkerUnresolvedExternalThenLinkFailedAndBuildLo NEO::LinkerInput::RelocationInfo relocation = {}; relocation.symbolName = "A"; relocation.offset = 0; - linkerInput->relocations.push_back(NEO::LinkerInput::Relocations{relocation}); + linkerInput->textRelocations.push_back(NEO::LinkerInput::Relocations{relocation}); linkerInput->traits.requiresPatchingOfInstructionSegments = true; auto device = std::make_unique(MockDevice::createWithNewExecutionEnvironment(defaultHwInfo.get())); auto rootDeviceIndex = device->getRootDeviceIndex(); @@ -605,9 +605,9 @@ TEST_F(ProgramDataTest, whenLinkerInputValidThenIsaIsProperlyPatched) { linkerInput->symbols["C"] = NEO::SymbolInfo{16U, 4U, NEO::SegmentType::Instructions}; auto relocationType = NEO::LinkerInput::RelocationInfo::Type::Address; - linkerInput->relocations.push_back({NEO::LinkerInput::RelocationInfo{"A", 8U, relocationType}, - NEO::LinkerInput::RelocationInfo{"B", 16U, relocationType}, - NEO::LinkerInput::RelocationInfo{"C", 24U, relocationType}}); + linkerInput->textRelocations.push_back({NEO::LinkerInput::RelocationInfo{"A", 8U, relocationType}, + NEO::LinkerInput::RelocationInfo{"B", 16U, relocationType}, + NEO::LinkerInput::RelocationInfo{"C", 24U, relocationType}}); linkerInput->traits.requiresPatchingOfInstructionSegments = true; linkerInput->exportedFunctionsSegmentId = 0; auto device = std::make_unique(MockDevice::createWithNewExecutionEnvironment(defaultHwInfo.get())); @@ -639,9 +639,9 @@ TEST_F(ProgramDataTest, whenLinkerInputValidThenIsaIsProperlyPatched) { linkerInput.reset(static_cast *>(buildInfo.linkerInput.release())); - for (size_t i = 0; i < linkerInput->relocations.size(); ++i) { - auto expectedPatch = buildInfo.globalSurface->getGpuAddress() + linkerInput->symbols[linkerInput->relocations[0][0].symbolName].offset; - auto relocationAddress = kernelHeap.data() + linkerInput->relocations[0][0].offset; + for (size_t i = 0; i < linkerInput->textRelocations.size(); ++i) { + auto expectedPatch = buildInfo.globalSurface->getGpuAddress() + linkerInput->symbols[linkerInput->textRelocations[0][0].symbolName].offset; + auto relocationAddress = kernelHeap.data() + linkerInput->textRelocations[0][0].offset; EXPECT_EQ(static_cast(expectedPatch), *reinterpret_cast(relocationAddress)) << i; } @@ -711,7 +711,7 @@ TEST(ProgramStringSectionTest, WhenConstStringBufferIsPresentThenUseItForLinking program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo); auto linkerInput = std::make_unique>(); - linkerInput->relocations.push_back({{".str", 0x8, LinkerInput::RelocationInfo::Type::Address, SegmentType::Instructions}}); + linkerInput->textRelocations.push_back({{".str", 0x8, LinkerInput::RelocationInfo::Type::Address, SegmentType::Instructions}}); linkerInput->symbols.insert({".str", {0x0, 0x8, SegmentType::GlobalStrings}}); linkerInput->traits.requiresPatchingOfInstructionSegments = true; @@ -745,7 +745,7 @@ TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndStackCallsThenKernelRequ program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo); auto linkerInput = std::make_unique>(); - linkerInput->relocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); + linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); linkerInput->traits.requiresPatchingOfInstructionSegments = true; program.setLinkerInput(rootDeviceIndex, std::move(linkerInput)); auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {}, program.externalFunctions); @@ -777,7 +777,7 @@ TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndEnabledDebuggerThenKerne program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo); auto linkerInput = std::make_unique>(); - linkerInput->relocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); + linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); linkerInput->traits.requiresPatchingOfInstructionSegments = true; program.setLinkerInput(rootDeviceIndex, std::move(linkerInput)); auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {}, program.externalFunctions); @@ -803,7 +803,7 @@ TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndNoStackCallsAndDisabledD program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo); auto linkerInput = std::make_unique>(); - linkerInput->relocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); + linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolNames[0], 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); linkerInput->traits.requiresPatchingOfInstructionSegments = true; program.setLinkerInput(rootDeviceIndex, std::move(linkerInput)); auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {}, program.externalFunctions); diff --git a/shared/source/compiler_interface/linker.cpp b/shared/source/compiler_interface/linker.cpp index e48e7e8536..76fbcfa42e 100644 --- a/shared/source/compiler_interface/linker.cpp +++ b/shared/source/compiler_interface/linker.cpp @@ -107,12 +107,12 @@ bool LinkerInput::decodeRelocationTable(const void *data, uint32_t numEntries, u this->traits.requiresPatchingOfInstructionSegments = true; auto relocEntryIt = reinterpret_cast(data); auto relocEntryEnd = relocEntryIt + numEntries; - if (instructionsSegmentId >= relocations.size()) { - static_assert(std::is_nothrow_move_constructible::value, ""); - relocations.resize(instructionsSegmentId + 1); + if (instructionsSegmentId >= textRelocations.size()) { + static_assert(std::is_nothrow_move_constructible::value, ""); + textRelocations.resize(instructionsSegmentId + 1); } - auto &outRelocInfo = relocations[instructionsSegmentId]; + auto &outRelocInfo = textRelocations[instructionsSegmentId]; outRelocInfo.reserve(numEntries); for (; relocEntryIt != relocEntryEnd; ++relocEntryIt) { RelocationInfo relocInfo{}; @@ -152,12 +152,12 @@ void LinkerInput::addDataRelocationInfo(const RelocationInfo &relocationInfo) { void LinkerInput::addElfTextSegmentRelocation(RelocationInfo relocationInfo, uint32_t instructionsSegmentId) { this->traits.requiresPatchingOfInstructionSegments = true; - if (instructionsSegmentId >= relocations.size()) { - static_assert(std::is_nothrow_move_constructible::value, ""); - relocations.resize(instructionsSegmentId + 1); + if (instructionsSegmentId >= textRelocations.size()) { + static_assert(std::is_nothrow_move_constructible::value, ""); + textRelocations.resize(instructionsSegmentId + 1); } - auto &outRelocInfo = relocations[instructionsSegmentId]; + auto &outRelocInfo = textRelocations[instructionsSegmentId]; relocationInfo.relocationSegment = SegmentType::Instructions; @@ -207,6 +207,7 @@ void LinkerInput::decodeElfSymbolTableAndRelocations(Elf::Elf for (auto &reloc : elf.getRelocations()) { NEO::LinkerInput::RelocationInfo relocationInfo; relocationInfo.offset = reloc.offset; + relocationInfo.addend = reloc.addend; relocationInfo.symbolName = reloc.symbolName; switch (reloc.relocType) { @@ -299,12 +300,12 @@ uint32_t addressSizeInBytes(LinkerInput::RelocationInfo::Type relocationtype) { return (relocationtype == LinkerInput::RelocationInfo::Type::Address) ? sizeof(uintptr_t) : sizeof(uint32_t); } -void Linker::patchAddress(void *relocAddress, const Linker::RelocatedSymbol &symbol, const Linker::RelocationInfo &relocation) { - uint64_t gpuAddressAs64bit = static_cast(symbol.gpuAddress); +void Linker::patchAddress(void *relocAddress, const uint64_t value, const Linker::RelocationInfo &relocation) { + uint64_t gpuAddressAs64bit = static_cast(value); switch (relocation.type) { default: UNRECOVERABLE_IF(RelocationInfo::Type::Address != relocation.type); - *reinterpret_cast(relocAddress) = symbol.gpuAddress; + *reinterpret_cast(relocAddress) = gpuAddressAs64bit; break; case RelocationInfo::Type::AddressLow: *reinterpret_cast(relocAddress) = static_cast(gpuAddressAs64bit & 0xffffffff); @@ -357,7 +358,8 @@ void Linker::patchInstructionsSegments(const std::vector &inst continue; } - patchAddress(relocAddress, symbolIt->second, relocation); + uint64_t patchValue = symbolIt->second.gpuAddress + relocation.addend; + patchAddress(relocAddress, patchValue, relocation); } } } @@ -396,19 +398,18 @@ void Linker::patchDataSegments(const SegmentInfo &globalVariablesSegInfo, const continue; } - uint64_t incrementValue = 0U; + uint64_t incrementValue = srcGpuAddressAs64Bit + relocation.addend; switch (relocType) { default: UNRECOVERABLE_IF(RelocationInfo::Type::Address != relocType); - incrementValue = srcGpuAddressAs64Bit; patchIncrement(pDevice, dst, static_cast(relocation.offset), initData, incrementValue); break; case RelocationInfo::Type::AddressLow: - incrementValue = srcGpuAddressAs64Bit & 0xffffffff; + incrementValue = incrementValue & 0xffffffff; patchIncrement(pDevice, dst, static_cast(relocation.offset), initData, incrementValue); break; case RelocationInfo::Type::AddressHigh: - incrementValue = (srcGpuAddressAs64Bit >> 32) & 0xffffffff; + incrementValue = (incrementValue >> 32) & 0xffffffff; patchIncrement(pDevice, dst, static_cast(relocation.offset), initData, incrementValue); break; } @@ -547,7 +548,7 @@ void Linker::resolveBuiltins(Device *pDevice, UnresolvedExternals &outUnresolved auto relocAddress = ptrOffset(instructionsSegments[outUnresolvedExternals[vecIndex].instructionsSegmentId].hostPointer, static_cast(outUnresolvedExternals[vecIndex].unresolvedRelocation.offset)); - NEO::Linker::patchAddress(relocAddress, symbol, outUnresolvedExternals[vecIndex].unresolvedRelocation); + NEO::Linker::patchAddress(relocAddress, symbol.gpuAddress, outUnresolvedExternals[vecIndex].unresolvedRelocation); outUnresolvedExternals[vecIndex] = outUnresolvedExternals[outUnresolvedExternals.size() - 1u]; outUnresolvedExternals.resize(outUnresolvedExternals.size() - 1u); diff --git a/shared/source/compiler_interface/linker.h b/shared/source/compiler_interface/linker.h index f80e28ca2f..f2cb43705d 100644 --- a/shared/source/compiler_interface/linker.h +++ b/shared/source/compiler_interface/linker.h @@ -91,6 +91,7 @@ struct LinkerInput { uint64_t offset = std::numeric_limits::max(); Type type = Type::Unknown; SegmentType relocationSegment = SegmentType::Unknown; + int64_t addend = 0U; }; using SectionNameToSegmentIdMap = std::unordered_map; @@ -127,7 +128,7 @@ struct LinkerInput { } const RelocationsPerInstSegment &getRelocationsInInstructionSegments() const { - return relocations; + return textRelocations; } const Relocations &getDataRelocations() const { @@ -155,7 +156,7 @@ struct LinkerInput { Traits traits; SymbolMap symbols; - RelocationsPerInstSegment relocations; + RelocationsPerInstSegment textRelocations; Relocations dataRelocations; std::vector> extFuncSymbols; int32_t exportedFunctionsSegmentId = -1; @@ -224,7 +225,7 @@ struct Linker { } return LinkingStatus::LinkedFully; } - static void patchAddress(void *relocAddress, const RelocatedSymbol &symbol, const RelocationInfo &relocation); + static void patchAddress(void *relocAddress, const uint64_t value, const RelocationInfo &relocation); RelocatedSymbolsMap extractRelocatedSymbols() { return RelocatedSymbolsMap(std::move(relocatedSymbols)); } diff --git a/shared/test/unit_test/compiler_interface/linker_mock.h b/shared/test/unit_test/compiler_interface/linker_mock.h index 1cca97a825..f5c534360a 100644 --- a/shared/test/unit_test/compiler_interface/linker_mock.h +++ b/shared/test/unit_test/compiler_interface/linker_mock.h @@ -28,8 +28,8 @@ struct WhiteBox : NEO::LinkerInput { using BaseClass::extFunDependencies; using BaseClass::kernelDependencies; using BaseClass::parseRelocationForExtFuncUsage; - using BaseClass::relocations; using BaseClass::symbols; + using BaseClass::textRelocations; using BaseClass::traits; using BaseClass::valid; }; @@ -38,6 +38,9 @@ template <> struct WhiteBox : NEO::Linker { using BaseClass = NEO::Linker; using BaseClass::BaseClass; + using BaseClass::patchDataSegments; + using BaseClass::patchInstructionsSegments; + using BaseClass::relocatedSymbols; using BaseClass::resolveExternalFunctions; }; diff --git a/shared/test/unit_test/compiler_interface/linker_tests.cpp b/shared/test/unit_test/compiler_interface/linker_tests.cpp index 5fad62d575..e7e15c794a 100644 --- a/shared/test/unit_test/compiler_interface/linker_tests.cpp +++ b/shared/test/unit_test/compiler_interface/linker_tests.cpp @@ -354,6 +354,43 @@ TEST(LinkerInputTests, WhenAddingTwoElfTextRelocationForSingleSegmentIndexThenBo EXPECT_TRUE(linkerInput.getTraits().requiresPatchingOfInstructionSegments); } +TEST(LinkerInputTests, WhenDecodingElfRelocationsWithAddendThenAddendIsSet) { + NEO::LinkerInput linkerInput = {}; + NEO::Elf::ElfFileHeader header; + MockElf elf64; + elf64.elfFileHeader = &header; + + std::unordered_map sectionNames; + sectionNames[0] = ".text.abc"; + sectionNames[1] = ".data.const"; + elf64.setupSecionNames(std::move(sectionNames)); + + NEO::Elf::Elf::RelocationInfo reloc; + reloc.offset = 64; + reloc.addend = 128; + reloc.relocType = static_cast(Elf::RELOCATION_X8664_TYPE::R_X8664_64); + reloc.symbolName = "symbol1"; + reloc.symbolSectionIndex = 1; + reloc.symbolTableIndex = 0; + reloc.targetSectionIndex = 0; + elf64.relocations.emplace_back(reloc); + + NEO::LinkerInput::SectionNameToSegmentIdMap nameToKernelId; + nameToKernelId["abc"] = 0; + linkerInput.decodeElfSymbolTableAndRelocations(elf64, nameToKernelId); + + auto &relocsPerInstSegment = linkerInput.getRelocationsInInstructionSegments(); + ASSERT_EQ(1u, relocsPerInstSegment.size()); + auto &relocsKernelABC = relocsPerInstSegment[0]; + ASSERT_EQ(1u, relocsKernelABC.size()); + + EXPECT_EQ(reloc.offset, relocsKernelABC[0].offset); + EXPECT_EQ(reloc.addend, relocsKernelABC[0].addend); + EXPECT_EQ(NEO::LinkerInput::RelocationInfo::Type::Address, relocsKernelABC[0].type); + EXPECT_EQ(NEO::SegmentType::Instructions, relocsKernelABC[0].relocationSegment); + EXPECT_STREQ(reloc.symbolName.c_str(), relocsKernelABC[0].symbolName.c_str()); +} + TEST(LinkerInputTests, WhenDecodingElfTextRelocationsThenCorrectRelocationsAreAdded) { NEO::LinkerInput linkerInput = {}; NEO::Elf::ElfFileHeader header; @@ -374,7 +411,6 @@ TEST(LinkerInputTests, WhenDecodingElfTextRelocationsThenCorrectRelocationsAreAd reloc.symbolSectionIndex = 1; reloc.symbolTableIndex = 0; reloc.targetSectionIndex = 0; - elf64.relocations.emplace_back(reloc); NEO::Elf::Elf::RelocationInfo reloc2; @@ -384,7 +420,6 @@ TEST(LinkerInputTests, WhenDecodingElfTextRelocationsThenCorrectRelocationsAreAd reloc2.symbolSectionIndex = 1; reloc2.symbolTableIndex = 0; reloc2.targetSectionIndex = 2; - elf64.relocations.emplace_back(reloc2); NEO::LinkerInput::SectionNameToSegmentIdMap nameToKernelId; @@ -1429,7 +1464,7 @@ TEST(LinkerTests, givenValidStringSymbolsAndRelocationsWhenPatchingThenItIsPrope relocation.relocationSegment = NEO::SegmentType::Instructions; relocation.symbolName = ".str"; relocation.type = NEO::LinkerInput::RelocationInfo::Type::Address; - linkerInput.relocations.push_back({relocation}); + linkerInput.textRelocations.push_back({relocation}); linkerInput.traits.requiresPatchingOfInstructionSegments = true; @@ -2376,3 +2411,56 @@ TEST(LinkerTests, givenDependencyOnMissingExternalFunctionAndNoExternalFunctionI unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); EXPECT_EQ(LinkingStatus::LinkedFully, linkResult); } + +TEST(LinkerTests, givenRelaWhenPatchingInstructionsSegmentThenAddendIsAdded) { + WhiteBox linkerInput; + linkerInput.traits.requiresPatchingOfInstructionSegments = true; + NEO::LinkerInput::RelocationInfo rela; + rela.offset = 0U; + rela.addend = 128U; + rela.type = NEO::LinkerInput::RelocationInfo::Type::Address; + rela.symbolName = "symbol"; + rela.relocationSegment = NEO::SegmentType::Instructions; + linkerInput.textRelocations.push_back({rela}); + + WhiteBox linker(linkerInput); + constexpr uint64_t symValue = 64U; + linker.relocatedSymbols[rela.symbolName].gpuAddress = symValue; + + uint64_t segmentData{0}; + NEO::Linker::PatchableSegment segmentToPatch; + segmentToPatch.hostPointer = reinterpret_cast(&segmentData); + segmentToPatch.segmentSize = sizeof(segmentData); + + NEO::Linker::UnresolvedExternals unresolvedExternals; + linker.patchInstructionsSegments({segmentToPatch}, unresolvedExternals); + EXPECT_EQ(static_cast(rela.addend + symValue), segmentData); +} + +TEST(LinkerTests, givenRelaWhenPatchingDataSegmentThenAddendIsAdded) { + uint64_t globalConstantSegmentData{0U}; + NEO::MockGraphicsAllocation globalConstantsPatchableSegment{&globalConstantSegmentData, sizeof(globalConstantSegmentData)}; + + NEO::Linker::SegmentInfo globalConstantsSegmentInfo; + globalConstantsSegmentInfo.gpuAddress = reinterpret_cast(globalConstantsPatchableSegment.getUnderlyingBuffer()); + globalConstantsSegmentInfo.segmentSize = globalConstantsPatchableSegment.getUnderlyingBufferSize(); + + WhiteBox linkerInput; + linkerInput.traits.requiresPatchingOfGlobalConstantsBuffer = true; + NEO::LinkerInput::RelocationInfo rela; + rela.offset = 0U; + rela.addend = 128U; + rela.type = NEO::LinkerInput::RelocationInfo::Type::Address; + rela.symbolName = "symbol"; + rela.relocationSegment = NEO::SegmentType::GlobalConstants; + linkerInput.dataRelocations.push_back({rela}); + + WhiteBox linker(linkerInput); + constexpr uint64_t symValue = 64U; + linker.relocatedSymbols[rela.symbolName].gpuAddress = symValue; + + auto device = std::unique_ptr(NEO::MockDevice::createWithNewExecutionEnvironment(NEO::defaultHwInfo.get())); + NEO::Linker::UnresolvedExternals unresolvedExternals; + linker.patchDataSegments({}, globalConstantsSegmentInfo, {}, &globalConstantsPatchableSegment, unresolvedExternals, device.get(), &globalConstantSegmentData, nullptr); + EXPECT_EQ(static_cast(rela.addend + symValue), globalConstantSegmentData); +}