mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-25 05:24:02 +08:00
Linker: add support for symbols with local binding
This commits add support for relocating symbols with local binding and of functional type (STB_LOCAL, STT_FUNC). Related-To: NEO-7299 Signed-off-by: Kacper Nowak <kacper.nowak@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
824c781ab5
commit
710c8cf5ef
@@ -203,6 +203,14 @@ void LinkerInput::decodeElfSymbolTableAndRelocations(Elf::Elf<Elf::EI_CLASS_64>
|
||||
} break;
|
||||
}
|
||||
symbols.insert({elf.getSymbolName(symbol.name), symbolInfo});
|
||||
} else if (type == Elf::SYMBOL_TABLE_TYPE::STT_FUNC) {
|
||||
DEBUG_BREAK_IF(Elf::SYMBOL_TABLE_BIND::STB_LOCAL != bind);
|
||||
LocalFuncSymbolInfo localSymbolInfo;
|
||||
localSymbolInfo.offset = static_cast<uint32_t>(symbol.value);
|
||||
localSymbolInfo.size = static_cast<uint32_t>(symbol.size);
|
||||
auto symbolSectionName = elf.getSectionName(symbol.shndx);
|
||||
localSymbolInfo.targetedKernelSectionName = symbolSectionName.substr(Elf::SectionsNamesZebin::textPrefix.length());
|
||||
localSymbols.insert({elf.getSymbolName(symbol.name), localSymbolInfo});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +275,8 @@ void LinkerInput::parseRelocationForExtFuncUsage(const RelocationInfo &relocInfo
|
||||
}
|
||||
}
|
||||
|
||||
bool Linker::processRelocations(const SegmentInfo &globalVariables, const SegmentInfo &globalConstants, const SegmentInfo &exportedFunctions, const SegmentInfo &globalStrings) {
|
||||
bool Linker::processRelocations(const SegmentInfo &globalVariables, const SegmentInfo &globalConstants, const SegmentInfo &exportedFunctions, const SegmentInfo &globalStrings,
|
||||
const PatchableSegments &instructionsSegments) {
|
||||
relocatedSymbols.reserve(data.getSymbols().size());
|
||||
for (auto &symbol : data.getSymbols()) {
|
||||
const SegmentInfo *seg = nullptr;
|
||||
@@ -295,6 +304,15 @@ bool Linker::processRelocations(const SegmentInfo &globalVariables, const Segmen
|
||||
}
|
||||
relocatedSymbols[symbol.first] = {symbol.second, gpuAddress};
|
||||
}
|
||||
localRelocatedSymbols.reserve(data.getLocalSymbols().size());
|
||||
for (auto &localSymbol : data.getLocalSymbols()) {
|
||||
for (auto &s : instructionsSegments) {
|
||||
if (s.kernelName == localSymbol.second.targetedKernelSectionName) {
|
||||
uintptr_t gpuAddress = s.gpuAddress + localSymbol.second.offset;
|
||||
localRelocatedSymbols[localSymbol.first] = {localSymbol.second, gpuAddress};
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -347,6 +365,20 @@ void Linker::patchInstructionsSegments(const std::vector<PatchableSegment> &inst
|
||||
continue;
|
||||
}
|
||||
auto symbolIt = relocatedSymbols.find(relocation.symbolName);
|
||||
if (symbolIt == relocatedSymbols.end()) {
|
||||
auto localSymbolIt = localRelocatedSymbols.find(relocation.symbolName);
|
||||
if (localRelocatedSymbols.end() != localSymbolIt) {
|
||||
if (localSymbolIt->first == kernelDescriptors[segId]->kernelMetadata.kernelName) {
|
||||
uint64_t patchValue = localSymbolIt->second.gpuAddress + relocation.addend;
|
||||
patchAddress(relocAddress, patchValue, relocation);
|
||||
continue;
|
||||
}
|
||||
} else if (relocation.symbolName.empty()) {
|
||||
uint64_t patchValue = 0;
|
||||
patchAddress(relocAddress, patchValue, relocation);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
bool unresolvedExternal = (symbolIt == relocatedSymbols.end());
|
||||
if (invalidOffset || unresolvedExternal) {
|
||||
uint32_t segId = static_cast<uint32_t>(segIt - instructionsSegments.begin());
|
||||
@@ -536,7 +568,7 @@ void Linker::resolveBuiltins(Device *pDevice, UnresolvedExternals &outUnresolved
|
||||
int vecIndex = static_cast<int>(outUnresolvedExternals.size() - 1u);
|
||||
for (; vecIndex >= 0; --vecIndex) {
|
||||
if (outUnresolvedExternals[vecIndex].unresolvedRelocation.symbolName == subDeviceID) {
|
||||
RelocatedSymbol symbol;
|
||||
RelocatedSymbol<SymbolInfo> symbol;
|
||||
symbol.gpuAddress = static_cast<uintptr_t>(pDevice->getDefaultEngine().commandStreamReceiver->getWorkPartitionAllocationGpuAddress());
|
||||
auto relocAddress = ptrOffset(instructionsSegments[outUnresolvedExternals[vecIndex].instructionsSegmentId].hostPointer,
|
||||
static_cast<uintptr_t>(outUnresolvedExternals[vecIndex].unresolvedRelocation.offset));
|
||||
|
||||
@@ -55,6 +55,12 @@ struct SymbolInfo {
|
||||
SegmentType segment = SegmentType::Unknown;
|
||||
};
|
||||
|
||||
struct LocalFuncSymbolInfo {
|
||||
uint32_t offset = std::numeric_limits<uint32_t>::max();
|
||||
uint32_t size = std::numeric_limits<uint32_t>::max();
|
||||
std::string targetedKernelSectionName;
|
||||
};
|
||||
|
||||
struct LinkerInput {
|
||||
union Traits {
|
||||
enum PointerSize : uint8_t {
|
||||
@@ -97,6 +103,7 @@ struct LinkerInput {
|
||||
using SectionNameToSegmentIdMap = std::unordered_map<std::string, uint32_t>;
|
||||
using Relocations = std::vector<RelocationInfo>;
|
||||
using SymbolMap = std::unordered_map<std::string, SymbolInfo>;
|
||||
using LocalSymbolMap = std::unordered_map<std::string, LocalFuncSymbolInfo>;
|
||||
using RelocationsPerInstSegment = std::vector<Relocations>;
|
||||
|
||||
virtual ~LinkerInput() = default;
|
||||
@@ -123,6 +130,10 @@ struct LinkerInput {
|
||||
return symbols;
|
||||
}
|
||||
|
||||
const LocalSymbolMap &getLocalSymbols() const {
|
||||
return localSymbols;
|
||||
}
|
||||
|
||||
void addSymbol(const std::string &symbolName, const SymbolInfo &symbolInfo) {
|
||||
symbols.emplace(std::make_pair(symbolName, symbolInfo));
|
||||
}
|
||||
@@ -156,6 +167,7 @@ struct LinkerInput {
|
||||
|
||||
Traits traits;
|
||||
SymbolMap symbols;
|
||||
LocalSymbolMap localSymbols;
|
||||
RelocationsPerInstSegment textRelocations;
|
||||
Relocations dataRelocations;
|
||||
std::vector<std::pair<std::string, SymbolInfo>> extFuncSymbols;
|
||||
@@ -177,7 +189,9 @@ struct Linker {
|
||||
|
||||
struct PatchableSegment {
|
||||
void *hostPointer = nullptr;
|
||||
uintptr_t gpuAddress = 0;
|
||||
size_t segmentSize = std::numeric_limits<size_t>::max();
|
||||
std::string kernelName;
|
||||
};
|
||||
|
||||
struct UnresolvedExternal {
|
||||
@@ -186,12 +200,14 @@ struct Linker {
|
||||
bool internalError = false;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RelocatedSymbol {
|
||||
SymbolInfo symbol;
|
||||
T symbol;
|
||||
uintptr_t gpuAddress = std::numeric_limits<uintptr_t>::max();
|
||||
};
|
||||
|
||||
using RelocatedSymbolsMap = std::unordered_map<std::string, RelocatedSymbol>;
|
||||
using RelocatedSymbolsMap = std::unordered_map<std::string, RelocatedSymbol<SymbolInfo>>;
|
||||
using LocalsRelocatedSymbolsMap = std::unordered_map<std::string, RelocatedSymbol<LocalFuncSymbolInfo>>;
|
||||
using PatchableSegments = std::vector<PatchableSegment>;
|
||||
using UnresolvedExternals = std::vector<UnresolvedExternal>;
|
||||
using KernelDescriptorsT = std::vector<KernelDescriptor *>;
|
||||
@@ -207,7 +223,7 @@ struct Linker {
|
||||
const KernelDescriptorsT &kernelDescriptors, ExternalFunctionsT &externalFunctions) {
|
||||
bool success = data.isValid();
|
||||
auto initialUnresolvedExternalsCount = outUnresolvedExternals.size();
|
||||
success = success && processRelocations(globalVariablesSegInfo, globalConstantsSegInfo, exportedFunctionsSegInfo, globalStringsSegInfo);
|
||||
success = success && processRelocations(globalVariablesSegInfo, globalConstantsSegInfo, exportedFunctionsSegInfo, globalStringsSegInfo, instructionsSegments);
|
||||
if (!success) {
|
||||
return LinkingStatus::Error;
|
||||
}
|
||||
@@ -238,8 +254,9 @@ struct Linker {
|
||||
protected:
|
||||
const LinkerInput &data;
|
||||
RelocatedSymbolsMap relocatedSymbols;
|
||||
LocalsRelocatedSymbolsMap localRelocatedSymbols;
|
||||
|
||||
bool processRelocations(const SegmentInfo &globalVariables, const SegmentInfo &globalConstants, const SegmentInfo &exportedFunctions, const SegmentInfo &globalStrings);
|
||||
bool processRelocations(const SegmentInfo &globalVariables, const SegmentInfo &globalConstants, const SegmentInfo &exportedFunctions, const SegmentInfo &globalStrings, const PatchableSegments &instructionsSegments);
|
||||
|
||||
void patchInstructionsSegments(const std::vector<PatchableSegment> &instructionsSegments, std::vector<UnresolvedExternal> &outUnresolvedExternals, const KernelDescriptorsT &kernelDescriptors);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user