2015-05-29 03:09:30 +08:00
|
|
|
//===- SymbolTable.cpp ----------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-12-09 04:20:22 +08:00
|
|
|
#include "SymbolTable.h"
|
2015-05-29 03:09:30 +08:00
|
|
|
#include "Config.h"
|
|
|
|
#include "Driver.h"
|
2017-02-03 07:58:14 +08:00
|
|
|
#include "LTO.h"
|
2018-04-18 07:32:33 +08:00
|
|
|
#include "PDB.h"
|
2015-06-30 02:50:11 +08:00
|
|
|
#include "Symbols.h"
|
[lld] unified COFF and ELF error handling on new Common/ErrorHandler
Summary:
The COFF linker and the ELF linker have long had similar but separate
Error.h and Error.cpp files to implement error handling. This change
introduces new error handling code in Common/ErrorHandler.h, changes the
COFF and ELF linkers to use it, and removes the old, separate
implementations.
Reviewers: ruiu
Reviewed By: ruiu
Subscribers: smeenai, jyknight, emaste, sdardis, nemanjai, nhaehnle, mgorny, javed.absar, kbarton, fedor.sergeev, llvm-commits
Differential Revision: https://reviews.llvm.org/D39259
llvm-svn: 316624
2017-10-26 06:28:38 +08:00
|
|
|
#include "lld/Common/ErrorHandler.h"
|
2017-11-29 04:39:17 +08:00
|
|
|
#include "lld/Common/Memory.h"
|
2018-01-18 03:16:26 +08:00
|
|
|
#include "lld/Common/Timer.h"
|
2015-12-04 10:42:47 +08:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2015-05-29 03:09:30 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2015-06-29 06:16:41 +08:00
|
|
|
#include <utility>
|
2015-05-29 03:09:30 +08:00
|
|
|
|
2015-05-31 11:57:30 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2015-05-29 03:09:30 +08:00
|
|
|
namespace lld {
|
|
|
|
namespace coff {
|
|
|
|
|
2018-01-18 03:16:26 +08:00
|
|
|
static Timer LTOTimer("LTO", Timer::root());
|
|
|
|
|
2016-12-10 05:55:24 +08:00
|
|
|
SymbolTable *Symtab;
|
2015-09-22 03:12:36 +08:00
|
|
|
|
2016-12-10 05:55:24 +08:00
|
|
|
void SymbolTable::addFile(InputFile *File) {
|
2017-02-22 07:22:56 +08:00
|
|
|
log("Reading " + toString(File));
|
2016-12-12 06:15:25 +08:00
|
|
|
File->parse();
|
|
|
|
|
|
|
|
MachineTypes MT = File->getMachineType();
|
|
|
|
if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
|
|
|
|
Config->Machine = MT;
|
|
|
|
} else if (MT != IMAGE_FILE_MACHINE_UNKNOWN && Config->Machine != MT) {
|
2018-05-23 04:20:25 +08:00
|
|
|
error(toString(File) + ": machine type " + machineToStr(MT) +
|
2016-12-12 06:15:25 +08:00
|
|
|
" conflicts with " + machineToStr(Config->Machine));
|
2018-05-23 04:20:25 +08:00
|
|
|
return;
|
2015-07-01 03:35:21 +08:00
|
|
|
}
|
2016-12-12 06:15:25 +08:00
|
|
|
|
2017-07-27 07:05:24 +08:00
|
|
|
if (auto *F = dyn_cast<ObjFile>(File)) {
|
2017-07-27 08:45:26 +08:00
|
|
|
ObjFile::Instances.push_back(F);
|
2015-07-01 03:35:21 +08:00
|
|
|
} else if (auto *F = dyn_cast<BitcodeFile>(File)) {
|
2017-07-27 08:45:26 +08:00
|
|
|
BitcodeFile::Instances.push_back(F);
|
2016-12-12 06:15:25 +08:00
|
|
|
} else if (auto *F = dyn_cast<ImportFile>(File)) {
|
2017-07-27 08:45:26 +08:00
|
|
|
ImportFile::Instances.push_back(F);
|
2015-07-01 03:35:21 +08:00
|
|
|
}
|
|
|
|
|
2016-12-12 06:15:25 +08:00
|
|
|
StringRef S = File->getDirectives();
|
|
|
|
if (S.empty())
|
2015-08-06 22:58:50 +08:00
|
|
|
return;
|
2015-07-01 03:35:21 +08:00
|
|
|
|
2017-02-22 07:22:56 +08:00
|
|
|
log("Directives: " + toString(File) + ": " + S);
|
2016-12-12 06:15:25 +08:00
|
|
|
Driver->parseDirectives(S);
|
2015-07-02 10:38:59 +08:00
|
|
|
}
|
|
|
|
|
2017-10-07 07:43:54 +08:00
|
|
|
static void errorOrWarn(const Twine &S) {
|
2018-09-14 06:05:10 +08:00
|
|
|
if (Config->ForceUnresolved)
|
2017-10-07 07:43:54 +08:00
|
|
|
warn(S);
|
|
|
|
else
|
|
|
|
error(S);
|
|
|
|
}
|
|
|
|
|
2018-09-16 02:27:09 +08:00
|
|
|
// Returns the symbol in SC whose value is <= Addr that is closest to Addr.
|
|
|
|
// This is generally the global variable or function whose definition contains
|
|
|
|
// Addr.
|
|
|
|
static Symbol *getSymbol(SectionChunk *SC, uint32_t Addr) {
|
2018-04-18 07:32:33 +08:00
|
|
|
DefinedRegular *Candidate = nullptr;
|
|
|
|
|
|
|
|
for (Symbol *S : SC->File->getSymbols()) {
|
|
|
|
auto *D = dyn_cast_or_null<DefinedRegular>(S);
|
|
|
|
if (!D || D->getChunk() != SC || D->getValue() > Addr ||
|
|
|
|
(Candidate && D->getValue() < Candidate->getValue()))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Candidate = D;
|
|
|
|
}
|
|
|
|
|
2018-09-16 02:27:09 +08:00
|
|
|
return Candidate;
|
2018-04-18 07:32:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex) {
|
|
|
|
struct Location {
|
2018-09-16 02:27:09 +08:00
|
|
|
Symbol *Sym;
|
2018-04-18 07:32:33 +08:00
|
|
|
std::pair<StringRef, uint32_t> FileLine;
|
|
|
|
};
|
|
|
|
std::vector<Location> Locations;
|
|
|
|
|
|
|
|
for (Chunk *C : File->getChunks()) {
|
|
|
|
auto *SC = dyn_cast<SectionChunk>(C);
|
|
|
|
if (!SC)
|
|
|
|
continue;
|
|
|
|
for (const coff_relocation &R : SC->Relocs) {
|
|
|
|
if (R.SymbolTableIndex != SymIndex)
|
|
|
|
continue;
|
|
|
|
std::pair<StringRef, uint32_t> FileLine =
|
|
|
|
getFileLine(SC, R.VirtualAddress);
|
2018-09-16 02:27:09 +08:00
|
|
|
Symbol *Sym = getSymbol(SC, R.VirtualAddress);
|
|
|
|
if (!FileLine.first.empty() || Sym)
|
|
|
|
Locations.push_back({Sym, FileLine});
|
2018-04-18 07:32:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Locations.empty())
|
2018-08-23 07:45:05 +08:00
|
|
|
return "\n>>> referenced by " + toString(File);
|
2018-04-18 07:32:33 +08:00
|
|
|
|
|
|
|
std::string Out;
|
|
|
|
llvm::raw_string_ostream OS(Out);
|
|
|
|
for (Location Loc : Locations) {
|
|
|
|
OS << "\n>>> referenced by ";
|
|
|
|
if (!Loc.FileLine.first.empty())
|
|
|
|
OS << Loc.FileLine.first << ":" << Loc.FileLine.second
|
|
|
|
<< "\n>>> ";
|
|
|
|
OS << toString(File);
|
2018-09-16 02:27:09 +08:00
|
|
|
if (Loc.Sym)
|
|
|
|
OS << ":(" << toString(*Loc.Sym) << ')';
|
2018-04-18 07:32:33 +08:00
|
|
|
}
|
|
|
|
return OS.str();
|
|
|
|
}
|
|
|
|
|
[COFF] Support MinGW automatic dllimport of data
Normally, in order to reference exported data symbols from a different
DLL, the declarations need to have the dllimport attribute, in order to
use the __imp_<var> symbol (which contains an address to the actual
variable) instead of the variable itself directly. This isn't an issue
in the same way for functions, since any reference to the function without
the dllimport attribute will end up as a reference to a thunk which loads
the actual target function from the import address table (IAT).
GNU ld, in MinGW environments, supports automatically importing data
symbols from DLLs, even if the references didn't have the appropriate
dllimport attribute. Since the PE/COFF format doesn't support the kind
of relocations that this would require, the MinGW's CRT startup code
has an custom framework of their own for manually fixing the missing
relocations once module is loaded and the target addresses in the IAT
are known.
For this to work, the linker (originall in GNU ld) creates a list of
remaining references needing fixup, which the runtime processes on
startup before handing over control to user code.
While this feature is rather controversial, it's one of the main features
allowing unix style libraries to be used on windows without any extra
porting effort.
Some sort of automatic fixing of data imports is also necessary for the
itanium C++ ABI on windows (as clang implements it right now) for importing
vtable pointers in certain cases, see D43184 for some discussion on that.
The runtime pseudo relocation handler supports 8/16/32/64 bit addresses,
either PC relative references (like IMAGE_REL_*_REL32*) or absolute
references (IMAGE_REL_AMD64_ADDR32, IMAGE_REL_AMD64_ADDR32,
IMAGE_REL_I386_DIR32). On linking, the relocation is handled as a
relocation against the corresponding IAT slot. For the absolute references,
a normal base relocation is created, to update the embedded address
in case the image is loaded at a different address.
The list of runtime pseudo relocations contains the RVA of the
imported symbol (the IAT slot), the RVA of the location the relocation
should be applied to, and a size of the memory location. When the
relocations are fixed at runtime, the difference between the actual
IAT slot value and the IAT slot address is added to the reference,
doing the right thing for both absolute and relative references.
With this patch alone, things work fine for i386 binaries, and mostly
for x86_64 binaries, with feature parity with GNU ld. Despite this,
there are a few gotchas:
- References to data from within code works fine on both x86 architectures,
since their relocations consist of plain 32 or 64 bit absolute/relative
references. On ARM and AArch64, references to data doesn't consist of
a plain 32 or 64 bit embedded address or offset in the code. On ARMNT,
it's usually a MOVW+MOVT instruction pair represented by a
IMAGE_REL_ARM_MOV32T relocation, each instruction containing 16 bit of
the target address), on AArch64, it's usually an ADRP+ADD/LDR/STR
instruction pair with an even more complex encoding, storing a PC
relative address (with a range of +/- 4 GB). This could theoretically
be remedied by extending the runtime pseudo relocation handler with new
relocation types, to support these instruction encodings. This isn't an
issue for GCC/GNU ld since they don't support windows on ARMNT/AArch64.
- For x86_64, if references in code are encoded as 32 bit PC relative
offsets, the runtime relocation will fail if the target turns out to be
out of range for a 32 bit offset.
- Fixing up the relocations at runtime requires making sections writable
if necessary, with the VirtualProtect function. In Windows Store/UWP apps,
this function is forbidden.
These limitations are addressed by a few later patches in lld and
llvm.
Differential Revision: https://reviews.llvm.org/D50917
llvm-svn: 340726
2018-08-27 16:43:31 +08:00
|
|
|
void SymbolTable::loadMinGWAutomaticImports() {
|
|
|
|
for (auto &I : SymMap) {
|
|
|
|
Symbol *Sym = I.second;
|
|
|
|
auto *Undef = dyn_cast<Undefined>(Sym);
|
|
|
|
if (!Undef)
|
|
|
|
continue;
|
|
|
|
if (!Sym->IsUsedInRegularObj)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
StringRef Name = Undef->getName();
|
|
|
|
|
|
|
|
if (Name.startswith("__imp_"))
|
|
|
|
continue;
|
|
|
|
// If we have an undefined symbol, but we have a Lazy representing a
|
|
|
|
// symbol we could load from file, make sure to load that.
|
|
|
|
Lazy *L = dyn_cast_or_null<Lazy>(find(("__imp_" + Name).str()));
|
|
|
|
if (!L || L->PendingArchiveLoad)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
log("Loading lazy " + L->getName() + " from " + L->File->getName() +
|
|
|
|
" for automatic import");
|
|
|
|
L->PendingArchiveLoad = true;
|
|
|
|
L->File->addMember(&L->Sym);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SymbolTable::handleMinGWAutomaticImport(Symbol *Sym, StringRef Name) {
|
|
|
|
if (Name.startswith("__imp_"))
|
|
|
|
return false;
|
2018-09-26 14:13:39 +08:00
|
|
|
Defined *Imp = dyn_cast_or_null<Defined>(find(("__imp_" + Name).str()));
|
[COFF] Support MinGW automatic dllimport of data
Normally, in order to reference exported data symbols from a different
DLL, the declarations need to have the dllimport attribute, in order to
use the __imp_<var> symbol (which contains an address to the actual
variable) instead of the variable itself directly. This isn't an issue
in the same way for functions, since any reference to the function without
the dllimport attribute will end up as a reference to a thunk which loads
the actual target function from the import address table (IAT).
GNU ld, in MinGW environments, supports automatically importing data
symbols from DLLs, even if the references didn't have the appropriate
dllimport attribute. Since the PE/COFF format doesn't support the kind
of relocations that this would require, the MinGW's CRT startup code
has an custom framework of their own for manually fixing the missing
relocations once module is loaded and the target addresses in the IAT
are known.
For this to work, the linker (originall in GNU ld) creates a list of
remaining references needing fixup, which the runtime processes on
startup before handing over control to user code.
While this feature is rather controversial, it's one of the main features
allowing unix style libraries to be used on windows without any extra
porting effort.
Some sort of automatic fixing of data imports is also necessary for the
itanium C++ ABI on windows (as clang implements it right now) for importing
vtable pointers in certain cases, see D43184 for some discussion on that.
The runtime pseudo relocation handler supports 8/16/32/64 bit addresses,
either PC relative references (like IMAGE_REL_*_REL32*) or absolute
references (IMAGE_REL_AMD64_ADDR32, IMAGE_REL_AMD64_ADDR32,
IMAGE_REL_I386_DIR32). On linking, the relocation is handled as a
relocation against the corresponding IAT slot. For the absolute references,
a normal base relocation is created, to update the embedded address
in case the image is loaded at a different address.
The list of runtime pseudo relocations contains the RVA of the
imported symbol (the IAT slot), the RVA of the location the relocation
should be applied to, and a size of the memory location. When the
relocations are fixed at runtime, the difference between the actual
IAT slot value and the IAT slot address is added to the reference,
doing the right thing for both absolute and relative references.
With this patch alone, things work fine for i386 binaries, and mostly
for x86_64 binaries, with feature parity with GNU ld. Despite this,
there are a few gotchas:
- References to data from within code works fine on both x86 architectures,
since their relocations consist of plain 32 or 64 bit absolute/relative
references. On ARM and AArch64, references to data doesn't consist of
a plain 32 or 64 bit embedded address or offset in the code. On ARMNT,
it's usually a MOVW+MOVT instruction pair represented by a
IMAGE_REL_ARM_MOV32T relocation, each instruction containing 16 bit of
the target address), on AArch64, it's usually an ADRP+ADD/LDR/STR
instruction pair with an even more complex encoding, storing a PC
relative address (with a range of +/- 4 GB). This could theoretically
be remedied by extending the runtime pseudo relocation handler with new
relocation types, to support these instruction encodings. This isn't an
issue for GCC/GNU ld since they don't support windows on ARMNT/AArch64.
- For x86_64, if references in code are encoded as 32 bit PC relative
offsets, the runtime relocation will fail if the target turns out to be
out of range for a 32 bit offset.
- Fixing up the relocations at runtime requires making sections writable
if necessary, with the VirtualProtect function. In Windows Store/UWP apps,
this function is forbidden.
These limitations are addressed by a few later patches in lld and
llvm.
Differential Revision: https://reviews.llvm.org/D50917
llvm-svn: 340726
2018-08-27 16:43:31 +08:00
|
|
|
if (!Imp)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Replace the reference directly to a variable with a reference
|
|
|
|
// to the import address table instead. This obviously isn't right,
|
|
|
|
// but we mark the symbol as IsRuntimePseudoReloc, and a later pass
|
|
|
|
// will add runtime pseudo relocations for every relocation against
|
|
|
|
// this Symbol. The runtime pseudo relocation framework expects the
|
|
|
|
// reference itself to point at the IAT entry.
|
2018-09-26 14:13:39 +08:00
|
|
|
size_t ImpSize = 0;
|
|
|
|
if (isa<DefinedImportData>(Imp)) {
|
|
|
|
log("Automatically importing " + Name + " from " +
|
|
|
|
cast<DefinedImportData>(Imp)->getDLLName());
|
|
|
|
ImpSize = sizeof(DefinedImportData);
|
|
|
|
} else if (isa<DefinedRegular>(Imp)) {
|
|
|
|
log("Automatically importing " + Name + " from " +
|
|
|
|
toString(cast<DefinedRegular>(Imp)->File));
|
|
|
|
ImpSize = sizeof(DefinedRegular);
|
|
|
|
} else {
|
|
|
|
warn("unable to automatically import " + Name + " from " + Imp->getName() +
|
|
|
|
" from " + toString(cast<DefinedRegular>(Imp)->File) +
|
|
|
|
"; unexpected symbol type");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Sym->replaceKeepingName(Imp, ImpSize);
|
|
|
|
Sym->IsRuntimePseudoReloc = true;
|
2018-08-31 15:45:20 +08:00
|
|
|
|
|
|
|
// There may exist symbols named .refptr.<name> which only consist
|
|
|
|
// of a single pointer to <name>. If it turns out <name> is
|
|
|
|
// automatically imported, we don't need to keep the .refptr.<name>
|
|
|
|
// pointer at all, but redirect all accesses to it to the IAT entry
|
|
|
|
// for __imp_<name> instead, and drop the whole .refptr.<name> chunk.
|
|
|
|
DefinedRegular *Refptr =
|
|
|
|
dyn_cast_or_null<DefinedRegular>(find((".refptr." + Name).str()));
|
2018-10-12 01:45:58 +08:00
|
|
|
if (Refptr && Refptr->getChunk()->getSize() == Config->Wordsize) {
|
2018-08-31 15:45:20 +08:00
|
|
|
SectionChunk *SC = dyn_cast_or_null<SectionChunk>(Refptr->getChunk());
|
|
|
|
if (SC && SC->Relocs.size() == 1 && *SC->symbols().begin() == Sym) {
|
2018-09-18 15:21:55 +08:00
|
|
|
log("Replacing .refptr." + Name + " with " + Imp->getName());
|
|
|
|
Refptr->getChunk()->Live = false;
|
2018-09-26 14:13:39 +08:00
|
|
|
Refptr->replaceKeepingName(Imp, ImpSize);
|
2018-08-31 15:45:20 +08:00
|
|
|
}
|
|
|
|
}
|
[COFF] Support MinGW automatic dllimport of data
Normally, in order to reference exported data symbols from a different
DLL, the declarations need to have the dllimport attribute, in order to
use the __imp_<var> symbol (which contains an address to the actual
variable) instead of the variable itself directly. This isn't an issue
in the same way for functions, since any reference to the function without
the dllimport attribute will end up as a reference to a thunk which loads
the actual target function from the import address table (IAT).
GNU ld, in MinGW environments, supports automatically importing data
symbols from DLLs, even if the references didn't have the appropriate
dllimport attribute. Since the PE/COFF format doesn't support the kind
of relocations that this would require, the MinGW's CRT startup code
has an custom framework of their own for manually fixing the missing
relocations once module is loaded and the target addresses in the IAT
are known.
For this to work, the linker (originall in GNU ld) creates a list of
remaining references needing fixup, which the runtime processes on
startup before handing over control to user code.
While this feature is rather controversial, it's one of the main features
allowing unix style libraries to be used on windows without any extra
porting effort.
Some sort of automatic fixing of data imports is also necessary for the
itanium C++ ABI on windows (as clang implements it right now) for importing
vtable pointers in certain cases, see D43184 for some discussion on that.
The runtime pseudo relocation handler supports 8/16/32/64 bit addresses,
either PC relative references (like IMAGE_REL_*_REL32*) or absolute
references (IMAGE_REL_AMD64_ADDR32, IMAGE_REL_AMD64_ADDR32,
IMAGE_REL_I386_DIR32). On linking, the relocation is handled as a
relocation against the corresponding IAT slot. For the absolute references,
a normal base relocation is created, to update the embedded address
in case the image is loaded at a different address.
The list of runtime pseudo relocations contains the RVA of the
imported symbol (the IAT slot), the RVA of the location the relocation
should be applied to, and a size of the memory location. When the
relocations are fixed at runtime, the difference between the actual
IAT slot value and the IAT slot address is added to the reference,
doing the right thing for both absolute and relative references.
With this patch alone, things work fine for i386 binaries, and mostly
for x86_64 binaries, with feature parity with GNU ld. Despite this,
there are a few gotchas:
- References to data from within code works fine on both x86 architectures,
since their relocations consist of plain 32 or 64 bit absolute/relative
references. On ARM and AArch64, references to data doesn't consist of
a plain 32 or 64 bit embedded address or offset in the code. On ARMNT,
it's usually a MOVW+MOVT instruction pair represented by a
IMAGE_REL_ARM_MOV32T relocation, each instruction containing 16 bit of
the target address), on AArch64, it's usually an ADRP+ADD/LDR/STR
instruction pair with an even more complex encoding, storing a PC
relative address (with a range of +/- 4 GB). This could theoretically
be remedied by extending the runtime pseudo relocation handler with new
relocation types, to support these instruction encodings. This isn't an
issue for GCC/GNU ld since they don't support windows on ARMNT/AArch64.
- For x86_64, if references in code are encoded as 32 bit PC relative
offsets, the runtime relocation will fail if the target turns out to be
out of range for a 32 bit offset.
- Fixing up the relocations at runtime requires making sections writable
if necessary, with the VirtualProtect function. In Windows Store/UWP apps,
this function is forbidden.
These limitations are addressed by a few later patches in lld and
llvm.
Differential Revision: https://reviews.llvm.org/D50917
llvm-svn: 340726
2018-08-27 16:43:31 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-12-10 05:55:24 +08:00
|
|
|
void SymbolTable::reportRemainingUndefines() {
|
2017-11-04 05:21:47 +08:00
|
|
|
SmallPtrSet<Symbol *, 8> Undefs;
|
2017-12-15 15:49:21 +08:00
|
|
|
DenseMap<Symbol *, Symbol *> LocalImports;
|
2017-10-07 07:43:54 +08:00
|
|
|
|
2017-11-28 07:16:06 +08:00
|
|
|
for (auto &I : SymMap) {
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *Sym = I.second;
|
2017-11-01 00:10:24 +08:00
|
|
|
auto *Undef = dyn_cast<Undefined>(Sym);
|
2015-05-29 03:09:30 +08:00
|
|
|
if (!Undef)
|
|
|
|
continue;
|
2016-12-10 05:55:24 +08:00
|
|
|
if (!Sym->IsUsedInRegularObj)
|
|
|
|
continue;
|
2017-10-07 07:43:54 +08:00
|
|
|
|
2015-06-25 10:21:44 +08:00
|
|
|
StringRef Name = Undef->getName();
|
2017-10-07 07:43:54 +08:00
|
|
|
|
2015-07-04 13:28:41 +08:00
|
|
|
// A weak alias may have been resolved, so check for that.
|
|
|
|
if (Defined *D = Undef->getWeakAlias()) {
|
2017-11-01 05:26:42 +08:00
|
|
|
// We want to replace Sym with D. However, we can't just blindly
|
|
|
|
// copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
|
|
|
|
// internal symbol, and internal symbols are stored as "unparented"
|
|
|
|
// Symbols. For that reason we need to check which type of symbol we
|
|
|
|
// are dealing with and copy the correct number of bytes.
|
|
|
|
if (isa<DefinedRegular>(D))
|
|
|
|
memcpy(Sym, D, sizeof(DefinedRegular));
|
|
|
|
else if (isa<DefinedAbsolute>(D))
|
|
|
|
memcpy(Sym, D, sizeof(DefinedAbsolute));
|
|
|
|
else
|
|
|
|
memcpy(Sym, D, sizeof(SymbolUnion));
|
2015-07-04 13:28:41 +08:00
|
|
|
continue;
|
2015-05-29 03:09:30 +08:00
|
|
|
}
|
2017-10-07 07:43:54 +08:00
|
|
|
|
2015-06-25 10:21:44 +08:00
|
|
|
// If we can resolve a symbol by removing __imp_ prefix, do that.
|
|
|
|
// This odd rule is for compatibility with MSVC linker.
|
|
|
|
if (Name.startswith("__imp_")) {
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *Imp = find(Name.substr(strlen("__imp_")));
|
2017-11-01 00:10:24 +08:00
|
|
|
if (Imp && isa<Defined>(Imp)) {
|
|
|
|
auto *D = cast<Defined>(Imp);
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedLocalImport>(Sym, Name, D);
|
2017-11-01 00:10:24 +08:00
|
|
|
LocalImportChunks.push_back(cast<DefinedLocalImport>(Sym)->getChunk());
|
2017-12-15 15:49:21 +08:00
|
|
|
LocalImports[Sym] = D;
|
2015-06-25 10:21:44 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2017-10-07 07:43:54 +08:00
|
|
|
|
[COFF] Support MinGW automatic dllimport of data
Normally, in order to reference exported data symbols from a different
DLL, the declarations need to have the dllimport attribute, in order to
use the __imp_<var> symbol (which contains an address to the actual
variable) instead of the variable itself directly. This isn't an issue
in the same way for functions, since any reference to the function without
the dllimport attribute will end up as a reference to a thunk which loads
the actual target function from the import address table (IAT).
GNU ld, in MinGW environments, supports automatically importing data
symbols from DLLs, even if the references didn't have the appropriate
dllimport attribute. Since the PE/COFF format doesn't support the kind
of relocations that this would require, the MinGW's CRT startup code
has an custom framework of their own for manually fixing the missing
relocations once module is loaded and the target addresses in the IAT
are known.
For this to work, the linker (originall in GNU ld) creates a list of
remaining references needing fixup, which the runtime processes on
startup before handing over control to user code.
While this feature is rather controversial, it's one of the main features
allowing unix style libraries to be used on windows without any extra
porting effort.
Some sort of automatic fixing of data imports is also necessary for the
itanium C++ ABI on windows (as clang implements it right now) for importing
vtable pointers in certain cases, see D43184 for some discussion on that.
The runtime pseudo relocation handler supports 8/16/32/64 bit addresses,
either PC relative references (like IMAGE_REL_*_REL32*) or absolute
references (IMAGE_REL_AMD64_ADDR32, IMAGE_REL_AMD64_ADDR32,
IMAGE_REL_I386_DIR32). On linking, the relocation is handled as a
relocation against the corresponding IAT slot. For the absolute references,
a normal base relocation is created, to update the embedded address
in case the image is loaded at a different address.
The list of runtime pseudo relocations contains the RVA of the
imported symbol (the IAT slot), the RVA of the location the relocation
should be applied to, and a size of the memory location. When the
relocations are fixed at runtime, the difference between the actual
IAT slot value and the IAT slot address is added to the reference,
doing the right thing for both absolute and relative references.
With this patch alone, things work fine for i386 binaries, and mostly
for x86_64 binaries, with feature parity with GNU ld. Despite this,
there are a few gotchas:
- References to data from within code works fine on both x86 architectures,
since their relocations consist of plain 32 or 64 bit absolute/relative
references. On ARM and AArch64, references to data doesn't consist of
a plain 32 or 64 bit embedded address or offset in the code. On ARMNT,
it's usually a MOVW+MOVT instruction pair represented by a
IMAGE_REL_ARM_MOV32T relocation, each instruction containing 16 bit of
the target address), on AArch64, it's usually an ADRP+ADD/LDR/STR
instruction pair with an even more complex encoding, storing a PC
relative address (with a range of +/- 4 GB). This could theoretically
be remedied by extending the runtime pseudo relocation handler with new
relocation types, to support these instruction encodings. This isn't an
issue for GCC/GNU ld since they don't support windows on ARMNT/AArch64.
- For x86_64, if references in code are encoded as 32 bit PC relative
offsets, the runtime relocation will fail if the target turns out to be
out of range for a 32 bit offset.
- Fixing up the relocations at runtime requires making sections writable
if necessary, with the VirtualProtect function. In Windows Store/UWP apps,
this function is forbidden.
These limitations are addressed by a few later patches in lld and
llvm.
Differential Revision: https://reviews.llvm.org/D50917
llvm-svn: 340726
2018-08-27 16:43:31 +08:00
|
|
|
if (Config->MinGW && handleMinGWAutomaticImport(Sym, Name))
|
|
|
|
continue;
|
|
|
|
|
2015-06-29 03:35:15 +08:00
|
|
|
// Remaining undefined symbols are not fatal if /force is specified.
|
|
|
|
// They are replaced with dummy defined symbols.
|
2018-09-14 06:05:10 +08:00
|
|
|
if (Config->ForceUnresolved)
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedAbsolute>(Sym, Name, 0);
|
2017-11-01 00:10:24 +08:00
|
|
|
Undefs.insert(Sym);
|
2015-05-29 03:09:30 +08:00
|
|
|
}
|
2017-10-07 07:43:54 +08:00
|
|
|
|
2017-12-15 15:49:21 +08:00
|
|
|
if (Undefs.empty() && LocalImports.empty())
|
2015-08-06 22:58:50 +08:00
|
|
|
return;
|
2017-10-07 07:43:54 +08:00
|
|
|
|
2017-12-15 15:49:21 +08:00
|
|
|
for (Symbol *B : Config->GCRoot) {
|
2016-12-10 05:55:24 +08:00
|
|
|
if (Undefs.count(B))
|
2018-09-16 02:27:09 +08:00
|
|
|
errorOrWarn("<root>: undefined symbol: " + toString(*B));
|
2017-12-28 15:02:13 +08:00
|
|
|
if (Config->WarnLocallyDefinedImported)
|
|
|
|
if (Symbol *Imp = LocalImports.lookup(B))
|
2018-09-16 02:27:09 +08:00
|
|
|
warn("<root>: locally defined symbol imported: " + toString(*Imp) +
|
2018-03-12 20:04:17 +08:00
|
|
|
" (defined in " + toString(Imp->getFile()) + ") [LNK4217]");
|
2017-12-15 15:49:21 +08:00
|
|
|
}
|
2017-10-07 07:43:54 +08:00
|
|
|
|
2017-12-15 15:49:21 +08:00
|
|
|
for (ObjFile *File : ObjFile::Instances) {
|
2018-06-29 23:34:36 +08:00
|
|
|
size_t SymIndex = (size_t)-1;
|
2017-12-15 15:49:21 +08:00
|
|
|
for (Symbol *Sym : File->getSymbols()) {
|
2018-04-18 07:32:33 +08:00
|
|
|
++SymIndex;
|
2017-12-15 15:49:21 +08:00
|
|
|
if (!Sym)
|
|
|
|
continue;
|
|
|
|
if (Undefs.count(Sym))
|
2018-09-16 02:27:09 +08:00
|
|
|
errorOrWarn("undefined symbol: " + toString(*Sym) +
|
2018-04-18 07:32:33 +08:00
|
|
|
getSymbolLocations(File, SymIndex));
|
2017-12-28 15:02:13 +08:00
|
|
|
if (Config->WarnLocallyDefinedImported)
|
|
|
|
if (Symbol *Imp = LocalImports.lookup(Sym))
|
2018-09-16 02:27:09 +08:00
|
|
|
warn(toString(File) +
|
|
|
|
": locally defined symbol imported: " + toString(*Imp) +
|
|
|
|
" (defined in " + toString(Imp->getFile()) + ") [LNK4217]");
|
2017-12-15 15:49:21 +08:00
|
|
|
}
|
|
|
|
}
|
2015-05-29 03:09:30 +08:00
|
|
|
}
|
|
|
|
|
2018-09-07 04:23:56 +08:00
|
|
|
std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
|
2018-08-03 04:39:19 +08:00
|
|
|
bool Inserted = false;
|
2017-11-28 07:16:06 +08:00
|
|
|
Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
|
2018-08-03 04:39:19 +08:00
|
|
|
if (!Sym) {
|
|
|
|
Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
|
|
|
|
Sym->IsUsedInRegularObj = false;
|
|
|
|
Sym->PendingArchiveLoad = false;
|
|
|
|
Inserted = true;
|
|
|
|
}
|
|
|
|
return {Sym, Inserted};
|
2015-07-01 03:35:21 +08:00
|
|
|
}
|
|
|
|
|
2018-09-07 04:23:56 +08:00
|
|
|
std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) {
|
|
|
|
std::pair<Symbol *, bool> Result = insert(Name);
|
|
|
|
if (!File || !isa<BitcodeFile>(File))
|
|
|
|
Result.first->IsUsedInRegularObj = true;
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F,
|
|
|
|
bool IsWeakAlias) {
|
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(Name, F);
|
2017-11-01 00:10:24 +08:00
|
|
|
if (WasInserted || (isa<Lazy>(S) && IsWeakAlias)) {
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<Undefined>(S, Name);
|
2016-12-10 05:55:24 +08:00
|
|
|
return S;
|
|
|
|
}
|
2017-11-01 00:10:24 +08:00
|
|
|
if (auto *L = dyn_cast<Lazy>(S)) {
|
2016-12-15 12:02:23 +08:00
|
|
|
if (!S->PendingArchiveLoad) {
|
|
|
|
S->PendingArchiveLoad = true;
|
|
|
|
L->File->addMember(&L->Sym);
|
|
|
|
}
|
|
|
|
}
|
2016-12-10 05:55:24 +08:00
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) {
|
|
|
|
StringRef Name = Sym.getName();
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-09-07 04:23:56 +08:00
|
|
|
std::tie(S, WasInserted) = insert(Name);
|
2016-12-10 05:55:24 +08:00
|
|
|
if (WasInserted) {
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<Lazy>(S, F, Sym);
|
2015-08-06 22:58:50 +08:00
|
|
|
return;
|
2015-06-01 10:58:15 +08:00
|
|
|
}
|
2017-11-01 00:10:24 +08:00
|
|
|
auto *U = dyn_cast<Undefined>(S);
|
2016-12-15 12:02:23 +08:00
|
|
|
if (!U || U->WeakAlias || S->PendingArchiveLoad)
|
2016-12-10 05:55:24 +08:00
|
|
|
return;
|
2016-12-15 12:02:23 +08:00
|
|
|
S->PendingArchiveLoad = true;
|
|
|
|
F->addMember(&Sym);
|
2016-12-10 05:55:24 +08:00
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
|
2018-09-14 06:05:10 +08:00
|
|
|
std::string Msg = "duplicate symbol: " + toString(*Existing) + " in " +
|
|
|
|
toString(Existing->getFile()) + " and in " +
|
|
|
|
toString(NewFile);
|
|
|
|
|
|
|
|
if (Config->ForceMultiple)
|
|
|
|
warn(Msg);
|
|
|
|
else
|
|
|
|
error(Msg);
|
2016-12-10 05:55:24 +08:00
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) {
|
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(N, nullptr);
|
2016-12-10 05:55:24 +08:00
|
|
|
S->IsUsedInRegularObj = true;
|
2017-11-01 00:10:24 +08:00
|
|
|
if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedAbsolute>(S, N, Sym);
|
2017-11-01 00:10:24 +08:00
|
|
|
else if (!isa<DefinedCOFF>(S))
|
2016-12-10 05:55:24 +08:00
|
|
|
reportDuplicate(S, nullptr);
|
|
|
|
return S;
|
|
|
|
}
|
2015-09-20 08:00:05 +08:00
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) {
|
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(N, nullptr);
|
2016-12-10 05:55:24 +08:00
|
|
|
S->IsUsedInRegularObj = true;
|
2017-11-01 00:10:24 +08:00
|
|
|
if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedAbsolute>(S, N, VA);
|
2017-11-01 00:10:24 +08:00
|
|
|
else if (!isa<DefinedCOFF>(S))
|
2016-12-10 05:55:24 +08:00
|
|
|
reportDuplicate(S, nullptr);
|
|
|
|
return S;
|
2015-05-29 03:09:30 +08:00
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) {
|
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(N, nullptr);
|
2016-12-10 05:55:24 +08:00
|
|
|
S->IsUsedInRegularObj = true;
|
2017-11-01 00:10:24 +08:00
|
|
|
if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedSynthetic>(S, N, C);
|
2017-11-01 00:10:24 +08:00
|
|
|
else if (!isa<DefinedCOFF>(S))
|
2016-12-10 05:55:24 +08:00
|
|
|
reportDuplicate(S, nullptr);
|
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
2017-11-28 09:30:07 +08:00
|
|
|
Symbol *SymbolTable::addRegular(InputFile *F, StringRef N,
|
2017-11-04 05:21:47 +08:00
|
|
|
const coff_symbol_generic *Sym,
|
|
|
|
SectionChunk *C) {
|
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(N, F);
|
2017-11-28 09:30:07 +08:00
|
|
|
if (WasInserted || !isa<DefinedRegular>(S))
|
|
|
|
replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ false,
|
|
|
|
/*IsExternal*/ true, Sym, C);
|
|
|
|
else
|
2017-02-03 07:58:14 +08:00
|
|
|
reportDuplicate(S, F);
|
2017-11-28 05:37:51 +08:00
|
|
|
return S;
|
2017-11-28 04:42:34 +08:00
|
|
|
}
|
|
|
|
|
2017-11-28 09:30:07 +08:00
|
|
|
std::pair<Symbol *, bool>
|
|
|
|
SymbolTable::addComdat(InputFile *F, StringRef N,
|
|
|
|
const coff_symbol_generic *Sym) {
|
|
|
|
Symbol *S;
|
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(N, F);
|
2017-11-28 09:30:07 +08:00
|
|
|
if (WasInserted || !isa<DefinedRegular>(S)) {
|
|
|
|
replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ true,
|
|
|
|
/*IsExternal*/ true, Sym, nullptr);
|
|
|
|
return {S, true};
|
|
|
|
}
|
|
|
|
if (!cast<DefinedRegular>(S)->isCOMDAT())
|
|
|
|
reportDuplicate(S, F);
|
|
|
|
return {S, false};
|
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size,
|
|
|
|
const coff_symbol_generic *Sym, CommonChunk *C) {
|
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(N, F);
|
2017-11-01 00:10:24 +08:00
|
|
|
if (WasInserted || !isa<DefinedCOFF>(S))
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C);
|
2017-11-01 00:10:24 +08:00
|
|
|
else if (auto *DC = dyn_cast<DefinedCommon>(S))
|
2017-02-03 07:58:14 +08:00
|
|
|
if (Size > DC->getSize())
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C);
|
2016-12-10 05:55:24 +08:00
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
2018-07-10 18:40:11 +08:00
|
|
|
Symbol *SymbolTable::addImportData(StringRef N, ImportFile *F) {
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(N, nullptr);
|
2016-12-10 05:55:24 +08:00
|
|
|
S->IsUsedInRegularObj = true;
|
2017-11-01 00:10:24 +08:00
|
|
|
if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedImportData>(S, N, F);
|
2018-07-10 18:40:11 +08:00
|
|
|
return S;
|
2017-09-02 06:12:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
reportDuplicate(S, F);
|
|
|
|
return nullptr;
|
2016-12-10 05:55:24 +08:00
|
|
|
}
|
|
|
|
|
2018-07-10 18:40:11 +08:00
|
|
|
Symbol *SymbolTable::addImportThunk(StringRef Name, DefinedImportData *ID,
|
|
|
|
uint16_t Machine) {
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *S;
|
2016-12-10 05:55:24 +08:00
|
|
|
bool WasInserted;
|
2018-08-03 04:39:19 +08:00
|
|
|
std::tie(S, WasInserted) = insert(Name, nullptr);
|
2016-12-10 05:55:24 +08:00
|
|
|
S->IsUsedInRegularObj = true;
|
2017-11-01 00:10:24 +08:00
|
|
|
if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {
|
2017-11-04 06:48:47 +08:00
|
|
|
replaceSymbol<DefinedImportThunk>(S, Name, ID, Machine);
|
2018-07-10 18:40:11 +08:00
|
|
|
return S;
|
2017-09-02 06:12:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
reportDuplicate(S, ID->File);
|
|
|
|
return nullptr;
|
2015-07-03 06:52:33 +08:00
|
|
|
}
|
|
|
|
|
2015-05-29 03:09:30 +08:00
|
|
|
std::vector<Chunk *> SymbolTable::getChunks() {
|
|
|
|
std::vector<Chunk *> Res;
|
2017-07-27 08:45:26 +08:00
|
|
|
for (ObjFile *File : ObjFile::Instances) {
|
2017-12-08 09:09:21 +08:00
|
|
|
ArrayRef<Chunk *> V = File->getChunks();
|
2015-05-29 03:09:30 +08:00
|
|
|
Res.insert(Res.end(), V.begin(), V.end());
|
|
|
|
}
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::find(StringRef Name) {
|
2018-03-01 07:03:06 +08:00
|
|
|
return SymMap.lookup(CachedHashStringRef(Name));
|
2015-06-29 09:03:53 +08:00
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::findUnderscore(StringRef Name) {
|
2015-07-29 06:56:02 +08:00
|
|
|
if (Config->Machine == I386)
|
|
|
|
return find(("_" + Name).str());
|
|
|
|
return find(Name);
|
|
|
|
}
|
|
|
|
|
2015-07-14 10:58:13 +08:00
|
|
|
StringRef SymbolTable::findByPrefix(StringRef Prefix) {
|
2017-11-28 07:16:06 +08:00
|
|
|
for (auto Pair : SymMap) {
|
2016-12-12 06:15:30 +08:00
|
|
|
StringRef Name = Pair.first.val();
|
2015-07-14 10:58:13 +08:00
|
|
|
if (Name.startswith(Prefix))
|
|
|
|
return Name;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef SymbolTable::findMangle(StringRef Name) {
|
2017-11-04 05:21:47 +08:00
|
|
|
if (Symbol *Sym = find(Name))
|
2017-11-01 00:10:24 +08:00
|
|
|
if (!isa<Undefined>(Sym))
|
2015-07-14 10:58:13 +08:00
|
|
|
return Name;
|
2015-07-26 05:54:50 +08:00
|
|
|
if (Config->Machine != I386)
|
2015-07-14 10:58:13 +08:00
|
|
|
return findByPrefix(("?" + Name + "@@Y").str());
|
|
|
|
if (!Name.startswith("_"))
|
|
|
|
return "";
|
2017-10-23 17:08:24 +08:00
|
|
|
// Search for x86 stdcall function.
|
2015-07-14 10:58:13 +08:00
|
|
|
StringRef S = findByPrefix((Name + "@").str());
|
2017-10-23 17:08:24 +08:00
|
|
|
if (!S.empty())
|
|
|
|
return S;
|
|
|
|
// Search for x86 fastcall function.
|
|
|
|
S = findByPrefix(("@" + Name.substr(1) + "@").str());
|
|
|
|
if (!S.empty())
|
|
|
|
return S;
|
|
|
|
// Search for x86 vectorcall function.
|
|
|
|
S = findByPrefix((Name.substr(1) + "@@").str());
|
2015-07-14 10:58:13 +08:00
|
|
|
if (!S.empty())
|
|
|
|
return S;
|
|
|
|
// Search for x86 C++ non-member function.
|
|
|
|
return findByPrefix(("?" + Name.substr(1) + "@@Y").str());
|
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
void SymbolTable::mangleMaybe(Symbol *B) {
|
2016-12-10 05:55:24 +08:00
|
|
|
auto *U = dyn_cast<Undefined>(B);
|
|
|
|
if (!U || U->WeakAlias)
|
2015-07-02 08:04:14 +08:00
|
|
|
return;
|
2015-07-14 10:58:13 +08:00
|
|
|
StringRef Alias = findMangle(U->getName());
|
2017-10-23 17:08:24 +08:00
|
|
|
if (!Alias.empty()) {
|
|
|
|
log(U->getName() + " aliased to " + Alias);
|
2015-07-14 10:58:13 +08:00
|
|
|
U->WeakAlias = addUndefined(Alias);
|
2017-10-23 17:08:24 +08:00
|
|
|
}
|
2015-06-29 06:16:41 +08:00
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::addUndefined(StringRef Name) {
|
2017-11-01 00:10:24 +08:00
|
|
|
return addUndefined(Name, nullptr, false);
|
2015-07-03 08:02:19 +08:00
|
|
|
}
|
|
|
|
|
2017-02-07 04:47:55 +08:00
|
|
|
std::vector<StringRef> SymbolTable::compileBitcodeFiles() {
|
2017-02-03 07:58:14 +08:00
|
|
|
LTO.reset(new BitcodeCompiler);
|
2017-07-27 08:45:26 +08:00
|
|
|
for (BitcodeFile *F : BitcodeFile::Instances)
|
2017-02-03 07:58:14 +08:00
|
|
|
LTO->add(*F);
|
2017-02-07 04:47:55 +08:00
|
|
|
return LTO->compile();
|
|
|
|
}
|
2015-06-02 04:10:10 +08:00
|
|
|
|
2017-02-07 04:47:55 +08:00
|
|
|
void SymbolTable::addCombinedLTOObjects() {
|
2017-07-27 08:45:26 +08:00
|
|
|
if (BitcodeFile::Instances.empty())
|
2017-02-07 04:47:55 +08:00
|
|
|
return;
|
2018-01-18 03:16:26 +08:00
|
|
|
|
|
|
|
ScopedTimer T(LTOTimer);
|
2017-02-07 04:47:55 +08:00
|
|
|
for (StringRef Object : compileBitcodeFiles()) {
|
2017-07-27 07:05:24 +08:00
|
|
|
auto *Obj = make<ObjFile>(MemoryBufferRef(Object, "lto.tmp"));
|
2017-02-03 07:58:14 +08:00
|
|
|
Obj->parse();
|
2017-07-27 08:45:26 +08:00
|
|
|
ObjFile::Instances.push_back(Obj);
|
2015-08-29 06:16:09 +08:00
|
|
|
}
|
2015-06-10 01:52:17 +08:00
|
|
|
}
|
2017-02-07 04:47:55 +08:00
|
|
|
|
2015-05-29 03:09:30 +08:00
|
|
|
} // namespace coff
|
|
|
|
} // namespace lld
|