//===-- 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/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())), 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); // Inital 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; } } // 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 (S->HasCommonSymbols()) { // 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)) { const 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[0], idxVec.size()); 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); const 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(Constant *List, ELFSection &Xtor) { // Should be an array of '{ int, void ()* }' structs. The first value is the // init priority, which we ignore. if (!isa(List)) return; ConstantArray *InitList = cast(List); for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. if (CS->getOperand(1)->isNullValue()) return; // Found a null terminator, exit printing. // 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()); }