summaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-06-06 03:56:29 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2009-06-06 03:56:29 +0000
commitf5b0c5a1c735dd2a6027edcca83cddc6d755bdc2 (patch)
tree755bfc73de0021d29c7e3d686398969a636d78df /lib/CodeGen
parent556929a84bb8842cb07bebf4df67810d17be096e (diff)
downloadllvm-f5b0c5a1c735dd2a6027edcca83cddc6d755bdc2.tar.gz
llvm-f5b0c5a1c735dd2a6027edcca83cddc6d755bdc2.tar.bz2
llvm-f5b0c5a1c735dd2a6027edcca83cddc6d755bdc2.tar.xz
Remove elf specific info from ELFWriter.h to Elf.h. Code cleanup and more comments added
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72982 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/ELF.h186
-rw-r--r--lib/CodeGen/ELFCodeEmitter.cpp10
-rw-r--r--lib/CodeGen/ELFCodeEmitter.h2
-rw-r--r--lib/CodeGen/ELFWriter.cpp73
-rw-r--r--lib/CodeGen/ELFWriter.h90
5 files changed, 245 insertions, 116 deletions
diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h
new file mode 100644
index 0000000000..bf43622a6f
--- /dev/null
+++ b/lib/CodeGen/ELF.h
@@ -0,0 +1,186 @@
+//===-- lib/CodeGen/ELF.h - ELF constants and data structures ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_ELF_H
+#define CODEGEN_ELF_H
+
+#include "llvm/Support/DataTypes.h"
+#include <cstring>
+
+namespace llvm {
+ class GlobalVariable;
+
+ // Identification Indexes
+ enum {
+ EI_MAG0 = 0,
+ EI_MAG1 = 1,
+ EI_MAG2 = 2,
+ EI_MAG3 = 3
+ };
+
+ // File types
+ enum {
+ ET_NONE = 0, // No file type
+ ET_REL = 1, // Relocatable file
+ ET_EXEC = 2, // Executable file
+ ET_DYN = 3, // Shared object file
+ ET_CORE = 4, // Core file
+ ET_LOPROC = 0xff00, // Beginning of processor-specific codes
+ 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
+ };
+
+ /// 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 {
+
+ // ELF specific fields
+ std::string Name; // Name of the section.
+ unsigned NameIdx; // Index in .shstrtab of name, once emitted.
+ unsigned Type;
+ unsigned Flags;
+ uint64_t Addr;
+ unsigned Offset;
+ unsigned Size;
+ unsigned Link;
+ unsigned Info;
+ unsigned Align;
+ unsigned EntSize;
+
+ // Section Header Flags
+ enum {
+ SHF_WRITE = 1 << 0, // Writable
+ SHF_ALLOC = 1 << 1, // Mapped into the process addr space
+ SHF_EXECINSTR = 1 << 2, // Executable
+ SHF_MERGE = 1 << 4, // Might be merged if equal
+ SHF_STRINGS = 1 << 5, // Contains null-terminated strings
+ SHF_INFO_LINK = 1 << 6, // 'sh_info' contains SHT index
+ SHF_LINK_ORDER = 1 << 7, // Preserve order after combining
+ SHF_OS_NONCONFORMING = 1 << 8, // nonstandard OS support required
+ SHF_GROUP = 1 << 9, // Section is a member of a group
+ SHF_TLS = 1 << 10 // Section holds thread-local data
+ };
+
+ // Section Types
+ enum {
+ SHT_NULL = 0, // No associated section (inactive entry).
+ SHT_PROGBITS = 1, // Program-defined contents.
+ SHT_SYMTAB = 2, // Symbol table.
+ SHT_STRTAB = 3, // String table.
+ SHT_RELA = 4, // Relocation entries; explicit addends.
+ SHT_HASH = 5, // Symbol hash table.
+ SHT_DYNAMIC = 6, // Information for dynamic linking.
+ SHT_NOTE = 7, // Information about the file.
+ SHT_NOBITS = 8, // Data occupies no space in the file.
+ 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_LOUSER = 0x80000000, // Lowest type reserved for applications.
+ SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
+ };
+
+ // Special section indices.
+ enum {
+ SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless
+ SHN_LORESERVE = 0xff00, // Lowest reserved index
+ SHN_LOPROC = 0xff00, // Lowest processor-specific index
+ SHN_HIPROC = 0xff1f, // Highest processor-specific index
+ SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation
+ SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables
+ SHN_HIRESERVE = 0xffff // Highest reserved index
+ };
+
+ /// 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;
+
+ 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) {}
+ };
+
+ /// ELFSym - This struct contains information about each symbol that is
+ /// added to logical symbol table for the module. This is eventually
+ /// turned into a real symbol table in the file.
+ struct ELFSym {
+ const GlobalValue *GV; // The global value this corresponds to.
+
+ // ELF specific fields
+ unsigned NameIdx; // Index in .strtab of name, once emitted.
+ uint64_t Value;
+ unsigned Size;
+ uint8_t Info;
+ uint8_t Other;
+ unsigned short SectionIdx;
+
+ enum {
+ STB_LOCAL = 0,
+ STB_GLOBAL = 1,
+ STB_WEAK = 2
+ };
+
+ enum {
+ STT_NOTYPE = 0,
+ STT_OBJECT = 1,
+ STT_FUNC = 2,
+ STT_SECTION = 3,
+ STT_FILE = 4
+ };
+
+ ELFSym(const GlobalValue *gv) : GV(gv), Value(0),
+ Size(0), Info(0), Other(0),
+ SectionIdx(ELFSection::SHN_UNDEF) {}
+
+ void SetBind(unsigned X) {
+ assert(X == (X & 0xF) && "Bind value out of range!");
+ Info = (Info & 0x0F) | (X << 4);
+ }
+ void SetType(unsigned X) {
+ assert(X == (X & 0xF) && "Type value out of range!");
+ Info = (Info & 0xF0) | X;
+ }
+ };
+
+} // end namespace llvm
+
+#endif
diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp
index 9e8accd807..9af276b4f9 100644
--- a/lib/CodeGen/ELFCodeEmitter.cpp
+++ b/lib/CodeGen/ELFCodeEmitter.cpp
@@ -71,7 +71,7 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) {
/// finished.
bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
// Add a symbol to represent the function.
- ELFWriter::ELFSym FnSym(MF.getFunction());
+ ELFSym FnSym(MF.getFunction());
// Figure out the binding (linkage) of the symbol.
switch (MF.getFunction()->getLinkage()) {
@@ -79,23 +79,23 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
// appending linkage is illegal for functions.
assert(0 && "Unknown linkage type!");
case GlobalValue::ExternalLinkage:
- FnSym.SetBind(ELFWriter::ELFSym::STB_GLOBAL);
+ FnSym.SetBind(ELFSym::STB_GLOBAL);
break;
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
- FnSym.SetBind(ELFWriter::ELFSym::STB_WEAK);
+ FnSym.SetBind(ELFSym::STB_WEAK);
break;
case GlobalValue::PrivateLinkage:
assert (0 && "PrivateLinkage should not be in the symbol table.");
case GlobalValue::InternalLinkage:
- FnSym.SetBind(ELFWriter::ELFSym::STB_LOCAL);
+ FnSym.SetBind(ELFSym::STB_LOCAL);
break;
}
// Set the symbol type as a function
- FnSym.SetType(ELFWriter::ELFSym::STT_FUNC);
+ FnSym.SetType(ELFSym::STT_FUNC);
FnSym.SectionIdx = ES->SectionIdx;
FnSym.Size = CurBufferPtr-FnStartPtr;
diff --git a/lib/CodeGen/ELFCodeEmitter.h b/lib/CodeGen/ELFCodeEmitter.h
index 7ea4d71b09..e9ee936a48 100644
--- a/lib/CodeGen/ELFCodeEmitter.h
+++ b/lib/CodeGen/ELFCodeEmitter.h
@@ -21,7 +21,7 @@ namespace llvm {
class ELFCodeEmitter : public MachineCodeEmitter {
ELFWriter &EW;
TargetMachine &TM;
- ELFWriter::ELFSection *ES; // Section to write to.
+ ELFSection *ES; // Section to write to.
uint8_t *FnStartPtr;
public:
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {}
diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp
index be8edce08d..24f12a38d4 100644
--- a/lib/CodeGen/ELFWriter.cpp
+++ b/lib/CodeGen/ELFWriter.cpp
@@ -33,6 +33,7 @@
#include "ELFWriter.h"
#include "ELFCodeEmitter.h"
+#include "ELF.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/DerivedTypes.h"
@@ -67,7 +68,8 @@ MachineCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM,
ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
: MachineFunctionPass(&ID), O(o), TM(tm) {
- e_flags = 0; // e_flags defaults to 0, no flags.
+ e_flags = 0; // e_flags defaults to 0, no flags.
+ e_machine = TM.getELFWriterInfo()->getEMachine();
is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
isLittleEndian = TM.getTargetData()->isLittleEndian();
@@ -90,24 +92,39 @@ bool ELFWriter::doInitialization(Module &M) {
std::vector<unsigned char> &FH = FileHeader;
OutputBuffer FHOut(FH, is64Bit, isLittleEndian);
- FHOut.outbyte(0x7F); // EI_MAG0
- FHOut.outbyte('E'); // EI_MAG1
- FHOut.outbyte('L'); // EI_MAG2
- FHOut.outbyte('F'); // EI_MAG3
- FHOut.outbyte(is64Bit ? 2 : 1); // EI_CLASS
- FHOut.outbyte(isLittleEndian ? 1 : 2); // EI_DATA
- FHOut.outbyte(1); // EI_VERSION
- FH.resize(16); // EI_PAD up to 16 bytes.
-
- // This should change for shared objects.
- FHOut.outhalf(1); // e_type = ET_REL
- FHOut.outhalf(TM.getELFWriterInfo()->getEMachine()); // target-defined
- FHOut.outword(1); // e_version = 1
- FHOut.outaddr(0); // e_entry = 0 -> no entry point in .o file
- FHOut.outaddr(0); // e_phoff = 0 -> no program header for .o
-
- ELFHeader_e_shoff_Offset = FH.size();
- FHOut.outaddr(0); // e_shoff
+ unsigned ElfClass = is64Bit ? ELFCLASS64 : ELFCLASS32;
+ unsigned ElfEndian = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
+
+ // ELF Header
+ // ----------
+ // Fields e_shnum e_shstrndx are only known after all section have
+ // been emitted. They locations in the ouput buffer are recorded so
+ // to be patched up later.
+ //
+ // Note
+ // ----
+ // FHOut.outaddr 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(ElfClass); // e_ident[EI_CLASS]
+ FHOut.outbyte(ElfEndian); // 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(e_machine); // 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(e_flags); // e_flags = whatever the target wants
FHOut.outhalf(is64Bit ? 64 : 52); // e_ehsize = ELF header size
@@ -115,14 +132,16 @@ bool ELFWriter::doInitialization(Module &M) {
FHOut.outhalf(0); // e_phnum = # prog header entries = 0
FHOut.outhalf(is64Bit ? 64 : 40); // e_shentsize = sect hdr entry size
+ // e_shnum = # of section header ents
+ ELFHdr_e_shnum_Offset = FH.size();
+ FHOut.outhalf(0);
- ELFHeader_e_shnum_Offset = FH.size();
- FHOut.outhalf(0); // e_shnum = # of section header ents
- ELFHeader_e_shstrndx_Offset = FH.size();
- FHOut.outhalf(0); // e_shstrndx = Section # of '.shstrtab'
+ // e_shstrndx = Section # of '.shstrtab'
+ ELFHdr_e_shstrndx_Offset = FH.size();
+ FHOut.outhalf(0);
// Add the null section, which is required to be first in the file.
- getSection("", 0, 0);
+ getSection("", ELFSection::SHT_NULL, 0);
// Start up the symbol table. The first entry in the symtab is the null
// entry.
@@ -334,7 +353,7 @@ 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, ELFHeader_e_shstrndx_Offset);
+ FHOut.fixhalf(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset);
// Set the NameIdx of each section in the string table and emit the bytes for
// the string table.
@@ -386,11 +405,11 @@ 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, ELFHeader_e_shnum_Offset);
+ FHOut.fixhalf(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, ELFHeader_e_shoff_Offset);
+ FHOut.fixaddr(FileOff, ELFHdr_e_shoff_Offset);
// Now that we know all of the data in the file header, emit it and all of the
// sections!
diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h
index 63d692bda1..0389185f1d 100644
--- a/lib/CodeGen/ELFWriter.h
+++ b/lib/CodeGen/ELFWriter.h
@@ -15,6 +15,7 @@
#define ELFWRITER_H
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "ELF.h"
#include <list>
#include <map>
@@ -82,10 +83,8 @@ namespace llvm {
/// doInitialization - Emit the file header and all of the global variables
/// for the module to the ELF file.
bool doInitialization(Module &M);
-
bool runOnMachineFunction(MachineFunction &MF);
-
/// doFinalization - Now that the module has been completely processed, emit
/// the ELF file to 'O'.
bool doFinalization(Module &M);
@@ -96,53 +95,6 @@ namespace llvm {
// as well!).
DataBuffer FileHeader;
- /// 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 {
- std::string Name; // Name of the section.
- unsigned NameIdx; // Index in .shstrtab of name, once emitted.
- unsigned Type;
- unsigned Flags;
- uint64_t Addr;
- unsigned Offset;
- unsigned Size;
- unsigned Link;
- unsigned Info;
- unsigned Align;
- unsigned EntSize;
-
- /// 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.
- DataBuffer SectionData;
-
- enum { SHT_NULL = 0, SHT_PROGBITS = 1, SHT_SYMTAB = 2, SHT_STRTAB = 3,
- SHT_RELA = 4, SHT_HASH = 5, SHT_DYNAMIC = 6, SHT_NOTE = 7,
- SHT_NOBITS = 8, SHT_REL = 9, SHT_SHLIB = 10, SHT_DYNSYM = 11 };
- enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1, SHN_COMMON = 0xFFF2 };
- enum { // SHF - ELF Section Header Flags
- SHF_WRITE = 1 << 0, // Writable
- SHF_ALLOC = 1 << 1, // Mapped into the process addr space
- SHF_EXECINSTR = 1 << 2, // Executable
- SHF_MERGE = 1 << 4, // Might be merged if equal
- SHF_STRINGS = 1 << 5, // Contains null-terminated strings
- SHF_INFO_LINK = 1 << 6, // 'sh_info' contains SHT index
- SHF_LINK_ORDER = 1 << 7, // Preserve order after combining
- SHF_OS_NONCONFORMING = 1 << 8, // nonstandard OS support required
- SHF_GROUP = 1 << 9, // Section is a member of a group
- SHF_TLS = 1 << 10 // Section holds thread-local data
- };
-
- 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) {
- }
- };
-
/// 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
/// is constructed from this info.
@@ -165,13 +117,13 @@ namespace llvm {
SN->SectionIdx = NumSections++;
SN->Type = Type;
SN->Flags = Flags;
+ SN->Link = ELFSection::SHN_UNDEF;
return *SN;
}
ELFSection &getTextSection() {
- return getSection(".text", ELFWriter::ELFSection::SHT_PROGBITS,
- ELFWriter::ELFSection::SHF_EXECINSTR |
- ELFWriter::ELFSection::SHF_ALLOC);
+ return getSection(".text", ELFSection::SHT_PROGBITS,
+ ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
}
ELFSection &getDataSection() {
@@ -183,34 +135,6 @@ namespace llvm {
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
}
- /// ELFSym - This struct contains information about each symbol that is
- /// added to logical symbol table for the module. This is eventually
- /// turned into a real symbol table in the file.
- struct ELFSym {
- const GlobalValue *GV; // The global value this corresponds to.
- unsigned NameIdx; // Index in .strtab of name, once emitted.
- uint64_t Value;
- unsigned Size;
- unsigned char Info;
- unsigned char Other;
- unsigned short SectionIdx;
-
- enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 };
- enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3,
- STT_FILE = 4 };
- ELFSym(const GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0),
- Other(0), SectionIdx(0) {}
-
- void SetBind(unsigned X) {
- assert(X == (X & 0xF) && "Bind value out of range!");
- Info = (Info & 0x0F) | (X << 4);
- }
- void SetType(unsigned X) {
- assert(X == (X & 0xF) && "Type value out of range!");
- Info = (Info & 0xF0) | X;
- }
- };
-
/// SymbolTable - 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).
@@ -220,9 +144,9 @@ namespace llvm {
// (e.g. the location of the section table). These members keep track of
// the offset in ELFHeader of these various pieces to update and other
// locations in the file.
- unsigned ELFHeader_e_shoff_Offset; // e_shoff in ELF header.
- unsigned ELFHeader_e_shstrndx_Offset; // e_shstrndx in ELF header.
- unsigned ELFHeader_e_shnum_Offset; // e_shnum in ELF header.
+ 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);