X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FELFWriter.h;h=6f7fbace8abaa83298a8bb805187dbc39da30a90;hb=fd9c4f76f4a1ec06891a3405198fc907f8253958;hp=8b577a0a783573b40cd2125681704e7c0264ad18;hpb=794fd75c67a2cdc128d67342c6d88a504d186896;p=oota-llvm.git diff --git a/lib/CodeGen/ELFWriter.h b/lib/CodeGen/ELFWriter.h index 8b577a0a783..6f7fbace8ab 100644 --- a/lib/CodeGen/ELFWriter.h +++ b/lib/CodeGen/ELFWriter.h @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Chris Lattner and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -14,14 +14,38 @@ #ifndef ELFWRITER_H #define ELFWRITER_H +#include "llvm/ADT/SetVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include +#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 ELFCodeEmitter; + 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 @@ -29,49 +53,49 @@ namespace llvm { /// class ELFWriter : public MachineFunctionPass { friend class ELFCodeEmitter; + friend class JITDebugRegisterer; public: - static const int ID; + static char ID; - MachineCodeEmitter &getMachineCodeEmitter() const { - return *(MachineCodeEmitter*)MCE; + /// Return the ELFCodeEmitter as an instance of ObjectCodeEmitter + ObjectCodeEmitter *getObjectCodeEmitter() { + return reinterpret_cast(ElfCE); } - ELFWriter(std::ostream &O, TargetMachine &TM); + ELFWriter(raw_ostream &O, TargetMachine &TM); ~ELFWriter(); - typedef std::vector DataBuffer; - protected: /// Output stream to send the resultant object file to. - /// - std::ostream &O; + 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 *MCE; + ELFCodeEmitter *ElfCE; - //===------------------------------------------------------------------===// - // Properties to be set by the derived class ctor, used to configure the - // ELFWriter. - - // e_machine - This field is the target specific value to emit as the - // e_machine member of the ELF header. - unsigned short e_machine; + /// TLOF - Target Lowering Object File, provide section names for globals + /// and other object file specific stuff + const TargetLoweringObjectFile &TLOF; - // e_flags - The machine flags for the target. This defaults to zero. - unsigned e_flags; + /// 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. @@ -80,148 +104,147 @@ namespace llvm { /// doInitialization - Emit the file header and all of the global variables /// for the module to the ELF file. bool doInitialization(Module &M); - bool runOnMachineFunction(MachineFunction &MF); - /// doFinalization - Now that the module has been completely processed, emit /// the ELF file to 'O'. bool doFinalization(Module &M); private: - // The buffer we accumulate the file header into. Note that this should be - // changed into something much more efficient later (and the bytecode writer - // as well!). - DataBuffer FileHeader; - - /// ELFSection - This struct contains information about each section that is - /// emitted to the file. This is eventually turned into the section header - /// table at the end of the file. - struct ELFSection { - std::string Name; // Name of the section. - unsigned NameIdx; // Index in .shstrtab of name, once emitted. - unsigned Type; - unsigned Flags; - uint64_t Addr; - unsigned Offset; - unsigned Size; - unsigned Link; - unsigned Info; - unsigned Align; - unsigned EntSize; - - /// SectionIdx - The number of the section in the Section Table. - /// - unsigned short SectionIdx; - - /// SectionData - The actual data for this section which we are building - /// up for emission to the file. - DataBuffer SectionData; - - enum { SHT_NULL = 0, SHT_PROGBITS = 1, SHT_SYMTAB = 2, SHT_STRTAB = 3, - SHT_RELA = 4, SHT_HASH = 5, SHT_DYNAMIC = 6, SHT_NOTE = 7, - SHT_NOBITS = 8, SHT_REL = 9, SHT_SHLIB = 10, SHT_DYNSYM = 11 }; - enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1, SHN_COMMON = 0xFFF2 }; - enum { // SHF - ELF Section Header Flags - SHF_WRITE = 1 << 0, // Writable - SHF_ALLOC = 1 << 1, // Mapped into the process addr space - SHF_EXECINSTR = 1 << 2, // Executable - SHF_MERGE = 1 << 4, // Might be merged if equal - SHF_STRINGS = 1 << 5, // Contains null-terminated strings - SHF_INFO_LINK = 1 << 6, // 'sh_info' contains SHT index - SHF_LINK_ORDER = 1 << 7, // Preserve order after combining - SHF_OS_NONCONFORMING = 1 << 8, // nonstandard OS support required - SHF_GROUP = 1 << 9, // Section is a member of a group - SHF_TLS = 1 << 10 // Section holds thread-local data - }; - - ELFSection(const std::string &name) - : Name(name), Type(0), Flags(0), Addr(0), Offset(0), Size(0), - Link(0), Info(0), Align(0), EntSize(0) { - } - }; + /// 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 + /// file. Once the file has been completely built, the section header table /// is constructed from this info. - std::list SectionList; + std::vector SectionList; unsigned NumSections; // Always = SectionList.size() /// SectionLookup - This is a mapping from section name to section number in - /// the SectionList. + /// 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) { + 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(Name); - SN = &SectionList.back(); + 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 &getDataSection() { - return getSection(".data", ELFSection::SHT_PROGBITS, - ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC); + ELFSection &getNonExecStackSection() { + return getSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0, 1); + } + + ELFSection &getSymbolTableSection() { + return getSection(".symtab", ELF::SHT_SYMTAB, 0); } - ELFSection &getBSSSection() { - return getSection(".bss", ELFSection::SHT_NOBITS, - ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC); + + ELFSection &getStringTableSection() { + return getSection(".strtab", ELF::SHT_STRTAB, 0, 1); } - /// ELFSym - This struct contains information about each symbol that is - /// added to logical symbol table for the module. This is eventually - /// turned into a real symbol table in the file. - struct ELFSym { - const GlobalValue *GV; // The global value this corresponds to. - unsigned NameIdx; // Index in .strtab of name, once emitted. - uint64_t Value; - unsigned Size; - unsigned char Info; - unsigned char Other; - unsigned short SectionIdx; - - enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 }; - enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3, - STT_FILE = 4 }; - ELFSym(const GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0), - Other(0), SectionIdx(0) {} - - void SetBind(unsigned X) { - assert(X == (X & 0xF) && "Bind value out of range!"); - Info = (Info & 0x0F) | (X << 4); - } - void SetType(unsigned X) { - assert(X == (X & 0xF) && "Type value out of range!"); - Info = (Info & 0xF0) | X; - } - }; - - /// SymbolTable - This is the list of symbols we have emitted to the file. - /// This actually gets rearranged before emission to the file (to put the - /// local symbols first in the list). - std::vector SymbolTable; + 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 ELFHeader_e_shoff_Offset; // e_shoff in ELF header. - unsigned ELFHeader_e_shstrndx_Offset; // e_shstrndx in ELF header. - unsigned ELFHeader_e_shnum_Offset; // e_shnum in ELF header. - private: - void EmitGlobal(GlobalVariable *GV); - - void EmitSymbolTable(); + 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); }; }