mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-04 15:53:45 +08:00
fix: correct resolving external functions dependencies
respect scenario when dependency comes from separate module Related-To: NEO-15211 Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
a0ff19823b
commit
8310b10987
@@ -297,21 +297,41 @@ void LinkerInput::decodeElfSymbolTableAndRelocations(Elf::Elf<numBits> &elf, con
|
||||
}
|
||||
|
||||
void LinkerInput::parseRelocationForExtFuncUsage(const RelocationInfo &relocInfo, const std::string &kernelName) {
|
||||
auto extFuncSymIt = std::find_if(extFuncSymbols.begin(), extFuncSymbols.end(), [relocInfo](auto &pair) {
|
||||
return pair.first == relocInfo.symbolName;
|
||||
});
|
||||
if (extFuncSymIt != extFuncSymbols.end()) {
|
||||
if (kernelName == Zebin::Elf::SectionNames::externalFunctions.str()) {
|
||||
auto callerIt = std::find_if(extFuncSymbols.begin(), extFuncSymbols.end(), [relocInfo](auto &pair) {
|
||||
auto &symbol = pair.second;
|
||||
return relocInfo.offset >= symbol.offset && relocInfo.offset < symbol.offset + symbol.size;
|
||||
});
|
||||
if (callerIt != extFuncSymbols.end()) {
|
||||
extFunDependencies.push_back({relocInfo.symbolName, callerIt->first});
|
||||
}
|
||||
} else {
|
||||
kernelDependencies.push_back({relocInfo.symbolName, kernelName});
|
||||
|
||||
auto shouldIgnoreRelocation = [&](const RelocationInfo &relocInfo) {
|
||||
if (relocInfo.symbolName.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ignore relocations for non-instruction symbols
|
||||
if (std::find_if(symbols.begin(), symbols.end(), [relocInfo](auto &pair) {
|
||||
auto &symbol = pair.second;
|
||||
return relocInfo.symbolName == pair.first && symbol.segment != SegmentType::instructions;
|
||||
}) != symbols.end()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto specialRelocationName : {implicitArgsRelocationSymbolName, Linker::perThreadOff, Linker::subDeviceID}) {
|
||||
if (relocInfo.symbolName == specialRelocationName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (shouldIgnoreRelocation(relocInfo)) {
|
||||
return;
|
||||
}
|
||||
if (kernelName == Zebin::Elf::SectionNames::externalFunctions.str()) {
|
||||
auto callerIt = std::find_if(extFuncSymbols.begin(), extFuncSymbols.end(), [relocInfo](auto &pair) {
|
||||
auto &symbol = pair.second;
|
||||
return relocInfo.offset >= symbol.offset && relocInfo.offset < symbol.offset + symbol.size;
|
||||
});
|
||||
if (callerIt != extFuncSymbols.end()) {
|
||||
extFunDependencies.push_back({relocInfo.symbolName, callerIt->first});
|
||||
}
|
||||
} else {
|
||||
kernelDependencies.push_back({relocInfo.symbolName, kernelName});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2024 Intel Corporation
|
||||
* Copyright (C) 2021-2025 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace NEO {
|
||||
@@ -19,7 +20,7 @@ namespace NEO {
|
||||
struct KernelDescriptor;
|
||||
struct RootDeviceEnvironment;
|
||||
|
||||
inline constexpr const char *implicitArgsRelocationSymbolName = "__INTEL_PATCH_CROSS_THREAD_OFFSET_OFF_R0";
|
||||
inline const std::string implicitArgsRelocationSymbolName = "__INTEL_PATCH_CROSS_THREAD_OFFSET_OFF_R0";
|
||||
|
||||
namespace ImplicitArgsHelper {
|
||||
std::array<uint8_t, 3> getDimensionOrderForLocalIds(const uint8_t *workgroupDimensionsOrder, std::optional<std::pair<bool /* localIdsGeneratedByRuntime */, uint32_t /* walkOrderForHwGenerationOfLocalIds */>> hwGenerationOfLocalIdsParams);
|
||||
|
||||
@@ -745,6 +745,83 @@ TEST(LinkerInputTests, GivenInvalidFunctionsSymbolsUsedInFunctionsRelocationsWhe
|
||||
EXPECT_TRUE(mockLinkerInput.extFunDependencies.empty());
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, GivenFunctionSymbolsUsedInFunctionsRelocationsWhenParsingRelocationsForExtFuncUsageThenAddDependency) {
|
||||
WhiteBox<NEO::LinkerInput> mockLinkerInput;
|
||||
|
||||
auto &extFuncSymbols = mockLinkerInput.extFuncSymbols;
|
||||
extFuncSymbols.resize(2);
|
||||
auto &funSym = extFuncSymbols[0];
|
||||
funSym.first = "fun";
|
||||
funSym.second.offset = 4U;
|
||||
funSym.second.size = 4U;
|
||||
|
||||
auto &fun2Sym = extFuncSymbols[1];
|
||||
fun2Sym.first = "fun2";
|
||||
fun2Sym.second.offset = 8U;
|
||||
fun2Sym.second.size = 4U;
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo{};
|
||||
relocInfo.symbolName = "fun3";
|
||||
|
||||
relocInfo.offset = 6U;
|
||||
mockLinkerInput.parseRelocationForExtFuncUsage(relocInfo, NEO::Zebin::Elf::SectionNames::externalFunctions.str());
|
||||
EXPECT_EQ(1u, mockLinkerInput.extFunDependencies.size());
|
||||
EXPECT_EQ(relocInfo.symbolName, mockLinkerInput.extFunDependencies[0].usedFuncName);
|
||||
EXPECT_EQ(funSym.first, mockLinkerInput.extFunDependencies[0].callerFuncName);
|
||||
|
||||
mockLinkerInput.extFunDependencies.clear();
|
||||
relocInfo.offset = 8U;
|
||||
mockLinkerInput.parseRelocationForExtFuncUsage(relocInfo, NEO::Zebin::Elf::SectionNames::externalFunctions.str());
|
||||
EXPECT_EQ(1u, mockLinkerInput.extFunDependencies.size());
|
||||
EXPECT_EQ(relocInfo.symbolName, mockLinkerInput.extFunDependencies[0].usedFuncName);
|
||||
EXPECT_EQ(fun2Sym.first, mockLinkerInput.extFunDependencies[0].callerFuncName);
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, GivenExternalFunctionsSymbolsUsedInKernelRelocationsWhenParsingRelocationsForExtFuncUsageForKernelThenAddKernelDependency) {
|
||||
WhiteBox<NEO::LinkerInput> mockLinkerInput;
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo{};
|
||||
relocInfo.symbolName = "fun";
|
||||
|
||||
std::string kernelName = "kernel";
|
||||
mockLinkerInput.parseRelocationForExtFuncUsage(relocInfo, kernelName);
|
||||
EXPECT_TRUE(mockLinkerInput.extFunDependencies.empty());
|
||||
EXPECT_EQ(1u, mockLinkerInput.kernelDependencies.size());
|
||||
EXPECT_EQ(relocInfo.symbolName, mockLinkerInput.kernelDependencies[0].usedFuncName);
|
||||
EXPECT_EQ(kernelName, mockLinkerInput.kernelDependencies[0].kernelName);
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, GivenNonFunctionRelocationInKernelRelocationsWhenParsingRelocationsForExtFuncUsageForKernelThenDoNotAddKernelDependency) {
|
||||
WhiteBox<NEO::LinkerInput> mockLinkerInput;
|
||||
|
||||
auto &symbols = mockLinkerInput.symbols;
|
||||
SymbolInfo symbol0 = {
|
||||
.segment = SegmentType::globalStrings};
|
||||
SymbolInfo symbol1 = {
|
||||
.segment = SegmentType::globalVariables};
|
||||
SymbolInfo symbol2 = {
|
||||
.segment = SegmentType::instructions};
|
||||
symbols.emplace(".str", symbol0);
|
||||
symbols.emplace("globalVar", symbol1);
|
||||
symbols.emplace("fun", symbol2);
|
||||
|
||||
for (auto nonFuncRelocationName : {
|
||||
implicitArgsRelocationSymbolName,
|
||||
std::string(".str"),
|
||||
std::string("globalVar"),
|
||||
Linker::perThreadOff,
|
||||
Linker::subDeviceID,
|
||||
std::string("")}) {
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo{};
|
||||
relocInfo.symbolName = nonFuncRelocationName;
|
||||
|
||||
std::string kernelName = "kernel";
|
||||
mockLinkerInput.parseRelocationForExtFuncUsage(relocInfo, kernelName);
|
||||
EXPECT_TRUE(mockLinkerInput.extFunDependencies.empty());
|
||||
EXPECT_EQ(0u, mockLinkerInput.kernelDependencies.size());
|
||||
}
|
||||
}
|
||||
HWTEST_F(LinkerTests, givenEmptyLinkerInputThenLinkerOutputIsEmpty) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
NEO::Linker linker(linkerInput);
|
||||
|
||||
Reference in New Issue
Block a user