1 //===- SymbolTable.cpp ----------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "SymbolTable.h"
11 #include "Error.h"
12 #include "Symbols.h"
13 
14 using namespace llvm;
15 
16 using namespace lld;
17 using namespace lld::elf2;
18 
19 SymbolTable::SymbolTable() { resolve(new (Alloc) Undefined("_start")); }
20 
21 void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
22   File->parse();
23   InputFile *FileP = File.release();
24   auto *P = cast<ObjectFileBase>(FileP);
25   addObject(P);
26 }
27 
28 void SymbolTable::addObject(ObjectFileBase *File) {
29   if (!ObjectFiles.empty()) {
30     ObjectFileBase &Old = *ObjectFiles[0];
31     if (!Old.isCompatibleWith(*File))
32       error(Twine(Old.getName() + " is incompatible with " + File->getName()));
33   }
34 
35   ObjectFiles.emplace_back(File);
36   for (SymbolBody *Body : File->getSymbols())
37     resolve(Body);
38 }
39 
40 void SymbolTable::reportRemainingUndefines() {
41   for (auto &I : Symtab) {
42     Symbol *Sym = I.second;
43     if (auto *Undef = dyn_cast<Undefined>(Sym->Body))
44       error(Twine("undefined symbol: ") + Undef->getName());
45   }
46 }
47 
48 // This function resolves conflicts if there's an existing symbol with
49 // the same name. Decisions are made based on symbol type.
50 void SymbolTable::resolve(SymbolBody *New) {
51   // Find an existing Symbol or create and insert a new one.
52   StringRef Name = New->getName();
53   Symbol *&Sym = Symtab[Name];
54   if (!Sym) {
55     Sym = new (Alloc) Symbol(New);
56     New->setBackref(Sym);
57     return;
58   }
59   New->setBackref(Sym);
60 
61   // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
62   // equivalent (conflicting), or more preferable, respectively.
63   SymbolBody *Existing = Sym->Body;
64   int comp = Existing->compare(New);
65   if (comp < 0)
66     Sym->Body = New;
67   if (comp == 0)
68     error(Twine("duplicate symbol: ") + Name);
69 }
70