forked from OSchip/llvm-project
COFF: Don't assume !is64() means i386.
In many places we assumed that is64() means AMD64 and i386 otherwise. This assumption is not sound because Windows also supports ARM. The linker doesn't support ARM yet, but this is a first step. llvm-svn: 243188
This commit is contained in:
parent
15663c530e
commit
35ccb0f7d4
|
@ -252,17 +252,23 @@ ImportThunkChunk::ImportThunkChunk(Defined *S) : ImpSymbol(S) {
|
|||
}
|
||||
|
||||
void ImportThunkChunk::getBaserels(std::vector<uint32_t> *Res) {
|
||||
if (!Config->is64())
|
||||
if (Config->MachineType == I386)
|
||||
Res->push_back(getRVA() + 2);
|
||||
}
|
||||
|
||||
void ImportThunkChunk::writeTo(uint8_t *Buf) {
|
||||
memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData));
|
||||
// The first two bytes is a JMP instruction. Fill its operand.
|
||||
uint32_t Operand = Config->is64()
|
||||
? ImpSymbol->getRVA() - RVA - getSize()
|
||||
: ImpSymbol->getRVA() + Config->ImageBase;
|
||||
write32le(Buf + FileOff + 2, Operand);
|
||||
switch (Config->MachineType) {
|
||||
case AMD64:
|
||||
write32le(Buf + FileOff + 2, ImpSymbol->getRVA() - RVA - getSize());
|
||||
break;
|
||||
case I386:
|
||||
write32le(Buf + FileOff + 2, ImpSymbol->getRVA() + Config->ImageBase);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported machine type");
|
||||
}
|
||||
}
|
||||
|
||||
void LocalImportChunk::getBaserels(std::vector<uint32_t> *Res) {
|
||||
|
@ -299,10 +305,17 @@ BaserelChunk::BaserelChunk(uint32_t Page, uint32_t *Begin, uint32_t *End) {
|
|||
write32le(P, Page);
|
||||
write32le(P + 4, Data.size());
|
||||
P += 8;
|
||||
uint16_t RelTy =
|
||||
Config->is64() ? IMAGE_REL_BASED_DIR64 : IMAGE_REL_BASED_HIGHLOW;
|
||||
for (uint32_t *I = Begin; I != End; ++I) {
|
||||
write16le(P, (RelTy << 12) | (*I - Page));
|
||||
switch (Config->MachineType) {
|
||||
case AMD64:
|
||||
write16le(P, (IMAGE_REL_BASED_DIR64 << 12) | (*I - Page));
|
||||
break;
|
||||
case I386:
|
||||
write16le(P, (IMAGE_REL_BASED_HIGHLOW << 12) | (*I - Page));
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported machine type");
|
||||
}
|
||||
P += 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace lld {
|
|||
namespace coff {
|
||||
|
||||
using llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
|
||||
using llvm::COFF::IMAGE_FILE_MACHINE_I386;
|
||||
using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
using llvm::COFF::WindowsSubsystem;
|
||||
using llvm::StringRef;
|
||||
|
@ -28,6 +29,11 @@ class DefinedAbsolute;
|
|||
class DefinedRelative;
|
||||
class Undefined;
|
||||
|
||||
// Short aliases.
|
||||
static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
|
||||
static const auto ARM = llvm::COFF::IMAGE_FILE_MACHINE_ARM;
|
||||
static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;
|
||||
|
||||
// Represents an /export option.
|
||||
struct Export {
|
||||
StringRef Name;
|
||||
|
|
|
@ -391,12 +391,7 @@ void DelayLoadContents::create(Defined *H) {
|
|||
|
||||
size_t Base = Addresses.size();
|
||||
for (DefinedImportData *S : Syms) {
|
||||
Chunk *T;
|
||||
if (Config->is64()) {
|
||||
T = new ThunkChunkX64(S, Dir.get(), Helper);
|
||||
} else {
|
||||
T = new ThunkChunkX86(S, Dir.get(), Helper);
|
||||
}
|
||||
Chunk *T = newThunkChunk(S, Dir.get());
|
||||
auto A = make_unique<DelayAddressChunk>(T);
|
||||
Addresses.push_back(std::move(A));
|
||||
Thunks.push_back(std::unique_ptr<Chunk>(T));
|
||||
|
@ -430,6 +425,17 @@ void DelayLoadContents::create(Defined *H) {
|
|||
make_unique<NullChunk>(sizeof(delay_import_directory_table_entry)));
|
||||
}
|
||||
|
||||
Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
|
||||
switch (Config->MachineType) {
|
||||
case AMD64:
|
||||
return new ThunkChunkX64(S, Dir, Helper);
|
||||
case I386:
|
||||
return new ThunkChunkX86(S, Dir, Helper);
|
||||
default:
|
||||
llvm_unreachable("unsupported machine type");
|
||||
}
|
||||
}
|
||||
|
||||
// Export table
|
||||
// Read Microsoft PE/COFF spec 5.3 for details.
|
||||
|
||||
|
|
|
@ -57,6 +57,8 @@ public:
|
|||
uint64_t getDirSize();
|
||||
|
||||
private:
|
||||
Chunk *newThunkChunk(DefinedImportData *S, Chunk *Dir);
|
||||
|
||||
Defined *Helper;
|
||||
std::vector<DefinedImportData *> Imports;
|
||||
std::vector<std::unique_ptr<Chunk>> Dirs;
|
||||
|
|
|
@ -108,7 +108,7 @@ LinkerDriver::parseDirectives(StringRef S) {
|
|||
ErrorOr<Export> E = parseExport(Arg->getValue());
|
||||
if (auto EC = E.getError())
|
||||
return EC;
|
||||
if (!Config->is64() && E->ExtName.startswith("_"))
|
||||
if (Config->MachineType == I386 && E->ExtName.startswith("_"))
|
||||
E->ExtName = E->ExtName.substr(1);
|
||||
Config->Exports.push_back(E.get());
|
||||
break;
|
||||
|
@ -554,8 +554,8 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
if (auto *Arg = Args.getLastArg(OPT_entry)) {
|
||||
Config->Entry = addUndefined(mangle(Arg->getValue()));
|
||||
} else if (Args.hasArg(OPT_dll) && !Config->NoEntry) {
|
||||
StringRef S =
|
||||
Config->is64() ? "_DllMainCRTStartup" : "__DllMainCRTStartup@12";
|
||||
StringRef S = (Config->MachineType == I386) ? "__DllMainCRTStartup@12"
|
||||
: "_DllMainCRTStartup";
|
||||
Config->Entry = addUndefined(S);
|
||||
} else if (!Config->NoEntry) {
|
||||
// Windows specific -- If entry point name is not given, we need to
|
||||
|
@ -575,7 +575,7 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
ErrorOr<Export> E = parseExport(Arg->getValue());
|
||||
if (E.getError())
|
||||
return false;
|
||||
if (!Config->is64() && !E->Name.startswith("_@?"))
|
||||
if (Config->MachineType == I386 && !E->Name.startswith("_@?"))
|
||||
E->Name = mangle(E->Name);
|
||||
Config->Exports.push_back(E.get());
|
||||
}
|
||||
|
@ -595,10 +595,10 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
// Handle /delayload
|
||||
for (auto *Arg : Args.filtered(OPT_delayload)) {
|
||||
Config->DelayLoads.insert(StringRef(Arg->getValue()).lower());
|
||||
if (Config->is64()) {
|
||||
Config->DelayLoadHelper = addUndefined("__delayLoadHelper2");
|
||||
} else {
|
||||
if (Config->MachineType == I386) {
|
||||
Config->DelayLoadHelper = addUndefined("___delayLoadHelper2@8");
|
||||
} else {
|
||||
Config->DelayLoadHelper = addUndefined("__delayLoadHelper2");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -428,7 +428,7 @@ std::error_code fixupExports() {
|
|||
if (!E.ExtName.empty())
|
||||
continue;
|
||||
StringRef S = E.Sym->repl()->getName();
|
||||
if (!Config->is64() && S.startswith("_"))
|
||||
if (Config->MachineType == I386 && S.startswith("_"))
|
||||
S = S.substr(1);
|
||||
E.ExtName = S;
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@ private:
|
|||
unget();
|
||||
}
|
||||
|
||||
if (!Config->is64() && !E.Name.startswith("_@?"))
|
||||
if (Config->MachineType == I386 && !E.Name.startswith("_@?"))
|
||||
E.Name = Alloc->save("_" + E.Name);
|
||||
|
||||
for (;;) {
|
||||
|
|
|
@ -287,7 +287,7 @@ StringRef SymbolTable::findMangle(StringRef Name) {
|
|||
if (Symbol *Sym = find(Name))
|
||||
if (!isa<Undefined>(Sym->Body))
|
||||
return Name;
|
||||
if (Config->is64())
|
||||
if (Config->MachineType != I386)
|
||||
return findByPrefix(("?" + Name + "@@Y").str());
|
||||
if (!Name.startswith("_"))
|
||||
return "";
|
||||
|
|
Loading…
Reference in New Issue