blob: 5e9a1c9ffa8302371e1ca4f10783d3e3b672275c [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 Espindolaf7d45f02015-08-31 01:46:20 +000030template <class ELFT> void SymbolTable::init() {
31 resolve<ELFT>(new (Alloc)
32 Undefined<ELFT>("_start", Undefined<ELFT>::Synthetic));
33}
34
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000035void SymbolTable::addObject(ObjectFileBase *File) {
Rafael Espindola8aeb13f2015-09-03 19:13:13 +000036 if (const ObjectFileBase *Old = getFirstObject()) {
37 if (!Old->isCompatibleWith(*File))
38 error(Twine(Old->getName() + " is incompatible with " + File->getName()));
Rafael Espindoladaa92a62015-08-31 01:16:19 +000039 } else {
Rafael Espindola905ad342015-09-02 20:43:43 +000040 switch (File->getELFKind()) {
41 case ELF32LEKind:
Rafael Espindolaf7d45f02015-08-31 01:46:20 +000042 init<ELF32LE>();
Rafael Espindoladaa92a62015-08-31 01:16:19 +000043 break;
Rafael Espindola905ad342015-09-02 20:43:43 +000044 case ELF32BEKind:
Rafael Espindolaf7d45f02015-08-31 01:46:20 +000045 init<ELF32BE>();
Rafael Espindoladaa92a62015-08-31 01:16:19 +000046 break;
Rafael Espindola905ad342015-09-02 20:43:43 +000047 case ELF64LEKind:
Rafael Espindolaf7d45f02015-08-31 01:46:20 +000048 init<ELF64LE>();
Rafael Espindoladaa92a62015-08-31 01:16:19 +000049 break;
Rafael Espindola905ad342015-09-02 20:43:43 +000050 case ELF64BEKind:
Rafael Espindolaf7d45f02015-08-31 01:46:20 +000051 init<ELF64BE>();
Rafael Espindoladaa92a62015-08-31 01:16:19 +000052 break;
53 }
Rafael Espindola3c9cb4b2015-08-05 12:03:34 +000054 }
55
Michael J. Spencer84487f12015-07-24 21:03:07 +000056 ObjectFiles.emplace_back(File);
Rafael Espindoladaa92a62015-08-31 01:16:19 +000057 for (SymbolBody *Body : File->getSymbols()) {
Rafael Espindola905ad342015-09-02 20:43:43 +000058 switch (File->getELFKind()) {
59 case ELF32LEKind:
Rafael Espindoladaa92a62015-08-31 01:16:19 +000060 resolve<ELF32LE>(Body);
61 break;
Rafael Espindola905ad342015-09-02 20:43:43 +000062 case ELF32BEKind:
Rafael Espindoladaa92a62015-08-31 01:16:19 +000063 resolve<ELF32BE>(Body);
64 break;
Rafael Espindola905ad342015-09-02 20:43:43 +000065 case ELF64LEKind:
Rafael Espindoladaa92a62015-08-31 01:16:19 +000066 resolve<ELF64LE>(Body);
67 break;
Rafael Espindola905ad342015-09-02 20:43:43 +000068 case ELF64BEKind:
Rafael Espindoladaa92a62015-08-31 01:16:19 +000069 resolve<ELF64BE>(Body);
70 break;
71 }
72 }
Michael J. Spencer84487f12015-07-24 21:03:07 +000073}
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. Spencer84487f12015-07-24 21:03:07 +000086 // Find an existing Symbol or create and insert a new one.
87 StringRef Name = New->getName();
88 Symbol *&Sym = Symtab[Name];
89 if (!Sym) {
90 Sym = new (Alloc) Symbol(New);
91 New->setBackref(Sym);
92 return;
93 }
94 New->setBackref(Sym);
95
96 // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
97 // equivalent (conflicting), or more preferable, respectively.
98 SymbolBody *Existing = Sym->Body;
Rafael Espindoladaa92a62015-08-31 01:16:19 +000099 int comp = Existing->compare<ELFT>(New);
Michael J. Spencer84487f12015-07-24 21:03:07 +0000100 if (comp < 0)
101 Sym->Body = New;
102 if (comp == 0)
103 error(Twine("duplicate symbol: ") + Name);
104}