[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