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() {
20   resolve(new (Alloc) SyntheticUndefined("_start"));
21 }
22 
23 void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
24   File->parse();
25   InputFile *FileP = File.release();
26   auto *P = cast<ObjectFileBase>(FileP);
27   addObject(P);
28 }
29 
30 void SymbolTable::addObject(ObjectFileBase *File) {
31   if (!ObjectFiles.empty()) {
32     ObjectFileBase &Old = *ObjectFiles[0];
33     if (!Old.isCompatibleWith(*File))
34       error(Twine(Old.getName() + " is incompatible with " + File->getName()));
35   }
36 
37   ObjectFiles.emplace_back(File);
38   for (SymbolBody *Body : File->getSymbols())
39     resolve(Body);
40 }
41 
42 void SymbolTable::reportRemainingUndefines() {
43   for (auto &I : Symtab) {
44     SymbolBody *Body = I.second->Body;
45     if (Body->isStrongUndefined())
46       error(Twine("undefined symbol: ") + Body->getName());
47   }
48 }
49 
50 // This function resolves conflicts if there's an existing symbol with
51 // the same name. Decisions are made based on symbol type.
52 void SymbolTable::resolve(SymbolBody *New) {
53   // Find an existing Symbol or create and insert a new one.
54   StringRef Name = New->getName();
55   Builder.add(Name);
56   Symbol *&Sym = Symtab[Name];
57   if (!Sym) {
58     Sym = new (Alloc) Symbol(New);
59     New->setBackref(Sym);
60     return;
61   }
62   New->setBackref(Sym);
63 
64   // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
65   // equivalent (conflicting), or more preferable, respectively.
66   SymbolBody *Existing = Sym->Body;
67   int comp = Existing->compare(New);
68   if (comp < 0)
69     Sym->Body = New;
70   if (comp == 0)
71     error(Twine("duplicate symbol: ") + Name);
72 }
73