mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-19 06:24:51 +08:00
fix: improve propagating external functions info to kernel
When relocation points to symbol that is not defined within module mark it as optional. When symbol is available at dynamic linking time then info from the function is retrieved but when the symbol is not available then ignore the dependency. Any unresolved symbol needed for module linking is already handled in a separate place. Related-To: NEO-16243, NEO-16263, NEO-16262, NEO-16268 Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
a440a3e8ea
commit
15d0feeda8
@@ -37,6 +37,9 @@ uint32_t getExtFuncDependencies(const FuncNameToIdMapT &funcNameToId, const Func
|
||||
auto funcDep = funcDependencies[i];
|
||||
if (funcNameToId.count(funcDep->callerFuncName) == 0 ||
|
||||
funcNameToId.count(funcDep->usedFuncName) == 0) {
|
||||
if (funcDep->optional) {
|
||||
continue;
|
||||
}
|
||||
return ERROR_EXTERNAL_FUNCTION_INFO_MISSING;
|
||||
}
|
||||
size_t callerId = funcNameToId.at(funcDep->callerFuncName);
|
||||
@@ -75,6 +78,9 @@ uint32_t resolveExtFuncDependencies(const ExternalFunctionInfosT &externalFuncti
|
||||
uint32_t resolveKernelDependencies(const ExternalFunctionInfosT &externalFunctionInfos, const FuncNameToIdMapT &funcNameToId, const KernelDependenciesT &kernelDependencies, const KernelDescriptorMapT &nameToKernelDescriptor) {
|
||||
for (auto &kernelDep : kernelDependencies) {
|
||||
if (funcNameToId.count(kernelDep->usedFuncName) == 0) {
|
||||
if (kernelDep->optional) {
|
||||
continue;
|
||||
}
|
||||
return ERROR_EXTERNAL_FUNCTION_INFO_MISSING;
|
||||
} else if (nameToKernelDescriptor.count(kernelDep->kernelName) == 0) {
|
||||
return ERROR_KERNEL_DESCRIPTOR_MISSING;
|
||||
|
||||
@@ -35,11 +35,13 @@ struct ExternalFunctionInfo {
|
||||
struct ExternalFunctionUsageKernel {
|
||||
std::string usedFuncName;
|
||||
std::string kernelName;
|
||||
bool optional = false;
|
||||
};
|
||||
|
||||
struct ExternalFunctionUsageExtFunc {
|
||||
std::string usedFuncName;
|
||||
std::string callerFuncName;
|
||||
bool optional = false;
|
||||
};
|
||||
|
||||
using ExternalFunctionInfosT = std::vector<ExternalFunctionInfo *>;
|
||||
|
||||
@@ -232,6 +232,7 @@ bool LinkerInput::addSymbol(Elf::Elf<numBits> &elf, const SectionNameToSegmentId
|
||||
auto symbolSectionName = elf.getSectionName(elfSymbol.shndx);
|
||||
auto segment = getSegmentForSection(symbolSectionName);
|
||||
if (segment == SegmentType::unknown) {
|
||||
externalSymbols.push_back(symbolName);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -298,6 +299,7 @@ void LinkerInput::decodeElfSymbolTableAndRelocations(Elf::Elf<numBits> &elf, con
|
||||
|
||||
void LinkerInput::parseRelocationForExtFuncUsage(const RelocationInfo &relocInfo, const std::string &kernelName) {
|
||||
|
||||
bool isExternalSymbol = false;
|
||||
auto shouldIgnoreRelocation = [&](const RelocationInfo &relocInfo) {
|
||||
if (relocInfo.symbolName.empty()) {
|
||||
return true;
|
||||
@@ -311,10 +313,8 @@ void LinkerInput::parseRelocationForExtFuncUsage(const RelocationInfo &relocInfo
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto specialRelocationName : {implicitArgsRelocationSymbolName, Linker::perThreadOff, Linker::subDeviceID}) {
|
||||
if (relocInfo.symbolName == specialRelocationName) {
|
||||
return true;
|
||||
}
|
||||
if (std::ranges::find(externalSymbols, relocInfo.symbolName) != externalSymbols.end()) {
|
||||
isExternalSymbol = true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -328,10 +328,10 @@ void LinkerInput::parseRelocationForExtFuncUsage(const RelocationInfo &relocInfo
|
||||
return relocInfo.offset >= symbol.offset && relocInfo.offset < symbol.offset + symbol.size;
|
||||
});
|
||||
if (callerIt != extFuncSymbols.end()) {
|
||||
extFunDependencies.push_back({relocInfo.symbolName, callerIt->first});
|
||||
extFunDependencies.push_back({relocInfo.symbolName, callerIt->first, isExternalSymbol});
|
||||
}
|
||||
} else {
|
||||
kernelDependencies.push_back({relocInfo.symbolName, kernelName});
|
||||
kernelDependencies.push_back({relocInfo.symbolName, kernelName, isExternalSymbol});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ struct LinkerInput : NEO::NonCopyableAndNonMovableClass {
|
||||
|
||||
Traits traits;
|
||||
SymbolMap symbols;
|
||||
std::vector<std::string> externalSymbols;
|
||||
std::vector<std::pair<std::string, SymbolInfo>> extFuncSymbols;
|
||||
Relocations dataRelocations;
|
||||
RelocationsPerInstSegment textRelocations;
|
||||
|
||||
@@ -24,6 +24,7 @@ struct WhiteBox<NEO::LinkerInput> : NEO::LinkerInput {
|
||||
|
||||
using BaseClass::dataRelocations;
|
||||
using BaseClass::exportedFunctionsSegmentId;
|
||||
using BaseClass::externalSymbols;
|
||||
using BaseClass::extFuncSymbols;
|
||||
using BaseClass::extFunDependencies;
|
||||
using BaseClass::kernelDependencies;
|
||||
|
||||
@@ -57,7 +57,7 @@ struct MockElf : public NEO::Elf::Elf<numBits> {
|
||||
relocations.emplace_back(reloc);
|
||||
}
|
||||
|
||||
void setupSecionNames(std::unordered_map<uint32_t, std::string> map) {
|
||||
void setupSectionNames(std::unordered_map<uint32_t, std::string> map) {
|
||||
sectionNames = map;
|
||||
overrideSectionNames = true;
|
||||
}
|
||||
|
||||
@@ -97,10 +97,16 @@ struct ExternalFunctionsTests : public ::testing::Test {
|
||||
nameToKernelDescriptor[kernelName] = kd.get();
|
||||
}
|
||||
void addFuncDependency(const std::string &calleeName, const std::string &callerName) {
|
||||
funcDependenciesStorage.push_back({calleeName, callerName});
|
||||
funcDependenciesStorage.push_back({calleeName, callerName, false});
|
||||
}
|
||||
void addKernelDependency(const std::string &calleeName, const std::string &kernelCallerName) {
|
||||
kernelDependenciesStorage.push_back({calleeName, kernelCallerName});
|
||||
kernelDependenciesStorage.push_back({calleeName, kernelCallerName, false});
|
||||
}
|
||||
void addOptionalFuncDependency(const std::string &calleeName, const std::string &callerName) {
|
||||
funcDependenciesStorage.push_back({calleeName, callerName, true});
|
||||
}
|
||||
void addOptionalKernelDependency(const std::string &calleeName, const std::string &kernelCallerName) {
|
||||
kernelDependenciesStorage.push_back({calleeName, kernelCallerName, true});
|
||||
}
|
||||
|
||||
void clear() {
|
||||
@@ -157,6 +163,27 @@ TEST_F(ExternalFunctionsTests, GivenMissingExtFuncInLookupMapWhenResolvingExtFun
|
||||
EXPECT_EQ(ERROR_EXTERNAL_FUNCTION_INFO_MISSING, error);
|
||||
}
|
||||
|
||||
TEST_F(ExternalFunctionsTests, GivenMissingOptionalExtFuncInLookupMapWhenResolvingExtFuncDependenciesThenReturnSuccess) {
|
||||
addOptionalFuncDependency("fun1", "fun0");
|
||||
set();
|
||||
auto error = resolveExtFuncDependencies(extFuncInfo, funcNameToId, functionDependencies);
|
||||
EXPECT_EQ(RESOLVE_SUCCESS, error);
|
||||
clear();
|
||||
|
||||
addOptionalFuncDependency("fun1", "fun0");
|
||||
addExternalFunction("fun1", {});
|
||||
set();
|
||||
error = resolveExtFuncDependencies(extFuncInfo, funcNameToId, functionDependencies);
|
||||
EXPECT_EQ(RESOLVE_SUCCESS, error);
|
||||
clear();
|
||||
|
||||
addOptionalFuncDependency("fun1", "fun0");
|
||||
addExternalFunction("fun0", {});
|
||||
set();
|
||||
error = resolveExtFuncDependencies(extFuncInfo, funcNameToId, functionDependencies);
|
||||
EXPECT_EQ(RESOLVE_SUCCESS, error);
|
||||
}
|
||||
|
||||
TEST_F(ExternalFunctionsTests, GivenMissingExtFuncInLookupMapWhenResolvingKernelDependenciesThenReturnError) {
|
||||
addKernel("kernel");
|
||||
addKernelDependency("fun0", "kernel");
|
||||
@@ -164,6 +191,13 @@ TEST_F(ExternalFunctionsTests, GivenMissingExtFuncInLookupMapWhenResolvingKernel
|
||||
auto error = resolveKernelDependencies(extFuncInfo, funcNameToId, kernelDependencies, nameToKernelDescriptor);
|
||||
EXPECT_EQ(ERROR_EXTERNAL_FUNCTION_INFO_MISSING, error);
|
||||
}
|
||||
TEST_F(ExternalFunctionsTests, GivenMissingOptionalExtFuncInLookupMapWhenResolvingKernelDependenciesThenReturnSuccess) {
|
||||
addKernel("kernel");
|
||||
addOptionalKernelDependency("fun0", "kernel");
|
||||
set();
|
||||
auto error = resolveKernelDependencies(extFuncInfo, funcNameToId, kernelDependencies, nameToKernelDescriptor);
|
||||
EXPECT_EQ(RESOLVE_SUCCESS, error);
|
||||
}
|
||||
|
||||
TEST_F(ExternalFunctionsTests, GivenMissingKernelInLookupMapWhenResolvingKernelDependenciesThenReturnError) {
|
||||
addExternalFunction("fun0", {});
|
||||
@@ -294,3 +328,28 @@ TEST_F(ExternalFunctionsTests, GivenValidFunctionAndKernelDependenciesWhenResolv
|
||||
EXPECT_FALSE(nameToKernelDescriptor["kernel1"]->kernelAttributes.flags.hasIndirectCalls);
|
||||
EXPECT_TRUE(nameToKernelDescriptor["kernel2"]->kernelAttributes.flags.hasIndirectCalls);
|
||||
}
|
||||
|
||||
TEST_F(ExternalFunctionsTests, GivenValidFunctionAndKernelOptionalDependenciesWhenResolvingDependenciesThenSetAppropriateHasIndirectfCallsAndReturnSuccess) {
|
||||
addKernel("kernel0");
|
||||
addKernel("kernel1");
|
||||
addKernel("kernel2");
|
||||
addExternalFunction("fun0", {.hasIndirectCalls = false});
|
||||
addExternalFunction("fun1", {.hasIndirectCalls = true});
|
||||
addExternalFunction("fun2", {.hasIndirectCalls = false});
|
||||
|
||||
addOptionalFuncDependency("fun1", "fun0");
|
||||
addOptionalKernelDependency("fun0", "kernel0");
|
||||
addOptionalKernelDependency("fun2", "kernel1");
|
||||
addOptionalKernelDependency("fun2", "kernel2");
|
||||
set();
|
||||
|
||||
nameToKernelDescriptor["kernel2"]->kernelAttributes.flags.hasIndirectCalls = true;
|
||||
auto error = resolveExternalDependencies(extFuncInfo, kernelDependencies, functionDependencies, nameToKernelDescriptor);
|
||||
EXPECT_EQ(RESOLVE_SUCCESS, error);
|
||||
EXPECT_TRUE(extFuncInfo[funcNameToId["fun0"]]->hasIndirectCalls);
|
||||
EXPECT_TRUE(extFuncInfo[funcNameToId["fun1"]]->hasIndirectCalls);
|
||||
EXPECT_FALSE(extFuncInfo[funcNameToId["fun2"]]->hasIndirectCalls);
|
||||
EXPECT_TRUE(nameToKernelDescriptor["kernel0"]->kernelAttributes.flags.hasIndirectCalls);
|
||||
EXPECT_FALSE(nameToKernelDescriptor["kernel1"]->kernelAttributes.flags.hasIndirectCalls);
|
||||
EXPECT_TRUE(nameToKernelDescriptor["kernel2"]->kernelAttributes.flags.hasIndirectCalls);
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ TEST(LinkerInputTests, GivenTwoGlobalSymbolsOfTypeFunctionEachPointingToDifferen
|
||||
sectionNames[1] = ".data.const";
|
||||
sectionNames[2] = ".text.hello";
|
||||
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.overrideSymbolName = true;
|
||||
|
||||
elf64.addSymbol(0, 0x1234000, 8, 0, Elf::STT_FUNC, Elf::STB_GLOBAL);
|
||||
@@ -405,7 +405,7 @@ TEST(LinkerInputTests, GivenGlobalSymbolOfTypeObjectPointingToDataGlobalSectionW
|
||||
std::unordered_map<uint32_t, std::string> sectionNames;
|
||||
sectionNames[0] = ".text.abc";
|
||||
sectionNames[1] = ".data.global";
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.overrideSymbolName = true;
|
||||
|
||||
elf64.addSymbol(0, 0x20, 8, 1, Elf::STT_OBJECT, Elf::STB_GLOBAL);
|
||||
@@ -428,7 +428,7 @@ TEST(LinkerInputTests, GivenGlobalSymbolOfTypeObjectPointingToDataConstSectionWh
|
||||
std::unordered_map<uint32_t, std::string> sectionNames;
|
||||
sectionNames[0] = ".text.abc";
|
||||
sectionNames[1] = ".data.const";
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.overrideSymbolName = true;
|
||||
|
||||
elf64.addSymbol(0, 0, 8, 1, Elf::STT_OBJECT, Elf::STB_GLOBAL);
|
||||
@@ -452,7 +452,7 @@ TEST(LinkerInputTests, GivenGlobalSymbolOfTypeFuncPointingToFunctionsSectionWhen
|
||||
std::unordered_map<uint32_t, std::string> sectionNames;
|
||||
sectionNames[0] = ".text.abc";
|
||||
sectionNames[1] = functionsSectionName.str();
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.overrideSymbolName = true;
|
||||
|
||||
elf64.addSymbol(0, 0, 32, 1, Elf::STT_FUNC, Elf::STB_GLOBAL);
|
||||
@@ -479,7 +479,7 @@ TEST(LinkerInputTests, GivenGlobalSymbolOfTypeDifferentThantObjectOrFuncWhenDeco
|
||||
std::unordered_map<uint32_t, std::string> sectionNames;
|
||||
sectionNames[0] = ".text.abc";
|
||||
sectionNames[1] = ".data.const";
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.overrideSymbolName = true;
|
||||
|
||||
elf64.addSymbol(0, 0, 8, 0, Elf::STT_NOTYPE, Elf::STB_GLOBAL);
|
||||
@@ -490,21 +490,24 @@ TEST(LinkerInputTests, GivenGlobalSymbolOfTypeDifferentThantObjectOrFuncWhenDeco
|
||||
EXPECT_EQ(0U, linkerInput.getSymbols().size());
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, GivenGlobalSymbolPointingToSectionDifferentThanInstructionsOrDataWhenDecodingElfThenItIsIgnored) {
|
||||
TEST(LinkerInputTests, GivenGlobalSymbolPointingToSectionDifferentThanInstructionsOrDataWhenDecodingElfThenItIsIgnoredAndAddedToExternalSymbols) {
|
||||
MockElf<NEO::Elf::EI_CLASS_64> elf64;
|
||||
|
||||
std::unordered_map<uint32_t, std::string> sectionNames;
|
||||
sectionNames[0] = ""; // UNDEF section
|
||||
sectionNames[1] = ".text.abc";
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.overrideSymbolName = true;
|
||||
|
||||
elf64.addSymbol(0, 0, 8, 0, Elf::STT_OBJECT, Elf::STB_GLOBAL);
|
||||
constexpr uint32_t externalSymbol = 3;
|
||||
elf64.addSymbol(externalSymbol, 0, 8, 0, Elf::STT_OBJECT, Elf::STB_GLOBAL);
|
||||
WhiteBox<NEO::LinkerInput> linkerInput;
|
||||
NEO::LinkerInput::SectionNameToSegmentIdMap nameToKernelId = {{"abc", 0}};
|
||||
NEO::LinkerInput linkerInput = {};
|
||||
linkerInput.decodeElfSymbolTableAndRelocations(elf64, nameToKernelId);
|
||||
EXPECT_TRUE(linkerInput.isValid());
|
||||
EXPECT_EQ(0U, linkerInput.getSymbols().size());
|
||||
EXPECT_EQ(1U, linkerInput.externalSymbols.size());
|
||||
EXPECT_EQ(std::to_string(externalSymbol), linkerInput.externalSymbols[0]);
|
||||
}
|
||||
|
||||
TEST(LInkerInputTests, GivenSymbolPointingToInstructionSegmentAndInvalidInstructionSectionNameMappingWhenDecodingElfThenLinkerInputIsInvalid) {
|
||||
@@ -513,7 +516,7 @@ TEST(LInkerInputTests, GivenSymbolPointingToInstructionSegmentAndInvalidInstruct
|
||||
|
||||
std::unordered_map<uint32_t, std::string> sectionNames;
|
||||
sectionNames[0] = ".text.abc";
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.overrideSymbolName = true;
|
||||
|
||||
elf64.addSymbol(0, 0, 8, 0, Elf::STT_FUNC, Elf::STB_GLOBAL);
|
||||
@@ -532,7 +535,7 @@ TEST(LinkerInputTests, GivenInstructionRelocationAndInvalidInstructionSectionNam
|
||||
sectionNames[0] = ".text.abc";
|
||||
sectionNames[1] = ".data.const";
|
||||
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.addReloc(64, 0, Zebin::Elf::R_ZE_SYM_ADDR, 0, 0, "0");
|
||||
|
||||
elf64.overrideSymbolName = true;
|
||||
@@ -548,7 +551,7 @@ TEST(LinkerInputTests, GivenRelocationWithSymbolIdOutOfBoundsOfSymbolTableWhenDe
|
||||
MockElf<NEO::Elf::EI_CLASS_64> elf64;
|
||||
|
||||
std::unordered_map<uint32_t, std::string> sectionNames = {{0, ".text.abc"}};
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
|
||||
elf64.addReloc(64, 0, Zebin::Elf::R_ZE_SYM_ADDR, 0, 2, "symbol");
|
||||
|
||||
@@ -564,7 +567,7 @@ TEST(LinkerInputTests, GivenRelocationToSectionDifferentThanDataOrInstructionsWh
|
||||
|
||||
std::unordered_map<uint32_t, std::string> sectionNames = {{0, ".text.abc"},
|
||||
{1, "unknown.section"}};
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.addReloc(64, 0, Zebin::Elf::R_ZE_SYM_ADDR, 1, 2, "symbol");
|
||||
|
||||
NEO::LinkerInput::SectionNameToSegmentIdMap nameToKernelId;
|
||||
@@ -584,7 +587,7 @@ TEST(LinkerInputTests, GivenGlobalDataRelocationWithLocalSymbolPointingToConstDa
|
||||
sectionNames[1] = ".data.const";
|
||||
sectionNames[2] = ".data.global";
|
||||
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.addReloc(64, 10, Zebin::Elf::R_ZE_SYM_ADDR, 2, 0, "0");
|
||||
|
||||
elf64.overrideSymbolName = true;
|
||||
@@ -617,7 +620,7 @@ TEST(LinkerInputTests, GivenInstructionRelocationWithLocalSymbolPointingToFuncti
|
||||
sectionNames[0] = ".text.abc";
|
||||
sectionNames[1] = functionsSectionName.str();
|
||||
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
elf64.addReloc(64, 10, Zebin::Elf::R_ZE_SYM_ADDR, 0, 0, "0");
|
||||
|
||||
elf64.overrideSymbolName = true;
|
||||
@@ -791,7 +794,7 @@ TEST(LinkerInputTests, GivenExternalFunctionsSymbolsUsedInKernelRelocationsWhenP
|
||||
EXPECT_EQ(kernelName, mockLinkerInput.kernelDependencies[0].kernelName);
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, GivenNonFunctionRelocationInKernelRelocationsWhenParsingRelocationsForExtFuncUsageForKernelThenDoNotAddKernelDependency) {
|
||||
TEST(LinkerInputTests, GivenNonFunctionSymbolRelocationInKernelRelocationsWhenParsingRelocationsForExtFuncUsageForKernelThenDoNotAddKernelDependency) {
|
||||
WhiteBox<NEO::LinkerInput> mockLinkerInput;
|
||||
|
||||
auto &symbols = mockLinkerInput.symbols;
|
||||
@@ -806,11 +809,8 @@ TEST(LinkerInputTests, GivenNonFunctionRelocationInKernelRelocationsWhenParsingR
|
||||
symbols.emplace("fun", symbol2);
|
||||
|
||||
for (auto nonFuncRelocationName : {
|
||||
implicitArgsRelocationSymbolName,
|
||||
std::string_view(".str"),
|
||||
std::string_view("globalVar"),
|
||||
Linker::perThreadOff,
|
||||
Linker::subDeviceID,
|
||||
std::string_view("")}) {
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo{};
|
||||
@@ -822,6 +822,35 @@ TEST(LinkerInputTests, GivenNonFunctionRelocationInKernelRelocationsWhenParsingR
|
||||
EXPECT_EQ(0u, mockLinkerInput.kernelDependencies.size());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LinkerInputTests, GivenExternalSymbolRelocationInKernelRelocationsWhenParsingRelocationsForExtFuncUsageForKernelThenAddOptionalKernelDependency) {
|
||||
WhiteBox<NEO::LinkerInput> mockLinkerInput;
|
||||
|
||||
auto &externalSymbols = mockLinkerInput.externalSymbols;
|
||||
|
||||
externalSymbols.push_back(std::string(implicitArgsRelocationSymbolName));
|
||||
externalSymbols.push_back(std::string(Linker::perThreadOff));
|
||||
externalSymbols.push_back(std::string(Linker::subDeviceID));
|
||||
|
||||
for (auto relocationName : {
|
||||
implicitArgsRelocationSymbolName,
|
||||
Linker::perThreadOff,
|
||||
Linker::subDeviceID}) {
|
||||
|
||||
NEO::LinkerInput::RelocationInfo relocInfo{};
|
||||
relocInfo.symbolName = relocationName;
|
||||
|
||||
std::string kernelName = "kernel";
|
||||
mockLinkerInput.parseRelocationForExtFuncUsage(relocInfo, kernelName);
|
||||
EXPECT_TRUE(mockLinkerInput.extFunDependencies.empty());
|
||||
}
|
||||
|
||||
EXPECT_EQ(3u, mockLinkerInput.kernelDependencies.size());
|
||||
for (auto &kernelDependency : mockLinkerInput.kernelDependencies) {
|
||||
EXPECT_TRUE(kernelDependency.optional);
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F(LinkerTests, givenEmptyLinkerInputThenLinkerOutputIsEmpty) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
NEO::Linker linker(linkerInput);
|
||||
@@ -2140,7 +2169,7 @@ TEST_F(LinkerTests, GivenDebugDataWhenApplyingDebugDataRelocationsThenRelocation
|
||||
sectionNames[4] = ".debug_line";
|
||||
sectionNames[5] = ".data.const";
|
||||
|
||||
elf64.setupSecionNames(std::move(sectionNames));
|
||||
elf64.setupSectionNames(std::move(sectionNames));
|
||||
|
||||
NEO::Elf::Elf<NEO::Elf::EI_CLASS_64>::RelocationInfo reloc0 = {};
|
||||
reloc0.offset = 64;
|
||||
|
||||
Reference in New Issue
Block a user