[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