[lld] r244175 - COFF: Simplify Writer interface by hiding Writer class.

Rui Ueyama ruiu at google.com
Wed Aug 5 16:43:53 PDT 2015


Author: ruiu
Date: Wed Aug  5 18:43:53 2015
New Revision: 244175

URL: http://llvm.org/viewvc/llvm-project?rev=244175&view=rev
Log:
COFF: Simplify Writer interface by hiding Writer class.

Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Writer.cpp
    lld/trunk/COFF/Writer.h

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=244175&r1=244174&r2=244175&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Wed Aug  5 18:43:53 2015
@@ -12,6 +12,7 @@
 #include "Error.h"
 #include "InputFiles.h"
 #include "SymbolTable.h"
+#include "Symbols.h"
 #include "Writer.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
@@ -725,8 +726,7 @@ bool LinkerDriver::link(llvm::ArrayRef<c
     touchFile(Arg->getValue());
 
   // Write the result.
-  Writer Out(&Symtab);
-  if (auto EC = Out.write(Config->OutputFile)) {
+  if (auto EC = writeResult(&Symtab, Config->OutputFile)) {
     llvm::errs() << EC.message() << "\n";
     return false;
   }

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=244175&r1=244174&r2=244175&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Wed Aug  5 18:43:53 2015
@@ -8,6 +8,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "Config.h"
+#include "DLL.h"
+#include "InputFiles.h"
+#include "SymbolTable.h"
+#include "Symbols.h"
 #include "Writer.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
@@ -20,6 +24,7 @@
 #include <algorithm>
 #include <cstdio>
 #include <map>
+#include <memory>
 #include <utility>
 
 using namespace llvm;
@@ -27,6 +32,8 @@ using namespace llvm::COFF;
 using namespace llvm::object;
 using namespace llvm::support;
 using namespace llvm::support::endian;
+using namespace lld;
+using namespace lld::coff;
 
 static const int PageSize = 4096;
 static const int FileAlignment = 512;
@@ -34,35 +41,115 @@ static const int SectionAlignment = 4096
 static const int DOSStubSize = 64;
 static const int NumberfOfDataDirectory = 16;
 
+namespace {
+// The writer writes a SymbolTable result to a file.
+class Writer {
+public:
+  Writer(SymbolTable *T, StringRef S) : Symtab(T), OutputPath(S) {}
+  std::error_code run();
+
+private:
+  void markLive();
+  void dedupCOMDATs();
+  void createSections();
+  void createMiscChunks();
+  void createImportTables();
+  void createExportTable();
+  void assignAddresses();
+  void removeEmptySections();
+  void createSymbolAndStringTable();
+  std::error_code openFile(StringRef OutputPath);
+  template <typename PEHeaderTy> void writeHeader();
+  void fixSafeSEHSymbols();
+  void writeSections();
+  void sortExceptionTable();
+  void applyRelocations();
+
+  llvm::Optional<coff_symbol16> createSymbol(Defined *D);
+  size_t addEntryToStringTable(StringRef Str);
+
+  OutputSection *findSection(StringRef Name);
+  OutputSection *createSection(StringRef Name);
+  void addBaserels(OutputSection *Dest);
+  void addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V);
+
+  uint32_t getSizeOfInitializedData();
+  std::map<StringRef, std::vector<DefinedImportData *>> binImports();
+
+  SymbolTable *Symtab;
+  StringRef OutputPath;
+  std::unique_ptr<llvm::FileOutputBuffer> Buffer;
+  llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc;
+  llvm::SpecificBumpPtrAllocator<BaserelChunk> BAlloc;
+  std::vector<OutputSection *> OutputSections;
+  std::vector<char> Strtab;
+  std::vector<llvm::object::coff_symbol16> OutputSymtab;
+  IdataContents Idata;
+  DelayLoadContents DelayIdata;
+  EdataContents Edata;
+  std::unique_ptr<SEHTableChunk> SEHTable;
+
+  bool Is64;
+  uint64_t FileSize;
+  uint32_t PointerToSymbolTable = 0;
+  uint64_t SizeOfImage;
+  uint64_t SizeOfHeaders;
+
+  std::vector<std::unique_ptr<Chunk>> Chunks;
+};
+} // anonymous namespace
+
 namespace lld {
 namespace coff {
 
-// The main function of the writer.
-std::error_code Writer::write(StringRef OutputPath) {
-  markLive();
-  dedupCOMDATs();
-  createSections();
-  createMiscChunks();
-  createImportTables();
-  createExportTable();
-  if (Config->Relocatable)
-    createSection(".reloc");
-  assignAddresses();
-  removeEmptySections();
-  createSymbolAndStringTable();
-  if (auto EC = openFile(OutputPath))
-    return EC;
-  if (Config->is64()) {
-    writeHeader<pe32plus_header>();
-  } else {
-    writeHeader<pe32_header>();
-  }
-  fixSafeSEHSymbols();
-  writeSections();
-  sortExceptionTable();
-  return Buffer->commit();
+std::error_code writeResult(SymbolTable *T, StringRef Path) {
+  return Writer(T, Path).run();
 }
 
+// OutputSection represents a section in an output file. It's a
+// container of chunks. OutputSection and Chunk are 1:N relationship.
+// Chunks cannot belong to more than one OutputSections. The writer
+// creates multiple OutputSections and assign them unique,
+// non-overlapping file offsets and RVAs.
+class OutputSection {
+public:
+  OutputSection(StringRef N) : Name(N), Header({}) {}
+  void setRVA(uint64_t);
+  void setFileOffset(uint64_t);
+  void addChunk(Chunk *C);
+  StringRef getName() { return Name; }
+  std::vector<Chunk *> &getChunks() { return Chunks; }
+  void addPermissions(uint32_t C);
+  uint32_t getPermissions() { return Header.Characteristics & PermMask; }
+  uint32_t getCharacteristics() { return Header.Characteristics; }
+  uint64_t getRVA() { return Header.VirtualAddress; }
+  uint64_t getFileOff() { return Header.PointerToRawData; }
+  void writeHeaderTo(uint8_t *Buf);
+
+  // Returns the size of this section in an executable memory image.
+  // This may be smaller than the raw size (the raw size is multiple
+  // of disk sector size, so there may be padding at end), or may be
+  // larger (if that's the case, the loader reserves spaces after end
+  // of raw data).
+  uint64_t getVirtualSize() { return Header.VirtualSize; }
+
+  // Returns the size of the section in the output file.
+  uint64_t getRawSize() { return Header.SizeOfRawData; }
+
+  // Set offset into the string table storing this section name.
+  // Used only when the name is longer than 8 bytes.
+  void setStringTableOff(uint32_t V) { StringTableOff = V; }
+
+  // N.B. The section index is one based.
+  uint32_t SectionIndex = 0;
+
+private:
+  StringRef Name;
+  coff_section Header;
+  uint32_t StringTableOff = 0;
+  std::vector<Chunk *> Chunks;
+};
+
 void OutputSection::setRVA(uint64_t RVA) {
   Header.VirtualAddress = RVA;
   for (Chunk *C : Chunks)
@@ -111,6 +198,54 @@ void OutputSection::writeHeaderTo(uint8_
   }
 }
 
+uint64_t Defined::getSecrel() {
+  if (auto *D = dyn_cast<DefinedRegular>(this))
+    return getRVA() - D->getChunk()->getOutputSection()->getRVA();
+  llvm::report_fatal_error("SECREL relocation points to a non-regular symbol");
+}
+
+uint64_t Defined::getSectionIndex() {
+  if (auto *D = dyn_cast<DefinedRegular>(this))
+    return D->getChunk()->getOutputSection()->SectionIndex;
+  llvm::report_fatal_error("SECTION relocation points to a non-regular symbol");
+}
+
+bool Defined::isExecutable() {
+  const auto X = IMAGE_SCN_MEM_EXECUTE;
+  if (auto *D = dyn_cast<DefinedRegular>(this))
+    return D->getChunk()->getOutputSection()->getPermissions() & X;
+  return isa<DefinedImportThunk>(this);
+}
+
+} // namespace coff
+} // namespace lld
+
+// The main function of the writer.
+std::error_code Writer::run() {
+  markLive();
+  dedupCOMDATs();
+  createSections();
+  createMiscChunks();
+  createImportTables();
+  createExportTable();
+  if (Config->Relocatable)
+    createSection(".reloc");
+  assignAddresses();
+  removeEmptySections();
+  createSymbolAndStringTable();
+  if (auto EC = openFile(OutputPath))
+    return EC;
+  if (Config->is64()) {
+    writeHeader<pe32plus_header>();
+  } else {
+    writeHeader<pe32_header>();
+  }
+  fixSafeSEHSymbols();
+  writeSections();
+  sortExceptionTable();
+  return Buffer->commit();
+}
+
 // Set live bit on for each reachable chunk. Unmarked (unreachable)
 // COMDAT chunks will be ignored in the next step, so that they don't
 // come to the final output file.
@@ -220,7 +355,7 @@ void Writer::createMiscChunks() {
   if (Config->Machine != I386)
     return;
   std::set<Defined *> Handlers;
-  for (ObjectFile *File : Symtab->ObjectFiles) {
+  for (lld::coff::ObjectFile *File : Symtab->ObjectFiles) {
     if (!File->SEHCompat)
       return;
     for (SymbolBody *B : File->SEHandlers)
@@ -361,7 +496,7 @@ void Writer::createSymbolAndStringTable(
     Sec->setStringTableOff(addEntryToStringTable(Name));
   }
 
-  for (ObjectFile *File : Symtab->ObjectFiles)
+  for (lld::coff::ObjectFile *File : Symtab->ObjectFiles)
     for (SymbolBody *B : File->getSymbols())
       if (auto *D = dyn_cast<Defined>(B))
         if (Optional<coff_symbol16> Sym = createSymbol(D))
@@ -681,25 +816,3 @@ void Writer::addBaserelBlocks(OutputSect
   BaserelChunk *Buf = BAlloc.Allocate();
   Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
 }
-
-uint64_t Defined::getSecrel() {
-  if (auto *D = dyn_cast<DefinedRegular>(this))
-    return getRVA() - D->getChunk()->getOutputSection()->getRVA();
-  llvm::report_fatal_error("SECREL relocation points to a non-regular symbol");
-}
-
-uint64_t Defined::getSectionIndex() {
-  if (auto *D = dyn_cast<DefinedRegular>(this))
-    return D->getChunk()->getOutputSection()->SectionIndex;
-  llvm::report_fatal_error("SECTION relocation points to a non-regular symbol");
-}
-
-bool Defined::isExecutable() {
-  const auto X = IMAGE_SCN_MEM_EXECUTE;
-  if (auto *D = dyn_cast<DefinedRegular>(this))
-    return D->getChunk()->getOutputSection()->getPermissions() & X;
-  return isa<DefinedImportThunk>(this);
-}
-
-} // namespace coff
-} // namespace lld

Modified: lld/trunk/COFF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.h?rev=244175&r1=244174&r2=244175&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.h (original)
+++ lld/trunk/COFF/Writer.h Wed Aug  5 18:43:53 2015
@@ -10,120 +10,20 @@
 #ifndef LLD_COFF_WRITER_H
 #define LLD_COFF_WRITER_H
 
-#include "DLL.h"
-#include "InputFiles.h"
-#include "SymbolTable.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include <memory>
 #include <vector>
 
 namespace lld {
 namespace coff {
 
-// Implemented in ICF.cpp.
-void doICF(const std::vector<Chunk *> &Chunks);
+class Chunk;
+class OutputSection;
 
-// OutputSection represents a section in an output file. It's a
-// container of chunks. OutputSection and Chunk are 1:N relationship.
-// Chunks cannot belong to more than one OutputSections. The writer
-// creates multiple OutputSections and assign them unique,
-// non-overlapping file offsets and RVAs.
-class OutputSection {
-public:
-  OutputSection(StringRef N) : Name(N), Header({}) {}
-  void setRVA(uint64_t);
-  void setFileOffset(uint64_t);
-  void addChunk(Chunk *C);
-  StringRef getName() { return Name; }
-  std::vector<Chunk *> &getChunks() { return Chunks; }
-  void addPermissions(uint32_t C);
-  uint32_t getPermissions() { return Header.Characteristics & PermMask; }
-  uint32_t getCharacteristics() { return Header.Characteristics; }
-  uint64_t getRVA() { return Header.VirtualAddress; }
-  uint64_t getFileOff() { return Header.PointerToRawData; }
-  void writeHeaderTo(uint8_t *Buf);
-
-  // Returns the size of this section in an executable memory image.
-  // This may be smaller than the raw size (the raw size is multiple
-  // of disk sector size, so there may be padding at end), or may be
-  // larger (if that's the case, the loader reserves spaces after end
-  // of raw data).
-  uint64_t getVirtualSize() { return Header.VirtualSize; }
-
-  // Returns the size of the section in the output file.
-  uint64_t getRawSize() { return Header.SizeOfRawData; }
-
-  // Set offset into the string table storing this section name.
-  // Used only when the name is longer than 8 bytes.
-  void setStringTableOff(uint32_t V) { StringTableOff = V; }
-
-  // N.B. The section index is one based.
-  uint32_t SectionIndex = 0;
-
-private:
-  StringRef Name;
-  coff_section Header;
-  uint32_t StringTableOff = 0;
-  std::vector<Chunk *> Chunks;
-};
-
-// The writer writes a SymbolTable result to a file.
-class Writer {
-public:
-  explicit Writer(SymbolTable *T) : Symtab(T) {}
-  std::error_code write(StringRef Path);
-
-private:
-  void markLive();
-  void dedupCOMDATs();
-  void createSections();
-  void createMiscChunks();
-  void createImportTables();
-  void createExportTable();
-  void assignAddresses();
-  void removeEmptySections();
-  void createSymbolAndStringTable();
-  std::error_code openFile(StringRef OutputPath);
-  template <typename PEHeaderTy> void writeHeader();
-  void fixSafeSEHSymbols();
-  void writeSections();
-  void sortExceptionTable();
-  void applyRelocations();
-
-  llvm::Optional<coff_symbol16> createSymbol(Defined *D);
-  size_t addEntryToStringTable(StringRef Str);
-
-  OutputSection *findSection(StringRef Name);
-  OutputSection *createSection(StringRef Name);
-  void addBaserels(OutputSection *Dest);
-  void addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V);
-
-  uint32_t getSizeOfInitializedData();
-  std::map<StringRef, std::vector<DefinedImportData *>> binImports();
-
-  SymbolTable *Symtab;
-  std::unique_ptr<llvm::FileOutputBuffer> Buffer;
-  llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc;
-  llvm::SpecificBumpPtrAllocator<BaserelChunk> BAlloc;
-  std::vector<OutputSection *> OutputSections;
-  std::vector<char> Strtab;
-  std::vector<llvm::object::coff_symbol16> OutputSymtab;
-  IdataContents Idata;
-  DelayLoadContents DelayIdata;
-  EdataContents Edata;
-  std::unique_ptr<SEHTableChunk> SEHTable;
-
-  bool Is64;
-  uint64_t FileSize;
-  uint32_t PointerToSymbolTable = 0;
-  uint64_t SizeOfImage;
-  uint64_t SizeOfHeaders;
+std::error_code writeResult(SymbolTable *T, StringRef Path);
 
-  std::vector<std::unique_ptr<Chunk>> Chunks;
-};
+// Implemented in ICF.cpp.
+void doICF(const std::vector<Chunk *> &Chunks);
 
-} // namespace coff
-} // namespace lld
+}
+}
 
 #endif




More information about the llvm-commits mailing list