From 611caf5f91c4abe934480259043fcbb30ea07e3a Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 5 Jan 2012 22:07:43 +0000 Subject: Remove the old ELF writer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@147615 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CMakeLists.txt | 2 - lib/CodeGen/ELF.h | 227 ----- lib/CodeGen/ELFCodeEmitter.cpp | 205 ----- lib/CodeGen/ELFCodeEmitter.h | 78 -- lib/CodeGen/ELFWriter.cpp | 1105 ------------------------ lib/CodeGen/ELFWriter.h | 251 ------ lib/ExecutionEngine/JIT/CMakeLists.txt | 1 - lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp | 211 ----- lib/ExecutionEngine/JIT/JITDebugRegisterer.h | 116 --- lib/ExecutionEngine/JIT/JITEmitter.cpp | 30 +- 10 files changed, 3 insertions(+), 2223 deletions(-) delete mode 100644 lib/CodeGen/ELF.h delete mode 100644 lib/CodeGen/ELFCodeEmitter.cpp delete mode 100644 lib/CodeGen/ELFCodeEmitter.h delete mode 100644 lib/CodeGen/ELFWriter.cpp delete mode 100644 lib/CodeGen/ELFWriter.h delete mode 100644 lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp delete mode 100644 lib/ExecutionEngine/JIT/JITDebugRegisterer.h (limited to 'lib') diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 09d109b7bc..0868eebe2e 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -12,8 +12,6 @@ add_llvm_library(LLVMCodeGen DFAPacketizer.cpp DwarfEHPrepare.cpp EdgeBundles.cpp - ELFCodeEmitter.cpp - ELFWriter.cpp ExecutionDepsFix.cpp ExpandISelPseudos.cpp ExpandPostRAPseudos.cpp diff --git a/lib/CodeGen/ELF.h b/lib/CodeGen/ELF.h deleted file mode 100644 index 5b634682cc..0000000000 --- a/lib/CodeGen/ELF.h +++ /dev/null @@ -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 diff --git a/lib/CodeGen/ELFCodeEmitter.cpp b/lib/CodeGen/ELFCodeEmitter.cpp deleted file mode 100644 index 660424c3c1..0000000000 --- a/lib/CodeGen/ELFCodeEmitter.cpp +++ /dev/null @@ -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::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 &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 &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 &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 diff --git a/lib/CodeGen/ELFCodeEmitter.h b/lib/CodeGen/ELFCodeEmitter.h deleted file mode 100644 index 8671c674ee..0000000000 --- a/lib/CodeGen/ELFCodeEmitter.h +++ /dev/null @@ -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 - -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 Relocations; - - /// JTRelocations - Record relocations needed by the relocation - /// section. - std::vector 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 - diff --git a/lib/CodeGen/ELFWriter.cpp b/lib/CodeGen/ELFWriter.cpp deleted file mode 100644 index f2c2185658..0000000000 --- a/lib/CodeGen/ELFWriter.cpp +++ /dev/null @@ -1,1105 +0,0 @@ -//===-- ELFWriter.cpp - Target-independent ELF Writer code ----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the target-independent ELF writer. This file writes out -// the ELF file in the following order: -// -// #1. ELF Header -// #2. '.text' section -// #3. '.data' section -// #4. '.bss' section (conceptual position in file) -// ... -// #X. '.shstrtab' section -// #Y. Section Table -// -// The entries in the section table are laid out as: -// #0. Null entry [required] -// #1. ".text" entry - the program code -// #2. ".data" entry - global variables with initializers. [ if needed ] -// #3. ".bss" entry - global variables without initializers. [ if needed ] -// ... -// #N. ".shstrtab" entry - String table for the section names. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "elfwriter" -#include "ELF.h" -#include "ELFWriter.h" -#include "ELFCodeEmitter.h" -#include "llvm/Constants.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/DerivedTypes.h" -#include "llvm/CodeGen/BinaryObject.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/CodeGen/ObjectCodeEmitter.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetELFWriterInfo.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetLoweringObjectFile.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/SmallString.h" -using namespace llvm; - -char ELFWriter::ID = 0; - -//===----------------------------------------------------------------------===// -// ELFWriter Implementation -//===----------------------------------------------------------------------===// - -ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm) - : MachineFunctionPass(ID), O(o), TM(tm), - OutContext(*new MCContext(*TM.getMCAsmInfo(), *TM.getRegisterInfo(), - &TM.getTargetLowering()->getObjFileLowering())), - TLOF(TM.getTargetLowering()->getObjFileLowering()), - is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64), - isLittleEndian(TM.getTargetData()->isLittleEndian()), - ElfHdr(isLittleEndian, is64Bit) { - - MAI = TM.getMCAsmInfo(); - TEW = TM.getELFWriterInfo(); - - // Create the object code emitter object for this target. - ElfCE = new ELFCodeEmitter(*this); - - // Initial number of sections - NumSections = 0; -} - -ELFWriter::~ELFWriter() { - delete ElfCE; - delete &OutContext; - - while(!SymbolList.empty()) { - delete SymbolList.back(); - SymbolList.pop_back(); - } - - while(!PrivateSyms.empty()) { - delete PrivateSyms.back(); - PrivateSyms.pop_back(); - } - - while(!SectionList.empty()) { - delete SectionList.back(); - SectionList.pop_back(); - } - - // Release the name mangler object. - delete Mang; Mang = 0; -} - -// doInitialization - Emit the file header and all of the global variables for -// the module to the ELF file. -bool ELFWriter::doInitialization(Module &M) { - // Initialize TargetLoweringObjectFile. - const_cast(TLOF).Initialize(OutContext, TM); - - Mang = new Mangler(OutContext, *TM.getTargetData()); - - // ELF Header - // ---------- - // Fields e_shnum e_shstrndx are only known after all section have - // been emitted. They locations in the ouput buffer are recorded so - // to be patched up later. - // - // Note - // ---- - // emitWord method behaves differently for ELF32 and ELF64, writing - // 4 bytes in the former and 8 in the last for *_off and *_addr elf types - - ElfHdr.emitByte(0x7f); // e_ident[EI_MAG0] - ElfHdr.emitByte('E'); // e_ident[EI_MAG1] - ElfHdr.emitByte('L'); // e_ident[EI_MAG2] - ElfHdr.emitByte('F'); // e_ident[EI_MAG3] - - ElfHdr.emitByte(TEW->getEIClass()); // e_ident[EI_CLASS] - ElfHdr.emitByte(TEW->getEIData()); // e_ident[EI_DATA] - ElfHdr.emitByte(ELF::EV_CURRENT); // e_ident[EI_VERSION] - ElfHdr.emitAlignment(16); // e_ident[EI_NIDENT-EI_PAD] - - ElfHdr.emitWord16(ELF::ET_REL); // e_type - ElfHdr.emitWord16(TEW->getEMachine()); // e_machine = target - ElfHdr.emitWord32(ELF::EV_CURRENT); // e_version - ElfHdr.emitWord(0); // e_entry, no entry point in .o file - ElfHdr.emitWord(0); // e_phoff, no program header for .o - ELFHdr_e_shoff_Offset = ElfHdr.size(); - ElfHdr.emitWord(0); // e_shoff = sec hdr table off in bytes - ElfHdr.emitWord32(TEW->getEFlags()); // e_flags = whatever the target wants - ElfHdr.emitWord16(TEW->getHdrSize()); // e_ehsize = ELF header size - ElfHdr.emitWord16(0); // e_phentsize = prog header entry size - ElfHdr.emitWord16(0); // e_phnum = # prog header entries = 0 - - // e_shentsize = Section header entry size - ElfHdr.emitWord16(TEW->getSHdrSize()); - - // e_shnum = # of section header ents - ELFHdr_e_shnum_Offset = ElfHdr.size(); - ElfHdr.emitWord16(0); // Placeholder - - // e_shstrndx = Section # of '.shstrtab' - ELFHdr_e_shstrndx_Offset = ElfHdr.size(); - ElfHdr.emitWord16(0); // Placeholder - - // Add the null section, which is required to be first in the file. - getNullSection(); - - // The first entry in the symtab is the null symbol and the second - // is a local symbol containing the module/file name - SymbolList.push_back(new ELFSym()); - SymbolList.push_back(ELFSym::getFileSym()); - - return false; -} - -// 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 ELFWriter::AddPendingGlobalSymbol(const GlobalValue *GV, - bool AddToLookup /* = false */) { - PendingGlobals.insert(GV); - if (AddToLookup) - GblSymLookup[GV] = 0; -} - -// 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 ELFWriter::AddPendingExternalSymbol(const char *External) { - PendingExternals.insert(External); - ExtSymLookup[External] = 0; -} - -ELFSection &ELFWriter::getDataSection() { - const MCSectionELF *Data = (const MCSectionELF *)TLOF.getDataSection(); - return getSection(Data->getSectionName(), Data->getType(), - Data->getFlags(), 4); -} - -ELFSection &ELFWriter::getBSSSection() { - const MCSectionELF *BSS = (const MCSectionELF *)TLOF.getBSSSection(); - return getSection(BSS->getSectionName(), BSS->getType(), BSS->getFlags(), 4); -} - -// getCtorSection - Get the static constructor section -ELFSection &ELFWriter::getCtorSection() { - const MCSectionELF *Ctor = (const MCSectionELF *)TLOF.getStaticCtorSection(); - return getSection(Ctor->getSectionName(), Ctor->getType(), Ctor->getFlags()); -} - -// getDtorSection - Get the static destructor section -ELFSection &ELFWriter::getDtorSection() { - const MCSectionELF *Dtor = (const MCSectionELF *)TLOF.getStaticDtorSection(); - return getSection(Dtor->getSectionName(), Dtor->getType(), Dtor->getFlags()); -} - -// getTextSection - Get the text section for the specified function -ELFSection &ELFWriter::getTextSection(const Function *F) { - const MCSectionELF *Text = - (const MCSectionELF *)TLOF.SectionForGlobal(F, Mang, TM); - return getSection(Text->getSectionName(), Text->getType(), Text->getFlags()); -} - -// getJumpTableSection - Get a read only section for constants when -// emitting jump tables. TODO: add PIC support -ELFSection &ELFWriter::getJumpTableSection() { - const MCSectionELF *JT = - (const MCSectionELF *)TLOF.getSectionForConstant(SectionKind::getReadOnly()); - return getSection(JT->getSectionName(), JT->getType(), JT->getFlags(), - TM.getTargetData()->getPointerABIAlignment()); -} - -// getConstantPoolSection - Get a constant pool section based on the machine -// constant pool entry type and relocation info. -ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) { - SectionKind Kind; - switch (CPE.getRelocationInfo()) { - default: llvm_unreachable("Unknown section kind"); - case 2: Kind = SectionKind::getReadOnlyWithRel(); break; - case 1: - Kind = SectionKind::getReadOnlyWithRelLocal(); - break; - case 0: - switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) { - case 4: Kind = SectionKind::getMergeableConst4(); break; - case 8: Kind = SectionKind::getMergeableConst8(); break; - case 16: Kind = SectionKind::getMergeableConst16(); break; - default: Kind = SectionKind::getMergeableConst(); break; - } - } - - const MCSectionELF *CPSect = - (const MCSectionELF *)TLOF.getSectionForConstant(Kind); - return getSection(CPSect->getSectionName(), CPSect->getType(), - CPSect->getFlags(), CPE.getAlignment()); -} - -// getRelocSection - Return the relocation section of section 'S'. 'RelA' -// is true if the relocation section contains entries with addends. -ELFSection &ELFWriter::getRelocSection(ELFSection &S) { - unsigned SectionType = TEW->hasRelocationAddend() ? - ELF::SHT_RELA : ELF::SHT_REL; - - std::string SectionName(".rel"); - if (TEW->hasRelocationAddend()) - SectionName.append("a"); - SectionName.append(S.getName()); - - return getSection(SectionName, SectionType, 0, TEW->getPrefELFAlignment()); -} - -// getGlobalELFVisibility - Returns the ELF specific visibility type -unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) { - switch (GV->getVisibility()) { - default: - llvm_unreachable("unknown visibility type"); - case GlobalValue::DefaultVisibility: - return ELF::STV_DEFAULT; - case GlobalValue::HiddenVisibility: - return ELF::STV_HIDDEN; - case GlobalValue::ProtectedVisibility: - return ELF::STV_PROTECTED; - } - return 0; -} - -// getGlobalELFBinding - Returns the ELF specific binding type -unsigned ELFWriter::getGlobalELFBinding(const GlobalValue *GV) { - if (GV->hasInternalLinkage()) - return ELF::STB_LOCAL; - - if (GV->isWeakForLinker() && !GV->hasCommonLinkage()) - return ELF::STB_WEAK; - - return ELF::STB_GLOBAL; -} - -// getGlobalELFType - Returns the ELF specific type for a global -unsigned ELFWriter::getGlobalELFType(const GlobalValue *GV) { - if (GV->isDeclaration()) - return ELF::STT_NOTYPE; - - if (isa(GV)) - return ELF::STT_FUNC; - - return ELF::STT_OBJECT; -} - -// IsELFUndefSym - True if the global value must be marked as a symbol -// which points to a SHN_UNDEF section. This means that the symbol has -// no definition on the module. -static bool IsELFUndefSym(const GlobalValue *GV) { - return GV->isDeclaration() || (isa(GV)); -} - -// AddToSymbolList - Update the symbol lookup and If the symbol is -// private add it to PrivateSyms list, otherwise to SymbolList. -void ELFWriter::AddToSymbolList(ELFSym *GblSym) { - assert(GblSym->isGlobalValue() && "Symbol must be a global value"); - - const GlobalValue *GV = GblSym->getGlobalValue(); - if (GV->hasPrivateLinkage()) { - // For a private symbols, keep track of the index inside - // the private list since it will never go to the symbol - // table and won't be patched up later. - PrivateSyms.push_back(GblSym); - GblSymLookup[GV] = PrivateSyms.size()-1; - } else { - // Non private symbol are left with zero indices until - // they are patched up during the symbol table emition - // (where the indicies are created). - SymbolList.push_back(GblSym); - GblSymLookup[GV] = 0; - } -} - -/// HasCommonSymbols - True if this section holds common symbols, this is -/// indicated on the ELF object file by a symbol with SHN_COMMON section -/// header index. -static bool HasCommonSymbols(const MCSectionELF &S) { - // FIXME: this is wrong, a common symbol can be in .data for example. - if (StringRef(S.getSectionName()).startswith(".gnu.linkonce.")) - return true; - - return false; -} - - -// EmitGlobal - Choose the right section for global and emit it -void ELFWriter::EmitGlobal(const GlobalValue *GV) { - - // Check if the referenced symbol is already emitted - if (GblSymLookup.find(GV) != GblSymLookup.end()) - return; - - // Handle ELF Bind, Visibility and Type for the current symbol - unsigned SymBind = getGlobalELFBinding(GV); - unsigned SymType = getGlobalELFType(GV); - bool IsUndefSym = IsELFUndefSym(GV); - - ELFSym *GblSym = IsUndefSym ? ELFSym::getUndefGV(GV, SymBind) - : ELFSym::getGV(GV, SymBind, SymType, getGlobalELFVisibility(GV)); - - if (!IsUndefSym) { - assert(isa(GV) && "GV not a global variable!"); - const GlobalVariable *GVar = dyn_cast(GV); - - // Handle special llvm globals - if (EmitSpecialLLVMGlobal(GVar)) - return; - - // Get the ELF section where this global belongs from TLOF - const MCSectionELF *S = - (const MCSectionELF *)TLOF.SectionForGlobal(GV, Mang, TM); - ELFSection &ES = - getSection(S->getSectionName(), S->getType(), S->getFlags()); - SectionKind Kind = S->getKind(); - - // The symbol align should update the section alignment if needed - const TargetData *TD = TM.getTargetData(); - unsigned Align = TD->getPreferredAlignment(GVar); - unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType()); - GblSym->Size = Size; - - if (HasCommonSymbols(*S)) { // Symbol must go to a common section - GblSym->SectionIdx = ELF::SHN_COMMON; - - // A new linkonce section is created for each global in the - // common section, the default alignment is 1 and the symbol - // value contains its alignment. - ES.Align = 1; - GblSym->Value = Align; - - } else if (Kind.isBSS() || Kind.isThreadBSS()) { // Symbol goes to BSS. - GblSym->SectionIdx = ES.SectionIdx; - - // Update the size with alignment and the next object can - // start in the right offset in the section - if (Align) ES.Size = (ES.Size + Align-1) & ~(Align-1); - ES.Align = std::max(ES.Align, Align); - - // GblSym->Value should contain the virtual offset inside the section. - // Virtual because the BSS space is not allocated on ELF objects - GblSym->Value = ES.Size; - ES.Size += Size; - - } else { // The symbol must go to some kind of data section - GblSym->SectionIdx = ES.SectionIdx; - - // GblSym->Value should contain the symbol offset inside the section, - // and all symbols should start on their required alignment boundary - ES.Align = std::max(ES.Align, Align); - ES.emitAlignment(Align); - GblSym->Value = ES.size(); - - // Emit the global to the data section 'ES' - EmitGlobalConstant(GVar->getInitializer(), ES); - } - } - - AddToSymbolList(GblSym); -} - -void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS, - ELFSection &GblS) { - - // Print the fields in successive locations. Pad to align if needed! - const TargetData *TD = TM.getTargetData(); - unsigned Size = TD->getTypeAllocSize(CVS->getType()); - const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType()); - uint64_t sizeSoFar = 0; - for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { - const Constant* field = CVS->getOperand(i); - - // Check if padding is needed and insert one or more 0s. - uint64_t fieldSize = TD->getTypeAllocSize(field->getType()); - uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1)) - - cvsLayout->getElementOffset(i)) - fieldSize; - sizeSoFar += fieldSize + padSize; - - // Now print the actual field value. - EmitGlobalConstant(field, GblS); - - // Insert padding - this may include padding to increase the size of the - // current field up to the ABI size (if the struct is not packed) as well - // as padding to ensure that the next field starts at the right offset. - GblS.emitZeros(padSize); - } - assert(sizeSoFar == cvsLayout->getSizeInBytes() && - "Layout of constant struct may be incorrect!"); -} - -void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) { - const TargetData *TD = TM.getTargetData(); - unsigned Size = TD->getTypeAllocSize(CV->getType()); - - if (const ConstantArray *CVA = dyn_cast(CV)) { - for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) - EmitGlobalConstant(CVA->getOperand(i), GblS); - return; - } else if (isa(CV)) { - GblS.emitZeros(Size); - return; - } else if (const ConstantStruct *CVS = dyn_cast(CV)) { - EmitGlobalConstantStruct(CVS, GblS); - return; - } else if (const ConstantFP *CFP = dyn_cast(CV)) { - APInt Val = CFP->getValueAPF().bitcastToAPInt(); - if (CFP->getType()->isDoubleTy()) - GblS.emitWord64(Val.getZExtValue()); - else if (CFP->getType()->isFloatTy()) - GblS.emitWord32(Val.getZExtValue()); - else if (CFP->getType()->isX86_FP80Ty()) { - unsigned PadSize = TD->getTypeAllocSize(CFP->getType())- - TD->getTypeStoreSize(CFP->getType()); - GblS.emitWordFP80(Val.getRawData(), PadSize); - } else if (CFP->getType()->isPPC_FP128Ty()) - llvm_unreachable("PPC_FP128Ty global emission not implemented"); - return; - } else if (const ConstantInt *CI = dyn_cast(CV)) { - if (Size == 1) - GblS.emitByte(CI->getZExtValue()); - else if (Size == 2) - GblS.emitWord16(CI->getZExtValue()); - else if (Size == 4) - GblS.emitWord32(CI->getZExtValue()); - else - EmitGlobalConstantLargeInt(CI, GblS); - return; - } else if (const ConstantVector *CP = dyn_cast(CV)) { - VectorType *PTy = CP->getType(); - for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I) - EmitGlobalConstant(CP->getOperand(I), GblS); - return; - } else if (const ConstantExpr *CE = dyn_cast(CV)) { - // Resolve a constant expression which returns a (Constant, Offset) - // pair. If 'Res.first' is a GlobalValue, emit a relocation with - // the offset 'Res.second', otherwise emit a global constant like - // it is always done for not contant expression types. - CstExprResTy Res = ResolveConstantExpr(CE); - const Constant *Op = Res.first; - - if (isa(Op)) - EmitGlobalDataRelocation(cast(Op), - TD->getTypeAllocSize(Op->getType()), - GblS, Res.second); - else - EmitGlobalConstant(Op, GblS); - - return; - } else if (CV->getType()->getTypeID() == Type::PointerTyID) { - // Fill the data entry with zeros or emit a relocation entry - if (isa(CV)) - GblS.emitZeros(Size); - else - EmitGlobalDataRelocation(cast(CV), - Size, GblS); - return; - } else if (const GlobalValue *GV = dyn_cast(CV)) { - // This is a constant address for a global variable or function and - // therefore must be referenced using a relocation entry. - EmitGlobalDataRelocation(GV, Size, GblS); - return; - } - - std::string msg; - raw_string_ostream ErrorMsg(msg); - ErrorMsg << "Constant unimp for type: " << *CV->getType(); - report_fatal_error(ErrorMsg.str()); -} - -// ResolveConstantExpr - Resolve the constant expression until it stop -// yielding other constant expressions. -CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) { - const TargetData *TD = TM.getTargetData(); - - // There ins't constant expression inside others anymore - if (!isa(CV)) - return std::make_pair(CV, 0); - - const ConstantExpr *CE = dyn_cast(CV); - switch (CE->getOpcode()) { - case Instruction::BitCast: - return ResolveConstantExpr(CE->getOperand(0)); - - case Instruction::GetElementPtr: { - const Constant *ptrVal = CE->getOperand(0); - SmallVector idxVec(CE->op_begin()+1, CE->op_end()); - int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), idxVec); - return std::make_pair(ptrVal, Offset); - } - case Instruction::IntToPtr: { - Constant *Op = CE->getOperand(0); - Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()), - false/*ZExt*/); - return ResolveConstantExpr(Op); - } - case Instruction::PtrToInt: { - Constant *Op = CE->getOperand(0); - Type *Ty = CE->getType(); - - // We can emit the pointer value into this slot if the slot is an - // integer slot greater or equal to the size of the pointer. - if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType())) - return ResolveConstantExpr(Op); - - llvm_unreachable("Integer size less then pointer size"); - } - case Instruction::Add: - case Instruction::Sub: { - // Only handle cases where there's a constant expression with GlobalValue - // as first operand and ConstantInt as second, which are the cases we can - // solve direclty using a relocation entry. GlobalValue=Op0, CstInt=Op1 - // 1) Instruction::Add => (global) + CstInt - // 2) Instruction::Sub => (global) + -CstInt - const Constant *Op0 = CE->getOperand(0); - const Constant *Op1 = CE->getOperand(1); - assert(isa(Op1) && "Op1 must be a ConstantInt"); - - CstExprResTy Res = ResolveConstantExpr(Op0); - assert(isa(Res.first) && "Op0 must be a GlobalValue"); - - const APInt &RHS = cast(Op1)->getValue(); - switch (CE->getOpcode()) { - case Instruction::Add: - return std::make_pair(Res.first, RHS.getSExtValue()); - case Instruction::Sub: - return std::make_pair(Res.first, (-RHS).getSExtValue()); - } - } - } - - report_fatal_error(CE->getOpcodeName() + - StringRef(": Unsupported ConstantExpr type")); - - return std::make_pair(CV, 0); // silence warning -} - -void ELFWriter::EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size, - ELFSection &GblS, int64_t Offset) { - // Create the relocation entry for the global value - MachineRelocation MR = - MachineRelocation::getGV(GblS.getCurrentPCOffset(), - TEW->getAbsoluteLabelMachineRelTy(), - const_cast(GV), - Offset); - - // Fill the data entry with zeros - GblS.emitZeros(Size); - - // Add the relocation entry for the current data section - GblS.addRelocation(MR); -} - -void ELFWriter::EmitGlobalConstantLargeInt(const ConstantInt *CI, - ELFSection &S) { - const TargetData *TD = TM.getTargetData(); - unsigned BitWidth = CI->getBitWidth(); - assert(isPowerOf2_32(BitWidth) && - "Non-power-of-2-sized integers not handled!"); - - const uint64_t *RawData = CI->getValue().getRawData(); - uint64_t Val = 0; - for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) { - Val = (TD->isBigEndian()) ? RawData[e - i - 1] : RawData[i]; - S.emitWord64(Val); - } -} - -/// EmitSpecialLLVMGlobal - Check to see if the specified global is a -/// special global used by LLVM. If so, emit it and return true, otherwise -/// do nothing and return false. -bool ELFWriter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) { - if (GV->getName() == "llvm.used") - llvm_unreachable("not implemented yet"); - - // Ignore debug and non-emitted data. This handles llvm.compiler.used. - if (GV->getSection() == "llvm.metadata" || - GV->hasAvailableExternallyLinkage()) - return true; - - if (!GV->hasAppendingLinkage()) return false; - - assert(GV->hasInitializer() && "Not a special LLVM global!"); - - const TargetData *TD = TM.getTargetData(); - unsigned Align = TD->getPointerPrefAlignment(); - if (GV->getName() == "llvm.global_ctors") { - ELFSection &Ctor = getCtorSection(); - Ctor.emitAlignment(Align); - EmitXXStructorList(GV->getInitializer(), Ctor); - return true; - } - - if (GV->getName() == "llvm.global_dtors") { - ELFSection &Dtor = getDtorSection(); - Dtor.emitAlignment(Align); - EmitXXStructorList(GV->getInitializer(), Dtor); - return true; - } - - return false; -} - -/// EmitXXStructorList - Emit the ctor or dtor list. This just emits out the -/// function pointers, ignoring the init priority. -void ELFWriter::EmitXXStructorList(const Constant *List, ELFSection &Xtor) { - // Should be an array of '{ i32, void ()* }' structs. The first value is the - // init priority, which we ignore. - if (List->isNullValue()) return; - const ConstantArray *InitList = cast(List); - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { - if (InitList->getOperand(i)->isNullValue()) - continue; - ConstantStruct *CS = cast(InitList->getOperand(i)); - - if (CS->getOperand(1)->isNullValue()) - continue; - - // Emit the function pointer. - EmitGlobalConstant(CS->getOperand(1), Xtor); - } -} - -bool ELFWriter::runOnMachineFunction(MachineFunction &MF) { - // Nothing to do here, this is all done through the ElfCE object above. - return false; -} - -/// doFinalization - Now that the module has been completely processed, emit -/// the ELF file to 'O'. -bool ELFWriter::doFinalization(Module &M) { - // Emit .data section placeholder - getDataSection(); - - // Emit .bss section placeholder - getBSSSection(); - - // Build and emit data, bss and "common" sections. - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - EmitGlobal(I); - - // Emit all pending globals - for (PendingGblsIter I = PendingGlobals.begin(), E = PendingGlobals.end(); - I != E; ++I) - EmitGlobal(*I); - - // Emit all pending externals - for (PendingExtsIter I = PendingExternals.begin(), E = PendingExternals.end(); - I != E; ++I) - SymbolList.push_back(ELFSym::getExtSym(*I)); - - // Emit a symbol for each section created until now, skip null section - for (unsigned i = 1, e = SectionList.size(); i < e; ++i) { - ELFSection &ES = *SectionList[i]; - ELFSym *SectionSym = ELFSym::getSectionSym(); - SectionSym->SectionIdx = ES.SectionIdx; - SymbolList.push_back(SectionSym); - ES.Sym = SymbolList.back(); - } - - // Emit string table - EmitStringTable(M.getModuleIdentifier()); - - // Emit the symbol table now, if non-empty. - EmitSymbolTable(); - - // Emit the relocation sections. - EmitRelocations(); - - // Emit the sections string table. - EmitSectionTableStringTable(); - - // Dump the sections and section table to the .o file. - OutputSectionsAndSectionTable(); - - return false; -} - -// RelocateField - Patch relocatable field with 'Offset' in 'BO' -// using a 'Value' of known 'Size' -void ELFWriter::RelocateField(BinaryObject &BO, uint32_t Offset, - int64_t Value, unsigned Size) { - if (Size == 32) - BO.fixWord32(Value, Offset); - else if (Size == 64) - BO.fixWord64(Value, Offset); - else - llvm_unreachable("don't know howto patch relocatable field"); -} - -/// EmitRelocations - Emit relocations -void ELFWriter::EmitRelocations() { - - // True if the target uses the relocation entry to hold the addend, - // otherwise the addend is written directly to the relocatable field. - bool HasRelA = TEW->hasRelocationAddend(); - - // Create Relocation sections for each section which needs it. - for (unsigned i=0, e=SectionList.size(); i != e; ++i) { - ELFSection &S = *SectionList[i]; - - // This section does not have relocations - if (!S.hasRelocations()) continue; - ELFSection &RelSec = getRelocSection(S); - - // 'Link' - Section hdr idx of the associated symbol table - // 'Info' - Section hdr idx of the section to which the relocation applies - ELFSection &SymTab = getSymbolTableSection(); - RelSec.Link = SymTab.SectionIdx; - RelSec.Info = S.SectionIdx; - RelSec.EntSize = TEW->getRelocationEntrySize(); - - // Get the relocations from Section - std::vector Relos = S.getRelocations(); - for (std::vector::iterator MRI = Relos.begin(), - MRE = Relos.end(); MRI != MRE; ++MRI) { - MachineRelocation &MR = *MRI; - - // Relocatable field offset from the section start - unsigned RelOffset = MR.getMachineCodeOffset(); - - // Symbol index in the symbol table - unsigned SymIdx = 0; - - // Target specific relocation field type and size - unsigned RelType = TEW->getRelocationType(MR.getRelocationType()); - unsigned RelTySize = TEW->getRelocationTySize(RelType); - int64_t Addend = 0; - - // There are several machine relocations types, and each one of - // them needs a different approach to retrieve the symbol table index. - if (MR.isGlobalValue()) { - const GlobalValue *G = MR.getGlobalValue(); - int64_t GlobalOffset = MR.getConstantVal(); - SymIdx = GblSymLookup[G]; - if (G->hasPrivateLinkage()) { - // If the target uses a section offset in the relocation: - // SymIdx + Addend = section sym for global + section offset - unsigned SectionIdx = PrivateSyms[SymIdx]->SectionIdx; - Addend = PrivateSyms[SymIdx]->Value + GlobalOffset; - SymIdx = SectionList[SectionIdx]->getSymbolTableIndex(); - } else { - Addend = TEW->getDefaultAddendForRelTy(RelType, GlobalOffset); - } - } else if (MR.isExternalSymbol()) { - const char *ExtSym = MR.getExternalSymbol(); - SymIdx = ExtSymLookup[ExtSym]; - Addend = TEW->getDefaultAddendForRelTy(RelType); - } else { - // Get the symbol index for the section symbol - unsigned SectionIdx = MR.getConstantVal(); - SymIdx = SectionList[SectionIdx]->getSymbolTableIndex(); - - // The symbol offset inside the section - int64_t SymOffset = (int64_t)MR.getResultPointer(); - - // For pc relative relocations where symbols are defined in the same - // section they are referenced, ignore the relocation entry and patch - // the relocatable field with the symbol offset directly. - if (S.SectionIdx == SectionIdx && TEW->isPCRelativeRel(RelType)) { - int64_t Value = TEW->computeRelocation(SymOffset, RelOffset, RelType); - RelocateField(S, RelOffset, Value, RelTySize); - continue; - } - - Addend = TEW->getDefaultAddendForRelTy(RelType, SymOffset); - } - - // The target without addend on the relocation symbol must be - // patched in the relocation place itself to contain the addend - // otherwise write zeros to make sure there is no garbage there - RelocateField(S, RelOffset, HasRelA ? 0 : Addend, RelTySize); - - // Get the relocation entry and emit to the relocation section - ELFRelocation Rel(RelOffset, SymIdx, RelType, HasRelA, Addend); - EmitRelocation(RelSec, Rel, HasRelA); - } - } -} - -/// EmitRelocation - Write relocation 'Rel' to the relocation section 'Rel' -void ELFWriter::EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel, - bool HasRelA) { - RelSec.emitWord(Rel.getOffset()); - RelSec.emitWord(Rel.getInfo(is64Bit)); - if (HasRelA) - RelSec.emitWord(Rel.getAddend()); -} - -/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable' -void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) { - if (is64Bit) { - SymbolTable.emitWord32(Sym.NameIdx); - SymbolTable.emitByte(Sym.Info); - SymbolTable.emitByte(Sym.Other); - SymbolTable.emitWord16(Sym.SectionIdx); - SymbolTable.emitWord64(Sym.Value); - SymbolTable.emitWord64(Sym.Size); - } else { - SymbolTable.emitWord32(Sym.NameIdx); - SymbolTable.emitWord32(Sym.Value); - SymbolTable.emitWord32(Sym.Size); - SymbolTable.emitByte(Sym.Info); - SymbolTable.emitByte(Sym.Other); - SymbolTable.emitWord16(Sym.SectionIdx); - } -} - -/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab' -/// Section Header Table -void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab, - const ELFSection &SHdr) { - SHdrTab.emitWord32(SHdr.NameIdx); - SHdrTab.emitWord32(SHdr.Type); - if (is64Bit) { - SHdrTab.emitWord64(SHdr.Flags); - SHdrTab.emitWord(SHdr.Addr); - SHdrTab.emitWord(SHdr.Offset); - SHdrTab.emitWord64(SHdr.Size); - SHdrTab.emitWord32(SHdr.Link); - SHdrTab.emitWord32(SHdr.Info); - SHdrTab.emitWord64(SHdr.Align); - SHdrTab.emitWord64(SHdr.EntSize); - } else { - SHdrTab.emitWord32(SHdr.Flags); - SHdrTab.emitWord(SHdr.Addr); - SHdrTab.emitWord(SHdr.Offset); - SHdrTab.emitWord32(SHdr.Size); - SHdrTab.emitWord32(SHdr.Link); - SHdrTab.emitWord32(SHdr.Info); - SHdrTab.emitWord32(SHdr.Align); - SHdrTab.emitWord32(SHdr.EntSize); - } -} - -/// EmitStringTable - If the current symbol table is non-empty, emit the string -/// table for it -void ELFWriter::EmitStringTable(const std::string &ModuleName) { - if (!SymbolList.size()) return; // Empty symbol table. - ELFSection &StrTab = getStringTableSection(); - - // Set the zero'th symbol to a null byte, as required. - StrTab.emitByte(0); - - // Walk on the symbol list and write symbol names into the string table. - unsigned Index = 1; - for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { - ELFSym &Sym = *(*I); - - std::string Name; - if (Sym.isGlobalValue()) { - SmallString<40> NameStr; - Mang->getNameWithPrefix(NameStr, Sym.getGlobalValue(), false); - Name.append(NameStr.begin(), NameStr.end()); - } else if (Sym.isExternalSym()) - Name.append(Sym.getExternalSymbol()); - else if (Sym.isFileType()) - Name.append(ModuleName); - - if (Name.empty()) { - Sym.NameIdx = 0; - } else { - Sym.NameIdx = Index; - StrTab.emitString(Name); - - // Keep track of the number of bytes emitted to this section. - Index += Name.size()+1; - } - } - assert(Index == StrTab.size()); - StrTab.Size = Index; -} - -// SortSymbols - On the symbol table local symbols must come before -// all other symbols with non-local bindings. The return value is -// the position of the first non local symbol. -unsigned ELFWriter::SortSymbols() { - unsigned FirstNonLocalSymbol; - std::vector LocalSyms, OtherSyms; - - for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) { - if ((*I)->isLocalBind()) - LocalSyms.push_back(*I); - else - OtherSyms.push_back(*I); - } - SymbolList.clear(); - FirstNonLocalSymbol = LocalSyms.size(); - - for (unsigned i = 0; i < FirstNonLocalSymbol; ++i) - SymbolList.push_back(LocalSyms[i]); - - for (ELFSymIter I=OtherSyms.begin(), E=OtherSyms.end(); I != E; ++I) - SymbolList.push_back(*I); - - LocalSyms.clear(); - OtherSyms.clear(); - - return FirstNonLocalSymbol; -} - -/// EmitSymbolTable - Emit the symbol table itself. -void ELFWriter::EmitSymbolTable() { - if (!SymbolList.size()) return; // Empty symbol table. - - // Now that we have emitted the string table and know the offset into the - // string table of each symbol, emit the symbol table itself. - ELFSection &SymTab = getSymbolTableSection(); - SymTab.Align = TEW->getPrefELFAlignment(); - - // Section Index of .strtab. - SymTab.Link = getStringTableSection().SectionIdx; - - // Size of each symtab entry. - SymTab.EntSize = TEW->getSymTabEntrySize(); - - // Reorder the symbol table with local symbols first! - unsigned FirstNonLocalSymbol = SortSymbols(); - - // Emit all the symbols to the symbol table. - for (unsigned i = 0, e = SymbolList.size(); i < e; ++i) { - ELFSym &Sym = *SymbolList[i]; - - // Emit symbol to the symbol table - EmitSymbol(SymTab, Sym); - - // Record the symbol table index for each symbol - if (Sym.isGlobalValue()) - GblSymLookup[Sym.getGlobalValue()] = i; - else if (Sym.isExternalSym()) - ExtSymLookup[Sym.getExternalSymbol()] = i; - - // Keep track on the symbol index into the symbol table - Sym.SymTabIdx = i; - } - - // One greater than the symbol table index of the last local symbol - SymTab.Info = FirstNonLocalSymbol; - SymTab.Size = SymTab.size(); -} - -/// EmitSectionTableStringTable - This method adds and emits a section for the -/// ELF Section Table string table: the string table that holds all of the -/// section names. -void ELFWriter::EmitSectionTableStringTable() { - // First step: add the section for the string table to the list of sections: - ELFSection &SHStrTab = getSectionHeaderStringTableSection(); - - // Now that we know which section number is the .shstrtab section, update the - // e_shstrndx entry in the ELF header. - ElfHdr.fixWord16(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset); - - // Set the NameIdx of each section in the string table and emit the bytes for - // the string table. - unsigned Index = 0; - - for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) { - ELFSection &S = *(*I); - // Set the index into the table. Note if we have lots of entries with - // common suffixes, we could memoize them here if we cared. - S.NameIdx = Index; - SHStrTab.emitString(S.getName()); - - // Keep track of the number of bytes emitted to this section. - Index += S.getName().size()+1; - } - - // Set the size of .shstrtab now that we know what it is. - assert(Index == SHStrTab.size()); - SHStrTab.Size = Index; -} - -/// OutputSectionsAndSectionTable - Now that we have constructed the file header -/// and all of the sections, emit these to the ostream destination and emit the -/// SectionTable. -void ELFWriter::OutputSectionsAndSectionTable() { - // Pass #1: Compute the file offset for each section. - size_t FileOff = ElfHdr.size(); // File header first. - - // Adjust alignment of all section if needed, skip the null section. - for (unsigned i=1, e=SectionList.size(); i < e; ++i) { - ELFSection &ES = *SectionList[i]; - if (!ES.size()) { - ES.Offset = FileOff; - continue; - } - - // Update Section size - if (!ES.Size) - ES.Size = ES.size(); - - // Align FileOff to whatever the alignment restrictions of the section are. - if (ES.Align) - FileOff = (FileOff+ES.Align-1) & ~(ES.Align-1); - - ES.Offset = FileOff; - FileOff += ES.Size; - } - - // Align Section Header. - unsigned TableAlign = TEW->getPrefELFAlignment(); - FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1); - - // Now that we know where all of the sections will be emitted, set the e_shnum - // entry in the ELF header. - ElfHdr.fixWord16(NumSections, ELFHdr_e_shnum_Offset); - - // Now that we know the offset in the file of the section table, update the - // e_shoff address in the ELF header. - ElfHdr.fixWord(FileOff, ELFHdr_e_shoff_Offset); - - // Now that we know all of the data in the file header, emit it and all of the - // sections! - O.write((char *)&ElfHdr.getData()[0], ElfHdr.size()); - FileOff = ElfHdr.size(); - - // Section Header Table blob - BinaryObject SHdrTable(isLittleEndian, is64Bit); - - // Emit all of sections to the file and build the section header table. - for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) { - ELFSection &S = *(*I); - DEBUG(dbgs() << "SectionIdx: " << S.SectionIdx << ", Name: " << S.getName() - << ", Size: " << S.Size << ", Offset: " << S.Offset - << ", SectionData Size: " << S.size() << "\n"); - - // Align FileOff to whatever the alignment restrictions of the section are. - if (S.size()) { - if (S.Align) { - for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1); - FileOff != NewFileOff; ++FileOff) - O << (char)0xAB; - } - O.write((char *)&S.getData()[0], S.Size); - FileOff += S.Size; - } - - EmitSectionHeader(SHdrTable, S); - } - - // Align output for the section table. - for (size_t NewFileOff = (FileOff+TableAlign-1) & ~(TableAlign-1); - FileOff != NewFileOff; ++FileOff) - O << (char)0xAB; - - // Emit the section table itself. - O.write((char *)&SHdrTable.getData()[0], SHdrTable.size()); -} diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h deleted file mode 100644 index 6f7fbace8a..0000000000 --- a/lib/CodeGen/ELFWriter.h +++ /dev/null @@ -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 - -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::iterator ELFSymIter; - typedef std::vector::iterator ELFSectionIter; - typedef SetVector::const_iterator PendingGblsIter; - typedef SetVector::const_iterator PendingExtsIter; - typedef std::pair 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(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 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 SectionLookup; - - /// PendingGlobals - Globals not processed as symbols yet. - SetVector 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 GblSymLookup; - - /// PendingExternals - Externals not processed as symbols yet. - SetVector 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 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 SymbolList; - - /// PrivateSyms - Record private symbols, every symbol here must never be - /// present in the SymbolList. - std::vector 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 diff --git a/lib/ExecutionEngine/JIT/CMakeLists.txt b/lib/ExecutionEngine/JIT/CMakeLists.txt index cefb0aedde..dcef08c47f 100644 --- a/lib/ExecutionEngine/JIT/CMakeLists.txt +++ b/lib/ExecutionEngine/JIT/CMakeLists.txt @@ -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 diff --git a/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp b/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp deleted file mode 100644 index abb70fb707..0000000000 --- a/lib/ExecutionEngine/JIT/JITDebugRegisterer.cpp +++ /dev/null @@ -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 - -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(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 diff --git a/lib/ExecutionEngine/JIT/JITDebugRegisterer.h b/lib/ExecutionEngine/JIT/JITDebugRegisterer.h deleted file mode 100644 index dce506bbfe..0000000000 --- a/lib/ExecutionEngine/JIT/JITDebugRegisterer.h +++ /dev/null @@ -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 - -// 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 > - 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 diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index d9fa509afb..91305fd384 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -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 DE; - /// DR - The debug registerer for the jit. - OwningPtr DR; - /// LabelLocations - This vector is a mapping from Label ID's to their /// address. DenseMap 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); - } } -- cgit v1.2.3