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:
parent
234aa2c4ea
commit
408112ede3
@ -12,8 +12,6 @@ add_llvm_library(LLVMCodeGen
|
||||
DFAPacketizer.cpp
|
||||
DwarfEHPrepare.cpp
|
||||
EdgeBundles.cpp
|
||||
ELFCodeEmitter.cpp
|
||||
ELFWriter.cpp
|
||||
ExecutionDepsFix.cpp
|
||||
ExpandISelPseudos.cpp
|
||||
ExpandPostRAPseudos.cpp
|
||||
|
@ -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
|
@ -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
|
@ -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
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user