blob: 5054b31f363f4ba38f3ec25744b697e68a32c9b8 [file] [log] [blame]
Michael J. Spencer84487f12015-07-24 21:03:07 +00001//===- 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 "Driver.h"
12#include "Symbols.h"
13
14using namespace llvm;
15
16using namespace lld;
17using namespace lld::elf2;
18
19template <class ELFT> SymbolTable<ELFT>::SymbolTable() {
20 resolve(new (Alloc) Undefined("_start"));
21}
22
23template <class ELFT>
24void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
25 File->parse();
26 InputFile *FileP = File.release();
27 auto *P = cast<ObjectFile<ELFT>>(FileP);
28 addObject(P);
Michael J. Spencer84487f12015-07-24 21:03:07 +000029}
30
31template <class ELFT>
32void SymbolTable<ELFT>::addObject(ObjectFile<ELFT> *File) {
33 ObjectFiles.emplace_back(File);
34 for (SymbolBody *Body : File->getSymbols())
35 if (Body->isExternal())
36 resolve(Body);
37}
38
39template <class ELFT> void SymbolTable<ELFT>::reportRemainingUndefines() {
40 for (auto &I : Symtab) {
41 Symbol *Sym = I.second;
42 if (auto *Undef = dyn_cast<Undefined>(Sym->Body))
43 error(Twine("undefined symbol: ") + Undef->getName());
44 }
45}
46
47// This function resolves conflicts if there's an existing symbol with
48// the same name. Decisions are made based on symbol type.
49template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
50 // Find an existing Symbol or create and insert a new one.
51 StringRef Name = New->getName();
52 Symbol *&Sym = Symtab[Name];
53 if (!Sym) {
54 Sym = new (Alloc) Symbol(New);
55 New->setBackref(Sym);
56 return;
57 }
58 New->setBackref(Sym);
59
60 // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
61 // equivalent (conflicting), or more preferable, respectively.
62 SymbolBody *Existing = Sym->Body;
63 int comp = Existing->compare(New);
64 if (comp < 0)
65 Sym->Body = New;
66 if (comp == 0)
67 error(Twine("duplicate symbol: ") + Name);
68}
69
Michael J. Spencer84487f12015-07-24 21:03:07 +000070namespace lld {
71namespace elf2 {
72template class SymbolTable<object::ELF32LE>;
73template class SymbolTable<object::ELF32BE>;
74template class SymbolTable<object::ELF64LE>;
75template class SymbolTable<object::ELF64BE>;
76}
77}