// Add all files to the symbol table. This will add almost all
// symbols that we need to the symbol table.
for (InputFile *F : Files)
- Symtab->addFile<ELFT>(F);
+ parseFile<ELFT>(F);
// Now that we have every file, we can decide if we will need a
// dynamic symbol table.
return MBRef;
}
+// All input object files must be for the same architecture
+// (e.g. it does not make sense to link x86 object files with
+// MIPS object files.) This function checks for that error.
+static bool isCompatible(InputFile *File) {
+ if (!File->isElf() && !isa<BitcodeFile>(File))
+ return true;
+
+ if (File->EKind == Config->EKind && File->EMachine == Config->EMachine) {
+ if (Config->EMachine != EM_MIPS)
+ return true;
+ if (isMipsN32Abi(File) == Config->MipsN32Abi)
+ return true;
+ }
+
+ if (!Config->Emulation.empty()) {
+ error(toString(File) + " is incompatible with " + Config->Emulation);
+ } else {
+ InputFile *Existing;
+ if (!ObjectFiles.empty())
+ Existing = ObjectFiles[0];
+ else if (!SharedFiles.empty())
+ Existing = SharedFiles[0];
+ else
+ Existing = BitcodeFiles[0];
+
+ error(toString(File) + " is incompatible with " + toString(Existing));
+ }
+
+ return false;
+}
+
+// Add symbols in File to the symbol table.
+template <class ELFT> void elf::parseFile(InputFile *File) {
+ // Comdat groups define "link once" sections. If two comdat groups have the
+ // same name, only one of them is linked, and the other is ignored. This set
+ // is used to uniquify them.
+ static llvm::DenseSet<llvm::CachedHashStringRef> ComdatGroups;
+
+ if (!isCompatible(File))
+ return;
+
+ // Binary file
+ if (auto *F = dyn_cast<BinaryFile>(File)) {
+ BinaryFiles.push_back(F);
+ F->parse();
+ return;
+ }
+
+ // .a file
+ if (auto *F = dyn_cast<ArchiveFile>(File)) {
+ F->parse<ELFT>();
+ return;
+ }
+
+ // Lazy object file
+ if (auto *F = dyn_cast<LazyObjFile>(File)) {
+ LazyObjFiles.push_back(F);
+ F->parse<ELFT>();
+ return;
+ }
+
+ if (Config->Trace)
+ message(toString(File));
+
+ // .so file
+ if (auto *F = dyn_cast<SharedFile>(File)) {
+ F->parse<ELFT>();
+ return;
+ }
+
+ // LLVM bitcode file
+ if (auto *F = dyn_cast<BitcodeFile>(File)) {
+ BitcodeFiles.push_back(F);
+ F->parse<ELFT>(ComdatGroups);
+ return;
+ }
+
+ // Regular object file
+ ObjectFiles.push_back(File);
+ cast<ObjFile<ELFT>>(File)->parse(ComdatGroups);
+}
+
// Concatenates arguments to construct a string representing an error location.
static std::string createFileLineMsg(StringRef Path, unsigned Line) {
std::string Filename = path::filename(Path);
return Path;
}
+template void elf::parseFile<ELF32LE>(InputFile *);
+template void elf::parseFile<ELF32BE>(InputFile *);
+template void elf::parseFile<ELF64LE>(InputFile *);
+template void elf::parseFile<ELF64BE>(InputFile *);
+
template void ArchiveFile::parse<ELF32LE>();
template void ArchiveFile::parse<ELF32BE>();
template void ArchiveFile::parse<ELF64LE>();
// Opens a given file.
llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
+// Add symbols in File to the symbol table.
+template <class ELFT> void parseFile(InputFile *File);
+
// The root class of input files.
class InputFile {
public:
SymbolTable *elf::Symtab;
-static InputFile *getFirstElf() {
- if (!ObjectFiles.empty())
- return ObjectFiles[0];
- if (!SharedFiles.empty())
- return SharedFiles[0];
- return BitcodeFiles[0];
-}
-
-// All input object files must be for the same architecture
-// (e.g. it does not make sense to link x86 object files with
-// MIPS object files.) This function checks for that error.
-static bool isCompatible(InputFile *F) {
- if (!F->isElf() && !isa<BitcodeFile>(F))
- return true;
-
- if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) {
- if (Config->EMachine != EM_MIPS)
- return true;
- if (isMipsN32Abi(F) == Config->MipsN32Abi)
- return true;
- }
-
- if (!Config->Emulation.empty())
- error(toString(F) + " is incompatible with " + Config->Emulation);
- else
- error(toString(F) + " is incompatible with " + toString(getFirstElf()));
- return false;
-}
-
-// Add symbols in File to the symbol table.
-template <class ELFT> void SymbolTable::addFile(InputFile *File) {
- if (!isCompatible(File))
- return;
-
- // Binary file
- if (auto *F = dyn_cast<BinaryFile>(File)) {
- BinaryFiles.push_back(F);
- F->parse();
- return;
- }
-
- // .a file
- if (auto *F = dyn_cast<ArchiveFile>(File)) {
- F->parse<ELFT>();
- return;
- }
-
- // Lazy object file
- if (auto *F = dyn_cast<LazyObjFile>(File)) {
- LazyObjFiles.push_back(F);
- F->parse<ELFT>();
- return;
- }
-
- if (Config->Trace)
- message(toString(File));
-
- // .so file
- if (auto *F = dyn_cast<SharedFile>(File)) {
- F->parse<ELFT>();
- return;
- }
-
- // LLVM bitcode file
- if (auto *F = dyn_cast<BitcodeFile>(File)) {
- BitcodeFiles.push_back(F);
- F->parse<ELFT>(ComdatGroups);
- return;
- }
-
- // Regular object file
- ObjectFiles.push_back(File);
- cast<ObjFile<ELFT>>(File)->parse(ComdatGroups);
-}
-
// This function is where all the optimizations of link-time
// optimization happens. When LTO is in use, some input files are
// not in native object file format but in the LLVM bitcode format.
}
if (InputFile *F = File.fetch(Sym))
- addFile<ELFT>(F);
+ parseFile<ELFT>(F);
}
template <class ELFT>
}
if (InputFile *F = File.fetch())
- addFile<ELFT>(F);
+ parseFile<ELFT>(F);
}
template <class ELFT> void SymbolTable::fetchLazy(Symbol *Sym) {
if (auto *S = dyn_cast<LazyArchive>(Sym)) {
if (InputFile *File = S->fetch())
- addFile<ELFT>(File);
+ parseFile<ELFT>(File);
return;
}
auto *S = cast<LazyObject>(Sym);
if (InputFile *File = cast<LazyObjFile>(S->File)->fetch())
- addFile<ELFT>(File);
+ parseFile<ELFT>(File);
}
// Initialize DemangledSyms with a map from demangled symbols to symbol
Sym->parseSymbolVersion();
}
-template void SymbolTable::addFile<ELF32LE>(InputFile *);
-template void SymbolTable::addFile<ELF32BE>(InputFile *);
-template void SymbolTable::addFile<ELF64LE>(InputFile *);
-template void SymbolTable::addFile<ELF64BE>(InputFile *);
-
template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef, uint8_t, uint8_t,
uint8_t, bool, InputFile *);
template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef, uint8_t, uint8_t,
// is one add* function per symbol type.
class SymbolTable {
public:
- template <class ELFT> void addFile(InputFile *File);
template <class ELFT> void addCombinedLTOObject();
void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap);