blob: 3efdf12889fb00af74d99e2110841079584611ce [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();
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000026 auto *P = cast<ObjectFileBase>(FileP);
Michael J. Spencer84487f12015-07-24 21:03:07 +000027 addObject(P);
Michael J. Spencer84487f12015-07-24 21:03:07 +000028}
29
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000030void SymbolTable::addObject(ObjectFileBase *File) {
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +000031 if (!ObjectFiles.empty()) {
32 ObjectFileBase &Old = *ObjectFiles[0];
33 if (!Old.isCompatibleWith(*File))
34 error(Twine(Old.getName() + " is incompatible with " + File->getName()));
Rafael Espindoladaa92a62015-08-31 01:16:19 +000035 } else {
36 auto *Start = new (Alloc) SyntheticUndefined("_start");
37 switch (File->kind()) {
38 case InputFile::Object32LEKind:
39 resolve<ELF32LE>(Start);
40 break;
41 case InputFile::Object32BEKind:
42 resolve<ELF32BE>(Start);
43 break;
44 case InputFile::Object64LEKind:
45 resolve<ELF64LE>(Start);
46 break;
47 case InputFile::Object64BEKind:
48 resolve<ELF64BE>(Start);
49 break;
50 }
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +000051 }
52
Michael J. Spencer84487f12015-07-24 21:03:07 +000053 ObjectFiles.emplace_back(File);
Rafael Espindoladaa92a62015-08-31 01:16:19 +000054 for (SymbolBody *Body : File->getSymbols()) {
55 switch (File->kind()) {
56 case InputFile::Object32LEKind:
57 resolve<ELF32LE>(Body);
58 break;
59 case InputFile::Object32BEKind:
60 resolve<ELF32BE>(Body);
61 break;
62 case InputFile::Object64LEKind:
63 resolve<ELF64LE>(Body);
64 break;
65 case InputFile::Object64BEKind:
66 resolve<ELF64BE>(Body);
67 break;
68 }
69 }
Michael J. Spencer84487f12015-07-24 21:03:07 +000070}
71
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000072void SymbolTable::reportRemainingUndefines() {
Michael J. Spencer84487f12015-07-24 21:03:07 +000073 for (auto &I : Symtab) {
Rafael Espindola1bd885a2015-08-14 16:46:28 +000074 SymbolBody *Body = I.second->Body;
75 if (Body->isStrongUndefined())
76 error(Twine("undefined symbol: ") + Body->getName());
Michael J. Spencer84487f12015-07-24 21:03:07 +000077 }
78}
79
80// This function resolves conflicts if there's an existing symbol with
81// the same name. Decisions are made based on symbol type.
Rafael Espindoladaa92a62015-08-31 01:16:19 +000082template <class ELFT> void SymbolTable::resolve(SymbolBody *New) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000083 // Find an existing Symbol or create and insert a new one.
84 StringRef Name = New->getName();
Rafael Espindola62b81b82015-08-14 13:07:05 +000085 Builder.add(Name);
Michael J. Spencer84487f12015-07-24 21:03:07 +000086 Symbol *&Sym = Symtab[Name];
87 if (!Sym) {
88 Sym = new (Alloc) Symbol(New);
89 New->setBackref(Sym);
90 return;
91 }
92 New->setBackref(Sym);
93
94 // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
95 // equivalent (conflicting), or more preferable, respectively.
96 SymbolBody *Existing = Sym->Body;
Rafael Espindoladaa92a62015-08-31 01:16:19 +000097 int comp = Existing->compare<ELFT>(New);
Michael J. Spencer84487f12015-07-24 21:03:07 +000098 if (comp < 0)
99 Sym->Body = New;
100 if (comp == 0)
101 error(Twine("duplicate symbol: ") + Name);
102}