[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