//===-- 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/CodeGen/MachineFunctionPass.h" #include #include namespace llvm { class GlobalVariable; class Mangler; class MachineCodeEmitter; class ELFCodeEmitter; class raw_ostream; /// 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; public: static char ID; MachineCodeEmitter &getMachineCodeEmitter() const { return *(MachineCodeEmitter*)MCE; } ELFWriter(raw_ostream &O, TargetMachine &TM); ~ELFWriter(); typedef std::vector DataBuffer; protected: /// Output stream to send the resultant object file to. /// raw_ostream &O; /// Target machine description. /// TargetMachine &TM; /// 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; //===------------------------------------------------------------------===// // 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; // e_flags - The machine flags for the target. This defaults to zero. unsigned e_flags; //===------------------------------------------------------------------===// // 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: // The buffer we accumulate the file header into. Note that this should be // changed into something much more efficient later (and the bitcode 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) { } }; /// 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::list SectionList; unsigned NumSections; // Always = SectionList.size() /// SectionLookup - This is a mapping from section name to section number in /// the SectionList. std::map SectionLookup; /// 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 *&SN = SectionLookup[Name]; if (SN) return *SN; SectionList.push_back(Name); SN = &SectionList.back(); SN->SectionIdx = NumSections++; SN->Type = Type; SN->Flags = Flags; return *SN; } ELFSection &getDataSection() { return getSection(".data", ELFSection::SHT_PROGBITS, ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC); } ELFSection &getBSSSection() { return getSection(".bss", ELFSection::SHT_NOBITS, ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC); } /// ELFSym - This struct contains information about each symbol that is /// added to logical symbol table for the module. This is eventually /// turned into a real symbol table in the file. struct ELFSym { const GlobalValue *GV; // The global value this corresponds to. unsigned NameIdx; // Index in .strtab of name, once emitted. uint64_t Value; unsigned Size; unsigned char Info; unsigned char Other; unsigned short SectionIdx; enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 }; enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3, STT_FILE = 4 }; ELFSym(const GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0), Other(0), SectionIdx(0) {} void SetBind(unsigned X) { assert(X == (X & 0xF) && "Bind value out of range!"); Info = (Info & 0x0F) | (X << 4); } void SetType(unsigned X) { assert(X == (X & 0xF) && "Type value out of range!"); Info = (Info & 0xF0) | X; } }; /// SymbolTable - This is the list of symbols we have emitted to the file. /// This actually gets rearranged before emission to the file (to put the /// local symbols first in the list). std::vector SymbolTable; // 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(); void EmitSectionTableStringTable(); void OutputSectionsAndSectionTable(); }; } #endif