mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-10-10 16:24:04 +00:00
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:
parent
556929a84b
commit
f5b0c5a1c7
@ -25,9 +25,23 @@ namespace llvm {
|
|||||||
// e_machine member of the ELF header.
|
// e_machine member of the ELF header.
|
||||||
unsigned short EMachine;
|
unsigned short EMachine;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Machine architectures
|
||||||
enum MachineType {
|
enum MachineType {
|
||||||
NoMachine,
|
EM_NONE = 0, // No machine
|
||||||
EM_386 = 3
|
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) {}
|
explicit TargetELFWriterInfo(MachineType machine) : EMachine(machine) {}
|
||||||
|
186
lib/CodeGen/ELF.h
Normal file
186
lib/CodeGen/ELF.h
Normal 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
|
@ -71,7 +71,7 @@ void ELFCodeEmitter::startFunction(MachineFunction &MF) {
|
|||||||
/// finished.
|
/// finished.
|
||||||
bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
||||||
// Add a symbol to represent the function.
|
// Add a symbol to represent the function.
|
||||||
ELFWriter::ELFSym FnSym(MF.getFunction());
|
ELFSym FnSym(MF.getFunction());
|
||||||
|
|
||||||
// Figure out the binding (linkage) of the symbol.
|
// Figure out the binding (linkage) of the symbol.
|
||||||
switch (MF.getFunction()->getLinkage()) {
|
switch (MF.getFunction()->getLinkage()) {
|
||||||
@ -79,23 +79,23 @@ bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
|||||||
// appending linkage is illegal for functions.
|
// appending linkage is illegal for functions.
|
||||||
assert(0 && "Unknown linkage type!");
|
assert(0 && "Unknown linkage type!");
|
||||||
case GlobalValue::ExternalLinkage:
|
case GlobalValue::ExternalLinkage:
|
||||||
FnSym.SetBind(ELFWriter::ELFSym::STB_GLOBAL);
|
FnSym.SetBind(ELFSym::STB_GLOBAL);
|
||||||
break;
|
break;
|
||||||
case GlobalValue::LinkOnceAnyLinkage:
|
case GlobalValue::LinkOnceAnyLinkage:
|
||||||
case GlobalValue::LinkOnceODRLinkage:
|
case GlobalValue::LinkOnceODRLinkage:
|
||||||
case GlobalValue::WeakAnyLinkage:
|
case GlobalValue::WeakAnyLinkage:
|
||||||
case GlobalValue::WeakODRLinkage:
|
case GlobalValue::WeakODRLinkage:
|
||||||
FnSym.SetBind(ELFWriter::ELFSym::STB_WEAK);
|
FnSym.SetBind(ELFSym::STB_WEAK);
|
||||||
break;
|
break;
|
||||||
case GlobalValue::PrivateLinkage:
|
case GlobalValue::PrivateLinkage:
|
||||||
assert (0 && "PrivateLinkage should not be in the symbol table.");
|
assert (0 && "PrivateLinkage should not be in the symbol table.");
|
||||||
case GlobalValue::InternalLinkage:
|
case GlobalValue::InternalLinkage:
|
||||||
FnSym.SetBind(ELFWriter::ELFSym::STB_LOCAL);
|
FnSym.SetBind(ELFSym::STB_LOCAL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the symbol type as a function
|
// Set the symbol type as a function
|
||||||
FnSym.SetType(ELFWriter::ELFSym::STT_FUNC);
|
FnSym.SetType(ELFSym::STT_FUNC);
|
||||||
|
|
||||||
FnSym.SectionIdx = ES->SectionIdx;
|
FnSym.SectionIdx = ES->SectionIdx;
|
||||||
FnSym.Size = CurBufferPtr-FnStartPtr;
|
FnSym.Size = CurBufferPtr-FnStartPtr;
|
||||||
|
@ -21,7 +21,7 @@ namespace llvm {
|
|||||||
class ELFCodeEmitter : public MachineCodeEmitter {
|
class ELFCodeEmitter : public MachineCodeEmitter {
|
||||||
ELFWriter &EW;
|
ELFWriter &EW;
|
||||||
TargetMachine &TM;
|
TargetMachine &TM;
|
||||||
ELFWriter::ELFSection *ES; // Section to write to.
|
ELFSection *ES; // Section to write to.
|
||||||
uint8_t *FnStartPtr;
|
uint8_t *FnStartPtr;
|
||||||
public:
|
public:
|
||||||
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {}
|
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "ELFWriter.h"
|
#include "ELFWriter.h"
|
||||||
#include "ELFCodeEmitter.h"
|
#include "ELFCodeEmitter.h"
|
||||||
|
#include "ELF.h"
|
||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/PassManager.h"
|
#include "llvm/PassManager.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
@ -67,7 +68,8 @@ MachineCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM,
|
|||||||
|
|
||||||
ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
|
ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
|
||||||
: MachineFunctionPass(&ID), O(o), TM(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;
|
is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
|
||||||
isLittleEndian = TM.getTargetData()->isLittleEndian();
|
isLittleEndian = TM.getTargetData()->isLittleEndian();
|
||||||
@ -90,24 +92,39 @@ bool ELFWriter::doInitialization(Module &M) {
|
|||||||
std::vector<unsigned char> &FH = FileHeader;
|
std::vector<unsigned char> &FH = FileHeader;
|
||||||
OutputBuffer FHOut(FH, is64Bit, isLittleEndian);
|
OutputBuffer FHOut(FH, is64Bit, isLittleEndian);
|
||||||
|
|
||||||
FHOut.outbyte(0x7F); // EI_MAG0
|
unsigned ElfClass = is64Bit ? ELFCLASS64 : ELFCLASS32;
|
||||||
FHOut.outbyte('E'); // EI_MAG1
|
unsigned ElfEndian = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
|
||||||
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.
|
// ELF Header
|
||||||
FHOut.outhalf(1); // e_type = ET_REL
|
// ----------
|
||||||
FHOut.outhalf(TM.getELFWriterInfo()->getEMachine()); // target-defined
|
// Fields e_shnum e_shstrndx are only known after all section have
|
||||||
FHOut.outword(1); // e_version = 1
|
// been emitted. They locations in the ouput buffer are recorded so
|
||||||
FHOut.outaddr(0); // e_entry = 0 -> no entry point in .o file
|
// to be patched up later.
|
||||||
FHOut.outaddr(0); // e_phoff = 0 -> no program header for .o
|
//
|
||||||
|
// 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.outbyte(0x7f); // e_ident[EI_MAG0]
|
||||||
FHOut.outaddr(0); // e_shoff
|
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.outword(e_flags); // e_flags = whatever the target wants
|
||||||
|
|
||||||
FHOut.outhalf(is64Bit ? 64 : 52); // e_ehsize = ELF header size
|
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(0); // e_phnum = # prog header entries = 0
|
||||||
FHOut.outhalf(is64Bit ? 64 : 40); // e_shentsize = sect hdr entry size
|
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();
|
// e_shstrndx = Section # of '.shstrtab'
|
||||||
FHOut.outhalf(0); // e_shnum = # of section header ents
|
ELFHdr_e_shstrndx_Offset = FH.size();
|
||||||
ELFHeader_e_shstrndx_Offset = FH.size();
|
FHOut.outhalf(0);
|
||||||
FHOut.outhalf(0); // e_shstrndx = Section # of '.shstrtab'
|
|
||||||
|
|
||||||
// Add the null section, which is required to be first in the file.
|
// 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
|
// Start up the symbol table. The first entry in the symtab is the null
|
||||||
// entry.
|
// entry.
|
||||||
@ -334,7 +353,7 @@ void ELFWriter::EmitSectionTableStringTable() {
|
|||||||
// Now that we know which section number is the .shstrtab section, update the
|
// Now that we know which section number is the .shstrtab section, update the
|
||||||
// e_shstrndx entry in the ELF header.
|
// e_shstrndx entry in the ELF header.
|
||||||
OutputBuffer FHOut(FileHeader, is64Bit, isLittleEndian);
|
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
|
// Set the NameIdx of each section in the string table and emit the bytes for
|
||||||
// the string table.
|
// 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
|
// Now that we know where all of the sections will be emitted, set the e_shnum
|
||||||
// entry in the ELF header.
|
// entry in the ELF header.
|
||||||
OutputBuffer FHOut(FileHeader, is64Bit, isLittleEndian);
|
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
|
// Now that we know the offset in the file of the section table, update the
|
||||||
// e_shoff address in the ELF header.
|
// 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
|
// Now that we know all of the data in the file header, emit it and all of the
|
||||||
// sections!
|
// sections!
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#define ELFWRITER_H
|
#define ELFWRITER_H
|
||||||
|
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
|
#include "ELF.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@ -82,10 +83,8 @@ namespace llvm {
|
|||||||
/// doInitialization - Emit the file header and all of the global variables
|
/// doInitialization - Emit the file header and all of the global variables
|
||||||
/// for the module to the ELF file.
|
/// for the module to the ELF file.
|
||||||
bool doInitialization(Module &M);
|
bool doInitialization(Module &M);
|
||||||
|
|
||||||
bool runOnMachineFunction(MachineFunction &MF);
|
bool runOnMachineFunction(MachineFunction &MF);
|
||||||
|
|
||||||
|
|
||||||
/// doFinalization - Now that the module has been completely processed, emit
|
/// doFinalization - Now that the module has been completely processed, emit
|
||||||
/// the ELF file to 'O'.
|
/// the ELF file to 'O'.
|
||||||
bool doFinalization(Module &M);
|
bool doFinalization(Module &M);
|
||||||
@ -96,53 +95,6 @@ namespace llvm {
|
|||||||
// as well!).
|
// as well!).
|
||||||
DataBuffer FileHeader;
|
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
|
/// 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
|
/// file. Once the file has been completely built, the section header table
|
||||||
/// is constructed from this info.
|
/// is constructed from this info.
|
||||||
@ -165,13 +117,13 @@ namespace llvm {
|
|||||||
SN->SectionIdx = NumSections++;
|
SN->SectionIdx = NumSections++;
|
||||||
SN->Type = Type;
|
SN->Type = Type;
|
||||||
SN->Flags = Flags;
|
SN->Flags = Flags;
|
||||||
|
SN->Link = ELFSection::SHN_UNDEF;
|
||||||
return *SN;
|
return *SN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ELFSection &getTextSection() {
|
ELFSection &getTextSection() {
|
||||||
return getSection(".text", ELFWriter::ELFSection::SHT_PROGBITS,
|
return getSection(".text", ELFSection::SHT_PROGBITS,
|
||||||
ELFWriter::ELFSection::SHF_EXECINSTR |
|
ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
|
||||||
ELFWriter::ELFSection::SHF_ALLOC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ELFSection &getDataSection() {
|
ELFSection &getDataSection() {
|
||||||
@ -183,34 +135,6 @@ namespace llvm {
|
|||||||
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
|
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.
|
/// 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
|
/// This actually gets rearranged before emission to the file (to put the
|
||||||
/// local symbols first in the list).
|
/// 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
|
// (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
|
// the offset in ELFHeader of these various pieces to update and other
|
||||||
// locations in the file.
|
// locations in the file.
|
||||||
unsigned ELFHeader_e_shoff_Offset; // e_shoff in ELF header.
|
unsigned ELFHdr_e_shoff_Offset; // e_shoff in ELF header.
|
||||||
unsigned ELFHeader_e_shstrndx_Offset; // e_shstrndx in ELF header.
|
unsigned ELFHdr_e_shstrndx_Offset; // e_shstrndx in ELF header.
|
||||||
unsigned ELFHeader_e_shnum_Offset; // e_shnum in ELF header.
|
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
|
||||||
private:
|
private:
|
||||||
void EmitGlobal(GlobalVariable *GV);
|
void EmitGlobal(GlobalVariable *GV);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user