From 28df04211cd50a0da0ef984e6163a32e3e38aa2b Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Sat, 25 Jul 2015 01:16:06 +0000 Subject: [PATCH] COFF: Split ImportThunkChunk into x86 and x64. NFC. This change should make it easy to port this code to ARM. llvm-svn: 243195 --- lld/COFF/Chunks.cpp | 28 ++++++++++++---------------- lld/COFF/Chunks.h | 18 ++++++++++++++---- lld/COFF/InputFiles.cpp | 6 ++++-- lld/COFF/Symbols.cpp | 15 +++++++++++++++ lld/COFF/Symbols.h | 13 ++++++------- 5 files changed, 51 insertions(+), 29 deletions(-) diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index fc6a1b4ad55c..93ac540ef8ca 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -245,31 +245,27 @@ void StringChunk::writeTo(uint8_t *Buf) { 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 // should be 16-byte aligned. MSVC linker does this too. if (Config->MachineType == AMD64) Align = 16; } -void ImportThunkChunk::getBaserels(std::vector *Res) { - if (Config->MachineType == I386) - Res->push_back(getRVA() + 2); +void ImportThunkChunkX64::writeTo(uint8_t *Buf) { + memcpy(Buf + FileOff, ImportThunkX86, sizeof(ImportThunkX86)); + // 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) { - memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData)); +void ImportThunkChunkX86::getBaserels(std::vector *Res) { + 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. - 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"); - } + write32le(Buf + FileOff + 2, ImpSymbol->getRVA() + Config->ImageBase); } void LocalImportChunk::getBaserels(std::vector *Res) { diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index e84c11e50e7e..cf087afce7b4 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -223,17 +223,27 @@ private: StringRef Str; }; -static const uint8_t ImportThunkData[] = { +static const uint8_t ImportThunkX86[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0 }; // Windows-specific. // A chunk for DLL import jump table entry. In a final output, it's // contents will be a JMP instruction to some __imp_ symbol. -class ImportThunkChunk : public Chunk { +class ImportThunkChunkX64 : public Chunk { public: - explicit ImportThunkChunk(Defined *ImpSymbol); - size_t getSize() const override { return sizeof(ImportThunkData); } + explicit ImportThunkChunkX64(Defined *S); + 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 *Res) override; void writeTo(uint8_t *Buf) override; diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index 4e5e34c3405f..3e6a6b907760 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -320,8 +320,10 @@ std::error_code ImportFile::parse() { // 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 // DLL functions just like regular non-DLL functions.) - if (Hdr->getType() == llvm::COFF::IMPORT_CODE) - SymbolBodies.push_back(new (Alloc) DefinedImportThunk(Name, ImpSym)); + if (Hdr->getType() == llvm::COFF::IMPORT_CODE) { + auto *B = new (Alloc) DefinedImportThunk(Name, ImpSym, Hdr->Machine); + SymbolBodies.push_back(B); + } return std::error_code(); } diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp index 7898dc9f4378..355442ae5aed 100644 --- a/lld/COFF/Symbols.cpp +++ b/lld/COFF/Symbols.cpp @@ -196,6 +196,21 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol() { return COFFSymbolRef(reinterpret_cast(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> Lazy::getMember() { auto MBRefOrErr = File->getMember(&Sym); if (auto EC = MBRefOrErr.getError()) diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index bb199a99be5e..8a4e698435b4 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -327,20 +327,19 @@ private: // a regular name. A function pointer is given as a DefinedImportData. class DefinedImportThunk : public Defined { public: - DefinedImportThunk(StringRef N, DefinedImportData *S) - : Defined(DefinedImportThunkKind, N), Data(S) {} + DefinedImportThunk(StringRef Name, DefinedImportData *S, + uint16_t MachineType); static bool classof(const SymbolBody *S) { return S->kind() == DefinedImportThunkKind; } - uint64_t getRVA() { return Data.getRVA(); } - uint64_t getFileOff() { return Data.getFileOff(); } - - Chunk *getChunk() { return &Data; } + uint64_t getRVA() { return Data->getRVA(); } + uint64_t getFileOff() { return Data->getFileOff(); } + Chunk *getChunk() { return Data.get(); } private: - ImportThunkChunk Data; + std::unique_ptr Data; }; // If you have a symbol "__imp_foo" in your object file, a symbol name