bool HexagonLDBackend::SetSDataSection() { SectionData *pTo = (m_psdata->getSectionData()); if (pTo) { MoveCommonData(*m_pscommon_1->getSectionData(), *pTo); MoveCommonData(*m_pscommon_2->getSectionData(), *pTo); MoveCommonData(*m_pscommon_4->getSectionData(), *pTo); MoveCommonData(*m_pscommon_8->getSectionData(), *pTo); SectionData::FragmentListType& to_list = pTo->getFragmentList(); SectionData::FragmentListType::iterator fragTo, fragToEnd = to_list.end(); uint32_t offset = 0; for (fragTo = to_list.begin(); fragTo != fragToEnd; ++fragTo) { fragTo->setOffset(offset); offset += fragTo->size(); } // set up pTo's header pTo->getSection().setSize(offset); SectionData::FragmentListType& newlist = pTo->getFragmentList(); for (fragTo = newlist.begin(), fragToEnd = newlist.end(); fragTo != fragToEnd; ++fragTo) { fragTo->setParent(pTo); } } return true; }
TEST_F(SectionDataTest, constructor_and_trivial_func) { LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0); SectionData* s = SectionData::Create(*test); EXPECT_TRUE(s->getSection().name() == "test" && s->getSection().kind() == LDFileFormat::Null); LDSection::Destroy(test); }
bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD) { Fragment* frag = NULL; uint32_t offset = pInput.fileOffset() + pSD.getSection().offset(); uint32_t size = pSD.getSection().size(); llvm::StringRef region = pInput.memArea()->request(offset, size); if (region.size() == 0) { // If the input section's size is zero, we got a NULL region. // use a virtual fill fragment frag = new FillFragment(0x0, 0, 0); } else { frag = new RegionFragment(region); } ObjectBuilder::AppendFragment(*frag, pSD); return true; }
bool HexagonLDBackend::MoveCommonData(SectionData &pFrom, SectionData &pTo) { SectionData::FragmentListType& to_list = pTo.getFragmentList(); SectionData::FragmentListType::iterator frag, fragEnd = to_list.end(); uint32_t pFromFlag = pFrom.getSection().align(); bool found = false; SectionData::FragmentListType::iterator fragInsert; for (frag = to_list.begin(); frag != fragEnd; ++frag) { if (frag->getKind() == mcld::Fragment::Alignment) { fragInsert = frag; continue; } if ((frag->getKind() != mcld::Fragment::Region) && (frag->getKind() != mcld::Fragment::Fillment)) { continue; } uint32_t flag = frag->getParent()->getSection().align(); if (pFromFlag < flag) { found = true; break; } } AlignFragment* align = NULL; if (pFrom.getSection().align() > 1) { // if the align constraint is larger than 1, append an alignment align = new AlignFragment(pFrom.getSection().align(), // alignment 0x0, // the filled value 1u, // the size of filled value pFrom.getSection().align() - 1 // max bytes to emit ); pFrom.getFragmentList().push_front(align); } if (found) to_list.splice(fragInsert, pFrom.getFragmentList()); else to_list.splice(frag, pFrom.getFragmentList()); return true; }
bool AArch64GNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished) { assert(getStubFactory() != NULL && getBRIslandFactory() != NULL); // Number of new stubs added size_t num_new_stubs = 0; // String lengh to hold new stub symbols size_t stubs_strlen = 0; if (config().targets().fixCA53Erratum835769() || config().targets().fixCA53Erratum843419()) { scanErrata(pModule, pBuilder, num_new_stubs, stubs_strlen); } ELFFileFormat* file_format = getOutputFormat(); // check branch relocs and create the related stubs if needed Module::obj_iterator input, inEnd = pModule.obj_end(); for (input = pModule.obj_begin(); input != inEnd; ++input) { LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) continue; RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end(); for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) { Relocation* relocation = llvm::cast<Relocation>(reloc); switch (relocation->type()) { case llvm::ELF::R_AARCH64_CALL26: case llvm::ELF::R_AARCH64_JUMP26: { // calculate the possible symbol value uint64_t sym_value = 0x0; LDSymbol* symbol = relocation->symInfo()->outSymbol(); if (symbol->hasFragRef()) { uint64_t value = symbol->fragRef()->getOutputOffset(); uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr(); sym_value = addr + value; } if ((relocation->symInfo()->reserved() & AArch64Relocator::ReservePLT) != 0x0) { // FIXME: we need to find out the address of the specific plt // entry assert(file_format->hasPLT()); sym_value = file_format->getPLT().addr(); } Stub* stub = getStubFactory()->create(*relocation, // relocation sym_value, // symbol value pBuilder, *getBRIslandFactory()); if (stub != NULL) { // a stub symbol should be local assert(stub->symInfo() != NULL && stub->symInfo()->isLocal()); // reset the branch target of the reloc to this stub instead relocation->setSymInfo(stub->symInfo()); ++num_new_stubs; stubs_strlen += stub->symInfo()->nameSize() + 1; } break; } default: { break; } } // end of switch } // for all relocations } // for all relocation section } // for all inputs // Find the first fragment w/ invalid offset due to stub insertion. std::vector<Fragment*> invalid_frags; pFinished = true; for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(), island_end = getBRIslandFactory()->end(); island != island_end; ++island) { if ((*island).size() > stubGroupSize()) { error(diag::err_no_space_to_place_stubs) << stubGroupSize(); return false; } if ((*island).numOfStubs() == 0) { continue; } Fragment* exit = &*(*island).end(); if (exit == (*island).begin()->getParent()->end()) { continue; } if (((*island).offset() + (*island).size()) > exit->getOffset()) { if (invalid_frags.empty() || (invalid_frags.back()->getParent() != (*island).getParent())) { invalid_frags.push_back(exit); pFinished = false; } continue; } } // Reset the offset of invalid fragments. for (auto it = invalid_frags.begin(), ie = invalid_frags.end(); it != ie; ++it) { Fragment* invalid = *it; while (invalid != NULL) { invalid->setOffset(invalid->getPrevNode()->getOffset() + invalid->getPrevNode()->size()); invalid = invalid->getNextNode(); } } // Fix up the size of .symtab, .strtab, and TEXT sections if (num_new_stubs == 0) { return false; } else { switch (config().options().getStripSymbolMode()) { case GeneralOptions::StripSymbolMode::StripAllSymbols: case GeneralOptions::StripSymbolMode::StripLocals: break; default: { LDSection& symtab = file_format->getSymTab(); LDSection& strtab = file_format->getStrTab(); symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym) * num_new_stubs); symtab.setInfo(symtab.getInfo() + num_new_stubs); strtab.setSize(strtab.size() + stubs_strlen); } } // switch (config().options().getStripSymbolMode()) SectionData* prev = NULL; for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(), island_end = getBRIslandFactory()->end(); island != island_end; ++island) { SectionData* sd = (*island).begin()->getParent(); if ((*island).numOfStubs() != 0) { if (sd != prev) { sd->getSection().setSize(sd->back().getOffset() + sd->back().size()); } } prev = sd; } return true; } // if (num_new_stubs == 0) }
/// MoveSectionData - move the fragments of pTO section data to pTo bool HexagonLDBackend::MoveSectionDataAndSort(SectionData& pFrom, SectionData& pTo) { assert(&pFrom != &pTo && "Cannot move section data to itself!"); SectionData::FragmentListType& to_list = pTo.getFragmentList(); SectionData::FragmentListType::iterator frag, fragEnd = to_list.end(); uint32_t pFromFlag = pFrom.getSection().align(); bool found = false; SectionData::FragmentListType::iterator fragInsert; for (frag = to_list.begin(); frag != fragEnd; ++frag) { if (frag->getKind() == mcld::Fragment::Alignment) { fragInsert = frag; continue; } if ((frag->getKind() != mcld::Fragment::Region) && (frag->getKind() != mcld::Fragment::Fillment)) { continue; } uint32_t flag = frag->getParent()->getSection().align(); if (pFromFlag < flag) { found = true; break; } } AlignFragment* align = NULL; if (pFrom.getSection().align() > 1) { // if the align constraint is larger than 1, append an alignment align = new AlignFragment(pFrom.getSection().align(), // alignment 0x0, // the filled value 1u, // the size of filled value pFrom.getSection().align() - 1 // max bytes to emit ); pFrom.getFragmentList().push_front(align); } if (found) to_list.splice(fragInsert, pFrom.getFragmentList()); else to_list.splice(frag, pFrom.getFragmentList()); uint32_t offset = 0; for (frag = to_list.begin(); frag != fragEnd; ++frag) { frag->setOffset(offset); offset += frag->size(); } // set up pTo's header pTo.getSection().setSize(offset); if (pFrom.getSection().align() > pTo.getSection().align()) pTo.getSection().setAlign(pFrom.getSection().align()); if (pFrom.getSection().flag() > pTo.getSection().flag()) pTo.getSection().setFlag(pFrom.getSection().flag()); return true; }