COFF: Split ImportThunkChunk into x86 and x64. NFC.
authorRui Ueyama <ruiu@google.com>
Sat, 25 Jul 2015 01:16:06 +0000 (01:16 +0000)
committerRui Ueyama <ruiu@google.com>
Sat, 25 Jul 2015 01:16:06 +0000 (01:16 +0000)
This change should make it easy to port this code to ARM.

llvm-svn: 243195

lld/COFF/Chunks.cpp
lld/COFF/Chunks.h
lld/COFF/InputFiles.cpp
lld/COFF/Symbols.cpp
lld/COFF/Symbols.h

index fc6a1b4..93ac540 100644 (file)
@@ -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<uint32_t> *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 ImportThunkChunkX86::getBaserels(std::vector<uint32_t> *Res) {
+  Res->push_back(getRVA() + 2);
 }
 
-void ImportThunkChunk::writeTo(uint8_t *Buf) {
-  memcpy(Buf + FileOff, ImportThunkData, sizeof(ImportThunkData));
+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<uint32_t> *Res) {
index e84c11e..cf087af 100644 (file)
@@ -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<uint32_t> *Res) override;
   void writeTo(uint8_t *Buf) override;
 
index 4e5e34c..3e6a6b9 100644 (file)
@@ -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();
 }
 
index 7898dc9..355442a 100644 (file)
@@ -196,6 +196,21 @@ COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
   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() {
   auto MBRefOrErr = File->getMember(&Sym);
   if (auto EC = MBRefOrErr.getError())
index bb199a9..8a4e698 100644 (file)
@@ -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<Chunk> Data;
 };
 
 // If you have a symbol "__imp_foo" in your object file, a symbol name