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 3af73bca84..3c111ef726 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 @@ -1931,7 +1931,7 @@ TEST_F(ModuleTests, givenConstDataStringSectionWhenLinkingModuleThenSegmentIsPat EXPECT_EQ(static_cast(stringsAddr), *reinterpret_cast(patchAddr)); } -TEST_F(ModuleTests, givenImplicitArgsRelocationWhenLinkingModuleThenSegmentIsPatchedAndImplicitArgsAreRequired) { +TEST_F(ModuleTests, givenImplicitArgsRelocationAndStackCallsWhenLinkingModuleThenSegmentIsPatchedAndImplicitArgsAreRequired) { auto pModule = std::make_unique(device, nullptr, ModuleType::User); char data[64]{}; @@ -1942,6 +1942,7 @@ TEST_F(ModuleTests, givenImplicitArgsRelocationWhenLinkingModuleThenSegmentIsPat std::unique_ptr> kernelImmData{new WhiteBox<::L0::KernelImmutableData>(this->device)}; kernelImmData->initialize(kernelInfo, device, 0, nullptr, nullptr, false); + kernelImmData->kernelDescriptor->kernelAttributes.flags.useStackCalls = true; auto isaCpuPtr = reinterpret_cast(kernelImmData->isaGraphicsAllocation->getUnderlyingBuffer()); pModule->kernelImmDatas.push_back(std::move(kernelImmData)); pModule->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); @@ -1959,6 +1960,73 @@ TEST_F(ModuleTests, givenImplicitArgsRelocationWhenLinkingModuleThenSegmentIsPat EXPECT_TRUE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); } +TEST_F(ModuleTests, givenImplicitArgsRelocationAndDebuggerEnabledWhenLinkingModuleThenSegmentIsPatchedAndImplicitArgsAreRequired) { + if (!defaultHwInfo->capabilityTable.debuggerSupported) { + GTEST_SKIP(); + } + DebugManagerStateRestore restorer; + DebugManager.flags.EnableMockSourceLevelDebugger.set(1); + auto pModule = std::make_unique(device, nullptr, ModuleType::User); + device->getNEODevice()->getRootDeviceEnvironmentRef().initDebugger(); + + EXPECT_NE(nullptr, neoDevice->getDebugger()); + + char data[64]{}; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 64; + kernelInfo->heapInfo.pKernelHeap = data; + + std::unique_ptr> kernelImmData{new WhiteBox<::L0::KernelImmutableData>(this->device)}; + kernelImmData->initialize(kernelInfo, device, 0, nullptr, nullptr, false); + + kernelImmData->kernelDescriptor->kernelAttributes.flags.useStackCalls = false; + auto isaCpuPtr = reinterpret_cast(kernelImmData->isaGraphicsAllocation->getUnderlyingBuffer()); + pModule->kernelImmDatas.push_back(std::move(kernelImmData)); + pModule->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + auto linkerInput = std::make_unique<::WhiteBox>(); + linkerInput->traits.requiresPatchingOfInstructionSegments = true; + linkerInput->relocations.push_back({{implicitArgsRelocationSymbolName, 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); + pModule->translationUnit->programInfo.linkerInput = std::move(linkerInput); + + EXPECT_FALSE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); + auto status = pModule->linkBinary(); + EXPECT_TRUE(status); + + EXPECT_EQ(sizeof(ImplicitArgs), *reinterpret_cast(ptrOffset(isaCpuPtr, 0x8))); + + EXPECT_TRUE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); +} + +TEST_F(ModuleTests, givenImplicitArgsRelocationAndNoDebuggerOrStackCallsWhenLinkingModuleThenSegmentIsPatchedAndImplicitArgsAreNotRequired) { + auto pModule = std::make_unique(device, nullptr, ModuleType::User); + EXPECT_EQ(nullptr, neoDevice->getDebugger()); + + char data[64]{}; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 64; + kernelInfo->heapInfo.pKernelHeap = data; + + std::unique_ptr> kernelImmData{new WhiteBox<::L0::KernelImmutableData>(this->device)}; + kernelImmData->initialize(kernelInfo, device, 0, nullptr, nullptr, false); + + kernelImmData->kernelDescriptor->kernelAttributes.flags.useStackCalls = false; + auto isaCpuPtr = reinterpret_cast(kernelImmData->isaGraphicsAllocation->getUnderlyingBuffer()); + pModule->kernelImmDatas.push_back(std::move(kernelImmData)); + pModule->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + auto linkerInput = std::make_unique<::WhiteBox>(); + linkerInput->traits.requiresPatchingOfInstructionSegments = true; + linkerInput->relocations.push_back({{implicitArgsRelocationSymbolName, 0x8, LinkerInput::RelocationInfo::Type::AddressLow, SegmentType::Instructions}}); + pModule->translationUnit->programInfo.linkerInput = std::move(linkerInput); + + EXPECT_FALSE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); + auto status = pModule->linkBinary(); + EXPECT_TRUE(status); + + EXPECT_EQ(0u, *reinterpret_cast(ptrOffset(isaCpuPtr, 0x8))); + + EXPECT_FALSE(kernelInfo->kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); +} + using ModuleWithZebinTest = Test; TEST_F(ModuleWithZebinTest, givenNoZebinThenSegmentsAreEmpty) { auto segments = module->getZebinSegments(); diff --git a/opencl/test/unit_test/program/program_data_tests.cpp b/opencl/test/unit_test/program/program_data_tests.cpp index 8e6c82b73c..e9772346a6 100644 --- a/opencl/test/unit_test/program/program_data_tests.cpp +++ b/opencl/test/unit_test/program/program_data_tests.cpp @@ -10,6 +10,7 @@ #include "shared/source/memory_manager/graphics_allocation.h" #include "shared/source/memory_manager/unified_memory_manager.h" #include "shared/source/program/program_info_from_patchtokens.h" +#include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/mocks/mock_csr.h" #include "shared/test/common/mocks/mock_execution_environment.h" #include "shared/test/common/mocks/mock_memory_manager.h" @@ -728,12 +729,13 @@ TEST(ProgramStringSectionTest, WhenConstStringBufferIsPresentThenUseItForLinking program.getKernelInfoArray(rootDeviceIndex).clear(); } -TEST(ProgramImplicitArgsTest, whenImplicitRelocationIsPresentThenKernelRequiresImplicitArgs) { +TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndStackCallsThenKernelRequiresImplicitArgs) { auto device = std::make_unique(MockDevice::createWithNewExecutionEnvironment(defaultHwInfo.get())); auto rootDeviceIndex = device->getRootDeviceIndex(); MockProgram program{nullptr, false, toClDeviceVector(*device)}; KernelInfo kernelInfo = {}; kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel"; + kernelInfo.kernelDescriptor.kernelAttributes.flags.useStackCalls = true; uint8_t kernelHeapData[64] = {}; kernelInfo.heapInfo.pKernelHeap = kernelHeapData; kernelInfo.heapInfo.KernelHeapSize = 64; @@ -751,3 +753,61 @@ TEST(ProgramImplicitArgsTest, whenImplicitRelocationIsPresentThenKernelRequiresI EXPECT_TRUE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); program.getKernelInfoArray(rootDeviceIndex).clear(); } + +TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndEnabledDebuggerThenKernelRequiresImplicitArgs) { + if (!defaultHwInfo->capabilityTable.debuggerSupported) { + GTEST_SKIP(); + } + DebugManagerStateRestore restorer; + DebugManager.flags.EnableMockSourceLevelDebugger.set(1); + auto device = std::make_unique(MockDevice::createWithNewExecutionEnvironment(defaultHwInfo.get())); + + EXPECT_NE(nullptr, device->getDebugger()); + auto rootDeviceIndex = device->getRootDeviceIndex(); + MockProgram program{nullptr, false, toClDeviceVector(*device)}; + KernelInfo kernelInfo = {}; + kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel"; + kernelInfo.kernelDescriptor.kernelAttributes.flags.useStackCalls = false; + uint8_t kernelHeapData[64] = {}; + kernelInfo.heapInfo.pKernelHeap = kernelHeapData; + kernelInfo.heapInfo.KernelHeapSize = 64; + MockGraphicsAllocation kernelIsa(kernelHeapData, 64); + kernelInfo.kernelAllocation = &kernelIsa; + program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo); + + auto linkerInput = std::make_unique>(); + linkerInput->relocations.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, {}); + EXPECT_EQ(CL_SUCCESS, ret); + + EXPECT_TRUE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); + program.getKernelInfoArray(rootDeviceIndex).clear(); +} + +TEST(ProgramImplicitArgsTest, givenImplicitRelocationAndNoStackCallsAndDisabledDebuggerThenKernelDoesntRequireImplicitArgs) { + auto device = std::make_unique(MockDevice::createWithNewExecutionEnvironment(defaultHwInfo.get())); + EXPECT_EQ(nullptr, device->getDebugger()); + auto rootDeviceIndex = device->getRootDeviceIndex(); + MockProgram program{nullptr, false, toClDeviceVector(*device)}; + KernelInfo kernelInfo = {}; + kernelInfo.kernelDescriptor.kernelMetadata.kernelName = "onlyKernel"; + kernelInfo.kernelDescriptor.kernelAttributes.flags.useStackCalls = false; + uint8_t kernelHeapData[64] = {}; + kernelInfo.heapInfo.pKernelHeap = kernelHeapData; + kernelInfo.heapInfo.KernelHeapSize = 64; + MockGraphicsAllocation kernelIsa(kernelHeapData, 64); + kernelInfo.kernelAllocation = &kernelIsa; + program.getKernelInfoArray(rootDeviceIndex).push_back(&kernelInfo); + + auto linkerInput = std::make_unique>(); + linkerInput->relocations.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, {}); + EXPECT_EQ(CL_SUCCESS, ret); + + EXPECT_FALSE(kernelInfo.kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); + program.getKernelInfoArray(rootDeviceIndex).clear(); +} diff --git a/shared/source/compiler_interface/linker.cpp b/shared/source/compiler_interface/linker.cpp index d909c6f12f..671708737e 100644 --- a/shared/source/compiler_interface/linker.cpp +++ b/shared/source/compiler_interface/linker.cpp @@ -470,9 +470,14 @@ void Linker::resolveImplicitArgs(const KernelDescriptorsT &kernelDescriptors, De UNRECOVERABLE_IF(!kernelDescriptors[i]); KernelDescriptor &kernelDescriptor = *kernelDescriptors[i]; auto pImplicitArgsReloc = pImplicitArgsRelocationAddresses.find(i); - kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = pImplicitArgsReloc != pImplicitArgsRelocationAddresses.end(); - if (kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs) { - *pImplicitArgsReloc->second = sizeof(ImplicitArgs); + if (pImplicitArgsReloc != pImplicitArgsRelocationAddresses.end()) { + UNRECOVERABLE_IF(!pDevice); + kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = kernelDescriptor.kernelAttributes.flags.useStackCalls || pDevice->getDebugger() != nullptr; + if (kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs) { + *pImplicitArgsReloc->second = sizeof(ImplicitArgs); + } else { + *pImplicitArgsReloc->second = 0u; + } } } } diff --git a/shared/test/unit_test/compiler_interface/linker_tests.cpp b/shared/test/unit_test/compiler_interface/linker_tests.cpp index 3ab07b2745..cfd841acde 100644 --- a/shared/test/unit_test/compiler_interface/linker_tests.cpp +++ b/shared/test/unit_test/compiler_interface/linker_tests.cpp @@ -17,6 +17,7 @@ #include "shared/test/common/mocks/mock_device.h" #include "shared/test/common/mocks/mock_elf.h" #include "shared/test/common/mocks/mock_graphics_allocation.h" +#include "shared/test/common/mocks/ult_device_factory.h" #include "RelocationInfo.h" #include "gmock/gmock.h" @@ -1899,7 +1900,7 @@ TEST(LinkerTests, GivenDebugDataWhenApplyingDebugDataRelocationsThenRelocationsA EXPECT_EQ(expectedValue5, *reloc5Location); } -TEST(LinkerTests, givenImplicitArgRelocationThenPatchRelocationWithSizeOfImplicitArgStructAndUpdateKernelDescriptor) { +TEST(LinkerTests, givenImplicitArgRelocationAndStackCallsThenPatchRelocationWithSizeOfImplicitArgStructAndUpdateKernelDescriptor) { NEO::LinkerInput linkerInput; vISA::GenRelocEntry reloc = {}; @@ -1926,6 +1927,9 @@ TEST(LinkerTests, givenImplicitArgRelocationThenPatchRelocationWithSizeOfImplici KernelDescriptor kernelDescriptor; kernelDescriptors.push_back(&kernelDescriptor); kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false; + kernelDescriptor.kernelAttributes.flags.useStackCalls = true; + + UltDeviceFactory deviceFactory{1, 0}; std::vector instructionSegment; uint32_t initData = 0x77777777; @@ -1937,7 +1941,7 @@ TEST(LinkerTests, givenImplicitArgRelocationThenPatchRelocationWithSizeOfImplici auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, - nullptr, nullptr, nullptr, kernelDescriptors); + deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors); EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); auto relocatedSymbols = linker.extractRelocatedSymbols(); EXPECT_EQ(0U, unresolvedExternals.size()); @@ -1948,4 +1952,212 @@ TEST(LinkerTests, givenImplicitArgRelocationThenPatchRelocationWithSizeOfImplici EXPECT_EQ(initData, *(addressToPatch - 1)); EXPECT_EQ(initData, *(addressToPatch + 1)); EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); -} \ No newline at end of file +} + +TEST(LinkerTests, givenImplicitArgRelocationAndEnabledDebuggerThenPatchRelocationWithSizeOfImplicitArgStructAndUpdateKernelDescriptor) { + if (!defaultHwInfo->capabilityTable.debuggerSupported) { + GTEST_SKIP(); + } + NEO::LinkerInput linkerInput; + + vISA::GenRelocEntry reloc = {}; + std::string relocationName = implicitArgsRelocationSymbolName; + memcpy_s(reloc.r_symbol, 1024, relocationName.c_str(), relocationName.size()); + reloc.r_offset = 8; + reloc.r_type = vISA::GenRelocType::R_SYM_ADDR_32; + + vISA::GenRelocEntry relocs[] = {reloc}; + constexpr uint32_t numRelocations = 1; + bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0); + EXPECT_TRUE(decodeRelocSuccess); + + NEO::Linker linker(linkerInput); + NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment; + globalVarSegment.gpuAddress = 8; + globalVarSegment.segmentSize = 64; + globalConstSegment.gpuAddress = 128; + globalConstSegment.segmentSize = 256; + exportedFuncSegment.gpuAddress = 4096; + exportedFuncSegment.segmentSize = 1024; + NEO::Linker::UnresolvedExternals unresolvedExternals; + NEO::Linker::KernelDescriptorsT kernelDescriptors; + KernelDescriptor kernelDescriptor; + kernelDescriptors.push_back(&kernelDescriptor); + kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false; + kernelDescriptor.kernelAttributes.flags.useStackCalls = false; + + DebugManagerStateRestore restorer; + DebugManager.flags.EnableMockSourceLevelDebugger.set(1); + UltDeviceFactory deviceFactory{1, 0}; + auto device = deviceFactory.rootDevices[0]; + EXPECT_NE(nullptr, device->getDebugger()); + + std::vector instructionSegment; + uint32_t initData = 0x77777777; + instructionSegment.resize(32, static_cast(initData)); + NEO::Linker::PatchableSegment seg0; + seg0.hostPointer = instructionSegment.data(); + seg0.segmentSize = instructionSegment.size(); + NEO::Linker::PatchableSegments patchableInstructionSegments{seg0}; + + auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, + nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, + device, nullptr, nullptr, kernelDescriptors); + EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); + auto relocatedSymbols = linker.extractRelocatedSymbols(); + EXPECT_EQ(0U, unresolvedExternals.size()); + EXPECT_EQ(0U, relocatedSymbols.size()); + + auto addressToPatch = reinterpret_cast(instructionSegment.data() + reloc.r_offset); + EXPECT_EQ(sizeof(ImplicitArgs), *addressToPatch); + EXPECT_EQ(initData, *(addressToPatch - 1)); + EXPECT_EQ(initData, *(addressToPatch + 1)); + EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); +} + +TEST(LinkerTests, givenImplicitArgRelocationWithoutStackCallsAndDisabledDebuggerThenPatchRelocationWithZeroAndUpdateKernelDescriptor) { + NEO::LinkerInput linkerInput; + + vISA::GenRelocEntry reloc = {}; + std::string relocationName = implicitArgsRelocationSymbolName; + memcpy_s(reloc.r_symbol, 1024, relocationName.c_str(), relocationName.size()); + reloc.r_offset = 8; + reloc.r_type = vISA::GenRelocType::R_SYM_ADDR_32; + + vISA::GenRelocEntry relocs[] = {reloc}; + constexpr uint32_t numRelocations = 1; + bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0); + EXPECT_TRUE(decodeRelocSuccess); + + NEO::Linker linker(linkerInput); + NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment; + globalVarSegment.gpuAddress = 8; + globalVarSegment.segmentSize = 64; + globalConstSegment.gpuAddress = 128; + globalConstSegment.segmentSize = 256; + exportedFuncSegment.gpuAddress = 4096; + exportedFuncSegment.segmentSize = 1024; + NEO::Linker::UnresolvedExternals unresolvedExternals; + NEO::Linker::KernelDescriptorsT kernelDescriptors; + KernelDescriptor kernelDescriptor; + kernelDescriptors.push_back(&kernelDescriptor); + kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false; + kernelDescriptor.kernelAttributes.flags.useStackCalls = false; + + UltDeviceFactory deviceFactory{1, 0}; + auto device = deviceFactory.rootDevices[0]; + EXPECT_EQ(nullptr, device->getDebugger()); + + std::vector instructionSegment; + uint32_t initData = 0x77777777; + instructionSegment.resize(32, static_cast(initData)); + NEO::Linker::PatchableSegment seg0; + seg0.hostPointer = instructionSegment.data(); + seg0.segmentSize = instructionSegment.size(); + NEO::Linker::PatchableSegments patchableInstructionSegments{seg0}; + + auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, + nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, + device, nullptr, nullptr, kernelDescriptors); + EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); + auto relocatedSymbols = linker.extractRelocatedSymbols(); + EXPECT_EQ(0U, unresolvedExternals.size()); + EXPECT_EQ(0U, relocatedSymbols.size()); + + auto addressToPatch = reinterpret_cast(instructionSegment.data() + reloc.r_offset); + EXPECT_EQ(0u, *addressToPatch); + EXPECT_EQ(initData, *(addressToPatch - 1)); + EXPECT_EQ(initData, *(addressToPatch + 1)); + EXPECT_FALSE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); +} + +TEST(LinkerTests, givenNoImplicitArgRelocationAndStackCallsThenImplicitArgsAreNotRequired) { + NEO::LinkerInput linkerInput; + + NEO::Linker linker(linkerInput); + NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment; + globalVarSegment.gpuAddress = 8; + globalVarSegment.segmentSize = 64; + globalConstSegment.gpuAddress = 128; + globalConstSegment.segmentSize = 256; + exportedFuncSegment.gpuAddress = 4096; + exportedFuncSegment.segmentSize = 1024; + NEO::Linker::UnresolvedExternals unresolvedExternals; + NEO::Linker::KernelDescriptorsT kernelDescriptors; + KernelDescriptor kernelDescriptor; + kernelDescriptors.push_back(&kernelDescriptor); + kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false; + kernelDescriptor.kernelAttributes.flags.useStackCalls = true; + + UltDeviceFactory deviceFactory{1, 0}; + + std::vector instructionSegment; + char initData = 0x77; + instructionSegment.resize(32, initData); + NEO::Linker::PatchableSegment seg0; + seg0.hostPointer = instructionSegment.data(); + seg0.segmentSize = instructionSegment.size(); + NEO::Linker::PatchableSegments patchableInstructionSegments{seg0}; + + auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, + nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, + deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors); + EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); + auto relocatedSymbols = linker.extractRelocatedSymbols(); + EXPECT_EQ(0U, unresolvedExternals.size()); + EXPECT_EQ(0U, relocatedSymbols.size()); + + for (auto &data : instructionSegment) { + EXPECT_EQ(initData, data); + } + EXPECT_FALSE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); +} + +TEST(LinkerTests, givenNoImplicitArgRelocationAndEnabledDebuggerThenImplicitArgsAreNotRequired) { + if (!defaultHwInfo->capabilityTable.debuggerSupported) { + GTEST_SKIP(); + } + NEO::LinkerInput linkerInput; + + NEO::Linker linker(linkerInput); + NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment; + globalVarSegment.gpuAddress = 8; + globalVarSegment.segmentSize = 64; + globalConstSegment.gpuAddress = 128; + globalConstSegment.segmentSize = 256; + exportedFuncSegment.gpuAddress = 4096; + exportedFuncSegment.segmentSize = 1024; + NEO::Linker::UnresolvedExternals unresolvedExternals; + NEO::Linker::KernelDescriptorsT kernelDescriptors; + KernelDescriptor kernelDescriptor; + kernelDescriptors.push_back(&kernelDescriptor); + kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false; + kernelDescriptor.kernelAttributes.flags.useStackCalls = false; + + DebugManagerStateRestore restorer; + DebugManager.flags.EnableMockSourceLevelDebugger.set(1); + UltDeviceFactory deviceFactory{1, 0}; + auto device = deviceFactory.rootDevices[0]; + EXPECT_NE(nullptr, device->getDebugger()); + + std::vector instructionSegment; + char initData = 0x77; + instructionSegment.resize(32, initData); + NEO::Linker::PatchableSegment seg0; + seg0.hostPointer = instructionSegment.data(); + seg0.segmentSize = instructionSegment.size(); + NEO::Linker::PatchableSegments patchableInstructionSegments{seg0}; + + auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {}, + nullptr, nullptr, patchableInstructionSegments, unresolvedExternals, + device, nullptr, nullptr, kernelDescriptors); + EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult); + auto relocatedSymbols = linker.extractRelocatedSymbols(); + EXPECT_EQ(0U, unresolvedExternals.size()); + EXPECT_EQ(0U, relocatedSymbols.size()); + + for (auto &data : instructionSegment) { + EXPECT_EQ(initData, data); + } + EXPECT_FALSE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs); +}