COFF: Split ImportThunkChunk into x86 and x64. NFC.

This change should make it easy to port this code to ARM.

llvm-svn: 243195
This commit is contained in:
Rui Ueyama 2015-07-25 01:16:06 +00:00
parent 1c341a54de
commit 28df04211c
5 changed files with 51 additions and 29 deletions

View File

@ -245,31 +245,27 @@ void StringChunk::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, Str.data(), Str.size()); memcpy(Buf + FileOff, Str.data(), Str.size());
} }
ImportThunkChunk::ImportThunkChunk(Defined *S) : ImpSymbol(S) { ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) {
// Intel Optimization Manual says that all branch targets // Intel Optimization Manual says that all branch targets
// should be 16-byte aligned. MSVC linker does this too. // should be 16-byte aligned. MSVC linker does this too.
if (Config->MachineType == AMD64) if (Config->MachineType == AMD64)
Align = 16; Align = 16;
} }
void ImportThunkChunk::getBaserels(std::vector<uint32_t> *Res) { void ImportThunkChunkX64::writeTo(uint8_t *Buf) {
if (Config->MachineType == I386) memcpy(Buf + FileOff, ImportThunkX86, sizeof(ImportThunkX86));
Res->push_back(getRVA() + 2); // The first two bytes is a JMP instruction. Fill its operand.
write32le(Buf + FileOff + 2, ImpSymbol->getRVA() - RVA - getSize());
} }
void ImportThunkChunk::writeTo(uint8_t *Buf) { void ImportThunkChunkX86::getBaserels(std::vector<uint32_t> *Res) {
memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData)); Res->push_back(getRVA() + 2);
}
void ImportThunkChunkX86::writeTo(uint8_t *Buf) {
memcpy(Buf + FileOff, ImportThunkX86, sizeof(ImportThunkX86));
// The first two bytes is a JMP instruction. Fill its operand. // The first two bytes is a JMP instruction. Fill its operand.
switch (Config->MachineType) { write32le(Buf + FileOff + 2, ImpSymbol->getRVA() + Config->ImageBase);
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) { void LocalImportChunk::getBaserels(std::vector<uint32_t> *Res) {

View File

@ -223,17 +223,27 @@ private:
StringRef Str; StringRef Str;
}; };
static const uint8_t ImportThunkData[] = { static const uint8_t ImportThunkX86[] = {
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0
}; };
// Windows-specific. // Windows-specific.
// A chunk for DLL import jump table entry. In a final output, it's // A chunk for DLL import jump table entry. In a final output, it's
// contents will be a JMP instruction to some __imp_ symbol. // contents will be a JMP instruction to some __imp_ symbol.
class ImportThunkChunk : public Chunk { class ImportThunkChunkX64 : public Chunk {
public: public:
explicit ImportThunkChunk(Defined *ImpSymbol); explicit ImportThunkChunkX64(Defined *S);
size_t getSize() const override { return sizeof(ImportThunkData); } size_t getSize() const override { return sizeof(ImportThunkX86); }
void writeTo(uint8_t *Buf) override;
private:
Defined *ImpSymbol;
};
class ImportThunkChunkX86 : public Chunk {
public:
explicit ImportThunkChunkX86(Defined *S) : ImpSymbol(S) {}
size_t getSize() const override { return sizeof(ImportThunkX86); }
void getBaserels(std::vector<uint32_t> *Res) override; void getBaserels(std::vector<uint32_t> *Res) override;
void writeTo(uint8_t *Buf) override; void writeTo(uint8_t *Buf) override;

View File

@ -320,8 +320,10 @@ std::error_code ImportFile::parse() {
// If type is function, we need to create a thunk which jump to an // If type is function, we need to create a thunk which jump to an
// address pointed by the __imp_ symbol. (This allows you to call // address pointed by the __imp_ symbol. (This allows you to call
// DLL functions just like regular non-DLL functions.) // DLL functions just like regular non-DLL functions.)
if (Hdr->getType() == llvm::COFF::IMPORT_CODE) if (Hdr->getType() == llvm::COFF::IMPORT_CODE) {
SymbolBodies.push_back(new (Alloc) DefinedImportThunk(Name, ImpSym)); auto *B = new (Alloc) DefinedImportThunk(Name, ImpSym, Hdr->Machine);
SymbolBodies.push_back(B);
}
return std::error_code(); return std::error_code();
} }

View File

@ -196,6 +196,21 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym)); return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
} }
DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S,
uint16_t MachineType)
: Defined(DefinedImportThunkKind, Name) {
switch (MachineType) {
case AMD64:
Data.reset(new ImportThunkChunkX64(S));
return;
case I386:
Data.reset(new ImportThunkChunkX86(S));
return;
default:
llvm_unreachable("unknown machine type");
}
}
ErrorOr<std::unique_ptr<InputFile>> Lazy::getMember() { ErrorOr<std::unique_ptr<InputFile>> Lazy::getMember() {
auto MBRefOrErr = File->getMember(&Sym); auto MBRefOrErr = File->getMember(&Sym);
if (auto EC = MBRefOrErr.getError()) if (auto EC = MBRefOrErr.getError())

View File

@ -327,20 +327,19 @@ private:
// a regular name. A function pointer is given as a DefinedImportData. // a regular name. A function pointer is given as a DefinedImportData.
class DefinedImportThunk : public Defined { class DefinedImportThunk : public Defined {
public: public:
DefinedImportThunk(StringRef N, DefinedImportData *S) DefinedImportThunk(StringRef Name, DefinedImportData *S,
: Defined(DefinedImportThunkKind, N), Data(S) {} uint16_t MachineType);
static bool classof(const SymbolBody *S) { static bool classof(const SymbolBody *S) {
return S->kind() == DefinedImportThunkKind; return S->kind() == DefinedImportThunkKind;
} }
uint64_t getRVA() { return Data.getRVA(); } uint64_t getRVA() { return Data->getRVA(); }
uint64_t getFileOff() { return Data.getFileOff(); } uint64_t getFileOff() { return Data->getFileOff(); }
Chunk *getChunk() { return Data.get(); }
Chunk *getChunk() { return &Data; }
private: private:
ImportThunkChunk Data; std::unique_ptr<Chunk> Data;
}; };
// If you have a symbol "__imp_foo" in your object file, a symbol name // If you have a symbol "__imp_foo" in your object file, a symbol name