1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

Remove the old ELF writer.

llvm-svn: 147615
This commit is contained in:
Rafael Espindola 2012-01-05 22:07:43 +00:00
parent 234aa2c4ea
commit 408112ede3
10 changed files with 3 additions and 2223 deletions

View File

@ -12,8 +12,6 @@ add_llvm_library(LLVMCodeGen
DFAPacketizer.cpp
DwarfEHPrepare.cpp
EdgeBundles.cpp
ELFCodeEmitter.cpp
ELFWriter.cpp
ExecutionDepsFix.cpp
ExpandISelPseudos.cpp
ExpandPostRAPseudos.cpp

View File

@ -1,227 +0,0 @@
//===-- 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 is based on HP/Intel definition of the
// ELF-64 object file format document, Version 1.5 Draft 2 May 27, 1998
//
//===----------------------------------------------------------------------===//
#ifndef CODEGEN_ELF_H
#define CODEGEN_ELF_H
#include "llvm/CodeGen/BinaryObject.h"
#include "llvm/CodeGen/MachineRelocation.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
class GlobalValue;
/// 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 {
// ELF symbols are related to llvm ones by being one of the two llvm
// types, for the other ones (section, file, func) a null pointer is
// assumed by default.
union {
const GlobalValue *GV; // If this is a pointer to a GV
const char *Ext; // If this is a pointer to a named symbol
} Source;
// Describes from which source type this ELF symbol comes from,
// they can be GlobalValue, ExternalSymbol or neither.
enum {
isGV, // The Source.GV field is valid.
isExtSym, // The Source.ExtSym field is valid.
isOther // Not a GlobalValue or External Symbol
};
unsigned SourceType;
bool isGlobalValue() const { return SourceType == isGV; }
bool isExternalSym() const { return SourceType == isExtSym; }
// getGlobalValue - If this is a global value which originated the
// elf symbol, return a reference to it.
const GlobalValue *getGlobalValue() const {
assert(SourceType == isGV && "This is not a global value");
return Source.GV;
}
// getExternalSym - If this is an external symbol which originated the
// elf symbol, return a reference to it.
const char *getExternalSymbol() const {
assert(SourceType == isExtSym && "This is not an external symbol");
return Source.Ext;
}
// getGV - From a global value return a elf symbol to represent it
static ELFSym *getGV(const GlobalValue *GV, unsigned Bind,
unsigned Type, unsigned Visibility) {
ELFSym *Sym = new ELFSym();
Sym->Source.GV = GV;
Sym->setBind(Bind);
Sym->setType(Type);
Sym->setVisibility(Visibility);
Sym->SourceType = isGV;
return Sym;
}
// getExtSym - Create and return an elf symbol to represent an
// external symbol
static ELFSym *getExtSym(const char *Ext) {
ELFSym *Sym = new ELFSym();
Sym->Source.Ext = Ext;
Sym->setBind(ELF::STB_GLOBAL);
Sym->setType(ELF::STT_NOTYPE);
Sym->setVisibility(ELF::STV_DEFAULT);
Sym->SourceType = isExtSym;
return Sym;
}
// getSectionSym - Returns a elf symbol to represent an elf section
static ELFSym *getSectionSym() {
ELFSym *Sym = new ELFSym();
Sym->setBind(ELF::STB_LOCAL);
Sym->setType(ELF::STT_SECTION);
Sym->setVisibility(ELF::STV_DEFAULT);
Sym->SourceType = isOther;
return Sym;
}
// getFileSym - Returns a elf symbol to represent the module identifier
static ELFSym *getFileSym() {
ELFSym *Sym = new ELFSym();
Sym->setBind(ELF::STB_LOCAL);
Sym->setType(ELF::STT_FILE);
Sym->setVisibility(ELF::STV_DEFAULT);
Sym->SectionIdx = 0xfff1; // ELFSection::SHN_ABS;
Sym->SourceType = isOther;
return Sym;
}
// getUndefGV - Returns a STT_NOTYPE symbol
static ELFSym *getUndefGV(const GlobalValue *GV, unsigned Bind) {
ELFSym *Sym = new ELFSym();
Sym->Source.GV = GV;
Sym->setBind(Bind);
Sym->setType(ELF::STT_NOTYPE);
Sym->setVisibility(ELF::STV_DEFAULT);
Sym->SectionIdx = 0; //ELFSection::SHN_UNDEF;
Sym->SourceType = isGV;
return Sym;
}
// 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;
// Symbol index into the Symbol table
unsigned SymTabIdx;
ELFSym() : SourceType(isOther), NameIdx(0), Value(0),
Size(0), Info(0), Other(ELF::STV_DEFAULT), SectionIdx(0),
SymTabIdx(0) {}
unsigned getBind() const { return (Info >> 4) & 0xf; }
unsigned getType() const { return Info & 0xf; }
bool isLocalBind() const { return getBind() == ELF::STB_LOCAL; }
bool isFileType() const { return getType() == ELF::STT_FILE; }
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;
}
void setVisibility(unsigned V) {
assert(V == (V & 0x3) && "Visibility value out of range!");
Other = V;
}
};
/// 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.
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
unsigned Flags; // sh_flags - Section flags.
uint64_t Addr; // sh_addr - The mem addr this section is in.
unsigned Offset; // sh_offset - Offset from the file start
unsigned Size; // sh_size - The section size.
unsigned Link; // sh_link - Section header table index link.
unsigned Info; // sh_info - Auxiliary information.
unsigned Align; // sh_addralign - Alignment of section.
unsigned EntSize; // sh_entsize - Size of entries in the section e
/// SectionIdx - The number of the section in the Section Table.
unsigned short SectionIdx;
/// Sym - The symbol to represent this section if it has one.
ELFSym *Sym;
/// getSymIndex - Returns the symbol table index of the symbol
/// representing this section.
unsigned getSymbolTableIndex() const {
assert(Sym && "section not present in the symbol table");
return Sym->SymTabIdx;
}
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), Sym(0) {}
};
/// ELFRelocation - This class contains all the information necessary to
/// to generate any 32-bit or 64-bit ELF relocation entry.
class ELFRelocation {
uint64_t r_offset; // offset in the section of the object this applies to
uint32_t r_symidx; // symbol table index of the symbol to use
uint32_t r_type; // machine specific relocation type
int64_t r_add; // explicit relocation addend
bool r_rela; // if true then the addend is part of the entry
// otherwise the addend is at the location specified
// by r_offset
public:
uint64_t getInfo(bool is64Bit) const {
if (is64Bit)
return ((uint64_t)r_symidx << 32) + ((uint64_t)r_type & 0xFFFFFFFFL);
else
return (r_symidx << 8) + (r_type & 0xFFL);
}
uint64_t getOffset() const { return r_offset; }
int64_t getAddend() const { return r_add; }
ELFRelocation(uint64_t off, uint32_t sym, uint32_t type,
bool rela = true, int64_t addend = 0) :
r_offset(off), r_symidx(sym), r_type(type),
r_add(addend), r_rela(rela) {}
};
} // end namespace llvm
#endif

View File

@ -1,205 +0,0 @@
//===-- lib/CodeGen/ELFCodeEmitter.cpp ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "elfce"
#include "ELF.h"
#include "ELFWriter.h"
#include "ELFCodeEmitter.h"
#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/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRelocation.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetELFWriterInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
//===----------------------------------------------------------------------===//
// ELFCodeEmitter Implementation
//===----------------------------------------------------------------------===//
namespace llvm {
/// startFunction - This callback is invoked when a new machine function is
/// about to be emitted.
void ELFCodeEmitter::startFunction(MachineFunction &MF) {
DEBUG(dbgs() << "processing function: "
<< MF.getFunction()->getName() << "\n");
// Get the ELF Section that this function belongs in.
ES = &EW.getTextSection(MF.getFunction());
// Set the desired binary object to be used by the code emitters
setBinaryObject(ES);
// Get the function alignment in bytes
unsigned Align = (1 << MF.getAlignment());
// The function must start on its required alignment
ES->emitAlignment(Align);
// Update the section alignment if needed.
ES->Align = std::max(ES->Align, Align);
// Record the function start offset
FnStartOff = ES->getCurrentPCOffset();
// Emit constant pool and jump tables to their appropriate sections.
// They need to be emitted before the function because in some targets
// the later may reference JT or CP entry address.
emitConstantPool(MF.getConstantPool());
if (MF.getJumpTableInfo())
emitJumpTables(MF.getJumpTableInfo());
}
/// finishFunction - This callback is invoked after the function is completely
/// finished.
bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
// Add a symbol to represent the function.
const Function *F = MF.getFunction();
ELFSym *FnSym = ELFSym::getGV(F, EW.getGlobalELFBinding(F), ELF::STT_FUNC,
EW.getGlobalELFVisibility(F));
FnSym->SectionIdx = ES->SectionIdx;
FnSym->Size = ES->getCurrentPCOffset()-FnStartOff;
EW.AddPendingGlobalSymbol(F, true);
// Offset from start of Section
FnSym->Value = FnStartOff;
if (!F->hasPrivateLinkage())
EW.SymbolList.push_back(FnSym);
// Patch up Jump Table Section relocations to use the real MBBs offsets
// now that the MBB label offsets inside the function are known.
if (MF.getJumpTableInfo()) {
ELFSection &JTSection = EW.getJumpTableSection();
for (std::vector<MachineRelocation>::iterator MRI = JTRelocations.begin(),
MRE = JTRelocations.end(); MRI != MRE; ++MRI) {
MachineRelocation &MR = *MRI;
uintptr_t MBBOffset = getMachineBasicBlockAddress(MR.getBasicBlock());
MR.setResultPointer((void*)MBBOffset);
MR.setConstantVal(ES->SectionIdx);
JTSection.addRelocation(MR);
}
}
// If we have emitted any relocations to function-specific objects such as
// basic blocks, constant pools entries, or jump tables, record their
// addresses now so that we can rewrite them with the correct addresses later
for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
MachineRelocation &MR = Relocations[i];
intptr_t Addr;
if (MR.isGlobalValue()) {
EW.AddPendingGlobalSymbol(MR.getGlobalValue());
} else if (MR.isExternalSymbol()) {
EW.AddPendingExternalSymbol(MR.getExternalSymbol());
} else if (MR.isBasicBlock()) {
Addr = getMachineBasicBlockAddress(MR.getBasicBlock());
MR.setConstantVal(ES->SectionIdx);
MR.setResultPointer((void*)Addr);
} else if (MR.isConstantPoolIndex()) {
Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex());
MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]);
MR.setResultPointer((void*)Addr);
} else if (MR.isJumpTableIndex()) {
ELFSection &JTSection = EW.getJumpTableSection();
Addr = getJumpTableEntryAddress(MR.getJumpTableIndex());
MR.setConstantVal(JTSection.SectionIdx);
MR.setResultPointer((void*)Addr);
} else {
llvm_unreachable("Unhandled relocation type");
}
ES->addRelocation(MR);
}
// Clear per-function data structures.
JTRelocations.clear();
Relocations.clear();
CPLocations.clear();
CPSections.clear();
JTLocations.clear();
MBBLocations.clear();
return false;
}
/// emitConstantPool - For each constant pool entry, figure out which section
/// the constant should live in and emit the constant
void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) {
const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
if (CP.empty()) return;
// TODO: handle PIC codegen
assert(TM.getRelocationModel() != Reloc::PIC_ &&
"PIC codegen not yet handled for elf constant pools!");
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
MachineConstantPoolEntry CPE = CP[i];
// Record the constant pool location and the section index
ELFSection &CstPool = EW.getConstantPoolSection(CPE);
CPLocations.push_back(CstPool.size());
CPSections.push_back(CstPool.SectionIdx);
if (CPE.isMachineConstantPoolEntry())
assert(0 && "CPE.isMachineConstantPoolEntry not supported yet");
// Emit the constant to constant pool section
EW.EmitGlobalConstant(CPE.Val.ConstVal, CstPool);
}
}
/// emitJumpTables - Emit all the jump tables for a given jump table info
/// record to the appropriate section.
void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) {
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
if (JT.empty()) return;
// FIXME: handle PIC codegen
assert(TM.getRelocationModel() != Reloc::PIC_ &&
"PIC codegen not yet handled for elf jump tables!");
const TargetELFWriterInfo *TEW = TM.getELFWriterInfo();
unsigned EntrySize = 4; //MJTI->getEntrySize();
// Get the ELF Section to emit the jump table
ELFSection &JTSection = EW.getJumpTableSection();
// For each JT, record its offset from the start of the section
for (unsigned i = 0, e = JT.size(); i != e; ++i) {
const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs;
// Record JT 'i' offset in the JT section
JTLocations.push_back(JTSection.size());
// Each MBB entry in the Jump table section has a relocation entry
// against the current text section.
for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) {
unsigned MachineRelTy = TEW->getAbsoluteLabelMachineRelTy();
MachineRelocation MR =
MachineRelocation::getBB(JTSection.size(), MachineRelTy, MBBs[mi]);
// Add the relocation to the Jump Table section
JTRelocations.push_back(MR);
// Output placeholder for MBB in the JT section
for (unsigned s=0; s < EntrySize; ++s)
JTSection.emitByte(0);
}
}
}
} // end namespace llvm

View File

@ -1,78 +0,0 @@
//===-- lib/CodeGen/ELFCodeEmitter.h ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef ELFCODEEMITTER_H
#define ELFCODEEMITTER_H
#include "llvm/CodeGen/ObjectCodeEmitter.h"
#include <vector>
namespace llvm {
class ELFWriter;
class ELFSection;
/// ELFCodeEmitter - This class is used by the ELFWriter to
/// emit the code for functions to the ELF file.
class ELFCodeEmitter : public ObjectCodeEmitter {
ELFWriter &EW;
/// Target machine description
TargetMachine &TM;
/// Section containing code for functions
ELFSection *ES;
/// Relocations - Record relocations needed by the current function
std::vector<MachineRelocation> Relocations;
/// JTRelocations - Record relocations needed by the relocation
/// section.
std::vector<MachineRelocation> JTRelocations;
/// FnStartPtr - Function offset from the beginning of ELFSection 'ES'
uintptr_t FnStartOff;
public:
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {}
/// addRelocation - Register new relocations for this function
void addRelocation(const MachineRelocation &MR) {
Relocations.push_back(MR);
}
/// emitConstantPool - For each constant pool entry, figure out which
/// section the constant should live in and emit data to it
void emitConstantPool(MachineConstantPool *MCP);
/// emitJumpTables - Emit all the jump tables for a given jump table
/// info and record them to the appropriate section.
void emitJumpTables(MachineJumpTableInfo *MJTI);
void startFunction(MachineFunction &F);
bool finishFunction(MachineFunction &F);
/// emitLabel - Emits a label
virtual void emitLabel(MCSymbol *Label) {
assert(0 && "emitLabel not implemented");
}
/// getLabelAddress - Return the address of the specified LabelID,
/// only usable after the LabelID has been emitted.
virtual uintptr_t getLabelAddress(MCSymbol *Label) const {
assert(0 && "getLabelAddress not implemented");
return 0;
}
virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) {}
}; // end class ELFCodeEmitter
} // end namespace llvm
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,251 +0,0 @@
//===-- ELFWriter.h - Target-independent ELF writer support -----*- 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 the ELFWriter class.
//
//===----------------------------------------------------------------------===//
#ifndef ELFWRITER_H
#define ELFWRITER_H
#include "llvm/ADT/SetVector.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include <map>
namespace llvm {
class BinaryObject;
class Constant;
class ConstantInt;
class ConstantStruct;
class ELFCodeEmitter;
class ELFRelocation;
class ELFSection;
struct ELFSym;
class GlobalVariable;
class JITDebugRegisterer;
class Mangler;
class MachineCodeEmitter;
class MachineConstantPoolEntry;
class ObjectCodeEmitter;
class MCAsmInfo;
class TargetELFWriterInfo;
class TargetLoweringObjectFile;
class raw_ostream;
class SectionKind;
class MCContext;
class TargetMachine;
typedef std::vector<ELFSym*>::iterator ELFSymIter;
typedef std::vector<ELFSection*>::iterator ELFSectionIter;
typedef SetVector<const GlobalValue*>::const_iterator PendingGblsIter;
typedef SetVector<const char *>::const_iterator PendingExtsIter;
typedef std::pair<const Constant *, int64_t> CstExprResTy;
/// ELFWriter - This class implements the common target-independent code for
/// writing ELF files. Targets should derive a class from this to
/// parameterize the output format.
///
class ELFWriter : public MachineFunctionPass {
friend class ELFCodeEmitter;
friend class JITDebugRegisterer;
public:
static char ID;
/// Return the ELFCodeEmitter as an instance of ObjectCodeEmitter
ObjectCodeEmitter *getObjectCodeEmitter() {
return reinterpret_cast<ObjectCodeEmitter*>(ElfCE);
}
ELFWriter(raw_ostream &O, TargetMachine &TM);
~ELFWriter();
protected:
/// Output stream to send the resultant object file to.
raw_ostream &O;
/// Target machine description.
TargetMachine &TM;
/// Context object for machine code objects.
MCContext &OutContext;
/// Target Elf Writer description.
const TargetELFWriterInfo *TEW;
/// Mang - The object used to perform name mangling for this module.
Mangler *Mang;
/// MCE - The MachineCodeEmitter object that we are exposing to emit machine
/// code for functions to the .o file.
ELFCodeEmitter *ElfCE;
/// TLOF - Target Lowering Object File, provide section names for globals
/// and other object file specific stuff
const TargetLoweringObjectFile &TLOF;
/// MAI - Target Asm Info, provide information about section names for
/// globals and other target specific stuff.
const MCAsmInfo *MAI;
//===------------------------------------------------------------------===//
// Properties inferred automatically from the target machine.
//===------------------------------------------------------------------===//
/// is64Bit/isLittleEndian - This information is inferred from the target
/// machine directly, indicating whether to emit a 32- or 64-bit ELF file.
bool is64Bit, isLittleEndian;
/// 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);
private:
/// 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
/// is constructed from this info.
std::vector<ELFSection*> SectionList;
unsigned NumSections; // Always = SectionList.size()
/// SectionLookup - This is a mapping from section name to section number in
/// the SectionList. Used to quickly gather the Section Index from MAI names
std::map<std::string, ELFSection*> SectionLookup;
/// PendingGlobals - Globals not processed as symbols yet.
SetVector<const GlobalValue*> PendingGlobals;
/// GblSymLookup - This is a mapping from global value to a symbol index
/// in the symbol table or private symbols list. This is useful since reloc
/// symbol references must be quickly mapped to their indices on the lists.
std::map<const GlobalValue*, uint32_t> GblSymLookup;
/// PendingExternals - Externals not processed as symbols yet.
SetVector<const char *> PendingExternals;
/// ExtSymLookup - This is a mapping from externals to a symbol index
/// in the symbol table list. This is useful since reloc symbol references
/// must be quickly mapped to their symbol table indices.
std::map<const char *, uint32_t> ExtSymLookup;
/// SymbolList - This is the list of symbols emitted to the symbol table.
/// When the SymbolList is finally built, local symbols must be placed in
/// the beginning while non-locals at the end.
std::vector<ELFSym*> SymbolList;
/// PrivateSyms - Record private symbols, every symbol here must never be
/// present in the SymbolList.
std::vector<ELFSym*> PrivateSyms;
/// getSection - Return the section with the specified name, creating a new
/// section if one does not already exist.
ELFSection &getSection(const std::string &Name, unsigned Type,
unsigned Flags = 0, unsigned Align = 0) {
ELFSection *&SN = SectionLookup[Name];
if (SN) return *SN;
SectionList.push_back(new ELFSection(Name, isLittleEndian, is64Bit));
SN = SectionList.back();
SN->SectionIdx = NumSections++;
SN->Type = Type;
SN->Flags = Flags;
SN->Link = ELF::SHN_UNDEF;
SN->Align = Align;
return *SN;
}
ELFSection &getNonExecStackSection() {
return getSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0, 1);
}
ELFSection &getSymbolTableSection() {
return getSection(".symtab", ELF::SHT_SYMTAB, 0);
}
ELFSection &getStringTableSection() {
return getSection(".strtab", ELF::SHT_STRTAB, 0, 1);
}
ELFSection &getSectionHeaderStringTableSection() {
return getSection(".shstrtab", ELF::SHT_STRTAB, 0, 1);
}
ELFSection &getNullSection() {
return getSection("", ELF::SHT_NULL, 0);
}
ELFSection &getDataSection();
ELFSection &getBSSSection();
ELFSection &getCtorSection();
ELFSection &getDtorSection();
ELFSection &getJumpTableSection();
ELFSection &getConstantPoolSection(MachineConstantPoolEntry &CPE);
ELFSection &getTextSection(const Function *F);
ELFSection &getRelocSection(ELFSection &S);
// Helpers for obtaining ELF specific info.
unsigned getGlobalELFBinding(const GlobalValue *GV);
unsigned getGlobalELFType(const GlobalValue *GV);
unsigned getGlobalELFVisibility(const GlobalValue *GV);
// AddPendingGlobalSymbol - Add a global to be processed and to
// the global symbol lookup, use a zero index because the table
// index will be determined later.
void AddPendingGlobalSymbol(const GlobalValue *GV,
bool AddToLookup = false);
// AddPendingExternalSymbol - Add the external to be processed
// and to the external symbol lookup, use a zero index because
// the symbol table index will be determined later.
void AddPendingExternalSymbol(const char *External);
// AddToSymbolList - Update the symbol lookup and If the symbol is
// private add it to PrivateSyms list, otherwise to SymbolList.
void AddToSymbolList(ELFSym *GblSym);
// As we complete the ELF file, we need to update fields in the ELF header
// (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 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(const GlobalValue *GV);
void EmitGlobalConstant(const Constant *C, ELFSection &GblS);
void EmitGlobalConstantStruct(const ConstantStruct *CVS,
ELFSection &GblS);
void EmitGlobalConstantLargeInt(const ConstantInt *CI, ELFSection &S);
void EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size,
ELFSection &GblS, int64_t Offset = 0);
bool EmitSpecialLLVMGlobal(const GlobalVariable *GV);
void EmitXXStructorList(const Constant *List, ELFSection &Xtor);
void EmitRelocations();
void EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, bool HasRelA);
void EmitSectionHeader(BinaryObject &SHdrTab, const ELFSection &SHdr);
void EmitSectionTableStringTable();
void EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym);
void EmitSymbolTable();
void EmitStringTable(const std::string &ModuleName);
void OutputSectionsAndSectionTable();
void RelocateField(BinaryObject &BO, uint32_t Offset, int64_t Value,
unsigned Size);
unsigned SortSymbols();
CstExprResTy ResolveConstantExpr(const Constant *CV);
};
}
#endif

View File

@ -4,7 +4,6 @@ add_definitions(-DENABLE_X86_JIT)
add_llvm_library(LLVMJIT
Intercept.cpp
JIT.cpp
JITDebugRegisterer.cpp
JITDwarfEmitter.cpp
JITEmitter.cpp
JITMemoryManager.cpp

View File

@ -1,211 +0,0 @@
//===-- JITDebugRegisterer.cpp - Register debug symbols for JIT -----------===//
//
// 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 JITDebugRegisterer object that is used by the JIT to
// register debug info with debuggers like GDB.
//
//===----------------------------------------------------------------------===//
#include "JITDebugRegisterer.h"
#include "../../CodeGen/ELF.h"
#include "../../CodeGen/ELFWriter.h"
#include "llvm/LLVMContext.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Mutex.h"
#include <string>
namespace llvm {
// This must be kept in sync with gdb/gdb/jit.h .
extern "C" {
// Debuggers puts a breakpoint in this function.
LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { }
// We put information about the JITed function in this global, which the
// debugger reads. Make sure to specify the version statically, because the
// debugger checks the version before we can set it during runtime.
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
}
namespace {
/// JITDebugLock - Used to serialize all code registration events, since they
/// modify global variables.
sys::Mutex JITDebugLock;
}
JITDebugRegisterer::JITDebugRegisterer(TargetMachine &tm) : TM(tm), FnMap() { }
JITDebugRegisterer::~JITDebugRegisterer() {
// Free all ELF memory.
for (RegisteredFunctionsMap::iterator I = FnMap.begin(), E = FnMap.end();
I != E; ++I) {
// Call the private method that doesn't update the map so our iterator
// doesn't break.
UnregisterFunctionInternal(I);
}
FnMap.clear();
}
std::string JITDebugRegisterer::MakeELF(const Function *F, DebugInfo &I) {
// Stack allocate an empty module with an empty LLVMContext for the ELFWriter
// API. We don't use the real module because then the ELFWriter would write
// out unnecessary GlobalValues during finalization.
LLVMContext Context;
Module M("", Context);
// Make a buffer for the ELF in memory.
std::string Buffer;
raw_string_ostream O(Buffer);
ELFWriter EW(O, TM);
EW.doInitialization(M);
// Copy the binary into the .text section. This isn't necessary, but it's
// useful to be able to disassemble the ELF by hand.
ELFSection &Text = EW.getTextSection(const_cast<Function *>(F));
Text.Addr = (uint64_t)I.FnStart;
// TODO: We could eliminate this copy if we somehow used a pointer/size pair
// instead of a vector.
Text.getData().assign(I.FnStart, I.FnEnd);
// Copy the exception handling call frame information into the .eh_frame
// section. This allows GDB to get a good stack trace, particularly on
// linux x86_64. Mark this as a PROGBITS section that needs to be loaded
// into memory at runtime.
ELFSection &EH = EW.getSection(".eh_frame", ELF::SHT_PROGBITS,
ELF::SHF_ALLOC);
// Pointers in the DWARF EH info are all relative to the EH frame start,
// which is stored here.
EH.Addr = (uint64_t)I.EhStart;
// TODO: We could eliminate this copy if we somehow used a pointer/size pair
// instead of a vector.
EH.getData().assign(I.EhStart, I.EhEnd);
// Add this single function to the symbol table, so the debugger prints the
// name instead of '???'. We give the symbol default global visibility.
ELFSym *FnSym = ELFSym::getGV(F,
ELF::STB_GLOBAL,
ELF::STT_FUNC,
ELF::STV_DEFAULT);
FnSym->SectionIdx = Text.SectionIdx;
FnSym->Size = I.FnEnd - I.FnStart;
FnSym->Value = 0; // Offset from start of section.
EW.SymbolList.push_back(FnSym);
EW.doFinalization(M);
O.flush();
// When trying to debug why GDB isn't getting the debug info right, it's
// awfully helpful to write the object file to disk so that it can be
// inspected with readelf and objdump.
if (TM.Options.JITEmitDebugInfoToDisk) {
std::string Filename;
raw_string_ostream O2(Filename);
O2 << "/tmp/llvm_function_" << I.FnStart << "_" << F->getName() << ".o";
O2.flush();
std::string Errors;
raw_fd_ostream O3(Filename.c_str(), Errors);
O3 << Buffer;
O3.close();
}
return Buffer;
}
void JITDebugRegisterer::RegisterFunction(const Function *F, DebugInfo &I) {
// TODO: Support non-ELF platforms.
if (!TM.getELFWriterInfo())
return;
std::string Buffer = MakeELF(F, I);
jit_code_entry *JITCodeEntry = new jit_code_entry();
JITCodeEntry->symfile_addr = Buffer.c_str();
JITCodeEntry->symfile_size = Buffer.size();
// Add a mapping from F to the entry and buffer, so we can delete this
// info later.
FnMap[F] = std::make_pair(Buffer, JITCodeEntry);
// Acquire the lock and do the registration.
{
MutexGuard locked(JITDebugLock);
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
// Insert this entry at the head of the list.
JITCodeEntry->prev_entry = NULL;
jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry;
JITCodeEntry->next_entry = NextEntry;
if (NextEntry != NULL) {
NextEntry->prev_entry = JITCodeEntry;
}
__jit_debug_descriptor.first_entry = JITCodeEntry;
__jit_debug_descriptor.relevant_entry = JITCodeEntry;
__jit_debug_register_code();
}
}
void JITDebugRegisterer::UnregisterFunctionInternal(
RegisteredFunctionsMap::iterator I) {
jit_code_entry *&JITCodeEntry = I->second.second;
// Acquire the lock and do the unregistration.
{
MutexGuard locked(JITDebugLock);
__jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
// Remove the jit_code_entry from the linked list.
jit_code_entry *PrevEntry = JITCodeEntry->prev_entry;
jit_code_entry *NextEntry = JITCodeEntry->next_entry;
if (NextEntry) {
NextEntry->prev_entry = PrevEntry;
}
if (PrevEntry) {
PrevEntry->next_entry = NextEntry;
} else {
assert(__jit_debug_descriptor.first_entry == JITCodeEntry);
__jit_debug_descriptor.first_entry = NextEntry;
}
// Tell GDB which entry we removed, and unregister the code.
__jit_debug_descriptor.relevant_entry = JITCodeEntry;
__jit_debug_register_code();
}
delete JITCodeEntry;
JITCodeEntry = NULL;
// Free the ELF file in memory.
std::string &Buffer = I->second.first;
Buffer.clear();
}
void JITDebugRegisterer::UnregisterFunction(const Function *F) {
// TODO: Support non-ELF platforms.
if (!TM.getELFWriterInfo())
return;
RegisteredFunctionsMap::iterator I = FnMap.find(F);
if (I == FnMap.end()) return;
UnregisterFunctionInternal(I);
FnMap.erase(I);
}
} // end namespace llvm

View File

@ -1,116 +0,0 @@
//===-- JITDebugRegisterer.h - Register debug symbols for JIT -------------===//
//
// 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 JITDebugRegisterer object that is used by the JIT to
// register debug info with debuggers like GDB.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H
#define LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/DataTypes.h"
#include <string>
// This must be kept in sync with gdb/gdb/jit.h .
extern "C" {
typedef enum {
JIT_NOACTION = 0,
JIT_REGISTER_FN,
JIT_UNREGISTER_FN
} jit_actions_t;
struct jit_code_entry {
struct jit_code_entry *next_entry;
struct jit_code_entry *prev_entry;
const char *symfile_addr;
uint64_t symfile_size;
};
struct jit_descriptor {
uint32_t version;
// This should be jit_actions_t, but we want to be specific about the
// bit-width.
uint32_t action_flag;
struct jit_code_entry *relevant_entry;
struct jit_code_entry *first_entry;
};
}
namespace llvm {
class ELFSection;
class Function;
class TargetMachine;
/// This class encapsulates information we want to send to the debugger.
///
struct DebugInfo {
uint8_t *FnStart;
uint8_t *FnEnd;
uint8_t *EhStart;
uint8_t *EhEnd;
DebugInfo() : FnStart(0), FnEnd(0), EhStart(0), EhEnd(0) {}
};
typedef DenseMap< const Function*, std::pair<std::string, jit_code_entry*> >
RegisteredFunctionsMap;
/// This class registers debug info for JITed code with an attached debugger.
/// Without proper debug info, GDB can't do things like source level debugging
/// or even produce a proper stack trace on linux-x86_64. To use this class,
/// whenever a function is JITed, create a DebugInfo struct and pass it to the
/// RegisterFunction method. The method will then do whatever is necessary to
/// inform the debugger about the JITed function.
class JITDebugRegisterer {
TargetMachine &TM;
/// FnMap - A map of functions that have been registered to the associated
/// temporary files. Used for cleanup.
RegisteredFunctionsMap FnMap;
/// MakeELF - Builds the ELF file in memory and returns a std::string that
/// contains the ELF.
std::string MakeELF(const Function *F, DebugInfo &I);
public:
JITDebugRegisterer(TargetMachine &tm);
/// ~JITDebugRegisterer - Unregisters all code and frees symbol files.
///
~JITDebugRegisterer();
/// RegisterFunction - Register debug info for the given function with an
/// attached debugger. Clients must call UnregisterFunction on all
/// registered functions before deleting them to free the associated symbol
/// file and unregister it from the debugger.
void RegisterFunction(const Function *F, DebugInfo &I);
/// UnregisterFunction - Unregister the debug info for the given function
/// from the debugger and free associated memory.
void UnregisterFunction(const Function *F);
private:
/// UnregisterFunctionInternal - Unregister the debug info for the given
/// function from the debugger and delete any temporary files. The private
/// version of this method does not remove the function from FnMap so that it
/// can be called while iterating over FnMap.
void UnregisterFunctionInternal(RegisteredFunctionsMap::iterator I);
};
} // end namespace llvm
#endif // LLVM_EXECUTION_ENGINE_JIT_DEBUGREGISTERER_H

View File

@ -14,7 +14,6 @@
#define DEBUG_TYPE "jit"
#include "JIT.h"
#include "JITDebugRegisterer.h"
#include "JITDwarfEmitter.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Constants.h"
@ -324,9 +323,6 @@ namespace {
/// DE - The dwarf emitter for the jit.
OwningPtr<JITDwarfEmitter> DE;
/// DR - The debug registerer for the jit.
OwningPtr<JITDebugRegisterer> DR;
/// LabelLocations - This vector is a mapping from Label ID's to their
/// address.
DenseMap<MCSymbol*, uintptr_t> LabelLocations;
@ -364,26 +360,20 @@ namespace {
bool JITExceptionHandling;
bool JITEmitDebugInfo;
public:
JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM)
: SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0),
EmittedFunctions(this), TheJIT(&jit),
JITExceptionHandling(TM.Options.JITExceptionHandling),
JITEmitDebugInfo(TM.Options.JITEmitDebugInfo) {
JITExceptionHandling(TM.Options.JITExceptionHandling) {
MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
if (jit.getJITInfo().needsGOT()) {
MemMgr->AllocateGOT();
DEBUG(dbgs() << "JIT is managing a GOT\n");
}
if (JITExceptionHandling || JITEmitDebugInfo) {
if (JITExceptionHandling) {
DE.reset(new JITDwarfEmitter(jit));
}
if (JITEmitDebugInfo) {
DR.reset(new JITDebugRegisterer(TM));
}
}
~JITEmitter() {
delete MemMgr;
@ -974,7 +964,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
}
});
if (JITExceptionHandling || JITEmitDebugInfo) {
if (JITExceptionHandling) {
uintptr_t ActualSize = 0;
SavedBufferBegin = BufferBegin;
SavedBufferEnd = BufferEnd;
@ -989,7 +979,6 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
EhStart);
MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
FrameRegister);
uint8_t *EhEnd = CurBufferPtr;
BufferBegin = SavedBufferBegin;
BufferEnd = SavedBufferEnd;
CurBufferPtr = SavedCurBufferPtr;
@ -997,15 +986,6 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
if (JITExceptionHandling) {
TheJIT->RegisterTable(F.getFunction(), FrameRegister);
}
if (JITEmitDebugInfo) {
DebugInfo I;
I.FnStart = FnStart;
I.FnEnd = FnEnd;
I.EhStart = EhStart;
I.EhEnd = EhEnd;
DR->RegisterFunction(F.getFunction(), I);
}
}
if (MMI)
@ -1046,10 +1026,6 @@ void JITEmitter::deallocateMemForFunction(const Function *F) {
if (JITExceptionHandling) {
TheJIT->DeregisterTable(F);
}
if (JITEmitDebugInfo) {
DR->UnregisterFunction(F);
}
}