blob: b9640fecb0fe9246a391435e2b3566878d456fd6 [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 Espindola4340aad2015-09-11 22:42:45 +000011#include "Config.h"
Rafael Espindola192e1fa2015-08-06 15:08:23 +000012#include "Error.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000013#include "Symbols.h"
Rafael Espindola01205f72015-09-22 18:19:46 +000014#include "Target.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000015
16using namespace llvm;
Rafael Espindoladaa92a62015-08-31 01:16:19 +000017using namespace llvm::object;
Rafael Espindola01205f72015-09-22 18:19:46 +000018using namespace llvm::ELF;
Michael J. Spencer84487f12015-07-24 21:03:07 +000019
20using namespace lld;
21using namespace lld::elf2;
22
Michael J. Spencerac5f0482015-09-08 22:51:46 +000023SymbolTable::SymbolTable() {}
Michael J. Spencer84487f12015-07-24 21:03:07 +000024
Rafael Espindola67a5da62015-09-17 14:02:10 +000025bool SymbolTable::shouldUseRela() const {
26 ELFKind K = getFirstELF()->getELFKind();
27 return K == ELF64LEKind || K == ELF64BEKind;
28}
29
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000030void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000031 File->parse();
32 InputFile *FileP = File.release();
Michael J. Spencer1b348a62015-09-04 22:28:10 +000033 if (auto *AF = dyn_cast<ArchiveFile>(FileP)) {
34 ArchiveFiles.emplace_back(AF);
35 for (Lazy &Sym : AF->getLazySymbols())
36 addLazy(&Sym);
37 return;
38 }
39 addELFFile(cast<ELFFileBase>(FileP));
Michael J. Spencer84487f12015-07-24 21:03:07 +000040}
41
Rafael Espindola1d6063e2015-09-22 21:24:52 +000042static TargetInfo *createTarget(uint16_t EMachine) {
43 switch (EMachine) {
44 case EM_PPC:
45 return new PPCTargetInfo();
46 case EM_ARM:
47 return new ARMTargetInfo();
48 case EM_PPC64:
49 return new PPC64TargetInfo();
50 case EM_X86_64:
51 return new X86_64TargetInfo();
52 case EM_386:
53 return new X86TargetInfo();
54 }
55 error("Unknown target machine");
56}
57
Rafael Espindola01205f72015-09-22 18:19:46 +000058template <class ELFT> void SymbolTable::init(uint16_t EMachine) {
Rafael Espindola1d6063e2015-09-22 21:24:52 +000059 Target.reset(createTarget(EMachine));
Rafael Espindola4340aad2015-09-11 22:42:45 +000060 if (Config->Shared)
61 return;
Michael J. Spencer546c64c2015-09-08 22:34:57 +000062 EntrySym = new (Alloc) Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic);
63 resolve<ELFT>(EntrySym);
Rafael Espindolaf7d45f02015-08-31 01:46:20 +000064}
65
Rafael Espindola824d1a92015-09-04 00:09:43 +000066template <class ELFT> void SymbolTable::addELFFile(ELFFileBase *File) {
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000067 if (const ELFFileBase *Old = getFirstELF()) {
Rafael Espindola8aeb13f2015-09-03 19:13:13 +000068 if (!Old->isCompatibleWith(*File))
69 error(Twine(Old->getName() + " is incompatible with " + File->getName()));
Rafael Espindoladaa92a62015-08-31 01:16:19 +000070 } else {
Rafael Espindola01205f72015-09-22 18:19:46 +000071 init<ELFT>(File->getEMachine());
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +000072 }
73
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000074 if (auto *O = dyn_cast<ObjectFileBase>(File)) {
75 ObjectFiles.emplace_back(O);
Rafael Espindola824d1a92015-09-04 00:09:43 +000076 for (SymbolBody *Body : O->getSymbols())
77 resolve<ELFT>(Body);
Rafael Espindoladaa92a62015-08-31 01:16:19 +000078 }
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000079
Rafael Espindola18173d42015-09-08 15:50:05 +000080 if (auto *S = dyn_cast<SharedFile<ELFT>>(File)) {
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000081 SharedFiles.emplace_back(S);
Rafael Espindola18173d42015-09-08 15:50:05 +000082 for (SharedSymbol<ELFT> &Body : S->getSharedSymbols())
83 resolve<ELFT>(&Body);
84 }
Michael J. Spencer84487f12015-07-24 21:03:07 +000085}
86
Rafael Espindola824d1a92015-09-04 00:09:43 +000087void SymbolTable::addELFFile(ELFFileBase *File) {
88 switch (File->getELFKind()) {
Rui Ueyamad5004e12015-09-09 18:02:23 +000089 case ELF32LEKind:
90 addELFFile<ELF32LE>(File);
91 break;
92 case ELF32BEKind:
93 addELFFile<ELF32BE>(File);
94 break;
95 case ELF64LEKind:
96 addELFFile<ELF64LE>(File);
97 break;
98 case ELF64BEKind:
99 addELFFile<ELF64BE>(File);
100 break;
Rafael Espindola824d1a92015-09-04 00:09:43 +0000101 }
102}
103
Michael J. Spencer84487f12015-07-24 21:03:07 +0000104// This function resolves conflicts if there's an existing symbol with
105// the same name. Decisions are made based on symbol type.
Rafael Espindoladaa92a62015-08-31 01:16:19 +0000106template <class ELFT> void SymbolTable::resolve(SymbolBody *New) {
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000107 Symbol *Sym = insert(New);
108 if (Sym->Body == New)
109 return;
110
111 SymbolBody *Existing = Sym->Body;
112
113 if (Lazy *L = dyn_cast<Lazy>(Existing)) {
114 if (New->isUndefined()) {
115 addMemberFile(L);
116 return;
117 }
118
119 // Found a definition for something also in an archive. Ignore the archive
120 // definition.
121 Sym->Body = New;
122 return;
123 }
124
125 // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
126 // equivalent (conflicting), or more preferable, respectively.
127 int comp = Existing->compare<ELFT>(New);
128 if (comp < 0)
129 Sym->Body = New;
130 if (comp == 0)
131 error(Twine("duplicate symbol: ") + Sym->Body->getName());
132}
133
134Symbol *SymbolTable::insert(SymbolBody *New) {
Michael J. Spencer84487f12015-07-24 21:03:07 +0000135 // Find an existing Symbol or create and insert a new one.
136 StringRef Name = New->getName();
137 Symbol *&Sym = Symtab[Name];
138 if (!Sym) {
139 Sym = new (Alloc) Symbol(New);
140 New->setBackref(Sym);
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000141 return Sym;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000142 }
143 New->setBackref(Sym);
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000144 return Sym;
145}
Michael J. Spencer84487f12015-07-24 21:03:07 +0000146
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000147void SymbolTable::addLazy(Lazy *New) {
148 Symbol *Sym = insert(New);
149 if (Sym->Body == New)
150 return;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000151 SymbolBody *Existing = Sym->Body;
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000152 if (Existing->isDefined() || Existing->isLazy())
153 return;
154 Sym->Body = New;
155 assert(Existing->isUndefined() && "Unexpected symbol kind.");
156 addMemberFile(New);
157}
158
159void SymbolTable::addMemberFile(Lazy *Body) {
160 std::unique_ptr<InputFile> File = Body->getMember();
161
162 // getMember returns nullptr if the member was already read from the library.
163 if (!File)
164 return;
165
166 addFile(std::move(File));
Michael J. Spencer84487f12015-07-24 21:03:07 +0000167}