Move code from InputFile to ELFCreator to decouple the two files.
authorRui Ueyama <ruiu@google.com>
Thu, 20 Oct 2016 21:57:06 +0000 (21:57 +0000)
committerRui Ueyama <ruiu@google.com>
Thu, 20 Oct 2016 21:57:06 +0000 (21:57 +0000)
Now that only one non-member function is exported from ELFCreator.h.
All the details are handled internally in ELFCreator.cpp file.

llvm-svn: 284786

lld/ELF/ELFCreator.cpp
lld/ELF/ELFCreator.h
lld/ELF/InputFiles.cpp
lld/ELF/InputFiles.h

index 3904449..d95f5ab 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "ELFCreator.h"
+#include "Config.h"
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Object/ELFTypes.h"
+#include "llvm/Support/StringSaver.h"
 
 using namespace llvm;
 using namespace llvm::ELF;
@@ -21,13 +25,45 @@ using namespace llvm::object;
 using namespace lld;
 using namespace lld::elf;
 
+namespace {
+template <class ELFT> class ELFCreator {
+  typedef typename ELFT::uint uintX_t;
+  typedef typename ELFT::Ehdr Elf_Ehdr;
+  typedef typename ELFT::Shdr Elf_Shdr;
+  typedef typename ELFT::Sym Elf_Sym;
+
+public:
+  struct Section {
+    Elf_Shdr *Header;
+    size_t Index;
+  };
+
+  ELFCreator(std::uint16_t Type, std::uint16_t Machine);
+  Section addSection(StringRef Name);
+  Elf_Sym *addSymbol(StringRef Name);
+  size_t layout();
+  void writeTo(uint8_t *Out);
+
+private:
+  Elf_Ehdr Header = {};
+  std::vector<Elf_Shdr *> Sections;
+  std::vector<Elf_Sym *> Symbols;
+  StringTableBuilder ShStrTabBuilder{StringTableBuilder::ELF};
+  StringTableBuilder StrTabBuilder{StringTableBuilder::ELF};
+  BumpPtrAllocator Alloc;
+  StringSaver Saver{Alloc};
+  Elf_Shdr *ShStrTab;
+  Elf_Shdr *StrTab;
+  Elf_Shdr *SymTab;
+};
+}
+
 template <class ELFT>
 ELFCreator<ELFT>::ELFCreator(std::uint16_t Type, std::uint16_t Machine) {
   std::memcpy(Header.e_ident, "\177ELF", 4);
   Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
-  Header.e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little
-                                ? ELFDATA2LSB
-                                : ELFDATA2MSB;
+  Header.e_ident[EI_DATA] =
+      ELFT::TargetEndianness == support::little ? ELFDATA2LSB : ELFDATA2MSB;
   Header.e_ident[EI_VERSION] = EV_CURRENT;
   Header.e_type = Type;
   Header.e_machine = Machine;
@@ -111,7 +147,50 @@ template <class ELFT> void ELFCreator<ELFT>::writeTo(uint8_t *Out) {
     *Shdr++ = *S;
 }
 
-template class elf::ELFCreator<ELF32LE>;
-template class elf::ELFCreator<ELF32BE>;
-template class elf::ELFCreator<ELF64LE>;
-template class elf::ELFCreator<ELF64BE>;
+template <class ELFT>
+std::vector<uint8_t> elf::wrapBinaryWithElfHeader(ArrayRef<uint8_t> Blob,
+                                                  std::string Filename) {
+  typedef typename ELFT::uint uintX_t;
+  typedef typename ELFT::Sym Elf_Sym;
+
+  // Fill the ELF file header.
+  ELFCreator<ELFT> File(ET_REL, Config->EMachine);
+  auto Sec = File.addSection(".data");
+  Sec.Header->sh_flags = SHF_ALLOC;
+  Sec.Header->sh_size = Blob.size();
+  Sec.Header->sh_type = SHT_PROGBITS;
+  Sec.Header->sh_addralign = 8;
+
+  // Replace non-alphanumeric characters with '_'.
+  std::transform(Filename.begin(), Filename.end(), Filename.begin(),
+                 [](char C) { return isalnum(C) ? C : '_'; });
+
+  // Add _start, _end and _size symbols.
+  auto AddSym = [&](std::string Name, uintX_t SecIdx, uintX_t Value) {
+    Elf_Sym *Sym = File.addSymbol("_binary_" + Filename + Name);
+    Sym->setBindingAndType(STB_GLOBAL, STT_OBJECT);
+    Sym->st_shndx = SecIdx;
+    Sym->st_value = Value;
+  };
+  AddSym("_start", Sec.Index, 0);
+  AddSym("_end", Sec.Index, Blob.size());
+  AddSym("_size", SHN_ABS, Blob.size());
+
+  // Fix the ELF file layout and write it down to a uint8_t vector.
+  size_t Size = File.layout();
+  std::vector<uint8_t> Ret(Size);
+  File.writeTo(Ret.data());
+
+  // Fill .data section with actual data.
+  memcpy(Ret.data() + Sec.Header->sh_offset, Blob.data(), Blob.size());
+  return Ret;
+}
+
+template std::vector<uint8_t>
+    elf::wrapBinaryWithElfHeader<ELF32LE>(ArrayRef<uint8_t>, std::string);
+template std::vector<uint8_t>
+    elf::wrapBinaryWithElfHeader<ELF32BE>(ArrayRef<uint8_t>, std::string);
+template std::vector<uint8_t>
+    elf::wrapBinaryWithElfHeader<ELF64LE>(ArrayRef<uint8_t>, std::string);
+template std::vector<uint8_t>
+    elf::wrapBinaryWithElfHeader<ELF64BE>(ArrayRef<uint8_t>, std::string);
index 5bf686f..ae4e19a 100644 (file)
 
 #include "lld/Core/LLVM.h"
 
-#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/Object/ELFTypes.h"
-#include "llvm/Support/StringSaver.h"
-
 namespace lld {
 namespace elf {
 
-template <class ELFT> class ELFCreator {
-  typedef typename ELFT::uint uintX_t;
-  typedef typename ELFT::Ehdr Elf_Ehdr;
-  typedef typename ELFT::Shdr Elf_Shdr;
-  typedef typename ELFT::Sym Elf_Sym;
-
-public:
-  struct Section {
-    Elf_Shdr *Header;
-    size_t Index;
-  };
-
-  ELFCreator(std::uint16_t Type, std::uint16_t Machine);
-  Section addSection(StringRef Name);
-  Elf_Sym *addSymbol(StringRef Name);
-  size_t layout();
-  void writeTo(uint8_t *Out);
-
-private:
-  Elf_Ehdr Header = {};
-  std::vector<Elf_Shdr *> Sections;
-  std::vector<Elf_Sym *> Symbols;
-  llvm::StringTableBuilder ShStrTabBuilder{llvm::StringTableBuilder::ELF};
-  llvm::StringTableBuilder StrTabBuilder{llvm::StringTableBuilder::ELF};
-  llvm::BumpPtrAllocator Alloc;
-  llvm::StringSaver Saver{Alloc};
-  Elf_Shdr *ShStrTab;
-  Elf_Shdr *StrTab;
-  Elf_Shdr *SymTab;
-};
+// Wraps a given binary blob with an ELF header so that the blob
+// can be linked as an ELF file. Used for "--format binary".
+template <class ELFT>
+std::vector<uint8_t> wrapBinaryWithElfHeader(ArrayRef<uint8_t> Data,
+                                             std::string Filename);
 }
 }
 
index 154f792..27cfcee 100644 (file)
@@ -781,44 +781,12 @@ static InputFile *createELFFile(MemoryBufferRef MB) {
 // Wraps a binary blob with an ELF header and footer
 // so that we can link it as a regular ELF file.
 template <class ELFT> InputFile *BinaryFile::createELF() {
-  typedef typename ELFT::uint uintX_t;
-  typedef typename ELFT::Sym Elf_Sym;
+  ArrayRef<uint8_t> Blob((uint8_t *)MB.getBufferStart(), MB.getBufferSize());
+  StringRef Filename = MB.getBufferIdentifier();
+  Buffer = wrapBinaryWithElfHeader<ELFT>(Blob, Filename);
 
-  // Fill the ELF file header.
-  ELFCreator<ELFT> File(ET_REL, Config->EMachine);
-  auto DataSec = File.addSection(".data");
-  DataSec.Header->sh_flags = SHF_ALLOC;
-  DataSec.Header->sh_size = MB.getBufferSize();
-  DataSec.Header->sh_type = SHT_PROGBITS;
-  DataSec.Header->sh_addralign = 8;
-
-  // Replace non-alphanumeric characters with '_'.
-  std::string Filepath = MB.getBufferIdentifier();
-  std::transform(Filepath.begin(), Filepath.end(), Filepath.begin(),
-                 [](char C) { return isalnum(C) ? C : '_'; });
-
-  // Add _start, _end and _size symbols.
-  auto AddSym = [&](std::string Name, uintX_t SecIdx, uintX_t Value) {
-    Elf_Sym *Sym = File.addSymbol("_binary_" + Filepath + Name);
-    Sym->setBindingAndType(STB_GLOBAL, STT_OBJECT);
-    Sym->st_shndx = SecIdx;
-    Sym->st_value = Value;
-  };
-  AddSym("_start", DataSec.Index, 0);
-  AddSym("_end", DataSec.Index, MB.getBufferSize());
-  AddSym("_size", SHN_ABS, MB.getBufferSize());
-
-  // Fix the ELF file layout and write it down to ELFData uint8_t vector.
-  size_t Size = File.layout();
-  ELFData.resize(Size);
-  File.writeTo(ELFData.data());
-
-  // Fill .data section with actual data.
-  memcpy(ELFData.data() + DataSec.Header->sh_offset, MB.getBufferStart(),
-         MB.getBufferSize());
-
-  return createELFFile<ObjectFile>(MemoryBufferRef(
-      StringRef((char *)ELFData.data(), Size), MB.getBufferIdentifier()));
+  return createELFFile<ObjectFile>(
+      MemoryBufferRef(toStringRef(Buffer), Filename));
 }
 
 static bool isBitcode(MemoryBufferRef MB) {
index 13f47b5..61e9bbe 100644 (file)
@@ -326,7 +326,7 @@ public:
   template <class ELFT> InputFile *createELF();
 
 private:
-  std::vector<uint8_t> ELFData;
+  std::vector<uint8_t> Buffer;
 };
 
 InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "",