[ExecutionEngine] Add weak symbol support to RuntimeDyld

Support weak symbols by first looking up if there is an externally visible symbol we can find,
and only if that fails using the one in the object file we're loading.

Reviewed By: lhames
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D6950

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227228 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Keno Fischer
2015-01-27 20:02:31 +00:00
parent 99b52293c7
commit 811b152d85
7 changed files with 93 additions and 2 deletions

View File

@@ -168,6 +168,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
uint32_t Flags = I->getFlags();
bool IsCommon = Flags & SymbolRef::SF_Common;
bool IsWeak = Flags & SymbolRef::SF_Weak;
if (IsCommon)
CommonSymbols.push_back(*I);
else {
@@ -188,6 +189,11 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
continue;
StringRef SectionData;
Check(SI->getContents(SectionData));
// TODO: It make make sense to delay emitting the section for weak
// symbols until they are actually required, but that's not possible
// currently, because we only know whether we will need the symbol
// in resolveRelocations, which happens after we have already finalized
// the Load.
bool IsCode = SI->isText();
unsigned SectionID =
findOrEmitSection(Obj, *SI, IsCode, LocalSections);
@@ -198,7 +204,11 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
SymbolInfo::Visibility Vis =
(Flags & SymbolRef::SF_Exported) ?
SymbolInfo::Default : SymbolInfo::Hidden;
GlobalSymbolTable[Name] = SymbolInfo(SectionID, SectOffset, Vis);
if (!IsWeak) {
GlobalSymbolTable[Name] = SymbolInfo(SectionID, SectOffset, Vis);
} else {
WeakSymbolTable[Name] = SymbolInfo(SectionID, SectOffset, Vis);
}
}
}
}
@@ -768,6 +778,21 @@ void RuntimeDyldImpl::resolveExternalSymbols() {
SymInfo.getOffset();
}
// If we didn't find the symbol yet, and it is present in the weak symbol
// table, the definition from this object file needs to be used, so emit
// it now
if (!Addr) {
RTDyldSymbolTable::const_iterator Loc = WeakSymbolTable.find(Name);
if (Loc != WeakSymbolTable.end()) {
SymbolInfo SymInfo = Loc->second;
Addr = getSectionLoadAddress(SymInfo.getSectionID()) + SymInfo.getOffset();
// Since the weak symbol is now, materialized, add it to the
// GlobalSymbolTable. If somebody later asks the ExecutionEngine
// for the address of this symbol that's where it'll look
GlobalSymbolTable[Name] = SymInfo;
}
}
// FIXME: Implement error handling that doesn't kill the host program!
if (!Addr)
report_fatal_error("Program used external function '" + Name +
@@ -784,6 +809,7 @@ void RuntimeDyldImpl::resolveExternalSymbols() {
ExternalSymbolRelocations.erase(i);
}
WeakSymbolTable.clear();
}
//===----------------------------------------------------------------------===//

View File

@@ -947,6 +947,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
break;
}
case SymbolRef::ST_Data:
case SymbolRef::ST_Function:
case SymbolRef::ST_Unknown: {
Value.SymbolName = TargetName.data();
Value.Addend = Addend;

View File

@@ -203,6 +203,9 @@ protected:
// A global symbol table for symbols from all loaded modules.
RTDyldSymbolTable GlobalSymbolTable;
// Like the global symbol table but for weak symbols
RTDyldSymbolTable WeakSymbolTable;
// Keep a map of common symbols to their info pairs
typedef std::vector<SymbolRef> CommonSymbolList;