diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index c0c25f0737..a061bcc5ae 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -893,7 +893,9 @@ bool ModuleImp::linkBinary() { globalsForPatching, constantsForPatching, isaSegmentsForPatching, unresolvedExternalsInfo, this->device->getNEODevice(), translationUnit->programInfo.globalConstants.initData, + translationUnit->programInfo.globalConstants.size, translationUnit->programInfo.globalVariables.initData, + translationUnit->programInfo.globalVariables.size, kernelDescriptors, translationUnit->programInfo.externalFunctions); this->symbols = linker.extractRelocatedSymbols(); if (LinkingStatus::LinkedFully != linkStatus) { diff --git a/opencl/source/program/process_device_binary.cpp b/opencl/source/program/process_device_binary.cpp index 5ebb7f5262..bb81f1c4b6 100644 --- a/opencl/source/program/process_device_binary.cpp +++ b/opencl/source/program/process_device_binary.cpp @@ -57,7 +57,7 @@ const KernelInfo *Program::getKernelInfo(size_t ordinal, uint32_t rootDeviceInde return kernelInfoArray[ordinal]; } -cl_int Program::linkBinary(Device *pDevice, const void *constantsInitData, const void *variablesInitData, +cl_int Program::linkBinary(Device *pDevice, const void *constantsInitData, size_t constantsInitDataSize, const void *variablesInitData, size_t variablesInitDataSize, const ProgramInfo::GlobalSurfaceInfo &stringsInfo, std::vector &extFuncInfos) { auto linkerInput = getLinkerInput(pDevice->getRootDeviceIndex()); if (linkerInput == nullptr) { @@ -112,7 +112,8 @@ cl_int Program::linkBinary(Device *pDevice, const void *constantsInitData, const bool linkSuccess = LinkingStatus::LinkedFully == linker.link(globals, constants, exportedFunctions, strings, globalsForPatching, constantsForPatching, isaSegmentsForPatching, unresolvedExternalsInfo, - pDevice, constantsInitData, variablesInitData, + pDevice, constantsInitData, constantsInitDataSize, + variablesInitData, variablesInitDataSize, kernelDescriptors, extFuncInfos); setSymbols(rootDeviceIndex, linker.extractRelocatedSymbols()); if (false == linkSuccess) { @@ -264,7 +265,8 @@ cl_int Program::processProgramInfo(ProgramInfo &src, const ClDevice &clDevice) { kernelInfo->apply(deviceInfoConstants); } - return linkBinary(&clDevice.getDevice(), src.globalConstants.initData, src.globalVariables.initData, src.globalStrings, src.externalFunctions); + return linkBinary(&clDevice.getDevice(), src.globalConstants.initData, src.globalConstants.size, src.globalVariables.initData, + src.globalVariables.size, src.globalStrings, src.externalFunctions); } void Program::processDebugData(uint32_t rootDeviceIndex) { diff --git a/opencl/source/program/program.h b/opencl/source/program/program.h index b98eaccc09..b581f0279d 100644 --- a/opencl/source/program/program.h +++ b/opencl/source/program/program.h @@ -297,8 +297,9 @@ class Program : public BaseObject<_cl_program> { cl_int packDeviceBinary(ClDevice &clDevice); - MOCKABLE_VIRTUAL cl_int linkBinary(Device *pDevice, const void *constantsInitData, const void *variablesInitData, - const ProgramInfo::GlobalSurfaceInfo &stringInfo, std::vector &extFuncInfos); + MOCKABLE_VIRTUAL cl_int linkBinary(Device *pDevice, const void *constantsInitData, size_t constantsInitDataSize, const void *variablesInitData, + size_t variablesInitDataSize, const ProgramInfo::GlobalSurfaceInfo &stringInfo, + std::vector &extFuncInfos); void updateNonUniformFlag(); void updateNonUniformFlag(const Program **inputProgram, size_t numInputPrograms); diff --git a/opencl/test/unit_test/command_queue/blit_enqueue_2_tests.cpp b/opencl/test/unit_test/command_queue/blit_enqueue_2_tests.cpp index 4a109f4bfa..0d6e23c838 100644 --- a/opencl/test/unit_test/command_queue/blit_enqueue_2_tests.cpp +++ b/opencl/test/unit_test/command_queue/blit_enqueue_2_tests.cpp @@ -605,7 +605,7 @@ HWTEST_TEMPLATED_F(BlitCopyTests, givenKernelAllocationInLocalMemoryWithoutCpuAc auto initialTaskCount = bcsMockContext->bcsCsr->peekTaskCount(); - auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {}, externalFunctions); + auto ret = program.linkBinary(&device->getDevice(), nullptr, 0, nullptr, 0, {}, externalFunctions); EXPECT_EQ(CL_SUCCESS, ret); EXPECT_EQ(initialTaskCount + 1, bcsMockContext->bcsCsr->peekTaskCount()); @@ -614,4 +614,4 @@ HWTEST_TEMPLATED_F(BlitCopyTests, givenKernelAllocationInLocalMemoryWithoutCpuAc device->getMemoryManager()->freeGraphicsMemory(kernelInfo.kernelAllocation); } -} // namespace NEO \ No newline at end of file +} // namespace NEO diff --git a/opencl/test/unit_test/program/program_data_tests.cpp b/opencl/test/unit_test/program/program_data_tests.cpp index 08a5324e3a..9ed334a999 100644 --- a/opencl/test/unit_test/program/program_data_tests.cpp +++ b/opencl/test/unit_test/program/program_data_tests.cpp @@ -491,9 +491,10 @@ TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeConstantB constantSurfaceStorage[1] = sentinel; programInfo.globalConstants.initData = constantSurface.mockGfxAllocation.getUnderlyingBuffer(); + programInfo.globalConstants.size = constantSurface.mockGfxAllocation.getUnderlyingBufferSize(); pProgram->setLinkerInput(pClDevice->getRootDeviceIndex(), std::move(programInfo.linkerInput)); - pProgram->linkBinary(&pClDevice->getDevice(), programInfo.globalConstants.initData, programInfo.globalVariables.initData, {}, prog->externalFunctions); + pProgram->linkBinary(&pClDevice->getDevice(), programInfo.globalConstants.initData, programInfo.globalConstants.size, programInfo.globalVariables.initData, programInfo.globalVariables.size, {}, prog->externalFunctions); uint32_t expectedAddr = static_cast(constantSurface.getGraphicsAllocation(pClDevice->getRootDeviceIndex())->getGpuAddressToPatch()); EXPECT_EQ(expectedAddr, constantSurfaceStorage[0]); EXPECT_EQ(sentinel, constantSurfaceStorage[1]); @@ -537,9 +538,10 @@ TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPoi globalSurfaceStorage[1] = sentinel; programInfo.globalVariables.initData = globalSurface.mockGfxAllocation.getUnderlyingBuffer(); + programInfo.globalVariables.size = globalSurface.mockGfxAllocation.getUnderlyingBufferSize(); pProgram->setLinkerInput(pClDevice->getRootDeviceIndex(), std::move(programInfo.linkerInput)); - pProgram->linkBinary(&pClDevice->getDevice(), programInfo.globalConstants.initData, programInfo.globalVariables.initData, {}, prog->externalFunctions); + pProgram->linkBinary(&pClDevice->getDevice(), programInfo.globalConstants.initData, programInfo.globalConstants.size, programInfo.globalVariables.initData, programInfo.globalVariables.size, {}, prog->externalFunctions); uint32_t expectedAddr = static_cast(globalSurface.getGraphicsAllocation(pClDevice->getRootDeviceIndex())->getGpuAddressToPatch()); EXPECT_EQ(expectedAddr, globalSurfaceStorage[0]); EXPECT_EQ(sentinel, globalSurfaceStorage[1]); @@ -566,7 +568,7 @@ TEST(ProgramLinkBinaryTest, whenLinkerInputEmptyThenLinkSuccessful) { auto device = std::make_unique(MockDevice::createWithNewExecutionEnvironment(defaultHwInfo.get())); MockProgram program{nullptr, false, toClDeviceVector(*device)}; program.setLinkerInput(device->getRootDeviceIndex(), std::move(linkerInput)); - auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {}, program.externalFunctions); + auto ret = program.linkBinary(&device->getDevice(), nullptr, 0, nullptr, 0, {}, program.externalFunctions); EXPECT_EQ(CL_SUCCESS, ret); } @@ -592,7 +594,7 @@ TEST(ProgramLinkBinaryTest, whenLinkerUnresolvedExternalThenLinkFailedAndBuildLo std::string buildLog = program.getBuildLog(device->getRootDeviceIndex()); EXPECT_TRUE(buildLog.empty()); - auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {}, program.externalFunctions); + auto ret = program.linkBinary(&device->getDevice(), nullptr, 0, nullptr, 0, {}, program.externalFunctions); EXPECT_NE(CL_SUCCESS, ret); program.getKernelInfoArray(rootDeviceIndex).clear(); buildLog = program.getBuildLog(rootDeviceIndex); @@ -640,7 +642,7 @@ TEST_F(ProgramDataTest, whenLinkerInputValidThenIsaIsProperlyPatched) { buildInfo.globalSurface = new MockGraphicsAllocation(globalVariablesBuffer.data(), globalVariablesBuffer.size()); buildInfo.constantSurface = new MockGraphicsAllocation(globalConstantsBuffer.data(), globalConstantsBuffer.size()); - auto ret = program.linkBinary(&pClDevice->getDevice(), globalConstantsInitData.data(), globalVariablesInitData.data(), {}, program.externalFunctions); + auto ret = program.linkBinary(&pClDevice->getDevice(), globalConstantsInitData.data(), globalConstantsInitData.size(), globalVariablesInitData.data(), globalVariablesInitData.size(), {}, program.externalFunctions); EXPECT_EQ(CL_SUCCESS, ret); linkerInput.reset(static_cast *>(buildInfo.linkerInput.release())); @@ -688,7 +690,7 @@ TEST_F(ProgramDataTest, whenRelocationsAreNotNeededThenIsaIsPreserved) { buildInfo.globalSurface = new MockGraphicsAllocation(globalVariablesBuffer.data(), globalVariablesBuffer.size()); buildInfo.constantSurface = new MockGraphicsAllocation(globalConstantsBuffer.data(), globalConstantsBuffer.size()); - auto ret = program.linkBinary(&pClDevice->getDevice(), globalConstantsInitData.data(), globalVariablesInitData.data(), {}, program.externalFunctions); + auto ret = program.linkBinary(&pClDevice->getDevice(), globalConstantsInitData.data(), globalConstantsInitData.size(), globalVariablesInitData.data(), globalVariablesInitData.size(), {}, program.externalFunctions); EXPECT_EQ(CL_SUCCESS, ret); EXPECT_EQ(kernelHeapData, kernelHeap); @@ -729,7 +731,7 @@ TEST(ProgramStringSectionTest, WhenConstStringBufferIsPresentThenUseItForLinking const char constStringData[] = "Hello World!\n"; auto stringsAddr = reinterpret_cast(constStringData); - auto ret = program.linkBinary(&device->getDevice(), nullptr, nullptr, {constStringData, sizeof(constStringData)}, program.externalFunctions); + auto ret = program.linkBinary(&device->getDevice(), nullptr, 0, nullptr, 0, {constStringData, sizeof(constStringData)}, program.externalFunctions); EXPECT_EQ(CL_SUCCESS, ret); EXPECT_EQ(static_cast(stringsAddr), *reinterpret_cast(patchAddr)); @@ -754,7 +756,7 @@ TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndStackCallsThenKernelRequ linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolName, 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); + auto ret = program.linkBinary(&device->getDevice(), nullptr, 0, nullptr, 0, {}, program.externalFunctions); EXPECT_EQ(CL_SUCCESS, ret); EXPECT_TRUE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); @@ -786,7 +788,7 @@ TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndEnabledDebuggerThenKerne linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolName, 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); + auto ret = program.linkBinary(&device->getDevice(), nullptr, 0, nullptr, 0, {}, program.externalFunctions); EXPECT_EQ(CL_SUCCESS, ret); EXPECT_TRUE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); @@ -812,7 +814,7 @@ TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndNoStackCallsAndDisabledD linkerInput->textRelocations.push_back({{implicitArgsRelocationSymbolName, 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); + auto ret = program.linkBinary(&device->getDevice(), nullptr, 0, nullptr, 0, {}, program.externalFunctions); EXPECT_EQ(CL_SUCCESS, ret); EXPECT_FALSE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); diff --git a/shared/source/compiler_interface/CMakeLists.txt b/shared/source/compiler_interface/CMakeLists.txt index 19a29c95ea..fcf04447cf 100644 --- a/shared/source/compiler_interface/CMakeLists.txt +++ b/shared/source/compiler_interface/CMakeLists.txt @@ -17,7 +17,6 @@ set(NEO_CORE_COMPILER_INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/external_functions.h ${CMAKE_CURRENT_SOURCE_DIR}/intermediate_representations.h ${CMAKE_CURRENT_SOURCE_DIR}/linker.h - ${CMAKE_CURRENT_SOURCE_DIR}/linker.inl ${CMAKE_CURRENT_SOURCE_DIR}/linker.cpp ${CMAKE_CURRENT_SOURCE_DIR}/compiler_options.h ${CMAKE_CURRENT_SOURCE_DIR}/compiler_options.cpp diff --git a/shared/source/compiler_interface/linker.cpp b/shared/source/compiler_interface/linker.cpp index a36d71158a..6e7b2b07c4 100644 --- a/shared/source/compiler_interface/linker.cpp +++ b/shared/source/compiler_interface/linker.cpp @@ -8,13 +8,13 @@ #include "shared/source/compiler_interface/linker.h" #include "shared/source/command_stream/command_stream_receiver.h" -#include "shared/source/compiler_interface/linker.inl" #include "shared/source/device/device.h" #include "shared/source/device_binary_format/elf/zebin_elf.h" #include "shared/source/helpers/blit_commands_helper.h" #include "shared/source/helpers/debug_helpers.h" #include "shared/source/helpers/hw_helper.h" #include "shared/source/helpers/ptr_math.h" +#include "shared/source/helpers/string.h" #include "shared/source/kernel/implicit_args.h" #include "shared/source/kernel/kernel_descriptor.h" #include "shared/source/memory_manager/graphics_allocation.h" @@ -278,6 +278,32 @@ void LinkerInput::parseRelocationForExtFuncUsage(const RelocationInfo &relocInfo } } +LinkingStatus Linker::link(const SegmentInfo &globalVariablesSegInfo, const SegmentInfo &globalConstantsSegInfo, const SegmentInfo &exportedFunctionsSegInfo, + const SegmentInfo &globalStringsSegInfo, GraphicsAllocation *globalVariablesSeg, GraphicsAllocation *globalConstantsSeg, + const PatchableSegments &instructionsSegments, UnresolvedExternals &outUnresolvedExternals, Device *pDevice, const void *constantsInitData, + size_t constantsInitDataSize, const void *variablesInitData, size_t variablesInitDataSize, const KernelDescriptorsT &kernelDescriptors, + ExternalFunctionsT &externalFunctions) { + bool success = data.isValid(); + auto initialUnresolvedExternalsCount = outUnresolvedExternals.size(); + success = success && processRelocations(globalVariablesSegInfo, globalConstantsSegInfo, exportedFunctionsSegInfo, globalStringsSegInfo, instructionsSegments); + if (!success) { + return LinkingStatus::Error; + } + patchInstructionsSegments(instructionsSegments, outUnresolvedExternals, kernelDescriptors); + patchDataSegments(globalVariablesSegInfo, globalConstantsSegInfo, globalVariablesSeg, globalConstantsSeg, + outUnresolvedExternals, pDevice, constantsInitData, constantsInitDataSize, variablesInitData, variablesInitDataSize); + resolveImplicitArgs(kernelDescriptors, pDevice); + resolveBuiltins(pDevice, outUnresolvedExternals, instructionsSegments); + if (initialUnresolvedExternalsCount < outUnresolvedExternals.size()) { + return LinkingStatus::LinkedPartially; + } + success = resolveExternalFunctions(kernelDescriptors, externalFunctions); + if (!success) { + return LinkingStatus::Error; + } + return LinkingStatus::LinkedFully; +} + bool Linker::processRelocations(const SegmentInfo &globalVariables, const SegmentInfo &globalConstants, const SegmentInfo &exportedFunctions, const SegmentInfo &globalStrings, const PatchableSegments &instructionsSegments) { relocatedSymbols.reserve(data.getSymbols().size()); @@ -397,7 +423,13 @@ void Linker::patchInstructionsSegments(const std::vector &inst void Linker::patchDataSegments(const SegmentInfo &globalVariablesSegInfo, const SegmentInfo &globalConstantsSegInfo, GraphicsAllocation *globalVariablesSeg, GraphicsAllocation *globalConstantsSeg, std::vector &outUnresolvedExternals, Device *pDevice, - const void *constantsInitData, const void *variablesInitData) { + const void *constantsInitData, size_t constantsInitDataSize, const void *variablesInitData, size_t variablesInitDataSize) { + std::vector constantsInitDataCopy(constantsInitDataSize); + memcpy_s(constantsInitDataCopy.data(), constantsInitDataCopy.size(), constantsInitData, constantsInitDataSize); + std::vector variablesInitDataCopy(variablesInitDataSize); + memcpy_s(variablesInitDataCopy.data(), variablesInitDataCopy.size(), variablesInitData, variablesInitDataSize); + bool isAnySymbolRelocated = false; + for (const auto &relocation : data.getDataRelocations()) { auto symbolIt = relocatedSymbols.find(relocation.symbolName); if (symbolIt == relocatedSymbols.end()) { @@ -406,14 +438,14 @@ void Linker::patchDataSegments(const SegmentInfo &globalVariablesSegInfo, const } uint64_t srcGpuAddressAs64Bit = symbolIt->second.gpuAddress; - GraphicsAllocation *dst = nullptr; + std::vector *dst = nullptr; const void *initData = nullptr; - if (SegmentType::GlobalVariables == relocation.relocationSegment) { - dst = globalVariablesSeg; - initData = variablesInitData; - } else if (SegmentType::GlobalConstants == relocation.relocationSegment) { - dst = globalConstantsSeg; + if (SegmentType::GlobalConstants == relocation.relocationSegment) { + dst = &constantsInitDataCopy; initData = constantsInitData; + } else if (SegmentType::GlobalVariables == relocation.relocationSegment) { + dst = &variablesInitDataCopy; + initData = variablesInitData; } else { outUnresolvedExternals.push_back(UnresolvedExternal{relocation}); continue; @@ -421,7 +453,7 @@ void Linker::patchDataSegments(const SegmentInfo &globalVariablesSegInfo, const UNRECOVERABLE_IF(nullptr == dst); auto relocType = (LinkerInput::Traits::PointerSize::Ptr32bit == data.getTraits().pointerSize) ? RelocationInfo::Type::AddressLow : relocation.type; - bool invalidOffset = relocation.offset + addressSizeInBytes(relocType) > dst->getUnderlyingBufferSize(); + bool invalidOffset = relocation.offset + addressSizeInBytes(relocType) > dst->size(); DEBUG_BREAK_IF(invalidOffset); if (invalidOffset) { outUnresolvedExternals.push_back(UnresolvedExternal{relocation}); @@ -429,21 +461,35 @@ void Linker::patchDataSegments(const SegmentInfo &globalVariablesSegInfo, const } uint64_t incrementValue = srcGpuAddressAs64Bit + relocation.addend; + isAnySymbolRelocated = true; switch (relocType) { default: UNRECOVERABLE_IF(RelocationInfo::Type::Address != relocType); - patchIncrement(pDevice, dst, static_cast(relocation.offset), initData, incrementValue); + patchIncrement(dst->data(), static_cast(relocation.offset), initData, incrementValue); break; case RelocationInfo::Type::AddressLow: incrementValue = incrementValue & 0xffffffff; - patchIncrement(pDevice, dst, static_cast(relocation.offset), initData, incrementValue); + patchIncrement(dst->data(), static_cast(relocation.offset), initData, incrementValue); break; case RelocationInfo::Type::AddressHigh: incrementValue = (incrementValue >> 32) & 0xffffffff; - patchIncrement(pDevice, dst, static_cast(relocation.offset), initData, incrementValue); + patchIncrement(dst->data(), static_cast(relocation.offset), initData, incrementValue); break; } } + + if (isAnySymbolRelocated) { + auto &hwInfo = pDevice->getHardwareInfo(); + auto &hwInfoConfig = *HwInfoConfig::get(hwInfo.platform.eProductFamily); + if (globalConstantsSeg) { + bool useBlitter = hwInfoConfig.isBlitCopyRequiredForLocalMemory(hwInfo, *globalConstantsSeg); + MemoryTransferHelper::transferMemoryToAllocation(useBlitter, *pDevice, globalConstantsSeg, 0, constantsInitDataCopy.data(), constantsInitDataCopy.size()); + } + if (globalVariablesSeg) { + bool useBlitter = hwInfoConfig.isBlitCopyRequiredForLocalMemory(hwInfo, *globalVariablesSeg); + MemoryTransferHelper::transferMemoryToAllocation(useBlitter, *pDevice, globalVariablesSeg, 0, variablesInitDataCopy.data(), variablesInitDataCopy.size()); + } + } } std::string constructLinkerErrorMessage(const Linker::UnresolvedExternals &unresolvedExternals, const std::vector &instructionsSegmentsNames) { @@ -583,4 +629,15 @@ void Linker::resolveBuiltins(Device *pDevice, UnresolvedExternals &outUnresolved } } } + +template +void Linker::patchIncrement(void *dstBegin, size_t relocationOffset, const void *initData, uint64_t incrementValue) { + auto initValue = ptrOffset(initData, relocationOffset); + PatchSizeT value = 0; + memcpy_s(&value, sizeof(PatchSizeT), initValue, sizeof(PatchSizeT)); + value += static_cast(incrementValue); + + auto destination = ptrOffset(dstBegin, relocationOffset); + memcpy_s(destination, sizeof(PatchSizeT), &value, sizeof(PatchSizeT)); +} } // namespace NEO diff --git a/shared/source/compiler_interface/linker.h b/shared/source/compiler_interface/linker.h index d7fab88eea..2f7abbcb04 100644 --- a/shared/source/compiler_interface/linker.h +++ b/shared/source/compiler_interface/linker.h @@ -21,6 +21,7 @@ namespace NEO { class Device; class GraphicsAllocation; struct KernelDescriptor; +struct ProgramInfo; enum class SegmentType : uint32_t { Unknown, @@ -219,30 +220,12 @@ struct Linker { : data(data) { } - LinkingStatus link(const SegmentInfo &globalVariablesSegInfo, const SegmentInfo &globalConstantsSegInfo, const SegmentInfo &exportedFunctionsSegInfo, const SegmentInfo &globalStringsSegInfo, - GraphicsAllocation *globalVariablesSeg, GraphicsAllocation *globalConstantsSeg, const PatchableSegments &instructionsSegments, - UnresolvedExternals &outUnresolvedExternals, Device *pDevice, const void *constantsInitData, const void *variablesInitData, - const KernelDescriptorsT &kernelDescriptors, ExternalFunctionsT &externalFunctions) { - bool success = data.isValid(); - auto initialUnresolvedExternalsCount = outUnresolvedExternals.size(); - success = success && processRelocations(globalVariablesSegInfo, globalConstantsSegInfo, exportedFunctionsSegInfo, globalStringsSegInfo, instructionsSegments); - if (!success) { - return LinkingStatus::Error; - } - patchInstructionsSegments(instructionsSegments, outUnresolvedExternals, kernelDescriptors); - patchDataSegments(globalVariablesSegInfo, globalConstantsSegInfo, globalVariablesSeg, globalConstantsSeg, - outUnresolvedExternals, pDevice, constantsInitData, variablesInitData); - resolveImplicitArgs(kernelDescriptors, pDevice); - resolveBuiltins(pDevice, outUnresolvedExternals, instructionsSegments); - if (initialUnresolvedExternalsCount < outUnresolvedExternals.size()) { - return LinkingStatus::LinkedPartially; - } - success = resolveExternalFunctions(kernelDescriptors, externalFunctions); - if (!success) { - return LinkingStatus::Error; - } - return LinkingStatus::LinkedFully; - } + LinkingStatus link(const SegmentInfo &globalVariablesSegInfo, const SegmentInfo &globalConstantsSegInfo, const SegmentInfo &exportedFunctionsSegInfo, + const SegmentInfo &globalStringsSegInfo, GraphicsAllocation *globalVariablesSeg, GraphicsAllocation *globalConstantsSeg, + const PatchableSegments &instructionsSegments, UnresolvedExternals &outUnresolvedExternals, Device *pDevice, const void *constantsInitData, + size_t constantsInitDataSize, const void *variablesInitData, size_t variablesInitDataSize, const KernelDescriptorsT &kernelDescriptors, + ExternalFunctionsT &externalFunctions); + static void patchAddress(void *relocAddress, const uint64_t value, const RelocationInfo &relocation); RelocatedSymbolsMap extractRelocatedSymbols() { return RelocatedSymbolsMap(std::move(relocatedSymbols)); @@ -265,14 +248,14 @@ struct Linker { void patchDataSegments(const SegmentInfo &globalVariablesSegInfo, const SegmentInfo &globalConstantsSegInfo, GraphicsAllocation *globalVariablesSeg, GraphicsAllocation *globalConstantsSeg, std::vector &outUnresolvedExternals, Device *pDevice, - const void *constantsInitData, const void *variablesInitData); + const void *constantsInitData, size_t constantsInitDataSize, const void *variablesInitData, size_t variablesInitDataSize); bool resolveExternalFunctions(const KernelDescriptorsT &kernelDescriptors, std::vector &externalFunctions); void resolveImplicitArgs(const KernelDescriptorsT &kernelDescriptors, Device *pDevice); void resolveBuiltins(Device *pDevice, UnresolvedExternals &outUnresolvedExternals, const std::vector &instructionsSegments); template - void patchIncrement(Device *pDevice, GraphicsAllocation *dstAllocation, size_t relocationOffset, const void *initData, uint64_t incrementValue); + void patchIncrement(void *dstAllocation, size_t relocationOffset, const void *initData, uint64_t incrementValue); std::unordered_map /*implicit args relocation address to patch*/> pImplicitArgsRelocationAddresses; }; diff --git a/shared/source/compiler_interface/linker.inl b/shared/source/compiler_interface/linker.inl deleted file mode 100644 index d46e12e859..0000000000 --- a/shared/source/compiler_interface/linker.inl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2020-2022 Intel Corporation - * - * SPDX-License-Identifier: MIT - * - */ - -#include "shared/source/compiler_interface/linker.h" -#include "shared/source/device/device.h" -#include "shared/source/helpers/blit_commands_helper.h" -#include "shared/source/helpers/hw_helper.h" -#include "shared/source/helpers/ptr_math.h" -#include "shared/source/helpers/string.h" -#include "shared/source/memory_manager/graphics_allocation.h" -#include "shared/source/memory_manager/memory_manager.h" - -namespace NEO { - -template -void Linker::patchIncrement(Device *pDevice, GraphicsAllocation *dstAllocation, size_t relocationOffset, const void *initData, uint64_t incrementValue) { - - auto &hwInfo = pDevice->getHardwareInfo(); - auto &hwInfoConfig = *HwInfoConfig::get(hwInfo.platform.eProductFamily); - - bool useBlitter = hwInfoConfig.isBlitCopyRequiredForLocalMemory(hwInfo, *dstAllocation); - - auto initValue = ptrOffset(initData, relocationOffset); - - PatchSizeT value = 0; - memcpy_s(&value, sizeof(PatchSizeT), initValue, sizeof(PatchSizeT)); - value += static_cast(incrementValue); - - MemoryTransferHelper::transferMemoryToAllocation(useBlitter, *pDevice, dstAllocation, relocationOffset, &value, sizeof(PatchSizeT)); -} - -} // namespace NEO diff --git a/shared/source/program/program_info.h b/shared/source/program/program_info.h index 270f4729cd..a2ca522c3b 100644 --- a/shared/source/program/program_info.h +++ b/shared/source/program/program_info.h @@ -54,4 +54,4 @@ size_t getMaxInlineSlmNeeded(const ProgramInfo &programInfo); bool requiresLocalMemoryWindowVA(const ProgramInfo &programInfo); bool isRebuiltToPatchtokensRequired(Device *neoDevice, ArrayRef archive, std::string &optionsString, bool isBuiltin); -} // namespace NEO \ No newline at end of file +} // namespace NEO diff --git a/shared/test/unit_test/compiler_interface/linker_tests.cpp b/shared/test/unit_test/compiler_interface/linker_tests.cpp index 1bade069d3..f88543a243 100644 --- a/shared/test/unit_test/compiler_interface/linker_tests.cpp +++ b/shared/test/unit_test/compiler_interface/linker_tests.cpp @@ -1052,7 +1052,7 @@ TEST(LinkerTests, givenEmptyLinkerInputThenLinkerOutputIsEmpty) { auto linkResult = linker.link( globalVar, globalConst, exportedFunc, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); EXPECT_EQ(0U, unresolvedExternals.size()); auto relocatedSymbols = linker.extractRelocatedSymbols(); @@ -1074,7 +1074,7 @@ TEST(LinkerTests, givenInvalidLinkerInputThenLinkerFails) { auto linkResult = linker.link( globalVar, globalConst, exportedFunc, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, extFuncs); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, extFuncs); EXPECT_EQ(NEO::LinkingStatus::Error, linkResult); } @@ -1149,7 +1149,7 @@ TEST(LinkerTests, givenUnresolvedExternalsWhenLinkThenSubDeviceIDSymbolsAreRemov linker.link( globalVar, globalConst, exportedFunc, {}, patchableGlobalVarSeg, patchableConstVarSeg, instructionsSegments, - unresolvedExternals, device.get(), nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, device.get(), nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, relocatedSymbols.size()); @@ -1190,7 +1190,7 @@ TEST(LinkerTests, givenUnresolvedExternalWhenPatchingInstructionsThenLinkPartial auto linkResult = linker.link( globalVar, globalConst, exportedFunc, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedPartially, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, relocatedSymbols.size()); @@ -1291,7 +1291,7 @@ TEST(LinkerTests, givenValidSymbolsAndRelocationsThenInstructionSegmentsArePrope auto linkResult = linker.link( globalVarSegment, globalConstSegment, exportedFuncSegment, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, unresolvedExternals, - nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -1355,7 +1355,7 @@ TEST(LinkerTests, givenInvalidSymbolOffsetWhenPatchingInstructionsThenRelocation auto linkResult = linker.link( globalVarSegment, globalConstSegment, exportedFuncSegment, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::Error, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -1365,7 +1365,7 @@ TEST(LinkerTests, givenInvalidSymbolOffsetWhenPatchingInstructionsThenRelocation linkResult = linker.link( globalVarSegment, globalConstSegment, exportedFuncSegment, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, unresolvedExternals, - nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); } @@ -1407,7 +1407,7 @@ TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfInstructionsFails) { auto linkResult = linker.link( globalVarSegment, globalConstSegment, exportedFuncSegment, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedPartially, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(1U, relocatedSymbols.size()); @@ -1418,7 +1418,7 @@ TEST(LinkerTests, givenInvalidRelocationOffsetThenPatchingOfInstructionsFails) { linkResult = linker.link( globalVarSegment, globalConstSegment, exportedFuncSegment, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); } @@ -1462,7 +1462,7 @@ TEST(LinkerTests, givenUnknownSymbolTypeWhenPatchingInstructionsThenRelocationFa auto linkResult = linker.link( globalVarSegment, globalConstSegment, exportedFuncSegment, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::Error, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, relocatedSymbols.size()); @@ -1471,7 +1471,7 @@ TEST(LinkerTests, givenUnknownSymbolTypeWhenPatchingInstructionsThenRelocationFa linkerInput.symbols["A"].segment = NEO::SegmentType::GlobalVariables; linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); } @@ -1510,7 +1510,7 @@ TEST(LinkerTests, givenValidStringSymbolsAndRelocationsWhenPatchingThenItIsPrope auto linkResult = linker.link( {}, {}, {}, stringSegment, nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, - nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); EXPECT_EQ(0U, unresolvedExternals.size()); EXPECT_EQ(1U, linker.extractRelocatedSymbols().size()); @@ -1661,7 +1661,8 @@ TEST(LinkerTests, givenValidSymbolsAndRelocationsWhenPatchingDataSegmentsThenThe NEO::Linker::ExternalFunctionsT externalFunctions; auto linkResult = linker.link(globalVariablesSegmentInfo, globalConstantsSegmentInfo, exportedFunctionsSegmentInfo, {}, &globalVariablesPatchableSegment, &globalConstantsPatchableSegment, {}, - unresolvedExternals, device.get(), initGlobalConstantData, initGlobalVariablesData, kernelDescriptors, externalFunctions); + unresolvedExternals, device.get(), initGlobalConstantData, sizeof(initGlobalConstantData), + initGlobalVariablesData, sizeof(initGlobalVariablesData), kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -1720,7 +1721,8 @@ TEST(LinkerTests, givenInvalidSymbolWhenPatchingDataSegmentsThenRelocationIsUnre NEO::Linker::ExternalFunctionsT externalFunctions; auto linkResult = linker.link(globalVariablesSegmentInfo, globalConstantsSegmentInfo, {}, {}, &globalVariablesPatchableSegment, &globalConstantsPatchableSegment, {}, - unresolvedExternals, device.get(), initGlobalConstantData, initGlobalVariablesData, kernelDescriptors, externalFunctions); + unresolvedExternals, device.get(), initGlobalConstantData, sizeof(initGlobalConstantData), initGlobalVariablesData, + sizeof(initGlobalVariablesData), kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedPartially, linkResult); EXPECT_EQ(1U, unresolvedExternals.size()); } @@ -1759,7 +1761,8 @@ TEST(LinkerTests, givenInvalidRelocationOffsetWhenPatchingDataSegmentsThenReloca NEO::Linker::ExternalFunctionsT externalFunctions; auto linkResult = linker.link(globalVariablesSegmentInfo, globalConstantsSegmentInfo, {}, {}, &globalVariablesPatchableSegment, &globalConstantsPatchableSegment, {}, - unresolvedExternals, device.get(), initGlobalConstantData, initGlobalVariablesData, kernelDescriptors, externalFunctions); + unresolvedExternals, device.get(), initGlobalConstantData, sizeof(initGlobalConstantData), + initGlobalVariablesData, sizeof(initGlobalVariablesData), kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedPartially, linkResult); EXPECT_EQ(1U, unresolvedExternals.size()); } @@ -1783,7 +1786,7 @@ TEST(LinkerTests, givenInvalidRelocationSegmentWhenPatchingDataSegmentsThenReloc NEO::Linker::ExternalFunctionsT externalFunctions; auto linkResult = linker.link({}, {}, {}, {}, nullptr, nullptr, {}, - unresolvedExternals, device.get(), nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, device.get(), nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedPartially, linkResult); EXPECT_EQ(1U, unresolvedExternals.size()); } @@ -1823,7 +1826,8 @@ TEST(LinkerTests, given32BitBinaryWithValidSymbolsAndRelocationsWhenPatchingData NEO::Linker::ExternalFunctionsT externalFunctions; auto linkResult = linker.link(globalVariablesSegmentInfo, globalConstantsSegmentInfo, {}, {}, &globalVariablesPatchableSegment, &globalConstantsPatchableSegment, {}, - unresolvedExternals, device.get(), initGlobalConstantData, initGlobalVariablesData, kernelDescriptors, externalFunctions); + unresolvedExternals, device.get(), initGlobalConstantData, sizeof(initGlobalConstantData), initGlobalVariablesData, + sizeof(initGlobalVariablesData), kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -2120,7 +2124,7 @@ TEST(LinkerTests, givenImplicitArgRelocationAndStackCallsThenPatchRelocationWith auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, - deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors, externalFunctions); + deviceFactory.rootDevices[0], nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -2182,7 +2186,7 @@ TEST(LinkerTests, givenImplicitArgRelocationAndEnabledDebuggerThenPatchRelocatio auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, - device, nullptr, nullptr, kernelDescriptors, externalFunctions); + device, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -2239,7 +2243,7 @@ TEST(LinkerTests, givenImplicitArgRelocationWithoutStackCallsAndDisabledDebugger auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, - device, nullptr, nullptr, kernelDescriptors, externalFunctions); + device, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -2283,7 +2287,7 @@ TEST(LinkerTests, givenNoImplicitArgRelocationAndStackCallsThenImplicitArgsAreNo auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, - deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors, externalFunctions); + deviceFactory.rootDevices[0], nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -2333,7 +2337,7 @@ TEST(LinkerTests, givenNoImplicitArgRelocationAndEnabledDebuggerThenImplicitArgs auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, - device, nullptr, nullptr, kernelDescriptors, externalFunctions); + device, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -2390,7 +2394,7 @@ TEST(LinkerTests, givenMultipleImplicitArgsRelocationsWithinSingleKernelWhenLink auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, - deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors, externalFunctions); + deviceFactory.rootDevices[0], nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -2417,7 +2421,7 @@ TEST(LinkerTests, givenDependencyOnMissingExternalFunctionWhenLinkingThenFail) { auto linkResult = linker.link( globalVar, globalConst, exportedFunc, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(LinkingStatus::Error, linkResult); } @@ -2435,7 +2439,7 @@ TEST(LinkerTests, givenDependencyOnMissingExternalFunctionAndNoExternalFunctionI auto linkResult = linker.link( globalVar, globalConst, exportedFunc, {}, patchableGlobalVarSeg, patchableConstVarSeg, patchableInstructionSegments, - unresolvedExternals, nullptr, nullptr, nullptr, kernelDescriptors, externalFunctions); + unresolvedExternals, nullptr, nullptr, 0, nullptr, 0, kernelDescriptors, externalFunctions); EXPECT_EQ(LinkingStatus::LinkedFully, linkResult); } @@ -2489,10 +2493,38 @@ TEST(LinkerTests, givenRelaWhenPatchingDataSegmentThenAddendIsAdded) { auto device = std::unique_ptr(NEO::MockDevice::createWithNewExecutionEnvironment(NEO::defaultHwInfo.get())); NEO::Linker::UnresolvedExternals unresolvedExternals; - linker.patchDataSegments({}, globalConstantsSegmentInfo, {}, &globalConstantsPatchableSegment, unresolvedExternals, device.get(), &globalConstantSegmentData, nullptr); + linker.patchDataSegments({}, globalConstantsSegmentInfo, {}, &globalConstantsPatchableSegment, unresolvedExternals, device.get(), &globalConstantSegmentData, sizeof(globalConstantSegmentData), nullptr, 0); EXPECT_EQ(static_cast(rela.addend + symValue), globalConstantSegmentData); } +TEST(LinkerTests, givenRelocationInfoWhenPatchingDataSegmentWithGlobalVariableSymbolThenAddendIsAdded) { + uint64_t globalVariableSegmentData{0U}; + NEO::MockGraphicsAllocation globalVariablesPatchableSegment{&globalVariableSegmentData, sizeof(globalVariableSegmentData)}; + + NEO::Linker::SegmentInfo globalVariablesSegmentInfo; + globalVariablesSegmentInfo.gpuAddress = reinterpret_cast(globalVariablesPatchableSegment.getUnderlyingBuffer()); + globalVariablesSegmentInfo.segmentSize = globalVariablesPatchableSegment.getUnderlyingBufferSize(); + + WhiteBox linkerInput; + linkerInput.traits.requiresPatchingOfGlobalVariablesBuffer = true; + NEO::LinkerInput::RelocationInfo relocationInfo; + relocationInfo.offset = 0U; + relocationInfo.addend = 128U; + relocationInfo.type = NEO::LinkerInput::RelocationInfo::Type::Address; + relocationInfo.symbolName = "symbol"; + relocationInfo.relocationSegment = NEO::SegmentType::GlobalVariables; + linkerInput.dataRelocations.push_back({relocationInfo}); + + WhiteBox linker(linkerInput); + constexpr uint64_t symValue = 64U; + linker.relocatedSymbols[relocationInfo.symbolName].gpuAddress = symValue; + + auto device = std::unique_ptr(NEO::MockDevice::createWithNewExecutionEnvironment(NEO::defaultHwInfo.get())); + NEO::Linker::UnresolvedExternals unresolvedExternals; + linker.patchDataSegments(globalVariablesSegmentInfo, {}, &globalVariablesPatchableSegment, {}, unresolvedExternals, device.get(), nullptr, 0, &globalVariableSegmentData, sizeof(globalVariableSegmentData)); + EXPECT_EQ(static_cast(relocationInfo.addend + symValue), globalVariableSegmentData); +} + TEST(LinkerTests, givenPerThreadPayloadOffsetRelocationWhenPatchingInstructionSegmentsThenPatchItWithCTDSize) { WhiteBox linkerInput; linkerInput.traits.requiresPatchingOfInstructionSegments = true;