bool ARMGNULDBackend::readSection(Input& pInput, MCLinker& pLinker, LDSection& pInputSectHdr) { LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(), pInputSectHdr.kind(), pInputSectHdr.type(), pInputSectHdr.flag()); // FIXME: (Luba) // Handle ARM attributes in the right way. // In current milestone, MCLinker goes through the shortcut. // It reads input's ARM attributes and copies the first ARM attributes // into the output file. The correct way is merge these sections, not // just copy. if ((0 == out_sect.name().compare(".ARM.attributes")) && (0 != out_sect.size())) return true; MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(), pInputSectHdr.size()); llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr); new MCRegionFragment(*region, §_data); out_sect.setSize(out_sect.size() + pInputSectHdr.size()); return true; }
void ARMGNULDBackend::initTargetSections(MCLinker& pLinker) { // FIXME: Currently we set exidx and extab to "Exception" and directly emit // them from input m_pEXIDX = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx", LDFileFormat::Exception, llvm::ELF::SHT_ARM_EXIDX, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER, bitclass() / 8); m_pEXTAB = &pLinker.getOrCreateOutputSectHdr(".ARM.extab", LDFileFormat::Exception, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC, 0x1); m_pAttributes = &pLinker.getOrCreateOutputSectHdr(".ARM.attributes", LDFileFormat::Target, llvm::ELF::SHT_ARM_ATTRIBUTES, 0x0, 0x1); }
void ELFFileFormat::initObjectFormat(MCLinker& pLinker) { f_pTextSection = &pLinker.getOrCreateOutputSectHdr(".text", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR, 0x1); f_pNULLSection = &pLinker.getOrCreateOutputSectHdr("", LDFileFormat::Null, llvm::ELF::SHT_NULL, 0x0); f_pReadOnlySection = &pLinker.getOrCreateOutputSectHdr(".rodata", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC, 0x1); f_pBSSSection = &pLinker.getOrCreateOutputSectHdr(".bss", LDFileFormat::BSS, llvm::ELF::SHT_NOBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pComment = &pLinker.getOrCreateOutputSectHdr(".comment", LDFileFormat::MetaData, llvm::ELF::SHT_PROGBITS, 0x0, 0x1); f_pDataSection = &pLinker.getOrCreateOutputSectHdr(".data", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pData1 = &pLinker.getOrCreateOutputSectHdr(".data1", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pDebug = &pLinker.getOrCreateOutputSectHdr(".debug", LDFileFormat::Debug, llvm::ELF::SHT_PROGBITS, 0x0, 0x1); f_pInit = &pLinker.getOrCreateOutputSectHdr(".init", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR, 0x1); f_pInitArray = &pLinker.getOrCreateOutputSectHdr(".init_array", LDFileFormat::Regular, llvm::ELF::SHT_INIT_ARRAY, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pFini = &pLinker.getOrCreateOutputSectHdr(".fini", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR, 0x1); f_pFiniArray = &pLinker.getOrCreateOutputSectHdr(".fini_array", LDFileFormat::Regular, llvm::ELF::SHT_FINI_ARRAY, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pLine = &pLinker.getOrCreateOutputSectHdr(".line", LDFileFormat::Debug, llvm::ELF::SHT_PROGBITS, 0x0, 0x1); f_pPreInitArray = &pLinker.getOrCreateOutputSectHdr(".preinit_array", LDFileFormat::Regular, llvm::ELF::SHT_PREINIT_ARRAY, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); // the definition of SHF_XXX attributes of rodata in Linux Standard Base // conflicts with System V standard. We follow System V standard. f_pROData1 = &pLinker.getOrCreateOutputSectHdr(".rodata1", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC, 0x1); f_pShStrTab = &pLinker.getOrCreateOutputSectHdr(".shstrtab", LDFileFormat::NamePool, llvm::ELF::SHT_STRTAB, 0x0, 0x1); // In ELF Spec Book I, p1-16. If symbol table and string table are in // loadable segments, set the attribute to SHF_ALLOC bit. But in the // real world, this bit always turn off. f_pSymTab = &pLinker.getOrCreateOutputSectHdr(".symtab", LDFileFormat::NamePool, llvm::ELF::SHT_SYMTAB, 0x0, f_Backend.bitclass() / 8); f_pStrTab = &pLinker.getOrCreateOutputSectHdr(".strtab", LDFileFormat::NamePool, llvm::ELF::SHT_STRTAB, 0x0, 0x1); f_pTBSS = &pLinker.getOrCreateOutputSectHdr(".tbss", LDFileFormat::BSS, llvm::ELF::SHT_NOBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_TLS, 0x1); f_pTData = &pLinker.getOrCreateOutputSectHdr(".tdata", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_TLS, 0x1); /// @ref 10.3.1.2, ISO/IEC 23360, Part 1:2010(E), p. 24. f_pCtors = &pLinker.getOrCreateOutputSectHdr(".ctor", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pDataRelRo = &pLinker.getOrCreateOutputSectHdr(".data.rel.ro", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pDtors = &pLinker.getOrCreateOutputSectHdr(".dtors", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pEhFrame = &pLinker.getOrCreateOutputSectHdr(".eh_frame", LDFileFormat::EhFrame, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC, 0x4); f_pGCCExceptTable = &pLinker.getOrCreateOutputSectHdr(".gcc_except_table", LDFileFormat::GCCExceptTable, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC, 0x4); f_pGNUVersion = &pLinker.getOrCreateOutputSectHdr(".gnu.version", LDFileFormat::Version, llvm::ELF::SHT_GNU_versym, llvm::ELF::SHF_ALLOC, 0x1); f_pGNUVersionD = &pLinker.getOrCreateOutputSectHdr(".gnu.version_d", LDFileFormat::Version, llvm::ELF::SHT_GNU_verdef, llvm::ELF::SHF_ALLOC, 0x1); f_pGNUVersionR = &pLinker.getOrCreateOutputSectHdr(".gnu.version_r", LDFileFormat::Version, llvm::ELF::SHT_GNU_verneed, llvm::ELF::SHF_ALLOC, 0x1); f_pJCR = &pLinker.getOrCreateOutputSectHdr(".jcr", LDFileFormat::Regular, llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE, 0x1); f_pStab = &pLinker.getOrCreateOutputSectHdr(".stab", LDFileFormat::Debug, llvm::ELF::SHT_PROGBITS, 0x0, 0x1); f_pStabStr = &pLinker.getOrCreateOutputSectHdr(".stabstr", LDFileFormat::Debug, llvm::ELF::SHT_STRTAB, 0x0, 0x1); }
/// allocateCommonSymbols - allocate common symbols in the corresponding /// sections. /// @refer Google gold linker: common.cc: 214 bool ARMGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const { SymbolCategory& symbol_list = pLinker.getOutputSymbols(); if (symbol_list.emptyCommons() && symbol_list.emptyLocals()) return true; // addralign := max value of all common symbols uint64_t addralign = 0x0; // Due to the visibility, some common symbols may be forcefully local. SymbolCategory::iterator com_sym, com_end = symbol_list.localEnd(); for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) { if (ResolveInfo::Common == (*com_sym)->desc()) { if ((*com_sym)->value() > addralign) addralign = (*com_sym)->value(); } } // global common symbols. com_end = symbol_list.commonEnd(); for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) { if ((*com_sym)->value() > addralign) addralign = (*com_sym)->value(); } // FIXME: If the order of common symbols is defined, then sort common symbols // com_sym = symbol_list.commonBegin(); // std::sort(com_sym, com_end, some kind of order); // get or create corresponding BSS LDSection LDSection* bss_sect_hdr = NULL; if (ResolveInfo::ThreadLocal == (*com_sym)->type()) { bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr( ".tbss", LDFileFormat::BSS, llvm::ELF::SHT_NOBITS, llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC); } else { bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss", LDFileFormat::BSS, llvm::ELF::SHT_NOBITS, llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC); } // get or create corresponding BSS MCSectionData assert(NULL != bss_sect_hdr); llvm::MCSectionData& bss_section = pLinker.getOrCreateSectData(*bss_sect_hdr); // allocate all common symbols uint64_t offset = bss_sect_hdr->size(); // allocate all local common symbols com_end = symbol_list.localEnd(); for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) { if (ResolveInfo::Common == (*com_sym)->desc()) { // We have to reset the description of the symbol here. When doing // incremental linking, the output relocatable object may have common // symbols. Therefore, we can not treat common symbols as normal symbols // when emitting the regular name pools. We must change the symbols' // description here. (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define); llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size()); (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0)); uint64_t size = pLinker.getLayout().appendFragment(*frag, bss_section, (*com_sym)->value()); offset += size; } } // allocate all global common symbols com_end = symbol_list.commonEnd(); for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) { // We have to reset the description of the symbol here. When doing // incremental linking, the output relocatable object may have common // symbols. Therefore, we can not treat common symbols as normal symbols // when emitting the regular name pools. We must change the symbols' // description here. (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define); llvm::MCFragment* frag = new llvm::MCFillFragment(0x0, 1, (*com_sym)->size()); (*com_sym)->setFragmentRef(new MCFragmentRef(*frag, 0)); uint64_t size = pLinker.getLayout().appendFragment(*frag, bss_section, (*com_sym)->value()); offset += size; } bss_sect_hdr->setSize(offset); symbol_list.changeCommonsToGlobal(); return true; }