[lld] r239239 - COFF: Move Windows-specific code from Chunk.{cpp, h} to DLL.{cpp, h}.

Rui Ueyama ruiu at google.com
Sat Jun 6 18:15:05 PDT 2015


Author: ruiu
Date: Sat Jun  6 20:15:04 2015
New Revision: 239239

URL: http://llvm.org/viewvc/llvm-project?rev=239239&view=rev
Log:
COFF: Move Windows-specific code from Chunk.{cpp,h} to DLL.{cpp,h}.

Added:
    lld/trunk/COFF/DLL.cpp
    lld/trunk/COFF/DLL.h
Modified:
    lld/trunk/COFF/CMakeLists.txt
    lld/trunk/COFF/Chunks.cpp
    lld/trunk/COFF/Chunks.h
    lld/trunk/COFF/Writer.h

Modified: lld/trunk/COFF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/CMakeLists.txt?rev=239239&r1=239238&r2=239239&view=diff
==============================================================================
--- lld/trunk/COFF/CMakeLists.txt (original)
+++ lld/trunk/COFF/CMakeLists.txt Sat Jun  6 20:15:04 2015
@@ -4,6 +4,7 @@ add_public_tablegen_target(COFFOptionsTa
 
 add_llvm_library(lldCOFF
   Chunks.cpp
+  DLL.cpp
   Driver.cpp
   DriverUtils.cpp
   InputFiles.cpp

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=239239&r1=239238&r2=239239&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Sat Jun  6 20:15:04 2015
@@ -26,9 +26,6 @@ using llvm::RoundUpToAlignment;
 namespace lld {
 namespace coff {
 
-const size_t LookupChunk::Size = sizeof(uint64_t);
-const size_t DirectoryChunk::Size = sizeof(ImportDirectoryTableEntry);
-
 SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H, uint32_t SI)
     : File(F), Header(H), SectionIndex(SI) {
   // Initialize SectionName.
@@ -170,109 +167,5 @@ void ImportThunkChunk::writeTo(uint8_t *
   write32le(Buf + FileOff + 2, Operand);
 }
 
-size_t HintNameChunk::getSize() const {
-  // Starts with 2 byte Hint field, followed by a null-terminated string,
-  // ends with 0 or 1 byte padding.
-  return RoundUpToAlignment(Name.size() + 3, 2);
-}
-
-void HintNameChunk::writeTo(uint8_t *Buf) {
-  write16le(Buf + FileOff, Hint);
-  memcpy(Buf + FileOff + 2, Name.data(), Name.size());
-}
-
-void LookupChunk::writeTo(uint8_t *Buf) {
-  write32le(Buf + FileOff, HintName->getRVA());
-}
-
-void OrdinalOnlyChunk::writeTo(uint8_t *Buf) {
-  // An import-by-ordinal slot has MSB 1 to indicate that
-  // this is import-by-ordinal (and not import-by-name).
-  write64le(Buf + FileOff, (uint64_t(1) << 63) | Ordinal);
-}
-
-void DirectoryChunk::writeTo(uint8_t *Buf) {
-  auto *E = (coff_import_directory_table_entry *)(Buf + FileOff);
-  E->ImportLookupTableRVA = LookupTab->getRVA();
-  E->NameRVA = DLLName->getRVA();
-  E->ImportAddressTableRVA = AddressTab->getRVA();
-}
-
-// Returns a list of .idata contents.
-// See Microsoft PE/COFF spec 5.4 for details.
-std::vector<Chunk *> IdataContents::getChunks() {
-  create();
-  std::vector<Chunk *> V;
-  // The loader assumes a specific order of data.
-  // Add each type in the correct order.
-  for (std::unique_ptr<Chunk> &C : Dirs)
-    V.push_back(C.get());
-  for (std::unique_ptr<Chunk> &C : Lookups)
-    V.push_back(C.get());
-  for (std::unique_ptr<Chunk> &C : Addresses)
-    V.push_back(C.get());
-  for (std::unique_ptr<Chunk> &C : Hints)
-    V.push_back(C.get());
-  for (auto &P : DLLNames) {
-    std::unique_ptr<Chunk> &C = P.second;
-    V.push_back(C.get());
-  }
-  return V;
-}
-
-void IdataContents::create() {
-  // Group DLL-imported symbols by DLL name because that's how
-  // symbols are layed out in the import descriptor table.
-  std::map<StringRef, std::vector<DefinedImportData *>> Map;
-  for (DefinedImportData *Sym : Imports)
-    Map[Sym->getDLLName()].push_back(Sym);
-
-  // Create .idata contents for each DLL.
-  for (auto &P : Map) {
-    StringRef Name = P.first;
-    std::vector<DefinedImportData *> &Syms = P.second;
-
-    // Sort symbols by name for each group.
-    std::sort(Syms.begin(), Syms.end(),
-              [](DefinedImportData *A, DefinedImportData *B) {
-                return A->getName() < B->getName();
-              });
-
-    // Create lookup and address tables. If they have external names,
-    // we need to create HintName chunks to store the names.
-    // If they don't (if they are import-by-ordinals), we store only
-    // ordinal values to the table.
-    size_t Base = Lookups.size();
-    for (DefinedImportData *S : Syms) {
-      uint16_t Ord = S->getOrdinal();
-      if (S->getExternalName().empty()) {
-        Lookups.push_back(make_unique<OrdinalOnlyChunk>(Ord));
-        Addresses.push_back(make_unique<OrdinalOnlyChunk>(Ord));
-        continue;
-      }
-      auto C = make_unique<HintNameChunk>(S->getExternalName(), Ord);
-      Lookups.push_back(make_unique<LookupChunk>(C.get()));
-      Addresses.push_back(make_unique<LookupChunk>(C.get()));
-      Hints.push_back(std::move(C));
-    }
-    // Terminate with null values.
-    Lookups.push_back(make_unique<NullChunk>(sizeof(uint64_t)));
-    Addresses.push_back(make_unique<NullChunk>(sizeof(uint64_t)));
-
-    for (int I = 0, E = Syms.size(); I < E; ++I)
-      Syms[I]->setLocation(Addresses[Base + I].get());
-
-    // Create the import table header.
-    if (!DLLNames.count(Name))
-      DLLNames[Name] = make_unique<StringChunk>(Name);
-    auto Dir = make_unique<DirectoryChunk>(DLLNames[Name].get());
-    Dir->LookupTab = Lookups[Base].get();
-    Dir->AddressTab = Addresses[Base].get();
-    Dirs.push_back(std::move(Dir));
-  }
-  // Add null terminator.
-  Dirs.push_back(make_unique<NullChunk>(DirectoryChunk::Size));
-}
-
 } // namespace coff
 } // namespace lld

Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=239239&r1=239238&r2=239239&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Sat Jun  6 20:15:04 2015
@@ -166,16 +166,11 @@ private:
   StringRef Str;
 };
 
-// All chunks below are for the DLL import descriptor table and
-// Windows-specific. You may need to read the Microsoft PE/COFF spec
-// to understand details about the data structures.
-// If you are not particularly interested, you can skip them and
-// still be able to understand the rest of the linker.
-
 static const uint8_t ImportThunkData[] = {
     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 {
@@ -188,87 +183,6 @@ private:
   Defined *ImpSymbol;
 };
 
-// A chunk for the import descriptor table.
-class HintNameChunk : public Chunk {
-public:
-  HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
-  size_t getSize() const override;
-  void writeTo(uint8_t *Buf) override;
-
-private:
-  StringRef Name;
-  uint16_t Hint;
-};
-
-// A chunk for the import descriptor table.
-class LookupChunk : public Chunk {
-public:
-  explicit LookupChunk(Chunk *C) : HintName(C) {}
-  size_t getSize() const override { return Size; }
-  void writeTo(uint8_t *Buf) override;
-  static const size_t Size;
-  Chunk *HintName;
-};
-
-// A chunk for the import descriptor table.
-// This chunk represent import-by-ordinal symbols.
-// See the Microsoft PE/COFF spec 7.1. Import Header for details.
-class OrdinalOnlyChunk : public Chunk {
-public:
-  explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {}
-  size_t getSize() const override { return sizeof(uint64_t); }
-  void writeTo(uint8_t *Buf) override;
-  uint16_t Ordinal;
-};
-
-// A chunk for the import descriptor table.
-class DirectoryChunk : public Chunk {
-public:
-  explicit DirectoryChunk(Chunk *N) : DLLName(N) {}
-  size_t getSize() const override { return Size; }
-  void writeTo(uint8_t *Buf) override;
-  static const size_t Size;
-  Chunk *DLLName;
-  Chunk *LookupTab;
-  Chunk *AddressTab;
-};
-
-// A chunk representing null terminator in the import table.
-// Contents of this chunk is always null bytes.
-class NullChunk : public Chunk {
-public:
-  explicit NullChunk(size_t N) : Size(N) {}
-  bool hasData() const override { return false; }
-  size_t getSize() const override { return Size; }
-
-private:
-  size_t Size;
-};
-
-// IdataContents creates all chunks for the .idata section.
-// You are supposed to call add() to add symbols and then
-// call getChunks() to get a list of chunks.
-class IdataContents {
-public:
-  void add(DefinedImportData *Sym) { Imports.push_back(Sym); }
-  std::vector<Chunk *> getChunks();
-
-  uint64_t getDirRVA() { return Dirs[0]->getRVA(); }
-  uint64_t getDirSize() { return Dirs.size() * DirectoryChunk::Size; }
-  uint64_t getIATRVA() { return Addresses[0]->getRVA(); }
-  uint64_t getIATSize() { return Addresses.size() * LookupChunk::Size; }
-
-private:
-  void create();
-
-  std::vector<DefinedImportData *> Imports;
-  std::vector<std::unique_ptr<Chunk>> Dirs;
-  std::vector<std::unique_ptr<Chunk>> Lookups;
-  std::vector<std::unique_ptr<Chunk>> Addresses;
-  std::vector<std::unique_ptr<Chunk>> Hints;
-  std::map<StringRef, std::unique_ptr<Chunk>> DLLNames;
-};
-
 } // namespace coff
 } // namespace lld
 

Added: lld/trunk/COFF/DLL.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.cpp?rev=239239&view=auto
==============================================================================
--- lld/trunk/COFF/DLL.cpp (added)
+++ lld/trunk/COFF/DLL.cpp Sat Jun  6 20:15:04 2015
@@ -0,0 +1,205 @@
+//===- DLL.cpp ------------------------------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines various types of chunks for the DLL import
+// descriptor table. They are inherently Windows-specific.
+// You need to read Microsoft PE/COFF spec to understand details
+// about the data structures.
+//
+// If you are not particularly interested in linking against Windows
+// DLL, you can skip this file, and you should still be able to
+// understand the rest of the linker.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Chunks.h"
+#include "DLL.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+using namespace llvm::COFF;
+using llvm::RoundUpToAlignment;
+
+const size_t LookupChunkSize = sizeof(uint64_t);
+const size_t DirectoryChunkSize = sizeof(ImportDirectoryTableEntry);
+
+namespace lld {
+namespace coff {
+
+// A chunk for the import descriptor table.
+class HintNameChunk : public Chunk {
+public:
+  HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
+
+  size_t getSize() const override {
+    // Starts with 2 byte Hint field, followed by a null-terminated string,
+    // ends with 0 or 1 byte padding.
+    return RoundUpToAlignment(Name.size() + 3, 2);
+  }
+
+  void writeTo(uint8_t *Buf) override {
+    write16le(Buf + FileOff, Hint);
+    memcpy(Buf + FileOff + 2, Name.data(), Name.size());
+  }
+
+private:
+  StringRef Name;
+  uint16_t Hint;
+};
+
+// A chunk for the import descriptor table.
+class LookupChunk : public Chunk {
+public:
+  explicit LookupChunk(Chunk *C) : HintName(C) {}
+  size_t getSize() const override { return LookupChunkSize; }
+
+  void writeTo(uint8_t *Buf) override {
+    write32le(Buf + FileOff, HintName->getRVA());
+  }
+
+  Chunk *HintName;
+};
+
+// A chunk for the import descriptor table.
+// This chunk represent import-by-ordinal symbols.
+// See Microsoft PE/COFF spec 7.1. Import Header for details.
+class OrdinalOnlyChunk : public Chunk {
+public:
+  explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {}
+  size_t getSize() const override { return sizeof(uint64_t); }
+
+  void writeTo(uint8_t *Buf) override {
+    // An import-by-ordinal slot has MSB 1 to indicate that
+    // this is import-by-ordinal (and not import-by-name).
+    write64le(Buf + FileOff, (uint64_t(1) << 63) | Ordinal);
+  }
+
+  uint16_t Ordinal;
+};
+
+// A chunk for the import descriptor table.
+class DirectoryChunk : public Chunk {
+public:
+  explicit DirectoryChunk(Chunk *N) : DLLName(N) {}
+  size_t getSize() const override { return DirectoryChunkSize; }
+
+  void writeTo(uint8_t *Buf) override {
+    auto *E = (coff_import_directory_table_entry *)(Buf + FileOff);
+    E->ImportLookupTableRVA = LookupTab->getRVA();
+    E->NameRVA = DLLName->getRVA();
+    E->ImportAddressTableRVA = AddressTab->getRVA();
+  }
+
+  Chunk *DLLName;
+  Chunk *LookupTab;
+  Chunk *AddressTab;
+};
+
+// A chunk representing null terminator in the import table.
+// Contents of this chunk is always null bytes.
+class NullChunk : public Chunk {
+public:
+  explicit NullChunk(size_t N) : Size(N) {}
+  bool hasData() const override { return false; }
+  size_t getSize() const override { return Size; }
+
+private:
+  size_t Size;
+};
+
+uint64_t IdataContents::getDirSize() {
+  return Dirs.size() * DirectoryChunkSize;
+}
+
+uint64_t IdataContents::getIATSize() {
+  return Addresses.size() * LookupChunkSize;
+}
+
+// Returns a list of .idata contents.
+// See Microsoft PE/COFF spec 5.4 for details.
+std::vector<Chunk *> IdataContents::getChunks() {
+  create();
+  std::vector<Chunk *> V;
+  // The loader assumes a specific order of data.
+  // Add each type in the correct order.
+  for (std::unique_ptr<Chunk> &C : Dirs)
+    V.push_back(C.get());
+  for (std::unique_ptr<Chunk> &C : Lookups)
+    V.push_back(C.get());
+  for (std::unique_ptr<Chunk> &C : Addresses)
+    V.push_back(C.get());
+  for (std::unique_ptr<Chunk> &C : Hints)
+    V.push_back(C.get());
+  for (auto &P : DLLNames) {
+    std::unique_ptr<Chunk> &C = P.second;
+    V.push_back(C.get());
+  }
+  return V;
+}
+
+void IdataContents::create() {
+  // Group DLL-imported symbols by DLL name because that's how
+  // symbols are layed out in the import descriptor table.
+  std::map<StringRef, std::vector<DefinedImportData *>> Map;
+  for (DefinedImportData *Sym : Imports)
+    Map[Sym->getDLLName()].push_back(Sym);
+
+  // Create .idata contents for each DLL.
+  for (auto &P : Map) {
+    StringRef Name = P.first;
+    std::vector<DefinedImportData *> &Syms = P.second;
+
+    // Sort symbols by name for each group.
+    std::sort(Syms.begin(), Syms.end(),
+              [](DefinedImportData *A, DefinedImportData *B) {
+                return A->getName() < B->getName();
+              });
+
+    // Create lookup and address tables. If they have external names,
+    // we need to create HintName chunks to store the names.
+    // If they don't (if they are import-by-ordinals), we store only
+    // ordinal values to the table.
+    size_t Base = Lookups.size();
+    for (DefinedImportData *S : Syms) {
+      uint16_t Ord = S->getOrdinal();
+      if (S->getExternalName().empty()) {
+        Lookups.push_back(make_unique<OrdinalOnlyChunk>(Ord));
+        Addresses.push_back(make_unique<OrdinalOnlyChunk>(Ord));
+        continue;
+      }
+      auto C = make_unique<HintNameChunk>(S->getExternalName(), Ord);
+      Lookups.push_back(make_unique<LookupChunk>(C.get()));
+      Addresses.push_back(make_unique<LookupChunk>(C.get()));
+      Hints.push_back(std::move(C));
+    }
+    // Terminate with null values.
+    Lookups.push_back(make_unique<NullChunk>(sizeof(uint64_t)));
+    Addresses.push_back(make_unique<NullChunk>(sizeof(uint64_t)));
+
+    for (int I = 0, E = Syms.size(); I < E; ++I)
+      Syms[I]->setLocation(Addresses[Base + I].get());
+
+    // Create the import table header.
+    if (!DLLNames.count(Name))
+      DLLNames[Name] = make_unique<StringChunk>(Name);
+    auto Dir = make_unique<DirectoryChunk>(DLLNames[Name].get());
+    Dir->LookupTab = Lookups[Base].get();
+    Dir->AddressTab = Addresses[Base].get();
+    Dirs.push_back(std::move(Dir));
+  }
+  // Add null terminator.
+  Dirs.push_back(make_unique<NullChunk>(DirectoryChunkSize));
+}
+
+} // namespace coff
+} // namespace lld

Added: lld/trunk/COFF/DLL.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DLL.h?rev=239239&view=auto
==============================================================================
--- lld/trunk/COFF/DLL.h (added)
+++ lld/trunk/COFF/DLL.h Sat Jun  6 20:15:04 2015
@@ -0,0 +1,47 @@
+//===- DLL.h -------------------------------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COFF_DLL_H
+#define LLD_COFF_DLL_H
+
+#include "Chunks.h"
+#include "Symbols.h"
+
+namespace lld {
+namespace coff {
+
+// Windows-specific.
+// IdataContents creates all chunks for the .idata section.
+// You are supposed to call add() to add symbols and then
+// call getChunks() to get a list of chunks.
+class IdataContents {
+public:
+  void add(DefinedImportData *Sym) { Imports.push_back(Sym); }
+  std::vector<Chunk *> getChunks();
+
+  uint64_t getDirRVA() { return Dirs[0]->getRVA(); }
+  uint64_t getDirSize();
+  uint64_t getIATRVA() { return Addresses[0]->getRVA(); }
+  uint64_t getIATSize();
+
+private:
+  void create();
+
+  std::vector<DefinedImportData *> Imports;
+  std::vector<std::unique_ptr<Chunk>> Dirs;
+  std::vector<std::unique_ptr<Chunk>> Lookups;
+  std::vector<std::unique_ptr<Chunk>> Addresses;
+  std::vector<std::unique_ptr<Chunk>> Hints;
+  std::map<StringRef, std::unique_ptr<Chunk>> DLLNames;
+};
+
+} // namespace coff
+} // namespace lld
+
+#endif

Modified: lld/trunk/COFF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.h?rev=239239&r1=239238&r2=239239&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.h (original)
+++ lld/trunk/COFF/Writer.h Sat Jun  6 20:15:04 2015
@@ -10,6 +10,7 @@
 #ifndef LLD_COFF_WRITER_H
 #define LLD_COFF_WRITER_H
 
+#include "DLL.h"
 #include "InputFiles.h"
 #include "SymbolTable.h"
 #include "llvm/Support/FileOutputBuffer.h"





More information about the llvm-commits mailing list