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
This commit is contained in:
Bruno Cardoso Lopes 2009-06-06 03:56:29 +00:00
parent 556929a84b
commit f5b0c5a1c7
6 changed files with 259 additions and 116 deletions

View File

@ -25,9 +25,23 @@ namespace llvm {
// e_machine member of the ELF header.
unsigned short EMachine;
public:
// Machine architectures
enum MachineType {
NoMachine,
EM_386 = 3
EM_NONE = 0, // No machine
EM_M32 = 1, // AT&T WE 32100
EM_SPARC = 2, // SPARC
EM_386 = 3, // Intel 386
EM_68K = 4, // Motorola 68000
EM_88K = 5, // Motorola 88000
EM_486 = 6, // Intel 486 (deprecated)
EM_860 = 7, // Intel 80860
EM_MIPS = 8, // MIPS R3000
EM_PPC = 20, // PowerPC
EM_ARM = 40, // ARM
EM_ALPHA = 41, // DEC Alpha
EM_SPARCV9 = 43, // SPARC V9
EM_X86_64 = 62 // AMD64
};
explicit TargetELFWriterInfo(MachineType machine) : EMachine(machine) {}

186
lib/CodeGen/ELF.h Normal file
View File

@ -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

View File

@ -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;

View File

@ -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) {}

View File

@ -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.
unsigned ElfClass = is64Bit ? ELFCLASS64 : ELFCLASS32;
unsigned ElfEndian = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
// 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
// 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
ELFHeader_e_shoff_Offset = FH.size();
FHOut.outaddr(0); // e_shoff
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!

View File

@ -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);