summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/BinaryObject.h325
-rw-r--r--include/llvm/Target/TargetELFWriterInfo.h26
-rw-r--r--lib/CodeGen/ELF.h86
-rw-r--r--lib/CodeGen/ELFCodeEmitter.cpp12
-rw-r--r--lib/CodeGen/ELFWriter.cpp303
-rw-r--r--lib/CodeGen/ELFWriter.h38
-rw-r--r--lib/Target/TargetELFWriterInfo.cpp5
7 files changed, 537 insertions, 258 deletions
diff --git a/include/llvm/CodeGen/BinaryObject.h b/include/llvm/CodeGen/BinaryObject.h
new file mode 100644
index 0000000000..0780cd6ab4
--- /dev/null
+++ b/include/llvm/CodeGen/BinaryObject.h
@@ -0,0 +1,325 @@
+//===-- llvm/CodeGen/BinaryObject.h - Binary Object. -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a Binary Object Aka. "blob" for holding data from code
+// generators, ready for data to the object module code writters.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_BINARYOBJECT_H
+#define LLVM_CODEGEN_BINARYOBJECT_H
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+class MachineRelocation;
+typedef std::vector<uint8_t> BinaryData;
+
+class BinaryObject {
+protected:
+ std::string Name;
+ bool IsLittleEndian;
+ bool Is64Bit;
+ BinaryData Data;
+ std::vector<MachineRelocation> Relocations;
+
+public:
+ /// Constructors and destructor
+ BinaryObject() {}
+
+ BinaryObject(bool isLittleEndian, bool is64Bit)
+ : IsLittleEndian(isLittleEndian), Is64Bit(is64Bit) {}
+
+ BinaryObject(const std::string &name, bool isLittleEndian, bool is64Bit)
+ : Name(name), IsLittleEndian(isLittleEndian), Is64Bit(is64Bit) {}
+
+ ~BinaryObject() {}
+
+ /// getName - get name of BinaryObject
+ inline std::string getName() const { return Name; }
+
+ /// get size of binary data
+ size_t size() const {
+ return Data.size();
+ }
+
+ /// get binary data
+ BinaryData& getData() {
+ return Data;
+ }
+
+ /// get machine relocations
+ const std::vector<MachineRelocation>& getRelocations() const {
+ return Relocations;
+ }
+
+ /// emitByte - This callback is invoked when a byte needs to be
+ /// written to the data stream.
+ inline void emitByte(uint8_t B) {
+ Data.push_back(B);
+ }
+
+ /// emitWord16 - This callback is invoked when a 16-bit word needs to be
+ /// written to the data stream in correct endian format and correct size.
+ inline void emitWord16(uint16_t W) {
+ if (IsLittleEndian)
+ emitWord16LE(W);
+ else
+ emitWord16BE(W);
+ }
+
+ /// emitWord16LE - This callback is invoked when a 16-bit word needs to be
+ /// written to the data stream in correct endian format and correct size.
+ inline void emitWord16LE(uint16_t W) {
+ Data.push_back((W >> 0) & 255);
+ Data.push_back((W >> 8) & 255);
+ }
+
+ /// emitWord16BE - This callback is invoked when a 16-bit word needs to be
+ /// written to the data stream in correct endian format and correct size.
+ inline void emitWord16BE(uint16_t W) {
+ Data.push_back((W >> 8) & 255);
+ Data.push_back((W >> 0) & 255);
+ }
+
+ /// emitWord - This callback is invoked when a word needs to be
+ /// written to the data stream in correct endian format and correct size.
+ inline void emitWord(uint64_t W) {
+ if (!Is64Bit)
+ emitWord32(W);
+ else
+ emitWord64(W);
+ }
+
+ /// emitWord32 - This callback is invoked when a 32-bit word needs to be
+ /// written to the data stream in correct endian format.
+ inline void emitWord32(uint32_t W) {
+ if (IsLittleEndian)
+ emitWordLE(W);
+ else
+ emitWordBE(W);
+ }
+
+ /// emitWord64 - This callback is invoked when a 32-bit word needs to be
+ /// written to the data stream in correct endian format.
+ inline void emitWord64(uint64_t W) {
+ if (IsLittleEndian)
+ emitDWordLE(W);
+ else
+ emitDWordBE(W);
+ }
+
+ /// emitWordLE - This callback is invoked when a 32-bit word needs to be
+ /// written to the data stream in little-endian format.
+ inline void emitWordLE(uint32_t W) {
+ Data.push_back((W >> 0) & 255);
+ Data.push_back((W >> 8) & 255);
+ Data.push_back((W >> 16) & 255);
+ Data.push_back((W >> 24) & 255);
+ }
+
+ /// emitWordBE - This callback is invoked when a 32-bit word needs to be
+ /// written to the data stream in big-endian format.
+ ///
+ inline void emitWordBE(uint32_t W) {
+ Data.push_back((W >> 24) & 255);
+ Data.push_back((W >> 16) & 255);
+ Data.push_back((W >> 8) & 255);
+ Data.push_back((W >> 0) & 255);
+ }
+
+ /// emitDWordLE - This callback is invoked when a 64-bit word needs to be
+ /// written to the data stream in little-endian format.
+ inline void emitDWordLE(uint64_t W) {
+ Data.push_back(unsigned(W >> 0) & 255);
+ Data.push_back(unsigned(W >> 8) & 255);
+ Data.push_back(unsigned(W >> 16) & 255);
+ Data.push_back(unsigned(W >> 24) & 255);
+ Data.push_back(unsigned(W >> 32) & 255);
+ Data.push_back(unsigned(W >> 40) & 255);
+ Data.push_back(unsigned(W >> 48) & 255);
+ Data.push_back(unsigned(W >> 56) & 255);
+ }
+
+ /// emitDWordBE - This callback is invoked when a 64-bit word needs to be
+ /// written to the data stream in big-endian format.
+ inline void emitDWordBE(uint64_t W) {
+ Data.push_back(unsigned(W >> 56) & 255);
+ Data.push_back(unsigned(W >> 48) & 255);
+ Data.push_back(unsigned(W >> 40) & 255);
+ Data.push_back(unsigned(W >> 32) & 255);
+ Data.push_back(unsigned(W >> 24) & 255);
+ Data.push_back(unsigned(W >> 16) & 255);
+ Data.push_back(unsigned(W >> 8) & 255);
+ Data.push_back(unsigned(W >> 0) & 255);
+ }
+
+ /// fixByte - This callback is invoked when a byte needs to be
+ /// fixup the buffer.
+ inline void fixByte(uint8_t B, uint32_t offset) {
+ Data[offset] = B;
+ }
+
+ /// fixWord16 - This callback is invoked when a 16-bit word needs to
+ /// fixup the data stream in correct endian format.
+ inline void fixWord16(uint16_t W, uint32_t offset) {
+ if (IsLittleEndian)
+ fixWord16LE(W, offset);
+ else
+ fixWord16BE(W, offset);
+ }
+
+ /// emitWord16LE - This callback is invoked when a 16-bit word needs to
+ /// fixup the data stream in little endian format.
+ inline void fixWord16LE(uint16_t W, uint32_t offset) {
+ Data[offset++] = W & 255;
+ Data[offset] = (W >> 8) & 255;
+ }
+
+ /// fixWord16BE - This callback is invoked when a 16-bit word needs to
+ /// fixup data stream in big endian format.
+ inline void fixWord16BE(uint16_t W, uint32_t offset) {
+ Data[offset++] = (W >> 8) & 255;
+ Data[offset] = W & 255;
+ }
+
+ /// emitWord - This callback is invoked when a word needs to
+ /// fixup the data in correct endian format and correct size.
+ inline void fixWord(uint64_t W, uint32_t offset) {
+ if (!Is64Bit)
+ fixWord32(W, offset);
+ else
+ fixWord64(W, offset);
+ }
+
+ /// fixWord32 - This callback is invoked when a 32-bit word needs to
+ /// fixup the data in correct endian format.
+ inline void fixWord32(uint32_t W, uint32_t offset) {
+ if (IsLittleEndian)
+ fixWord32LE(W, offset);
+ else
+ fixWord32BE(W, offset);
+ }
+
+ /// fixWord32LE - This callback is invoked when a 32-bit word needs to
+ /// fixup the data in little endian format.
+ inline void fixWord32LE(uint32_t W, uint32_t offset) {
+ Data[offset++] = W & 255;
+ Data[offset++] = (W >> 8) & 255;
+ Data[offset++] = (W >> 16) & 255;
+ Data[offset] = (W >> 24) & 255;
+ }
+
+ /// fixWord32BE - This callback is invoked when a 32-bit word needs to
+ /// fixup the data in big endian format.
+ inline void fixWord32BE(uint32_t W, uint32_t offset) {
+ Data[offset++] = (W >> 24) & 255;
+ Data[offset++] = (W >> 16) & 255;
+ Data[offset++] = (W >> 8) & 255;
+ Data[offset] = W & 255;
+ }
+
+ /// fixWord64 - This callback is invoked when a 64-bit word needs to
+ /// fixup the data in correct endian format.
+ inline void fixWord64(uint64_t W, uint32_t offset) {
+ if (IsLittleEndian)
+ fixWord64LE(W, offset);
+ else
+ fixWord64BE(W, offset);
+ }
+
+ /// fixWord64BE - This callback is invoked when a 64-bit word needs to
+ /// fixup the data in little endian format.
+ inline void fixWord64LE(uint64_t W, uint32_t offset) {
+ Data[offset++] = W & 255;
+ Data[offset++] = (W >> 8) & 255;
+ Data[offset++] = (W >> 16) & 255;
+ Data[offset++] = (W >> 24) & 255;
+ Data[offset++] = (W >> 32) & 255;
+ Data[offset++] = (W >> 40) & 255;
+ Data[offset++] = (W >> 48) & 255;
+ Data[offset] = (W >> 56) & 255;
+ }
+
+ /// fixWord64BE - This callback is invoked when a 64-bit word needs to
+ /// fixup the data in big endian format.
+ inline void fixWord64BE(uint64_t W, uint32_t offset) {
+ Data[offset++] = (W >> 56) & 255;
+ Data[offset++] = (W >> 48) & 255;
+ Data[offset++] = (W >> 40) & 255;
+ Data[offset++] = (W >> 32) & 255;
+ Data[offset++] = (W >> 24) & 255;
+ Data[offset++] = (W >> 16) & 255;
+ Data[offset++] = (W >> 8) & 255;
+ Data[offset] = W & 255;
+ }
+
+ /// emitAlignment - Pad the data to the specified alignment.
+ void emitAlignment(unsigned Alignment) {
+ if (Alignment <= 1) return;
+ unsigned PadSize = -Data.size() & (Alignment-1);
+ for (unsigned i = 0; i<PadSize; ++i)
+ Data.push_back(0);
+ }
+
+ /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be
+ /// written to the data stream.
+ void emitULEB128Bytes(uint64_t Value) {
+ do {
+ unsigned char Byte = Value & 0x7f;
+ Value >>= 7;
+ if (Value) Byte |= 0x80;
+ emitByte(Byte);
+ } while (Value);
+ }
+
+ /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be
+ /// written to the data stream.
+ void emitSLEB128Bytes(int64_t Value) {
+ int Sign = Value >> (8 * sizeof(Value) - 1);
+ bool IsMore;
+
+ do {
+ unsigned char Byte = Value & 0x7f;
+ Value >>= 7;
+ IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
+ if (IsMore) Byte |= 0x80;
+ emitByte(Byte);
+ } while (IsMore);
+ }
+
+ /// emitString - This callback is invoked when a String needs to be
+ /// written to the data stream.
+ void emitString(const std::string &String) {
+ for (unsigned i = 0, N = static_cast<unsigned>(String.size()); i<N; ++i) {
+ unsigned char C = String[i];
+ emitByte(C);
+ }
+ emitByte(0);
+ }
+
+ /// getCurrentPCOffset - Return the offset from the start of the emitted
+ /// buffer that we are currently writing to.
+ uintptr_t getCurrentPCOffset() const {
+ return Data.size();
+ }
+
+ /// addRelocation - Whenever a relocatable address is needed, it should be
+ /// noted with this interface.
+ void addRelocation(const MachineRelocation& relocation) {
+ Relocations.push_back(relocation);
+ }
+};
+
+} // end namespace llvm
+
+#endif
+
diff --git a/include/llvm/Target/TargetELFWriterInfo.h b/include/llvm/Target/TargetELFWriterInfo.h
index 6037826555..f7e3392577 100644
--- a/include/llvm/Target/TargetELFWriterInfo.h
+++ b/include/llvm/Target/TargetELFWriterInfo.h
@@ -29,6 +29,7 @@ namespace llvm {
// e_machine member of the ELF header.
unsigned short EMachine;
TargetMachine &TM;
+ bool is64Bit, isLittleEndian;
public:
// Machine architectures
@@ -49,10 +50,35 @@ namespace llvm {
EM_X86_64 = 62 // AMD64
};
+ // ELF File classes
+ enum {
+ ELFCLASS32 = 1, // 32-bit object file
+ ELFCLASS64 = 2 // 64-bit object file
+ };
+
+ // ELF Endianess
+ enum {
+ ELFDATA2LSB = 1, // Little-endian object file
+ ELFDATA2MSB = 2 // Big-endian object file
+ };
+
explicit TargetELFWriterInfo(TargetMachine &tm);
virtual ~TargetELFWriterInfo();
unsigned short getEMachine() const { return EMachine; }
+ unsigned getEFlags() const { return 0; }
+ unsigned getEIClass() const { return is64Bit ? ELFCLASS64 : ELFCLASS32; }
+ unsigned getEIData() const {
+ return isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
+ }
+
+ /// ELF Header and ELF Section Header Info
+ unsigned getHdrSize() const { return is64Bit ? 64 : 52; }
+ unsigned getSHdrSize() const { return is64Bit ? 64 : 40; }
+
+ /// Symbol Table Info
+ unsigned getSymTabEntrySize() const { return is64Bit ? 24 : 16; }
+ unsigned getSymTabAlignment() const { return is64Bit ? 8 : 4; }
/// getFunctionAlignment - Returns the alignment for function 'F', targets
/// with different alignment constraints should overload this method
diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h
index 79c6c8cdaf..796bc2c3b2 100644
--- a/lib/CodeGen/ELF.h
+++ b/lib/CodeGen/ELF.h
@@ -10,11 +10,10 @@
// This header contains common, non-processor-specific data structures and
// constants for the ELF file format.
//
-// The details of the ELF32 bits in this file are largely based on
-// the Tool Interface Standard (TIS) Executable and Linking Format
-// (ELF) Specification Version 1.2, May 1995. The ELF64 stuff is not
-// standardized, as far as I can tell. It was largely based on information
-// I found in OpenBSD header files.
+// The details of the ELF32 bits in this file are largely based on the Tool
+// Interface Standard (TIS) Executable and Linking Format (ELF) Specification
+// Version 1.2, May 1995. The ELF64 is based on HP/Intel definition of the
+// ELF-64 object file format document, Version 1.5 Draft 2 May 27, 1998
//
//===----------------------------------------------------------------------===//
@@ -22,11 +21,13 @@
#define CODEGEN_ELF_H
#include "llvm/GlobalVariable.h"
+#include "llvm/CodeGen/BinaryObject.h"
#include "llvm/CodeGen/MachineRelocation.h"
#include "llvm/Support/DataTypes.h"
#include <cstring>
namespace llvm {
+ class BinaryObject;
// Identification Indexes
enum {
@@ -47,62 +48,17 @@ namespace llvm {
ET_HIPROC = 0xffff // Processor-specific
};
- // Object file classes.
- enum {
- ELFCLASS32 = 1, // 32-bit object file
- ELFCLASS64 = 2 // 64-bit object file
- };
-
- // Object file byte orderings.
- enum {
- ELFDATA2LSB = 1, // Little-endian object file
- ELFDATA2MSB = 2 // Big-endian object file
- };
-
// Versioning
enum {
EV_NONE = 0,
EV_CURRENT = 1
};
- struct ELFHeader {
- // e_machine - This field is the target specific value to emit as the
- // e_machine member of the ELF header.
- unsigned short e_machine;
-
- // e_flags - The machine flags for the target. This defaults to zero.
- unsigned e_flags;
-
- // e_size - Holds the ELF header's size in bytes
- unsigned e_ehsize;
-
- // Endianess and ELF Class (64 or 32 bits)
- unsigned ByteOrder;
- unsigned ElfClass;
-
- unsigned getByteOrder() const { return ByteOrder; }
- unsigned getElfClass() const { return ElfClass; }
- unsigned getSize() const { return e_ehsize; }
- unsigned getMachine() const { return e_machine; }
- unsigned getFlags() const { return e_flags; }
-
- ELFHeader(unsigned short machine, unsigned flags,
- bool is64Bit, bool isLittleEndian)
- : e_machine(machine), e_flags(flags) {
- ElfClass = is64Bit ? ELFCLASS64 : ELFCLASS32;
- ByteOrder = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
- e_ehsize = is64Bit ? 64 : 52;
- }
- };
-
/// ELFSection - This struct contains information about each section that is
/// emitted to the file. This is eventually turned into the section header
/// table at the end of the file.
- struct ELFSection {
-
- // Name of the section
- std::string Name;
-
+ class ELFSection : public BinaryObject {
+ public:
// ELF specific fields
unsigned NameIdx; // sh_name - .shstrtab idx of name, once emitted.
unsigned Type; // sh_type - Section contents & semantics
@@ -143,8 +99,8 @@ namespace llvm {
SHT_REL = 9, // Relocation entries; no explicit addends.
SHT_SHLIB = 10, // Reserved.
SHT_DYNSYM = 11, // Symbol table.
- SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type.
- SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type.
+ SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type.
+ SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type.
SHT_LOUSER = 0x80000000, // Lowest type reserved for applications.
SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
};
@@ -163,22 +119,9 @@ namespace llvm {
/// SectionIdx - The number of the section in the Section Table.
unsigned short SectionIdx;
- /// SectionData - The actual data for this section which we are building
- /// up for emission to the file.
- std::vector<unsigned char> SectionData;
-
- /// Relocations - The relocations that we have encountered so far in this
- /// section that we will need to convert to Elf relocation entries when
- /// the file is written.
- std::vector<MachineRelocation> Relocations;
-
- /// Section Header Size
- static unsigned getSectionHdrSize(bool is64Bit)
- { return is64Bit ? 64 : 40; }
-
- ELFSection(const std::string &name)
- : Name(name), Type(0), Flags(0), Addr(0), Offset(0), Size(0),
- Link(0), Info(0), Align(0), EntSize(0) {}
+ ELFSection(const std::string &name, bool isLittleEndian, bool is64Bit)
+ : BinaryObject(name, isLittleEndian, is64Bit), Type(0), Flags(0), Addr(0),
+ Offset(0), Size(0), Link(0), Info(0), Align(0), EntSize(0) {}
};
/// ELFSym - This struct contains information about each symbol that is
@@ -245,9 +188,6 @@ namespace llvm {
assert(X == (X & 0xF) && "Type value out of range!");
Info = (Info & 0xF0) | X;
}
-
- static unsigned getEntrySize(bool is64Bit)
- { return is64Bit ? 24 : 16; }
};
} // end namespace llvm
diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp
index 780ec57191..ca683969e4 100644
--- a/lib/CodeGen/ELFCodeEmitter.cpp
+++ b/lib/CodeGen/ELFCodeEmitter.cpp
@@ -13,6 +13,7 @@
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
+#include "llvm/CodeGen/BinaryObject.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/Target/TargetMachine.h"
@@ -33,9 +34,10 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) {
DOUT << "processing function: " << MF.getFunction()->getName() << "\n";
// FIXME: better memory management, this will be replaced by BinaryObjects
- ES->SectionData.reserve(4096);
- BufferBegin = &ES->SectionData[0];
- BufferEnd = BufferBegin + ES->SectionData.capacity();
+ BinaryData &BD = ES->getData();
+ BD.reserve(4096);
+ BufferBegin = &BD[0];
+ BufferEnd = BufferBegin + BD.capacity();
// Align the output buffer with function alignment, and
// upgrade the section alignment if required
@@ -100,7 +102,7 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
FnSym.Value = FnStartPtr-BufferBegin;
// Finally, add it to the symtab.
- EW.SymbolTable.push_back(FnSym);
+ EW.SymbolList.push_back(FnSym);
// Relocations
// -----------
@@ -121,7 +123,7 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
} else {
assert(0 && "Unhandled relocation type");
}
- ES->Relocations.push_back(MR);
+ ES->addRelocation(MR);
}
Relocations.clear();
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index 8dd4aab3f0..aeccefbd3e 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -37,6 +37,7 @@
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/CodeGen/BinaryObject.h"
#include "llvm/CodeGen/FileWriters.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -66,22 +67,23 @@ MachineCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM,
//===----------------------------------------------------------------------===//
ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
- : MachineFunctionPass(&ID), O(o), TM(tm), ElfHdr() {
- is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
- isLittleEndian = TM.getTargetData()->isLittleEndian();
+ : MachineFunctionPass(&ID), O(o), TM(tm),
+ is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64),
+ isLittleEndian(TM.getTargetData()->isLittleEndian()),
+ ElfHdr(isLittleEndian, is64Bit) {
- ElfHdr = new ELFHeader(TM.getELFWriterInfo()->getEMachine(), 0,
- is64Bit, isLittleEndian);
TAI = TM.getTargetAsmInfo();
+ TEW = TM.getELFWriterInfo();
// Create the machine code emitter object for this target.
MCE = new ELFCodeEmitter(*this);
+
+ // Inital number of sections
NumSections = 0;
}
ELFWriter::~ELFWriter() {
delete MCE;
- delete ElfHdr;
}
// doInitialization - Emit the file header and all of the global variables for
@@ -89,10 +91,6 @@ ELFWriter::~ELFWriter() {
bool ELFWriter::doInitialization(Module &M) {
Mang = new Mangler(M);
- // Local alias to shortenify coming code.
- std::vector<unsigned char> &FH = FileHeader;
- OutputBuffer FHOut(FH, is64Bit, isLittleEndian);
-
// ELF Header
// ----------
// Fields e_shnum e_shstrndx are only known after all section have
@@ -101,49 +99,48 @@ bool ELFWriter::doInitialization(Module &M) {
//
// Note
// ----
- // FHOut.outaddr method behaves differently for ELF32 and ELF64 writing
+ // emitWord method behaves differently for ELF32 and ELF64, writing
// 4 bytes in the former and 8 in the last for *_off and *_addr elf types
- FHOut.outbyte(0x7f); // e_ident[EI_MAG0]
- FHOut.outbyte('E'); // e_ident[EI_MAG1]
- FHOut.outbyte('L'); // e_ident[EI_MAG2]
- FHOut.outbyte('F'); // e_ident[EI_MAG3]
-
- FHOut.outbyte(ElfHdr->getElfClass()); // e_ident[EI_CLASS]
- FHOut.outbyte(ElfHdr->getByteOrder()); // e_ident[EI_DATA]
- FHOut.outbyte(EV_CURRENT); // e_ident[EI_VERSION]
-
- FH.resize(16); // e_ident[EI_NIDENT-EI_PAD]
-
- FHOut.outhalf(ET_REL); // e_type
- FHOut.outhalf(ElfHdr->getMachine()); // e_machine = target
- FHOut.outword(EV_CURRENT); // e_version
- FHOut.outaddr(0); // e_entry = 0, no entry point in .o file
- FHOut.outaddr(0); // e_phoff = 0, no program header for .o
- ELFHdr_e_shoff_Offset = FH.size();
- FHOut.outaddr(0); // e_shoff = sec hdr table off in bytes
- FHOut.outword(ElfHdr->getFlags()); // e_flags = whatever the target wants
- FHOut.outhalf(ElfHdr->getSize()); // e_ehsize = ELF header size
- FHOut.outhalf(0); // e_phentsize = prog header entry size
- FHOut.outhalf(0); // e_phnum = # prog header entries = 0
+ ElfHdr.emitByte(0x7f); // e_ident[EI_MAG0]
+ ElfHdr.emitByte('E'); // e_ident[EI_MAG1]
+ ElfHdr.emitByte('L'); // e_ident[EI_MAG2]
+ ElfHdr.emitByte('F'); // e_ident[EI_MAG3]
+
+ ElfHdr.emitByte(TEW->getEIClass()); // e_ident[EI_CLASS]
+ ElfHdr.emitByte(TEW->getEIData()); // e_ident[EI_DATA]
+ ElfHdr.emitByte(EV_CURRENT); // e_ident[EI_VERSION]
+ ElfHdr.emitAlignment(16); // e_ident[EI_NIDENT-EI_PAD]
+
+ ElfHdr.emitWord16(ET_REL); // e_type
+ ElfHdr.emitWord16(TEW->getEMachine()); // e_machine = target
+ ElfHdr.emitWord32(EV_CURRENT); // e_version
+ ElfHdr.emitWord(0); // e_entry, no entry point in .o file
+ ElfHdr.emitWord(0); // e_phoff, no program header for .o
+ ELFHdr_e_shoff_Offset = ElfHdr.size();
+ ElfHdr.emitWord(0); // e_shoff = sec hdr table off in bytes
+ ElfHdr.emitWord32(TEW->getEFlags()); // e_flags = whatever the target wants
+ ElfHdr.emitWord16(TEW->getHdrSize()); // e_ehsize = ELF header size
+ ElfHdr.emitWord16(0); // e_phentsize = prog header entry size
+ ElfHdr.emitWord16(0); // e_phnum = # prog header entries = 0
// e_shentsize = Section header entry size
- FHOut.outhalf(ELFSection::getSectionHdrSize(is64Bit));
+ ElfHdr.emitWord16(TEW->getSHdrSize());
// e_shnum = # of section header ents
- ELFHdr_e_shnum_Offset = FH.size();
- FHOut.outhalf(0);
+ ELFHdr_e_shnum_Offset = ElfHdr.size();
+ ElfHdr.emitWord16(0); // Placeholder
// e_shstrndx = Section # of '.shstrtab'
- ELFHdr_e_shstrndx_Offset = FH.size();
- FHOut.outhalf(0);
+ ELFHdr_e_shstrndx_Offset = ElfHdr.size();
+ ElfHdr.emitWord16(0); // Placeholder
// Add the null section, which is required to be first in the file.
getSection("", ELFSection::SHT_NULL, 0);
- // Start up the symbol table. The first entry in the symtab is the null
+ // Start up the symbol table. The first entry in the symtab is the null
// entry.
- SymbolTable.push_back(ELFSym(0));
+ SymbolList.push_back(ELFSym(0));
return false;
}
@@ -162,7 +159,7 @@ void ELFWriter::EmitGlobal(GlobalVariable *GV) {
ExternalSym.SetBind(ELFSym::STB_GLOBAL);
ExternalSym.SetType(ELFSym::STT_NOTYPE);
ExternalSym.SectionIdx = ELFSection::SHN_UNDEF;
- SymbolTable.push_back(ExternalSym);
+ SymbolList.push_back(ExternalSym);
return;
}
@@ -185,7 +182,7 @@ void ELFWriter::EmitGlobal(GlobalVariable *GV) {
CommonSym.SetBind(ELFSym::STB_GLOBAL);
CommonSym.SetType(ELFSym::STT_OBJECT);
CommonSym.SectionIdx = ELFSection::SHN_COMMON;
- SymbolTable.push_back(CommonSym);
+ SymbolList.push_back(CommonSym);
getSection(S->getName(), ELFSection::SHT_NOBITS,
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC, 1);
return;
@@ -222,7 +219,7 @@ void ELFWriter::EmitGlobal(GlobalVariable *GV) {
// Set the idx of the .bss section
BSSSym.SectionIdx = BSSSection.SectionIdx;
if (!GV->hasPrivateLinkage())
- SymbolTable.push_back(BSSSym);
+ SymbolList.push_back(BSSSym);
// Reserve space in the .bss section for this symbol.
BSSSection.Size += Size;
@@ -262,21 +259,18 @@ void ELFWriter::EmitGlobal(GlobalVariable *GV) {
if (Align > ElfS.Align)
ElfS.Align = Align;
- DataBuffer &GblCstBuf = ElfS.SectionData;
- OutputBuffer GblCstTab(GblCstBuf, is64Bit, isLittleEndian);
-
// S.Value should contain the symbol index inside the section,
// and all symbols should start on their required alignment boundary
- GblSym.Value = (GblCstBuf.size() + (Align-1)) & (-Align);
- GblCstBuf.insert(GblCstBuf.end(), GblSym.Value-GblCstBuf.size(), 0);
+ GblSym.Value = (ElfS.size() + (Align-1)) & (-Align);
+ ElfS.emitAlignment(Align);
// Emit the constant symbol to its section
- EmitGlobalConstant(CV, GblCstTab);
- SymbolTable.push_back(GblSym);
+ EmitGlobalConstant(CV, ElfS);
+ SymbolList.push_back(GblSym);
}
void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
- OutputBuffer &GblCstTab) {
+ ELFSection &GblS) {
// Print the fields in successive locations. Pad to align if needed!
const TargetData *TD = TM.getTargetData();
@@ -293,40 +287,40 @@ void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
sizeSoFar += fieldSize + padSize;
// Now print the actual field value.
- EmitGlobalConstant(field, GblCstTab);
+ EmitGlobalConstant(field, GblS);
// Insert padding - this may include padding to increase the size of the
// current field up to the ABI size (if the struct is not packed) as well
// as padding to ensure that the next field starts at the right offset.
for (unsigned p=0; p < padSize; p++)
- GblCstTab.outbyte(0);
+ GblS.emitByte(0);
}
assert(sizeSoFar == cvsLayout->getSizeInBytes() &&
"Layout of constant struct may be incorrect!");
}
-void ELFWriter::EmitGlobalConstant(const Constant *CV, OutputBuffer &GblCstTab) {
+void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
const TargetData *TD = TM.getTargetData();
unsigned Size = TD->getTypeAllocSize(CV->getType());
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
if (CVA->isString()) {
std::string GblStr = CVA->getAsString();
- GblCstTab.outstring(GblStr, GblStr.length());
+ GblS.emitString(GblStr);
} else { // Not a string. Print the values in successive locations
for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
- EmitGlobalConstant(CVA->getOperand(i), GblCstTab);
+ EmitGlobalConstant(CVA->getOperand(i), GblS);
}
return;
} else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
- EmitGlobalConstantStruct(CVS, GblCstTab);
+ EmitGlobalConstantStruct(CVS, GblS);
return;
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
uint64_t Val = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
if (CFP->getType() == Type::DoubleTy)
- GblCstTab.outxword(Val);
+ GblS.emitWord64(Val);
else if (CFP->getType() == Type::FloatTy)
- GblCstTab.outword(Val);
+ GblS.emitWord32(Val);
else if (CFP->getType() == Type::X86_FP80Ty) {
assert(0 && "X86_FP80Ty global emission not implemented");
} else if (CFP->getType() == Type::PPC_FP128Ty)
@@ -334,16 +328,16 @@ void ELFWriter::EmitGlobalConstant(const Constant *CV, OutputBuffer &GblCstTab)
return;
} else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
if (Size == 4)
- GblCstTab.outword(CI->getZExtValue());
+ GblS.emitWord32(CI->getZExtValue());
else if (Size == 8)
- GblCstTab.outxword(CI->getZExtValue());
+ GblS.emitWord64(CI->getZExtValue());
else
assert(0 && "LargeInt global emission not implemented");
return;
} else if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) {
const VectorType *PTy = CP->getType();
for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I)
- EmitGlobalConstant(CP->getOperand(I), GblCstTab);
+ EmitGlobalConstant(CP->getOperand(I), GblS);
return;
}
assert(0 && "unknown global constant");
@@ -358,26 +352,30 @@ bool ELFWriter::runOnMachineFunction(MachineFunction &MF) {
/// doFinalization - Now that the module has been completely processed, emit
/// the ELF file to 'O'.
bool ELFWriter::doFinalization(Module &M) {
- /// FIXME: This should be removed when moving to BinaryObjects. Since the
- /// current ELFCodeEmiter uses CurrBuff, ... it doesn't update S.SectionData
+ /// FIXME: This should be removed when moving to ObjectCodeEmiter. Since the
+ /// current ELFCodeEmiter uses CurrBuff, ... it doesn't update S.Data
/// vector size for .text sections, so this is a quick dirty fix
ELFSection &TS = getTextSection();
- if (TS.Size)
+ if (TS.Size) {
+ BinaryData &BD = TS.getData();
for (unsigned e=0; e<TS.Size; ++e)
- TS.SectionData.push_back(TS.SectionData[e]);
+ BD.push_back(BD[e]);
+ }
- // Get .data and .bss section, they should always be present in the binary
+ // Emit .data section placeholder
getDataSection();
+
+ // Emit .bss section placeholder
getBSSSection();
- // build data, bss and "common" sections.
+ // Build and emit data, bss and "common" sections.
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I)
EmitGlobal(I);
// Emit non-executable stack note
if (TAI->getNonexecutableStackDirective())
- getSection(".note.GNU-stack", ELFSection::SHT_PROGBITS, 0, 1);
+ getNonExecStackSection();
// Emit the symbol table now, if non-empty.
EmitSymbolTable();
@@ -385,10 +383,10 @@ bool ELFWriter::doFinalization(Module &M) {
// Emit the relocation sections.
EmitRelocations();
- // Emit the string table for the sections in the ELF file.
+ // Emit the sections string table.
EmitSectionTableStringTable();
- // Emit the sections to the .o file, and emit the section table for the file.
+ // Dump the sections and section table to the .o file.
OutputSectionsAndSectionTable();
// We are done with the abstract symbols.
@@ -404,106 +402,97 @@ bool ELFWriter::doFinalization(Module &M) {
void ELFWriter::EmitRelocations() {
}
-/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymTabOut'
-void ELFWriter::EmitSymbol(OutputBuffer &SymTabOut, ELFSym &Sym) {
+/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable'
+void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) {
if (is64Bit) {
- SymTabOut.outword(Sym.NameIdx);
- SymTabOut.outbyte(Sym.Info);
- SymTabOut.outbyte(Sym.Other);
- SymTabOut.outhalf(Sym.SectionIdx);
- SymTabOut.outaddr64(Sym.Value);
- SymTabOut.outxword(Sym.Size);
+ SymbolTable.emitWord32(Sym.NameIdx);
+ SymbolTable.emitByte(Sym.Info);
+ SymbolTable.emitByte(Sym.Other);
+ SymbolTable.emitWord16(Sym.SectionIdx);
+ SymbolTable.emitWord64(Sym.Value);
+ SymbolTable.emitWord64(Sym.Size);
} else {
- SymTabOut.outword(Sym.NameIdx);
- SymTabOut.outaddr32(Sym.Value);
- SymTabOut.outword(Sym.Size);
- SymTabOut.outbyte(Sym.Info);
- SymTabOut.outbyte(Sym.Other);
- SymTabOut.outhalf(Sym.SectionIdx);
+ SymbolTable.emitWord32(Sym.NameIdx);
+ SymbolTable.emitWord32(Sym.Value);
+ SymbolTable.emitWord32(Sym.Size);
+ SymbolTable.emitByte(Sym.Info);
+ SymbolTable.emitByte(Sym.Other);
+ SymbolTable.emitWord16(Sym.SectionIdx);
}
}
-/// EmitSectionHeader - Write section 'Section' header in 'TableOut'
+/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab'
/// Section Header Table
-void ELFWriter::EmitSectionHeader(OutputBuffer &TableOut, const ELFSection &S) {
- TableOut.outword(S.NameIdx);
- TableOut.outword(S.Type);
+void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
+ const ELFSection &SHdr) {
+ SHdrTab.emitWord32(SHdr.NameIdx);
+ SHdrTab.emitWord32(SHdr.Type);
if (is64Bit) {
- TableOut.outxword(S.Flags);
- TableOut.outaddr(S.Addr);
- TableOut.outaddr(S.Offset);
- TableOut.outxword(S.Size);
- TableOut.outword(S.Link);
- TableOut.outword(S.Info);
- TableOut.outxword(S.Align);
- TableOut.outxword(S.EntSize);
+ SHdrTab.emitWord64(SHdr.Flags);
+ SHdrTab.emitWord(SHdr.Addr);
+ SHdrTab.emitWord(SHdr.Offset);
+ SHdrTab.emitWord64(SHdr.Size);
+ SHdrTab.emitWord32(SHdr.Link);
+ SHdrTab.emitWord32(SHdr.Info);
+ SHdrTab.emitWord64(SHdr.Align);
+ SHdrTab.emitWord64(SHdr.EntSize);
} else {
- TableOut.outword(S.Flags);
- TableOut.outaddr(S.Addr);
- TableOut.outaddr(S.Offset);
- TableOut.outword(S.Size);
- TableOut.outword(S.Link);
- TableOut.outword(S.Info);
- TableOut.outword(S.Align);
- TableOut.outword(S.EntSize);
+ SHdrTab.emitWord32(SHdr.Flags);
+ SHdrTab.emitWord(SHdr.Addr);
+ SHdrTab.emitWord(SHdr.Offset);
+ SHdrTab.emitWord32(SHdr.Size);
+ SHdrTab.emitWord32(SHdr.Link);
+ SHdrTab.emitWord32(SHdr.Info);
+ SHdrTab.emitWord32(SHdr.Align);
+ SHdrTab.emitWord32(SHdr.EntSize);
}
}
/// EmitSymbolTable - If the current symbol table is non-empty, emit the string
/// table for it and then the symbol table itself.
void ELFWriter::EmitSymbolTable() {
- if (SymbolTable.size() == 1) return; // Only the null entry.
+ if (SymbolList.size() == 1) return; // Only the null entry.
// FIXME: compact all local symbols to the start of the symtab.
unsigned FirstNonLocalSymbol = 1;
ELFSection &StrTab = getStringTableSection();
- DataBuffer &StrTabBuf = StrTab.SectionData;
- OutputBuffer StrTabOut(StrTabBuf, is64Bit, isLittleEndian);
// Set the zero'th symbol to a null byte, as required.
- StrTabOut.outbyte(0);
+ StrTab.emitByte(0);
unsigned Index = 1;
- for (unsigned i = 1, e = SymbolTable.size(); i != e; ++i) {
+ for (unsigned i = 1, e = SymbolList.size(); i != e; ++i) {
// Use the name mangler to uniquify the LLVM symbol.
- std::string Name = Mang->getValueName(SymbolTable[i].GV);
+ std::string Name = Mang->getValueName(SymbolList[i].GV);
if (Name.empty()) {
- SymbolTable[i].NameIdx = 0;
+ SymbolList[i].NameIdx = 0;
} else {
- SymbolTable[i].NameIdx = Index;
-
- // Add the name to the output buffer, including the null terminator.
- StrTabBuf.insert(StrTabBuf.end(), Name.begin(), Name.end());
-
- // Add a null terminator.
- StrTabBuf.push_back(0);
+ SymbolList[i].NameIdx = Index;
+ StrTab.emitString(Name);
// Keep track of the number of bytes emitted to this section.
Index += Name.size()+1;
}
}
- assert(Index == StrTabBuf.size());
+ assert(Index == StrTab.size());
StrTab.Size = Index;
// Now that we have emitted the string table and know the offset into the
// string table of each symbol, emit the symbol table itself.
ELFSection &SymTab = getSymbolTableSection();
- SymTab.Align = is64Bit ? 8 : 4;
- SymTab.Link = StrTab.SectionIdx; // Section Index of .strtab.
- SymTab.Info = FirstNonLocalSymbol; // First non-STB_LOCAL symbol.
+ SymTab.Align = TEW->getSymTabAlignment();
+ SymTab.Link = StrTab.SectionIdx; // Section Index of .strtab.
+ SymTab.Info = FirstNonLocalSymbol; // First non-STB_LOCAL symbol.
// Size of each symtab entry.
- SymTab.EntSize = ELFSym::getEntrySize(is64Bit);
-
- DataBuffer &SymTabBuf = SymTab.SectionData;
- OutputBuffer SymTabOut(SymTabBuf, is64Bit, isLittleEndian);
+ SymTab.EntSize = TEW->getSymTabEntrySize();
- for (unsigned i = 0, e = SymbolTable.size(); i != e; ++i)
- EmitSymbol(SymTabOut, SymbolTable[i]);
+ for (unsigned i = 0, e = SymbolList.size(); i != e; ++i)
+ EmitSymbol(SymTab, SymbolList[i]);
- SymTab.Size = SymTabBuf.size();
+ SymTab.Size = SymTab.size();
}
/// EmitSectionTableStringTable - This method adds and emits a section for the
@@ -515,32 +504,25 @@ void ELFWriter::EmitSectionTableStringTable() {
// Now that we know which section number is the .shstrtab section, update the
// e_shstrndx entry in the ELF header.
- OutputBuffer FHOut(FileHeader, is64Bit, isLittleEndian);
- FHOut.fixhalf(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset);
+ ElfHdr.fixWord16(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset);
// Set the NameIdx of each section in the string table and emit the bytes for
// the string table.
unsigned Index = 0;
- DataBuffer &Buf = SHStrTab.SectionData;
for (std::list<ELFSection>::iterator I = SectionList.begin(),
E = SectionList.end(); I != E; ++I) {
// Set the index into the table. Note if we have lots of entries with
// common suffixes, we could memoize them here if we cared.
I->NameIdx = Index;
-
- // Add the name to the output buffer, including the null terminator.
- Buf.insert(Buf.end(), I->Name.begin(), I->Name.end());
-
- // Add a null terminator.
- Buf.push_back(0);
+ SHStrTab.emitString(I->getName());
// Keep track of the number of bytes emitted to this section.
- Index += I->Name.size()+1;
+ Index += I->getName().size()+1;
}
// Set the size of .shstrtab now that we know what it is.
- assert(Index == Buf.size());
+ assert(Index == SHStrTab.size());
SHStrTab.Size = Index;
}
@@ -549,7 +531,7 @@ void ELFWriter::EmitSectionTableStringTable() {
/// SectionTable.
void ELFWriter::OutputSectionsAndSectionTable() {
// Pass #1: Compute the file offset for each section.
- size_t FileOff = FileHeader.size(); // File header first.
+ size_t FileOff = ElfHdr.size(); // File header first.
// Adjust alignment of all section if needed.
for (std::list<ELFSection>::iterator I = SectionList.begin(),
@@ -559,14 +541,14 @@ void ELFWriter::OutputSectionsAndSectionTable() {
if (!I->SectionIdx)
continue;
- if (!I->SectionData.size()) {
+ if (!I->size()) {
I->Offset = FileOff;
continue;
}
// Update Section size
if (!I->Size)
- I->Size = I->SectionData.size();
+ I->Size = I->size();
// Align FileOff to whatever the alignment restrictions of the section are.
if (I->Align)
@@ -582,43 +564,40 @@ void ELFWriter::OutputSectionsAndSectionTable() {
// Now that we know where all of the sections will be emitted, set the e_shnum
// entry in the ELF header.
- OutputBuffer FHOut(FileHeader, is64Bit, isLittleEndian);
- FHOut.fixhalf(NumSections, ELFHdr_e_shnum_Offset);
+ ElfHdr.fixWord16(NumSections, ELFHdr_e_shnum_Offset);
// Now that we know the offset in the file of the section table, update the
// e_shoff address in the ELF header.
- FHOut.fixaddr(FileOff, ELFHdr_e_shoff_Offset);
+ ElfHdr.fixWord(FileOff, ELFHdr_e_shoff_Offset);
// Now that we know all of the data in the file header, emit it and all of the
// sections!
- O.write((char*)&FileHeader[0], FileHeader.size());
- FileOff = FileHeader.size();
- DataBuffer().swap(FileHeader);
+ O.write((char *)&ElfHdr.getData()[0], ElfHdr.size());
+ FileOff = ElfHdr.size();
- DataBuffer Table;
- OutputBuffer TableOut(Table, is64Bit, isLittleEndian);
+ // Section Header Table blob
+ BinaryObject SHdrTable(isLittleEndian, is64Bit);
- // Emit all of the section data and build the section table itself.
+ // Emit all of sections to the file and build the section header table.
while (!SectionList.empty()) {
- const ELFSection &S = *SectionList.begin();
- DOUT << "SectionIdx: " << S.SectionIdx << ", Name: " << S.Name
+ ELFSection &S = *SectionList.begin();
+ DOUT << "SectionIdx: " << S.SectionIdx << ", Name: " << S.getName()
<< ", Size: " << S.Size << ", Offset: " << S.Offset
- << ", SectionData Size: " << S.SectionData.size() << "\n";
-
+ << ", SectionData Size: " << S.size() << "\n";
// Align FileOff to whatever the alignment restrictions of the section are.
if (S.Align) {
for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1);
- FileOff != NewFileOff; ++FileOff)
+ FileOff != NewFileOff; ++FileOff)
O << (char)0xAB;
}
- if (S.SectionData.size()) {
- O.write((char*)&S.SectionData[0], S.Size);
+ if (S.size()) {
+ O.write((char *)&S.getData()[0], S.Size);
FileOff += S.Size;
}
- EmitSectionHeader(TableOut, S);
+ EmitSectionHeader(SHdrTable, S);
SectionList.pop_front();
}
@@ -628,5 +607,5 @@ void ELFWriter::OutputSectionsAndSectionTable() {
O << (char)0xAB;
// Emit the section table itself.
- O.write((char*)&Table[0], Table.size());
+ O.write((char *)&SHdrTable.getData()[0], SHdrTable.size());
}
diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h
index 04918f7acb..8a380f0340 100644
--- a/lib/CodeGen/ELFWriter.h
+++ b/lib/CodeGen/ELFWriter.h
@@ -24,6 +24,7 @@
#include <map>
namespace llvm {
+ class BinaryObject;
class ConstantStruct;
class ELFCodeEmitter;
class GlobalVariable;
@@ -56,6 +57,9 @@ namespace llvm {
/// Target machine description.
TargetMachine &TM;
+ /// Target Elf Writer description.
+ const TargetELFWriterInfo *TEW;
+
/// Mang - The object used to perform name mangling for this module.
Mangler *Mang;
@@ -85,13 +89,8 @@ namespace llvm {
bool doFinalization(Module &M);
private:
- // The buffer we accumulate the file header into. Note that this should be
- // changed into something much more efficient later (and the bitcode writer
- // as well!).
- DataBuffer FileHeader;
-
- /// ElfHdr - Hold information about the ELF Header
- ELFHeader *ElfHdr;
+ // Blob containing the Elf header
+ BinaryObject ElfHdr;
/// SectionList - This is the list of sections that we have emitted to the
/// file. Once the file has been completely built, the section header table
@@ -110,7 +109,7 @@ namespace llvm {
ELFSection *&SN = SectionLookup[Name];
if (SN) return *SN;
- SectionList.push_back(Name);
+ SectionList.push_back(ELFSection(Name, isLittleEndian, is64Bit));
SN = &SectionList.back();
SN->SectionIdx = NumSections++;
SN->Type = Type;
@@ -125,6 +124,10 @@ namespace llvm {
ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
}
+ ELFSection &getNonExecStackSection() {
+ return getSection(".note.GNU-stack", ELFSection::SHT_PROGBITS, 0, 1);
+ }
+
ELFSection &getSymbolTableSection() {
return getSection(".symtab", ELFSection::SHT_SYMTAB, 0);
}
@@ -143,14 +146,14 @@ namespace llvm {
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
}
- /// SymbolTable - This is the list of symbols we have emitted to the file.
+ /// SymbolList - This is the list of symbols we have emitted to the file.
/// This actually gets rearranged before emission to the file (to put the
/// local symbols first in the list).
- std::vector<ELFSym> SymbolTable;
+ std::vector<ELFSym> SymbolList;
- /// PendingSyms - This is a list of externally defined symbols that we have
- /// been asked to emit, but have not seen a reference to. When a reference
- /// is seen, the symbol will move from this list to the SymbolTable.
+ /// PendingGlobals - List of externally defined symbols that we have been
+ /// asked to emit, but have not seen a reference to. When a reference
+ /// is seen, the symbol will move from this list to the SymbolList.
SetVector<GlobalValue*> PendingGlobals;
// As we complete the ELF file, we need to update fields in the ELF header
@@ -160,15 +163,16 @@ namespace llvm {
unsigned ELFHdr_e_shoff_Offset; // e_shoff in ELF header.
unsigned ELFHdr_e_shstrndx_Offset; // e_shstrndx in ELF header.
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
+
private:
void EmitGlobal(GlobalVariable *GV);
- void EmitGlobalConstant(const Constant *C, OutputBuffer &GblCstTab);
+ void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
void EmitGlobalConstantStruct(const ConstantStruct *CVS,
- OutputBuffer &GblCstTab);
+ ELFSection &GblS);
void EmitRelocations();
- void EmitSectionHeader(OutputBuffer &TableOut, const ELFSection &Section);
+ void EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr);
void EmitSectionTableStringTable();
- void EmitSymbol(OutputBuffer &SymTabOut, ELFSym &Sym);
+ void EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym);
void EmitSymbolTable();
void OutputSectionsAndSectionTable();
};
diff --git a/lib/Target/TargetELFWriterInfo.cpp b/lib/Target/TargetELFWriterInfo.cpp
index 255a22c37c..9651e65495 100644
--- a/lib/Target/TargetELFWriterInfo.cpp
+++ b/lib/Target/TargetELFWriterInfo.cpp
@@ -17,7 +17,10 @@
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
-TargetELFWriterInfo::TargetELFWriterInfo(TargetMachine &tm) : TM(tm) {}
+TargetELFWriterInfo::TargetELFWriterInfo(TargetMachine &tm) : TM(tm) {
+ is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
+ isLittleEndian = TM.getTargetData()->isLittleEndian();
+}
TargetELFWriterInfo::~TargetELFWriterInfo() {}