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; }
/// addStub - add a stub into the island bool BranchIsland::addStub(const Stub* pPrototype, const Relocation& pReloc, Stub& pStub) { bool exist = false; Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend()); StubEntryType* entry = m_StubMap.insert(key, exist); if (!exist) { entry->setValue(&pStub); m_pRear = &pStub; SectionData* sd = m_Entry.getParent(); // insert alignment fragment // TODO: check if we can reduce this alignment fragment for some cases AlignFragment* align_frag = new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1); align_frag->setParent(sd); sd->getFragmentList().insert(end(), align_frag); align_frag->setOffset(align_frag->getPrevNode()->getOffset() + align_frag->getPrevNode()->size()); // insert stub fragment pStub.setParent(sd); sd->getFragmentList().insert(end(), &pStub); pStub.setOffset(pStub.getPrevNode()->getOffset() + pStub.getPrevNode()->size()); } return !exist; }
/// 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; }
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; }
void ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) { if (!m_pEXIDX->hasSectionData()) { // Return if this is empty section. return; } SectionData* sectData = m_pEXIDX->getSectionData(); SectionData::FragmentListType& list = sectData->getFragmentList(); // Move the first fragment (align fragment) and last fragment (null fragment) // to temporary list because we would only like to sort the region fragment. SectionData::FragmentListType tmp; { SectionData::iterator first = sectData->begin(); SectionData::iterator last = sectData->end(); --last; assert(first->getKind() == Fragment::Alignment); assert(last->getKind() == Fragment::Null); tmp.splice(tmp.end(), list, first); tmp.splice(tmp.end(), list, last); } // Sort the region fragments in the .ARM.exidx output section. sort(list, ExIdxFragmentComparator(m_ExData)); // Fix the coverage of the .ARM.exidx table. llvm::StringRef cantUnwindRegion(g_CantUnwindEntry, sizeof(g_CantUnwindEntry)); SectionData::FragmentListType::iterator it = list.begin(); if (it != list.end()) { Fragment* prevTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment(); uint64_t prevTextEnd = prevTextFrag->getParent()->getSection().addr() + prevTextFrag->getOffset() + prevTextFrag->size(); ++it; while (it != list.end()) { Fragment* currTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment(); uint64_t currTextBegin = currTextFrag->getParent()->getSection().addr() + currTextFrag->getOffset(); if (currTextBegin > prevTextEnd) { // Found a gap. Insert a can't unwind entry. RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr); frag->setParent(sectData); list.insert(it, frag); // Add PREL31 reference to the beginning of the uncovered region. Relocation* reloc = Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31), *FragmentRef::Create(*frag, /* pOffset */0), /* pAddend */0); reloc->setSymInfo( CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag)); addExtraRelocation(reloc); } prevTextEnd = currTextBegin + currTextFrag->size(); prevTextFrag = currTextFrag; ++it; } // Add a can't unwind entry to terminate .ARM.exidx section. RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr); frag->setParent(sectData); list.push_back(frag); // Add PREL31 reference to the end of the .text section. Relocation* reloc = Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31), *FragmentRef::Create(*frag, /* pOffset */0), /* pAddend */0); reloc->setSymInfo(CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag)); addExtraRelocation(reloc); } // Add the first and the last fragment back. list.splice(list.begin(), tmp, tmp.begin()); list.splice(list.end(), tmp, tmp.begin()); // Update the fragment offsets. uint64_t offset = 0; for (SectionData::iterator it = sectData->begin(), end = sectData->end(); it != end; ++it) { it->setOffset(offset); offset += it->size(); } // Update the section size. m_pEXIDX->setSize(offset); // Rebuild the section header. setOutputSectionAddress(pModule); }