blob: 43b82d688d046aeff8d25f799c8f9e08be31281d [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"
14
15using namespace llvm;
Rafael Espindoladaa92a62015-08-31 01:16:19 +000016using namespace llvm::object;
Michael J. Spencer84487f12015-07-24 21:03:07 +000017
18using namespace lld;
19using namespace lld::elf2;
20
Michael J. Spencerac5f0482015-09-08 22:51:46 +000021SymbolTable::SymbolTable() {}
Michael J. Spencer84487f12015-07-24 21:03:07 +000022
Rafael Espindola67a5da62015-09-17 14:02:10 +000023bool SymbolTable::shouldUseRela() const {
24 ELFKind K = getFirstELF()->getELFKind();
25 return K == ELF64LEKind || K == ELF64BEKind;
26}
27
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000028void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000029 File->parse();
30 InputFile *FileP = File.release();
Michael J. Spencer1b348a62015-09-04 22:28:10 +000031 if (auto *AF = dyn_cast<ArchiveFile>(FileP)) {
32 ArchiveFiles.emplace_back(AF);
33 for (Lazy &Sym : AF->getLazySymbols())
34 addLazy(&Sym);
35 return;
36 }
37 addELFFile(cast<ELFFileBase>(FileP));
Michael J. Spencer84487f12015-07-24 21:03:07 +000038}
39
Rafael Espindolaf7d45f02015-08-31 01:46:20 +000040template <class ELFT> void SymbolTable::init() {
Rafael Espindola4340aad2015-09-11 22:42:45 +000041 if (Config->Shared)
42 return;
Michael J. Spencer546c64c2015-09-08 22:34:57 +000043 EntrySym = new (Alloc) Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic);
44 resolve<ELFT>(EntrySym);
Rafael Espindolaf7d45f02015-08-31 01:46:20 +000045}
46
Rafael Espindola824d1a92015-09-04 00:09:43 +000047template <class ELFT> void SymbolTable::addELFFile(ELFFileBase *File) {
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000048 if (const ELFFileBase *Old = getFirstELF()) {
Rafael Espindola8aeb13f2015-09-03 19:13:13 +000049 if (!Old->isCompatibleWith(*File))
50 error(Twine(Old->getName() + " is incompatible with " + File->getName()));
Rafael Espindoladaa92a62015-08-31 01:16:19 +000051 } else {
Rafael Espindola824d1a92015-09-04 00:09:43 +000052 init<ELFT>();
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +000053 }
54
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000055 if (auto *O = dyn_cast<ObjectFileBase>(File)) {
56 ObjectFiles.emplace_back(O);
Rafael Espindola824d1a92015-09-04 00:09:43 +000057 for (SymbolBody *Body : O->getSymbols())
58 resolve<ELFT>(Body);
Rafael Espindoladaa92a62015-08-31 01:16:19 +000059 }
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000060
Rafael Espindola18173d42015-09-08 15:50:05 +000061 if (auto *S = dyn_cast<SharedFile<ELFT>>(File)) {
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000062 SharedFiles.emplace_back(S);
Rafael Espindola18173d42015-09-08 15:50:05 +000063 for (SharedSymbol<ELFT> &Body : S->getSharedSymbols())
64 resolve<ELFT>(&Body);
65 }
Michael J. Spencer84487f12015-07-24 21:03:07 +000066}
67
Rafael Espindola824d1a92015-09-04 00:09:43 +000068void SymbolTable::addELFFile(ELFFileBase *File) {
69 switch (File->getELFKind()) {
Rui Ueyamad5004e12015-09-09 18:02:23 +000070 case ELF32LEKind:
71 addELFFile<ELF32LE>(File);
72 break;
73 case ELF32BEKind:
74 addELFFile<ELF32BE>(File);
75 break;
76 case ELF64LEKind:
77 addELFFile<ELF64LE>(File);
78 break;
79 case ELF64BEKind:
80 addELFFile<ELF64BE>(File);
81 break;
Rafael Espindola824d1a92015-09-04 00:09:43 +000082 }
83}
84
Michael J. Spencer84487f12015-07-24 21:03:07 +000085// This function resolves conflicts if there's an existing symbol with
86// the same name. Decisions are made based on symbol type.
Rafael Espindoladaa92a62015-08-31 01:16:19 +000087template <class ELFT> void SymbolTable::resolve(SymbolBody *New) {
Michael J. Spencer1b348a62015-09-04 22:28:10 +000088 Symbol *Sym = insert(New);
89 if (Sym->Body == New)
90 return;
91
92 SymbolBody *Existing = Sym->Body;
93
94 if (Lazy *L = dyn_cast<Lazy>(Existing)) {
95 if (New->isUndefined()) {
96 addMemberFile(L);
97 return;
98 }
99
100 // Found a definition for something also in an archive. Ignore the archive
101 // definition.
102 Sym->Body = New;
103 return;
104 }
105
106 // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
107 // equivalent (conflicting), or more preferable, respectively.
108 int comp = Existing->compare<ELFT>(New);
109 if (comp < 0)
110 Sym->Body = New;
111 if (comp == 0)
112 error(Twine("duplicate symbol: ") + Sym->Body->getName());
113}
114
115Symbol *SymbolTable::insert(SymbolBody *New) {
Michael J. Spencer84487f12015-07-24 21:03:07 +0000116 // Find an existing Symbol or create and insert a new one.
117 StringRef Name = New->getName();
118 Symbol *&Sym = Symtab[Name];
119 if (!Sym) {
120 Sym = new (Alloc) Symbol(New);
121 New->setBackref(Sym);
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000122 return Sym;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000123 }
124 New->setBackref(Sym);
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000125 return Sym;
126}
Michael J. Spencer84487f12015-07-24 21:03:07 +0000127
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000128void SymbolTable::addLazy(Lazy *New) {
129 Symbol *Sym = insert(New);
130 if (Sym->Body == New)
131 return;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000132 SymbolBody *Existing = Sym->Body;
Michael J. Spencer1b348a62015-09-04 22:28:10 +0000133 if (Existing->isDefined() || Existing->isLazy())
134 return;
135 Sym->Body = New;
136 assert(Existing->isUndefined() && "Unexpected symbol kind.");
137 addMemberFile(New);
138}
139
140void SymbolTable::addMemberFile(Lazy *Body) {
141 std::unique_ptr<InputFile> File = Body->getMember();
142
143 // getMember returns nullptr if the member was already read from the library.
144 if (!File)
145 return;
146
147 addFile(std::move(File));
Michael J. Spencer84487f12015-07-24 21:03:07 +0000148}