void EhFrame::moveInputFragments(EhFrame& pInFrame, CIE& pInCIE, CIE* pOutCIE) { SectionData& in_sd = *pInFrame.getSectionData(); SectionData::FragmentListType& in_frag_list = in_sd.getFragmentList(); SectionData& out_sd = *getSectionData(); SectionData::FragmentListType& out_frag_list = out_sd.getFragmentList(); if (!pOutCIE) { // Newly inserted Fragment* frag = in_frag_list.remove(SectionData::iterator(pInCIE)); out_frag_list.push_back(frag); frag->setParent(&out_sd); for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) { frag = in_frag_list.remove(SectionData::iterator(**i)); out_frag_list.push_back(frag); frag->setParent(&out_sd); } return; } SectionData::iterator cur_iter(*pOutCIE); assert (cur_iter != out_frag_list.end()); for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) { Fragment* frag = in_frag_list.remove(SectionData::iterator(**i)); cur_iter = out_frag_list.insertAfter(cur_iter, frag); frag->setParent(&out_sd); } }
void EhFrame::removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocSect) { if (!pRelocSect) return; typedef std::vector<FDE*> FDERemoveList; FDERemoveList to_be_removed_fdes; const RelocData* reloc_data = pRelocSect->getRelocData(); for (fde_iterator i = pCIE.begin(), e = pCIE.end(); i != e; ++i) { FDE& fde = **i; for (RelocData::const_iterator ri = reloc_data->begin(), re = reloc_data->end(); ri != re; ++ri) { const Relocation& rel = *ri; if (rel.targetRef().getOutputOffset() == fde.getOffset() + getDataStartOffset<32>()) { bool has_section = rel.symInfo()->outSymbol()->hasFragRef(); if (!has_section) // The section was discarded, just ignore this FDE. // This may happen when redundant group section was read. to_be_removed_fdes.push_back(&fde); break; } } } for (FDERemoveList::iterator i = to_be_removed_fdes.begin(), e = to_be_removed_fdes.end(); i != e; ++i) { FDE& fde = **i; fde.getCIE().remove(fde); // FIXME: This traverses relocations from the beginning on each FDE, which // may cause performance degration. Actually relocations will be sequential // order, so we can bookkeep the previously found relocation for next use. // Note: We must ensure FDE order is ordered. for (RelocData::const_iterator ri = reloc_data->begin(), re = reloc_data->end(); ri != re;) { Relocation& rel = const_cast<Relocation&>(*ri++); if (rel.targetRef().getOutputOffset() >= fde.getOffset() && rel.targetRef().getOutputOffset() < fde.getOffset() + fde.size()) { const_cast<RelocData*>(reloc_data)->remove(rel); } } } }
void EhFrame::removeAndUpdateCIEForFDE(EhFrame& pInFrame, CIE& pInCIE, CIE& pOutCIE, const LDSection* rel_sect) { // Make this relocation to be ignored. Relocation* rel = const_cast<Relocation*>(pInCIE.getRelocation()); if (rel && rel_sect) const_cast<RelocData*>(rel_sect->getRelocData())->remove(*rel); // Update the CIE-pointed FDEs for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) (*i)->setCIE(pOutCIE); // We cannot know whether there are references to this fragment, so just // keep it in input fragment list instead of memory deallocation pInCIE.clearFDEs(); }