[lld] r200176 - [ELF] Create Target specific Writers.

Shankar Easwaran shankare at codeaurora.org
Sun Jan 26 17:20:53 PST 2014


Author: shankare
Date: Sun Jan 26 19:20:53 2014
New Revision: 200176

URL: http://llvm.org/viewvc/llvm-project?rev=200176&view=rev
Log:
[ELF] Create Target specific Writers.

Modified:
    lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
    lld/trunk/include/lld/ReaderWriter/Writer.h
    lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h
    lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
    lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h
    lld/trunk/lib/ReaderWriter/ELF/Writer.cpp

Modified: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h?rev=200176&r1=200175&r2=200176&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h Sun Jan 26 19:20:53 2014
@@ -42,6 +42,8 @@ public:
   virtual std::unique_ptr<Reader> getObjReader(bool) = 0;
 
   virtual std::unique_ptr<Reader> getDSOReader(bool) = 0;
+
+  virtual std::unique_ptr<Writer> getWriter() = 0;
 };
 
 class ELFLinkingContext : public LinkingContext {

Modified: lld/trunk/include/lld/ReaderWriter/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/Writer.h?rev=200176&r1=200175&r2=200176&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/Writer.h (original)
+++ lld/trunk/include/lld/ReaderWriter/Writer.h Sun Jan 26 19:20:53 2014
@@ -21,6 +21,7 @@ class ELFLinkingContext;
 class MachOLinkingContext;
 class PECOFFLinkingContext;
 class LinkingContext;
+class TargetHandlerBase;
 
 /// \brief The Writer is an abstract class for writing object files, shared
 /// library files, and executable files.  Each file format (e.g. ELF, mach-o,
@@ -42,7 +43,7 @@ protected:
   Writer();
 };
 
-std::unique_ptr<Writer> createWriterELF(const ELFLinkingContext &);
+std::unique_ptr<Writer> createWriterELF(TargetHandlerBase *handler);
 std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &);
 std::unique_ptr<Writer> createWriterPECOFF(const PECOFFLinkingContext &);
 std::unique_ptr<Writer> createWriterNative(const LinkingContext &);

Modified: lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h?rev=200176&r1=200175&r2=200176&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/DefaultTargetHandler.h Sun Jan 26 19:20:53 2014
@@ -13,6 +13,8 @@
 #include "DefaultLayout.h"
 #include "TargetHandler.h"
 #include "ELFReader.h"
+#include "DynamicLibraryWriter.h"
+#include "ExecutableWriter.h"
 
 #include "lld/ReaderWriter/ELFLinkingContext.h"
 
@@ -78,10 +80,64 @@ public:
     return std::unique_ptr<Reader>(new ELFDSOReader(useShlibUndefines));
   }
 
+  virtual std::unique_ptr<Writer> getWriter();
+
 protected:
   llvm::BumpPtrAllocator _alloc;
 };
+
+template <class ELFT>
+std::unique_ptr<Writer> DefaultTargetHandler<ELFT>::getWriter() {
+  switch (this->_context.getOutputELFType()) {
+  case llvm::ELF::ET_EXEC:
+    if (this->_context.is64Bits()) {
+      if (this->_context.isLittleEndian())
+        return std::unique_ptr<Writer>(
+            new elf::ExecutableWriter<ELFType<support::little, 8, true>>(
+                this->_context));
+      else
+        return std::unique_ptr<Writer>(
+            new elf::ExecutableWriter<ELFType<support::big, 8, true>>(
+                this->_context));
+    } else {
+      if (this->_context.isLittleEndian())
+        return std::unique_ptr<Writer>(
+            new elf::ExecutableWriter<ELFType<support::little, 4, false>>(
+                this->_context));
+      else
+        return std::unique_ptr<Writer>(
+            new elf::ExecutableWriter<ELFType<support::big, 4, false>>(
+                this->_context));
+    }
+    break;
+  case llvm::ELF::ET_DYN:
+    if (this->_context.is64Bits()) {
+      if (this->_context.isLittleEndian())
+        return std::unique_ptr<Writer>(
+            new elf::DynamicLibraryWriter<ELFType<support::little, 8, true>>(
+                this->_context));
+      else
+        return std::unique_ptr<Writer>(
+            new elf::DynamicLibraryWriter<ELFType<support::big, 8, true>>(
+                this->_context));
+    } else {
+      if (this->_context.isLittleEndian())
+        return std::unique_ptr<Writer>(
+            new elf::DynamicLibraryWriter<ELFType<support::little, 4, false>>(
+                this->_context));
+      else
+        return std::unique_ptr<Writer>(
+            new elf::DynamicLibraryWriter<ELFType<support::big, 4, false>>(
+                this->_context));
+    }
+    break;
+  case llvm::ELF::ET_REL:
+    llvm_unreachable("TODO: support -r mode");
+  default:
+    llvm_unreachable("unsupported output type");
+  }
+}
+
 } // end namespace elf
 } // end namespace lld
-
 #endif

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=200176&r1=200175&r2=200176&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Sun Jan 26 19:20:53 2014
@@ -90,7 +90,7 @@ bool ELFLinkingContext::validateImpl(raw
     llvm_unreachable("Unimplemented");
     break;
   default:
-    _writer = createWriterELF(*this);
+    _writer = createWriterELF(this->targetHandler());
     break;
   }
   return true;

Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h?rev=200176&r1=200175&r2=200176&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h Sun Jan 26 19:20:53 2014
@@ -53,9 +53,18 @@ protected:
   // Build the output file
   virtual error_code buildOutput(const File &file);
 
+  // Setup the ELF header.
+  virtual error_code setELFHeader();
+
   // Write the file to the path specified
   virtual error_code writeFile(const File &File, StringRef path);
 
+  // Write to the output file.
+  virtual error_code writeOutput(const File &file, StringRef path);
+
+  // Get the size of the output file that the linker would emit.
+  virtual uint64_t outputFileSize() const;
+
   // Build the atom to address map, this has to be called
   // before applying relocations
   virtual void buildAtomToAddressMap(const File &file);
@@ -365,22 +374,7 @@ error_code OutputELFWriter<ELFT>::buildO
   return error_code::success();
 }
 
-template <class ELFT>
-error_code OutputELFWriter<ELFT>::writeFile(const File &file, StringRef path) {
-  buildOutput(file);
-
-  uint64_t totalSize = _shdrtab->fileOffset() + _shdrtab->fileSize();
-
-  OwningPtr<FileOutputBuffer> buffer;
-  ScopedTask createOutputTask(getDefaultDomain(), "ELF Writer Create Output");
-  error_code ec = FileOutputBuffer::create(path,
-                                           totalSize, buffer,
-                                           FileOutputBuffer::F_executable);
-  createOutputTask.end();
-
-  if (ec)
-    return ec;
-
+template <class ELFT> error_code OutputELFWriter<ELFT>::setELFHeader() {
   _elfHeader->e_ident(ELF::EI_CLASS,
                       _context.is64Bits() ? ELF::ELFCLASS64 : ELF::ELFCLASS32);
   _elfHeader->e_ident(ELF::EI_DATA, _context.isLittleEndian()
@@ -388,15 +382,9 @@ error_code OutputELFWriter<ELFT>::writeF
                                         : ELF::ELFDATA2MSB);
   _elfHeader->e_type(_context.getOutputELFType());
   _elfHeader->e_machine(_context.getOutputMachine());
-
-  if (!_targetHandler.doesOverrideELFHeader()) {
-    _elfHeader->e_ident(ELF::EI_VERSION, 1);
-    _elfHeader->e_ident(ELF::EI_OSABI, 0);
-    _elfHeader->e_version(1);
-  } else {
-    // override the contents of the ELF Header
-    _targetHandler.setELFHeader(_elfHeader.get());
-  }
+  _elfHeader->e_ident(ELF::EI_VERSION, 1);
+  _elfHeader->e_ident(ELF::EI_OSABI, 0);
+  _elfHeader->e_version(1);
   _elfHeader->e_phoff(_programHeader->fileOffset());
   _elfHeader->e_shoff(_shdrtab->fileOffset());
   _elfHeader->e_phentsize(_programHeader->entsize());
@@ -408,20 +396,53 @@ error_code OutputELFWriter<ELFT>::writeF
   _layout->findAtomAddrByName(_context.entrySymbolName(), virtualAddr);
   _elfHeader->e_entry(virtualAddr);
 
+  return error_code::success();
+}
+
+template <class ELFT> uint64_t OutputELFWriter<ELFT>::outputFileSize() const {
+  return _shdrtab->fileOffset() + _shdrtab->fileSize();
+}
+
+template <class ELFT>
+error_code OutputELFWriter<ELFT>::writeOutput(const File &file,
+                                              StringRef path) {
+  OwningPtr<FileOutputBuffer> buffer;
+  ScopedTask createOutputTask(getDefaultDomain(), "ELF Writer Create Output");
+  error_code ec = FileOutputBuffer::create(path, outputFileSize(), buffer,
+                                           FileOutputBuffer::F_executable);
+  createOutputTask.end();
+
+  if (ec)
+    return ec;
+
+  ScopedTask writeTask(getDefaultDomain(), "ELF Writer write to memory");
+
   // HACK: We have to write out the header and program header here even though
   // they are a member of a segment because only sections are written in the
   // following loop.
-  ScopedTask writeTask(getDefaultDomain(), "ELF Writer write to memory");
   _elfHeader->write(this, *buffer);
   _programHeader->write(this, *buffer);
 
   for (auto section : _layout->sections())
-      section->write(this, *buffer);
+    section->write(this, *buffer);
   writeTask.end();
 
   ScopedTask commitTask(getDefaultDomain(), "ELF Writer commit to disk");
   return buffer->commit();
 }
+
+template <class ELFT>
+error_code OutputELFWriter<ELFT>::writeFile(const File &file, StringRef path) {
+  error_code ec = buildOutput(file);
+  if (ec)
+    return ec;
+
+  ec = setELFHeader();
+  if (ec)
+    return ec;
+
+  return writeOutput(file, path);
+}
 } // namespace elf
 } // namespace lld
 

Modified: lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h?rev=200176&r1=200175&r2=200176&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/TargetHandler.h Sun Jan 26 19:20:53 2014
@@ -96,6 +96,8 @@ public:
 
   virtual std::unique_ptr<Reader> getDSOReader(bool) = 0;
 
+  virtual std::unique_ptr<Writer> getWriter() = 0;
+
 protected:
   ELFLinkingContext &_context;
 };

Modified: lld/trunk/lib/ReaderWriter/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Writer.cpp?rev=200176&r1=200175&r2=200176&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Writer.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Writer.cpp Sun Jan 26 19:20:53 2014
@@ -17,52 +17,8 @@ using namespace llvm;
 using namespace llvm::object;
 namespace lld {
 
-std::unique_ptr<Writer> createWriterELF(const ELFLinkingContext &info) {
-  using llvm::object::ELFType;
-  // Set the default layout to be the static executable layout
-  // We would set the layout to a dynamic executable layout
-  // if we came across any shared libraries in the process
-
-  switch (info.getOutputELFType()) {
-  case llvm::ELF::ET_EXEC:
-    if (info.is64Bits()) {
-      if (info.isLittleEndian())
-        return std::unique_ptr<Writer>(new
-            elf::ExecutableWriter<ELFType<support::little, 8, true>>(info));
-      else
-        return std::unique_ptr<Writer>(new
-                elf::ExecutableWriter<ELFType<support::big, 8, true>>(info));
-    } else {
-      if (info.isLittleEndian())
-        return std::unique_ptr<Writer>(new
-            elf::ExecutableWriter<ELFType<support::little, 4, false>>(info));
-      else
-        return std::unique_ptr<Writer>(new
-                elf::ExecutableWriter<ELFType<support::big, 4, false>>(info));
-    }
-  break;
-  case llvm::ELF::ET_DYN:
-    if (info.is64Bits()) {
-      if (info.isLittleEndian())
-        return std::unique_ptr<Writer>(new
-          elf::DynamicLibraryWriter<ELFType<support::little, 8, true>>(info));
-      else
-        return std::unique_ptr<Writer>(new
-              elf::DynamicLibraryWriter<ELFType<support::big, 8, true>>(info));
-    } else {
-      if (info.isLittleEndian())
-        return std::unique_ptr<Writer>(new
-          elf::DynamicLibraryWriter<ELFType<support::little, 4, false>>(info));
-      else
-        return std::unique_ptr<Writer>(new
-              elf::DynamicLibraryWriter<ELFType<support::big, 4, false>>(info));
-    }
-  break;
-  case llvm::ELF::ET_REL:
-    llvm_unreachable("TODO: support -r mode");
-  default:
-    llvm_unreachable("unsupported output type");
-  }
+std::unique_ptr<Writer> createWriterELF(TargetHandlerBase *handler) {
+  return std::move(handler->getWriter());
 }
 
 } // namespace lld





More information about the llvm-commits mailing list