COFF: Resolve AlternateNames using weak aliases.

Previously, we use SymbolTable::rename to resolve AlternateName symbols.
This patch is to merge that mechanism with weak aliases, so that we
remove that function.

llvm-svn: 241230
This commit is contained in:
Rui Ueyama 2015-07-02 02:38:59 +00:00
parent c3ca6e563b
commit 3d4c69c04d
5 changed files with 33 additions and 58 deletions

View File

@ -555,8 +555,6 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// A new file may contain a directive section to add new command line options.
// That's why we have to repeat until converge.)
for (;;) {
size_t Ver = Symtab.getVersion();
// Windows specific -- if entry point is not found,
// search for its mangled names.
if (Config->Entry)
@ -570,22 +568,23 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Add weak aliases. Weak aliases is a mechanism to give remaining
// undefined symbols final chance to be resolved successfully.
// This is symbol renaming.
for (auto &P : Config->AlternateNames) {
StringRef From = P.first;
StringRef To = P.second;
if (auto EC = Symtab.rename(From, To)) {
llvm::errs() << EC.message() << "\n";
return false;
}
for (auto Pair : Config->AlternateNames) {
StringRef From = Pair.first;
StringRef To = Pair.second;
Symbol* Sym = Symtab.findSymbol(From);
if (!Sym)
continue;
if (auto *U = dyn_cast<Undefined>(Sym->Body))
if (!U->WeakAlias)
U->WeakAlias = Symtab.addUndefined(To);
}
if (Symtab.queueEmpty())
break;
if (auto EC = Symtab.run()) {
llvm::errs() << EC.message() << "\n";
return false;
}
if (Ver == Symtab.getVersion())
break;
}
// Make sure we have resolved all symbols.

View File

@ -197,7 +197,7 @@ Undefined *ObjectFile::createWeakExternal(COFFSymbolRef Sym, const void *AuxP) {
COFFObj->getSymbolName(Sym, Name);
auto *U = new (Alloc) Undefined(Name);
auto *Aux = (const coff_aux_weak_external *)AuxP;
U->WeakAlias = SparseSymbolBodies[Aux->TagIndex];
U->WeakAlias = cast<Undefined>(SparseSymbolBodies[Aux->TagIndex]);
return U;
}

View File

@ -45,12 +45,11 @@ void SymbolTable::addFile(std::unique_ptr<InputFile> FileP) {
}
std::error_code SymbolTable::run() {
while (!ArchiveQueue.empty() || !ObjectQueue.empty()) {
while (!queueEmpty()) {
if (auto EC = readArchives())
return EC;
if (auto EC = readObjects())
return EC;
++Version;
}
return std::error_code();
}
@ -112,6 +111,10 @@ std::error_code SymbolTable::readObjects() {
return std::error_code();
}
bool SymbolTable::queueEmpty() {
return ArchiveQueue.empty() && ObjectQueue.empty();
}
bool SymbolTable::reportRemainingUndefines() {
bool Ret = false;
for (auto &I : Symtab) {
@ -120,11 +123,12 @@ bool SymbolTable::reportRemainingUndefines() {
if (!Undef)
continue;
StringRef Name = Undef->getName();
// The weak alias may have been resovled, so check for that.
if (SymbolBody *Alias = Undef->WeakAlias) {
if (auto *D = dyn_cast<Defined>(Alias->repl())) {
// A weak alias may have been resovled, so check for that. A weak alias
// may be an weak alias to other symbol, so check recursively.
for (Undefined *U = Undef->WeakAlias; U; U = U->WeakAlias) {
if (auto *D = dyn_cast<Defined>(U->repl())) {
Sym->Body = D;
continue;
goto next;
}
}
// If we can resolve a symbol by removing __imp_ prefix, do that.
@ -145,6 +149,7 @@ bool SymbolTable::reportRemainingUndefines() {
continue;
}
Ret = true;
next:;
}
return Ret;
}
@ -253,44 +258,21 @@ void SymbolTable::mangleMaybe(Undefined *U) {
// In Microsoft ABI, a non-member function name is mangled this way.
std::string Prefix = ("?" + U->getName() + "@@Y").str();
for (auto I : Symtab) {
StringRef Name = I.first;
Symbol *New = I.second;
for (auto Pair : Symtab) {
StringRef Name = Pair.first;
if (!Name.startswith(Prefix))
continue;
U->WeakAlias = New->Body;
if (auto *L = dyn_cast<Lazy>(New->Body))
addMemberFile(L);
U->WeakAlias = addUndefined(Name);
return;
}
}
Undefined *SymbolTable::addUndefined(StringRef Name) {
auto *U = new (Alloc) Undefined(Name);
addSymbol(U);
return U;
}
// Resolve To, and make From an alias to To.
std::error_code SymbolTable::rename(StringRef From, StringRef To) {
// If From is not undefined, do nothing.
// Otherwise, rename it to see if To can be resolved instead.
auto It = Symtab.find(From);
if (It == Symtab.end())
return std::error_code();
Symbol *Sym = It->second;
if (!isa<Undefined>(Sym->Body))
return std::error_code();
SymbolBody *Body = new (Alloc) Undefined(To);
if (auto EC = addSymbol(Body))
return EC;
SymbolBody *Repl = Body->repl();
if (isa<Undefined>(Repl))
return std::error_code();
Sym->Body = Repl;
Body->setBackref(Sym);
++Version;
return std::error_code();
auto *New = new (Alloc) Undefined(Name);
addSymbol(New);
if (auto *U = dyn_cast<Undefined>(New->repl()))
return U;
return New;
}
void SymbolTable::printMap(llvm::raw_ostream &OS) {

View File

@ -46,7 +46,7 @@ public:
std::error_code run();
std::error_code readArchives();
std::error_code readObjects();
size_t getVersion() { return Version; }
bool queueEmpty();
// Print an error message on undefined symbols.
bool reportRemainingUndefines();
@ -85,9 +85,6 @@ public:
// Creates an Undefined symbol for a given name.
Undefined *addUndefined(StringRef Name);
// Rename From -> To in the symbol table.
std::error_code rename(StringRef From, StringRef To);
// A list of chunks which to be added to .rdata.
std::vector<Chunk *> LocalImportChunks;
@ -107,9 +104,6 @@ private:
std::vector<BitcodeFile *> BitcodeFiles;
std::unique_ptr<MemoryBuffer> LTOMB;
llvm::BumpPtrAllocator Alloc;
// This variable is incremented every time Symtab is updated.
size_t Version = 0;
};
} // namespace coff

View File

@ -249,7 +249,7 @@ public:
// undefined symbol a second chance if it would remain undefined.
// If it remains undefined, it'll be replaced with whatever the
// Alias pointer points to.
SymbolBody *WeakAlias = nullptr;
Undefined *WeakAlias = nullptr;
};
// Windows-specific classes.