namespace coff {
SymbolTable::SymbolTable() {
- resolve(new (Alloc) DefinedAbsolute("__ImageBase", Config->ImageBase));
+ addSymbol(new (Alloc) DefinedAbsolute("__ImageBase", Config->ImageBase));
if (!Config->EntryName.empty())
- resolve(new (Alloc) Undefined(Config->EntryName));
+ addSymbol(new (Alloc) Undefined(Config->EntryName));
}
-void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
- Files.push_back(std::move(File));
+void SymbolTable::addFile(std::unique_ptr<InputFile> FileP) {
+ InputFile *File = FileP.get();
+ Files.push_back(std::move(FileP));
+ if (auto *F = dyn_cast<ArchiveFile>(File)) {
+ ArchiveQueue.push_back(F);
+ return;
+ }
+ ObjectQueue.push_back(File);
+ if (auto *F = dyn_cast<ObjectFile>(File)) {
+ ObjectFiles.push_back(F);
+ } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
+ BitcodeFiles.push_back(F);
+ } else {
+ ImportFiles.push_back(cast<ImportFile>(File));
+ }
}
std::error_code SymbolTable::run() {
- while (FileIdx < Files.size()) {
- InputFile *F = Files[FileIdx++].get();
+ while (!ArchiveQueue.empty() || !ObjectQueue.empty()) {
+ if (auto EC = readArchives())
+ return EC;
+ if (auto EC = readObjects())
+ return EC;
+ ++Version;
+ }
+ return std::error_code();
+}
+
+std::error_code SymbolTable::readArchives() {
+ if (ArchiveQueue.empty())
+ return std::error_code();
+
+ // Add lazy symbols to the symbol table. Lazy symbols that conflict
+ // with existing undefined symbols are accumulated in LazySyms.
+ std::vector<Symbol *> LazySyms;
+ for (ArchiveFile *File : ArchiveQueue) {
if (Config->Verbose)
- llvm::outs() << "Reading " << F->getShortName() << "\n";
- if (auto EC = F->parse())
+ llvm::outs() << "Reading " << File->getShortName() << "\n";
+ if (auto EC = File->parse())
return EC;
- if (auto *P = dyn_cast<ObjectFile>(F)) {
- ObjectFiles.push_back(P);
- } else if (auto *P = dyn_cast<ArchiveFile>(F)) {
- ArchiveFiles.push_back(P);
- } else if (auto *P = dyn_cast<BitcodeFile>(F)) {
- BitcodeFiles.push_back(P);
- } else {
- ImportFiles.push_back(cast<ImportFile>(F));
- }
+ for (Lazy *Sym : File->getLazySymbols())
+ addLazy(Sym, &LazySyms);
+ }
+ ArchiveQueue.clear();
- for (SymbolBody *B : F->getSymbols())
- if (B->isExternal())
- if (auto EC = resolve(B))
- return EC;
+ // Add archive member files to ObjectQueue that should resolve
+ // existing undefined symbols.
+ for (Symbol *Sym : LazySyms)
+ if (auto EC = addMemberFile(cast<Lazy>(Sym->Body)))
+ return EC;
+ return std::error_code();
+}
- // If a object file contains .drectve section,
- // read that and add files listed there.
- StringRef S = F->getDirectives();
+std::error_code SymbolTable::readObjects() {
+ if (ObjectQueue.empty())
+ return std::error_code();
+
+ // Add defined and undefined symbols to the symbol table.
+ std::vector<StringRef> Directives;
+ for (size_t I = 0; I < ObjectQueue.size(); ++I) {
+ InputFile *File = ObjectQueue[I];
+ if (Config->Verbose)
+ llvm::outs() << "Reading " << File->getShortName() << "\n";
+ if (auto EC = File->parse())
+ return EC;
+ // Adding symbols may add more files to ObjectQueue
+ // (but not to ArchiveQueue).
+ for (SymbolBody *Sym : File->getSymbols())
+ if (Sym->isExternal())
+ if (auto EC = addSymbol(Sym))
+ return EC;
+ StringRef S = File->getDirectives();
if (!S.empty())
- if (auto EC = Driver->parseDirectives(S))
- return EC;
+ Directives.push_back(S);
}
+ ObjectQueue.clear();
+
+ // Parse directive sections. This may add files to
+ // ArchiveQueue and ObjectQueue.
+ for (StringRef S : Directives)
+ if (auto EC = Driver->parseDirectives(S))
+ return EC;
return std::error_code();
}
return Ret;
}
-// This function resolves conflicts if there's an existing symbol with
-// the same name. Decisions are made based on symbol type.
-std::error_code SymbolTable::resolve(SymbolBody *New) {
- // Find an existing Symbol or create and insert a new one.
- StringRef Name = New->getName();
- Symbol *&Sym = Symtab[Name];
+void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
+ Symbol *&Sym = Symtab[New->getName()];
+ if (!Sym) {
+ Sym = new (Alloc) Symbol(New);
+ New->setBackref(Sym);
+ return;
+ }
+ SymbolBody *Existing = Sym->Body;
+ if (!isa<Undefined>(Existing))
+ return;
+ Sym->Body = New;
+ New->setBackref(Sym);
+ Accum->push_back(Sym);
+}
+
+std::error_code SymbolTable::addSymbol(SymbolBody *New) {
+ // Find an existing symbol or create and insert a new one.
+ assert(isa<Defined>(New) || isa<Undefined>(New));
+ Symbol *&Sym = Symtab[New->getName()];
if (!Sym) {
Sym = new (Alloc) Symbol(New);
New->setBackref(Sym);
- ++Version;
return std::error_code();
}
New->setBackref(Sym);
- // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
- // equivalent (conflicting), or more preferable, respectively.
+ // If we have an undefined symbol and a lazy symbol,
+ // let the lazy symbol to read a member file.
SymbolBody *Existing = Sym->Body;
- int comp = Existing->compare(New);
- if (comp < 0) {
+ if (auto *L = dyn_cast<Lazy>(Existing)) {
+ if (auto *U = dyn_cast<Undefined>(New))
+ if (!U->getWeakAlias())
+ return addMemberFile(L);
Sym->Body = New;
- ++Version;
+ return std::error_code();
}
- if (comp == 0) {
+
+ // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
+ // equivalent (conflicting), or more preferable, respectively.
+ int Comp = Existing->compare(New);
+ if (Comp == 0) {
llvm::errs() << "duplicate symbol: " << Existing->getDebugName()
<< " and " << New->getDebugName() << "\n";
return make_error_code(LLDError::DuplicateSymbols);
}
-
- // If we have an Undefined symbol for a Lazy symbol, we need
- // to read an archive member to replace the Lazy symbol with
- // a Defined symbol.
- if (isa<Undefined>(Existing) || isa<Undefined>(New))
- if (auto *B = dyn_cast<Lazy>(Sym->Body))
- return addMemberFile(B);
+ if (Comp < 0)
+ Sym->Body = New;
return std::error_code();
}
}
std::error_code SymbolTable::addUndefined(StringRef Name) {
- return resolve(new (Alloc) Undefined(Name));
+ return addSymbol(new (Alloc) Undefined(Name));
}
// Resolve To, and make From an alias to To.
if (!isa<Undefined>(Sym->Body))
return std::error_code();
SymbolBody *Body = new (Alloc) Undefined(To);
- if (auto EC = resolve(Body))
+ if (auto EC = addSymbol(Body))
return EC;
SymbolBody *Repl = Body->getReplacement();
if (isa<Undefined>(Repl))
return EC;
ObjectFile *Obj = FileOrErr.get();
- // Skip the combined object file as the file is processed below
- // rather than by run().
- ++FileIdx;
-
for (SymbolBody *Body : Obj->getSymbols()) {
if (!Body->isExternal())
continue;
return make_error_code(LLDError::BrokenFile);
}
Sym->Body = Body;
- } else {
- int comp = Sym->Body->compare(Body);
- if (comp < 0)
- Sym->Body = Body;
- if (comp == 0) {
- llvm::errs() << "LTO: unexpected duplicate symbol: " << Name << "\n";
- return make_error_code(LLDError::BrokenFile);
- }
+ continue;
}
-
- // We may see new references to runtime library symbols such as __chkstk
- // here. These symbols must be wholly defined in non-bitcode files.
- if (auto *B = dyn_cast<Lazy>(Sym->Body))
- if (auto EC = addMemberFile(B))
+ if (auto *L = dyn_cast<Lazy>(Sym->Body)) {
+ // We may see new references to runtime library symbols such as __chkstk
+ // here. These symbols must be wholly defined in non-bitcode files.
+ if (auto EC = addMemberFile(L))
return EC;
+ continue;
+ }
+ SymbolBody *Existing = Sym->Body;
+ int Comp = Existing->compare(Body);
+ if (Comp == 0) {
+ llvm::errs() << "LTO: unexpected duplicate symbol: " << Name << "\n";
+ return make_error_code(LLDError::BrokenFile);
+ }
+ if (Comp < 0)
+ Sym->Body = Body;
}
size_t NumBitcodeFiles = BitcodeFiles.size();