2015-05-29 03:09:30 +08:00
|
|
|
//===- Symbols.h ----------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLD_COFF_SYMBOLS_H
|
|
|
|
#define LLD_COFF_SYMBOLS_H
|
|
|
|
|
|
|
|
#include "Chunks.h"
|
|
|
|
#include "Config.h"
|
|
|
|
#include "lld/Core/LLVM.h"
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/Object/Archive.h"
|
|
|
|
#include "llvm/Object/COFF.h"
|
|
|
|
#include <memory>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace lld {
|
|
|
|
namespace coff {
|
|
|
|
|
|
|
|
using llvm::object::Archive;
|
2015-06-09 03:43:59 +08:00
|
|
|
using llvm::object::COFFObjectFile;
|
2015-05-29 03:09:30 +08:00
|
|
|
using llvm::object::COFFSymbolRef;
|
2015-05-29 23:45:35 +08:00
|
|
|
using llvm::object::coff_import_header;
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
class ArchiveFile;
|
|
|
|
class InputFile;
|
|
|
|
class ObjectFile;
|
|
|
|
class SymbolBody;
|
|
|
|
|
|
|
|
// A real symbol object, SymbolBody, is usually accessed indirectly
|
|
|
|
// through a Symbol. There's always one Symbol for each symbol name.
|
|
|
|
// The resolver updates SymbolBody pointers as it resolves symbols.
|
|
|
|
struct Symbol {
|
|
|
|
explicit Symbol(SymbolBody *P) : Body(P) {}
|
|
|
|
SymbolBody *Body;
|
|
|
|
};
|
|
|
|
|
|
|
|
// The base class for real symbol classes.
|
|
|
|
class SymbolBody {
|
|
|
|
public:
|
|
|
|
enum Kind {
|
|
|
|
DefinedFirst,
|
2015-06-16 03:06:53 +08:00
|
|
|
DefinedBitcodeKind,
|
2015-05-29 03:09:30 +08:00
|
|
|
DefinedAbsoluteKind,
|
|
|
|
DefinedImportDataKind,
|
|
|
|
DefinedImportThunkKind,
|
2015-06-25 11:31:47 +08:00
|
|
|
DefinedLocalImportKind,
|
2015-06-20 15:21:57 +08:00
|
|
|
DefinedCommonKind,
|
2015-06-23 03:56:01 +08:00
|
|
|
DefinedCOMDATKind,
|
2015-06-16 03:06:53 +08:00
|
|
|
DefinedRegularKind,
|
2015-05-29 03:09:30 +08:00
|
|
|
DefinedLast,
|
|
|
|
LazyKind,
|
2015-06-16 03:06:53 +08:00
|
|
|
UndefinedKind,
|
2015-05-29 03:09:30 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
Kind kind() const { return SymbolKind; }
|
|
|
|
virtual ~SymbolBody() {}
|
|
|
|
|
|
|
|
// Returns true if this is an external symbol.
|
|
|
|
virtual bool isExternal() { return true; }
|
|
|
|
|
|
|
|
// Returns the symbol name.
|
2015-06-09 03:43:59 +08:00
|
|
|
virtual StringRef getName() = 0;
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
// A SymbolBody has a backreference to a Symbol. Originally they are
|
|
|
|
// doubly-linked. A backreference will never change. But the pointer
|
|
|
|
// in the Symbol may be mutated by the resolver. If you have a
|
|
|
|
// pointer P to a SymbolBody and are not sure whether the resolver
|
|
|
|
// has chosen the object among other objects having the same name,
|
2015-06-01 11:55:02 +08:00
|
|
|
// you can access P->Backref->Body to get the resolver's result.
|
2015-05-29 03:09:30 +08:00
|
|
|
void setBackref(Symbol *P) { Backref = P; }
|
|
|
|
SymbolBody *getReplacement() { return Backref ? Backref->Body : this; }
|
|
|
|
|
|
|
|
// Decides which symbol should "win" in the symbol table, this or
|
|
|
|
// the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
|
|
|
|
// they are duplicate (conflicting) symbols.
|
|
|
|
virtual int compare(SymbolBody *Other) = 0;
|
|
|
|
|
|
|
|
protected:
|
2015-06-09 03:43:59 +08:00
|
|
|
SymbolBody(Kind K) : SymbolKind(K) {}
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
const Kind SymbolKind;
|
|
|
|
Symbol *Backref = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
// The base class for any defined symbols, including absolute symbols,
|
|
|
|
// etc.
|
|
|
|
class Defined : public SymbolBody {
|
|
|
|
public:
|
2015-06-09 03:43:59 +08:00
|
|
|
Defined(Kind K) : SymbolBody(K) {}
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
Kind K = S->kind();
|
|
|
|
return DefinedFirst <= K && K <= DefinedLast;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the RVA (relative virtual address) of this symbol. The
|
|
|
|
// writer sets and uses RVAs.
|
|
|
|
virtual uint64_t getRVA() = 0;
|
|
|
|
|
|
|
|
// Returns the file offset of this symbol in the final executable.
|
|
|
|
// The writer uses this information to apply relocations.
|
|
|
|
virtual uint64_t getFileOff() = 0;
|
|
|
|
|
|
|
|
// Called by the garbage collector. All Defined subclasses should
|
2015-06-04 00:50:41 +08:00
|
|
|
// know how to call depending symbols' markLive functions.
|
2015-05-29 03:09:30 +08:00
|
|
|
virtual void markLive() {}
|
|
|
|
|
|
|
|
int compare(SymbolBody *Other) override;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Regular defined symbols read from object file symbol tables.
|
|
|
|
class DefinedRegular : public Defined {
|
|
|
|
public:
|
2015-06-09 03:43:59 +08:00
|
|
|
DefinedRegular(COFFObjectFile *F, COFFSymbolRef S, Chunk *C)
|
|
|
|
: Defined(DefinedRegularKind), COFFFile(F), Sym(S), Data(C) {}
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == DefinedRegularKind;
|
|
|
|
}
|
|
|
|
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef getName() override;
|
2015-05-29 03:09:30 +08:00
|
|
|
uint64_t getRVA() override { return Data->getRVA() + Sym.getValue(); }
|
|
|
|
bool isExternal() override { return Sym.isExternal(); }
|
|
|
|
void markLive() override { Data->markLive(); }
|
|
|
|
uint64_t getFileOff() override { return Data->getFileOff() + Sym.getValue(); }
|
2015-06-23 03:56:01 +08:00
|
|
|
int compare(SymbolBody *Other) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
StringRef Name;
|
|
|
|
COFFObjectFile *COFFFile;
|
|
|
|
COFFSymbolRef Sym;
|
|
|
|
Chunk *Data;
|
|
|
|
};
|
|
|
|
|
|
|
|
class DefinedCOMDAT : public Defined {
|
|
|
|
public:
|
2015-06-24 12:36:52 +08:00
|
|
|
DefinedCOMDAT(COFFObjectFile *F, COFFSymbolRef S, SectionChunk *C)
|
2015-06-23 03:56:01 +08:00
|
|
|
: Defined(DefinedCOMDATKind), COFFFile(F), Sym(S), Data(C) {}
|
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == DefinedCOMDATKind;
|
|
|
|
}
|
|
|
|
|
2015-06-24 12:36:52 +08:00
|
|
|
uint64_t getFileOff() override {
|
|
|
|
return Data->repl()->getFileOff() + Sym.getValue();
|
|
|
|
}
|
|
|
|
|
2015-06-23 03:56:01 +08:00
|
|
|
StringRef getName() override;
|
2015-06-24 12:36:52 +08:00
|
|
|
uint64_t getRVA() override { return Data->repl()->getRVA() + Sym.getValue(); }
|
2015-06-23 03:56:01 +08:00
|
|
|
bool isExternal() override { return Sym.isExternal(); }
|
2015-06-24 12:36:52 +08:00
|
|
|
void markLive() override { Data->repl()->markLive(); }
|
2015-06-16 03:06:53 +08:00
|
|
|
int compare(SymbolBody *Other) override;
|
2015-06-24 12:36:52 +08:00
|
|
|
Chunk *getChunk() { return Data->repl(); }
|
2015-05-29 03:09:30 +08:00
|
|
|
|
2015-06-20 15:21:57 +08:00
|
|
|
private:
|
|
|
|
StringRef Name;
|
|
|
|
COFFObjectFile *COFFFile;
|
|
|
|
COFFSymbolRef Sym;
|
2015-06-24 12:36:52 +08:00
|
|
|
SectionChunk *Data;
|
2015-06-20 15:21:57 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class DefinedCommon : public Defined {
|
|
|
|
public:
|
|
|
|
DefinedCommon(COFFObjectFile *F, COFFSymbolRef S, Chunk *C)
|
|
|
|
: Defined(DefinedCommonKind), COFFFile(F), Sym(S), Data(C) {}
|
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == DefinedCommonKind;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef getName() override;
|
|
|
|
uint64_t getRVA() override { return Data->getRVA(); }
|
|
|
|
bool isExternal() override { return Sym.isExternal(); }
|
|
|
|
void markLive() override { Data->markLive(); }
|
|
|
|
uint64_t getFileOff() override { return Data->getFileOff(); }
|
|
|
|
int compare(SymbolBody *Other) override;
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
private:
|
2015-06-20 15:21:57 +08:00
|
|
|
uint64_t getSize() { return Sym.getValue(); }
|
|
|
|
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef Name;
|
|
|
|
COFFObjectFile *COFFFile;
|
2015-05-29 03:09:30 +08:00
|
|
|
COFFSymbolRef Sym;
|
|
|
|
Chunk *Data;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Absolute symbols.
|
|
|
|
class DefinedAbsolute : public Defined {
|
|
|
|
public:
|
2015-06-09 03:43:59 +08:00
|
|
|
DefinedAbsolute(StringRef N, uint64_t VA)
|
|
|
|
: Defined(DefinedAbsoluteKind), Name(N), RVA(VA - Config->ImageBase) {}
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == DefinedAbsoluteKind;
|
|
|
|
}
|
|
|
|
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef getName() override { return Name; }
|
2015-05-29 03:09:30 +08:00
|
|
|
uint64_t getRVA() override { return RVA; }
|
|
|
|
uint64_t getFileOff() override { llvm_unreachable("internal error"); }
|
|
|
|
|
|
|
|
private:
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef Name;
|
2015-05-29 03:09:30 +08:00
|
|
|
uint64_t RVA;
|
|
|
|
};
|
|
|
|
|
|
|
|
// This class represents a symbol defined in an archive file. It is
|
|
|
|
// created from an archive file header, and it knows how to load an
|
|
|
|
// object file from an archive to replace itself with a defined
|
|
|
|
// symbol. If the resolver finds both Undefined and Lazy for
|
|
|
|
// the same name, it will ask the Lazy to load a file.
|
|
|
|
class Lazy : public SymbolBody {
|
|
|
|
public:
|
|
|
|
Lazy(ArchiveFile *F, const Archive::Symbol S)
|
2015-06-09 03:43:59 +08:00
|
|
|
: SymbolBody(LazyKind), Name(S.getName()), File(F), Sym(S) {}
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; }
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef getName() override { return Name; }
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
// Returns an object file for this symbol, or a nullptr if the file
|
|
|
|
// was already returned.
|
|
|
|
ErrorOr<std::unique_ptr<InputFile>> getMember();
|
|
|
|
|
|
|
|
int compare(SymbolBody *Other) override;
|
|
|
|
|
|
|
|
private:
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef Name;
|
2015-05-29 03:09:30 +08:00
|
|
|
ArchiveFile *File;
|
|
|
|
const Archive::Symbol Sym;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Undefined symbols.
|
|
|
|
class Undefined : public SymbolBody {
|
|
|
|
public:
|
2015-06-09 03:43:59 +08:00
|
|
|
explicit Undefined(StringRef N, SymbolBody **S = nullptr)
|
|
|
|
: SymbolBody(UndefinedKind), Name(N), Alias(S) {}
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == UndefinedKind;
|
|
|
|
}
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef getName() override { return Name; }
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
// An undefined symbol can have a fallback symbol which gives an
|
|
|
|
// undefined symbol a second chance if it would remain undefined.
|
|
|
|
// If it remains undefined, it'll be replaced with whatever the
|
|
|
|
// Alias pointer points to.
|
|
|
|
SymbolBody *getWeakAlias() { return Alias ? *Alias : nullptr; }
|
|
|
|
|
|
|
|
int compare(SymbolBody *Other) override;
|
|
|
|
|
|
|
|
private:
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef Name;
|
2015-05-29 03:09:30 +08:00
|
|
|
SymbolBody **Alias;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Windows-specific classes.
|
|
|
|
|
2015-05-29 23:49:09 +08:00
|
|
|
// This class represents a symbol imported from a DLL. This has two
|
|
|
|
// names for internal use and external use. The former is used for
|
|
|
|
// name resolution, and the latter is used for the import descriptor
|
|
|
|
// table in an output. The former has "__imp_" prefix.
|
|
|
|
class DefinedImportData : public Defined {
|
|
|
|
public:
|
2015-06-09 03:43:59 +08:00
|
|
|
DefinedImportData(StringRef D, StringRef N, StringRef E,
|
2015-05-29 23:49:09 +08:00
|
|
|
const coff_import_header *H)
|
2015-06-09 03:43:59 +08:00
|
|
|
: Defined(DefinedImportDataKind), Name(N), DLLName(D), ExternalName(E),
|
|
|
|
Hdr(H) {}
|
2015-05-29 23:49:09 +08:00
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == DefinedImportDataKind;
|
|
|
|
}
|
|
|
|
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef getName() override { return Name; }
|
2015-05-29 23:49:09 +08:00
|
|
|
uint64_t getRVA() override { return Location->getRVA(); }
|
|
|
|
uint64_t getFileOff() override { return Location->getFileOff(); }
|
|
|
|
StringRef getDLLName() { return DLLName; }
|
2015-06-02 05:05:27 +08:00
|
|
|
StringRef getExternalName() { return ExternalName; }
|
2015-05-29 23:49:09 +08:00
|
|
|
void setLocation(Chunk *AddressTable) { Location = AddressTable; }
|
|
|
|
uint16_t getOrdinal() { return Hdr->OrdinalHint; }
|
|
|
|
|
|
|
|
private:
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef Name;
|
2015-05-29 23:49:09 +08:00
|
|
|
StringRef DLLName;
|
2015-06-02 05:05:27 +08:00
|
|
|
StringRef ExternalName;
|
2015-05-29 23:49:09 +08:00
|
|
|
const coff_import_header *Hdr;
|
|
|
|
Chunk *Location = nullptr;
|
|
|
|
};
|
|
|
|
|
2015-05-29 03:09:30 +08:00
|
|
|
// This class represents a symbol for a jump table entry which jumps
|
|
|
|
// to a function in a DLL. Linker are supposed to create such symbols
|
|
|
|
// without "__imp_" prefix for all function symbols exported from
|
|
|
|
// DLLs, so that you can call DLL functions as regular functions with
|
|
|
|
// a regular name. A function pointer is given as a DefinedImportData.
|
|
|
|
class DefinedImportThunk : public Defined {
|
|
|
|
public:
|
2015-06-09 03:43:59 +08:00
|
|
|
DefinedImportThunk(StringRef N, DefinedImportData *S)
|
|
|
|
: Defined(DefinedImportThunkKind), Name(N), Data(S) {}
|
2015-05-29 03:09:30 +08:00
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == DefinedImportThunkKind;
|
|
|
|
}
|
|
|
|
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef getName() override { return Name; }
|
2015-05-29 03:09:30 +08:00
|
|
|
uint64_t getRVA() override { return Data.getRVA(); }
|
|
|
|
uint64_t getFileOff() override { return Data.getFileOff(); }
|
|
|
|
Chunk *getChunk() { return &Data; }
|
|
|
|
|
|
|
|
private:
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef Name;
|
2015-05-29 03:09:30 +08:00
|
|
|
ImportThunkChunk Data;
|
|
|
|
};
|
|
|
|
|
2015-06-25 11:31:47 +08:00
|
|
|
// If you have a symbol "__imp_foo" in your object file, a symbol name
|
|
|
|
// "foo" becomes automatically available as a pointer to "__imp_foo".
|
|
|
|
// This class is for such automatically-created symbols.
|
|
|
|
// Yes, this is an odd feature. We didn't intend to implement that.
|
|
|
|
// This is here just for compatibility with MSVC.
|
|
|
|
class DefinedLocalImport : public Defined {
|
|
|
|
public:
|
|
|
|
DefinedLocalImport(StringRef N, Defined *S)
|
|
|
|
: Defined(DefinedLocalImportKind), Name(N), Data(S) {}
|
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == DefinedLocalImportKind;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef getName() override { return Name; }
|
|
|
|
uint64_t getRVA() override { return Data.getRVA(); }
|
|
|
|
uint64_t getFileOff() override { return Data.getFileOff(); }
|
|
|
|
Chunk *getChunk() { return &Data; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
StringRef Name;
|
|
|
|
LocalImportChunk Data;
|
|
|
|
};
|
|
|
|
|
2015-06-02 04:10:10 +08:00
|
|
|
class DefinedBitcode : public Defined {
|
|
|
|
public:
|
2015-06-12 05:49:54 +08:00
|
|
|
DefinedBitcode(StringRef N, bool R)
|
|
|
|
: Defined(DefinedBitcodeKind), Name(N), Replaceable(R) {}
|
2015-06-02 04:10:10 +08:00
|
|
|
|
|
|
|
static bool classof(const SymbolBody *S) {
|
|
|
|
return S->kind() == DefinedBitcodeKind;
|
|
|
|
}
|
|
|
|
|
2015-06-09 03:43:59 +08:00
|
|
|
StringRef getName() override { return Name; }
|
2015-06-02 04:10:10 +08:00
|
|
|
uint64_t getRVA() override { llvm_unreachable("bitcode reached writer"); }
|
|
|
|
uint64_t getFileOff() override { llvm_unreachable("bitcode reached writer"); }
|
2015-06-12 05:49:54 +08:00
|
|
|
int compare(SymbolBody *Other) override;
|
2015-06-09 03:43:59 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
StringRef Name;
|
2015-06-12 05:49:54 +08:00
|
|
|
bool Replaceable;
|
2015-06-02 04:10:10 +08:00
|
|
|
};
|
|
|
|
|
2015-05-29 03:09:30 +08:00
|
|
|
} // namespace coff
|
|
|
|
} // namespace lld
|
|
|
|
|
|
|
|
#endif
|