blob: f3cb0a2d611b614537d33121eb8cbcc4b5e9f902 [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"
Rafael Espindola192e1fa2015-08-06 15:08:23 +000011#include "Error.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000012#include "Symbols.h"
13
14using namespace llvm;
Rafael Espindoladaa92a62015-08-31 01:16:19 +000015using namespace llvm::object;
Michael J. Spencer84487f12015-07-24 21:03:07 +000016
17using namespace lld;
18using namespace lld::elf2;
19
Rafael Espindola1bd885a2015-08-14 16:46:28 +000020SymbolTable::SymbolTable() {
Rafael Espindola1bd885a2015-08-14 16:46:28 +000021}
Michael J. Spencer84487f12015-07-24 21:03:07 +000022
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000023void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000024 File->parse();
25 InputFile *FileP = File.release();
Michael J. Spencer1b348a62015-09-04 22:28:10 +000026 if (auto *AF = dyn_cast<ArchiveFile>(FileP)) {
27 ArchiveFiles.emplace_back(AF);
28 for (Lazy &Sym : AF->getLazySymbols())
29 addLazy(&Sym);
30 return;
31 }
32 addELFFile(cast<ELFFileBase>(FileP));
Michael J. Spencer84487f12015-07-24 21:03:07 +000033}
34
Rafael Espindolaf7d45f02015-08-31 01:46:20 +000035template <class ELFT> void SymbolTable::init() {
36 resolve<ELFT>(new (Alloc)
37 Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic));
38}
39
Rafael Espindola824d1a92015-09-04 00:09:43 +000040template <class ELFT> void SymbolTable::addELFFile(ELFFileBase *File) {
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000041 if (const ELFFileBase *Old = getFirstELF()) {
Rafael Espindola8aeb13f2015-09-03 19:13:13 +000042 if (!Old->isCompatibleWith(*File))
43 error(Twine(Old->getName() + " is incompatible with " + File->getName()));
Rafael Espindoladaa92a62015-08-31 01:16:19 +000044 } else {
Rafael Espindola824d1a92015-09-04 00:09:43 +000045 init<ELFT>();
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +000046 }
47
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000048 if (auto *O = dyn_cast<ObjectFileBase>(File)) {
49 ObjectFiles.emplace_back(O);
Rafael Espindola824d1a92015-09-04 00:09:43 +000050 for (SymbolBody *Body : O->getSymbols())
51 resolve<ELFT>(Body);
Rafael Espindoladaa92a62015-08-31 01:16:19 +000052 }
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000053
54 if (auto *S = dyn_cast<SharedFileBase>(File))
55 SharedFiles.emplace_back(S);
Michael J. Spencer84487f12015-07-24 21:03:07 +000056}
57
Rafael Espindola824d1a92015-09-04 00:09:43 +000058void SymbolTable::addELFFile(ELFFileBase *File) {
59 switch (File->getELFKind()) {
60 case ELF32LEKind:
61 addELFFile<ELF32LE>(File);
62 break;
63 case ELF32BEKind:
64 addELFFile<ELF32BE>(File);
65 break;
66 case ELF64LEKind:
67 addELFFile<ELF64LE>(File);
68 break;
69 case ELF64BEKind:
70 addELFFile<ELF64BE>(File);
71 break;
72 }
73}
74
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000075void SymbolTable::reportRemainingUndefines() {
Michael J. Spencer84487f12015-07-24 21:03:07 +000076 for (auto &I : Symtab) {
Rafael Espindola1bd885a2015-08-14 16:46:28 +000077 SymbolBody *Body = I.second->Body;
78 if (Body->isStrongUndefined())
79 error(Twine("undefined symbol: ") + Body->getName());
Michael J. Spencer84487f12015-07-24 21:03:07 +000080 }
81}
82
83// This function resolves conflicts if there's an existing symbol with
84// the same name. Decisions are made based on symbol type.
Rafael Espindoladaa92a62015-08-31 01:16:19 +000085template <class ELFT> void SymbolTable::resolve(SymbolBody *New) {
Michael J. Spencer1b348a62015-09-04 22:28:10 +000086 Symbol *Sym = insert(New);
87 if (Sym->Body == New)
88 return;
89
90 SymbolBody *Existing = Sym->Body;
91
92 if (Lazy *L = dyn_cast<Lazy>(Existing)) {
93 if (New->isUndefined()) {
94 addMemberFile(L);
95 return;
96 }
97
98 // Found a definition for something also in an archive. Ignore the archive
99 // definition.
100 Sym->Body = New;
101 return;
102 }
103
104 // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
105 // equivalent (conflicting), or more preferable, respectively.
106 int comp = Existing->compare<ELFT>(New);
107 if (comp < 0)
108 Sym->Body = New;
109 if (comp == 0)
110 error(Twine("duplicate symbol: ") + Sym->Body->getName());
111}
112
113Symbol *SymbolTable::insert(SymbolBody *New) {
Michael J. Spencer84487f12015-07-24 21:03:07 +0000114 // Find an existing Symbol or create and insert a new one.
115 StringRef Name = New->getName();
116 Symbol *&Sym = Symtab[Name];
117 if (!Sym) {
118 Sym = new (Alloc) Symbol(New);
119 New->setBackref(Sym);
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000120 return Sym;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000121 }
122 New->setBackref(Sym);
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000123 return Sym;
124}
Michael J. Spencer84487f12015-07-24 21:03:07 +0000125
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000126void SymbolTable::addLazy(Lazy *New) {
127 Symbol *Sym = insert(New);
128 if (Sym->Body == New)
129 return;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000130 SymbolBody *Existing = Sym->Body;
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000131 if (Existing->isDefined() || Existing->isLazy())
132 return;
133 Sym->Body = New;
134 assert(Existing->isUndefined() && "Unexpected symbol kind.");
135 addMemberFile(New);
136}
137
138void SymbolTable::addMemberFile(Lazy *Body) {
139 std::unique_ptr<InputFile> File = Body->getMember();
140
141 // getMember returns nullptr if the member was already read from the library.
142 if (!File)
143 return;
144
145 addFile(std::move(File));
Michael J. Spencer84487f12015-07-24 21:03:07 +0000146}