blob: b9880985b2b8a28bed7c40781d2e88b9cebed084 [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"
11#include "Driver.h"
12#include "Symbols.h"
13
14using namespace llvm;
15
16using namespace lld;
17using namespace lld::elf2;
18
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000019SymbolTable::SymbolTable() { resolve(new (Alloc) Undefined("_start")); }
Michael J. Spencer84487f12015-07-24 21:03:07 +000020
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000021void SymbolTable::addFile(std::unique_ptr<InputFile> File) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000022 File->parse();
23 InputFile *FileP = File.release();
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000024 auto *P = cast<ObjectFileBase>(FileP);
Michael J. Spencer84487f12015-07-24 21:03:07 +000025 addObject(P);
Michael J. Spencer84487f12015-07-24 21:03:07 +000026}
27
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000028void SymbolTable::addObject(ObjectFileBase *File) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000029 ObjectFiles.emplace_back(File);
30 for (SymbolBody *Body : File->getSymbols())
31 if (Body->isExternal())
32 resolve(Body);
33}
34
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000035void SymbolTable::reportRemainingUndefines() {
Michael J. Spencer84487f12015-07-24 21:03:07 +000036 for (auto &I : Symtab) {
37 Symbol *Sym = I.second;
38 if (auto *Undef = dyn_cast<Undefined>(Sym->Body))
39 error(Twine("undefined symbol: ") + Undef->getName());
40 }
41}
42
43// This function resolves conflicts if there's an existing symbol with
44// the same name. Decisions are made based on symbol type.
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000045void SymbolTable::resolve(SymbolBody *New) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000046 // Find an existing Symbol or create and insert a new one.
47 StringRef Name = New->getName();
48 Symbol *&Sym = Symtab[Name];
49 if (!Sym) {
50 Sym = new (Alloc) Symbol(New);
51 New->setBackref(Sym);
52 return;
53 }
54 New->setBackref(Sym);
55
56 // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
57 // equivalent (conflicting), or more preferable, respectively.
58 SymbolBody *Existing = Sym->Body;
59 int comp = Existing->compare(New);
60 if (comp < 0)
61 Sym->Body = New;
62 if (comp == 0)
63 error(Twine("duplicate symbol: ") + Name);
64}