| //===- EhFrame.cpp --------------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include <mcld/LD/EhFrame.h> |
| #include <mcld/LD/LDSection.h> |
| #include <mcld/LD/SectionData.h> |
| #include <mcld/Object/ObjectBuilder.h> |
| #include <mcld/Support/MemoryRegion.h> |
| #include <mcld/Support/GCFactory.h> |
| |
| #include <llvm/Support/ManagedStatic.h> |
| |
| using namespace mcld; |
| |
| typedef GCFactory<EhFrame, MCLD_SECTIONS_PER_INPUT> EhFrameFactory; |
| |
| static llvm::ManagedStatic<EhFrameFactory> g_EhFrameFactory; |
| |
| //===----------------------------------------------------------------------===// |
| // EhFrame::CIE |
| //===----------------------------------------------------------------------===// |
| EhFrame::CIE::CIE(MemoryRegion& pRegion) |
| : RegionFragment(pRegion) { |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // EhFrame::FDE |
| //===----------------------------------------------------------------------===// |
| EhFrame::FDE::FDE(MemoryRegion& pRegion, |
| const EhFrame::CIE& pCIE, |
| uint32_t pDataStart) |
| : RegionFragment(pRegion), |
| m_CIE(pCIE), |
| m_DataStart(pDataStart) { |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // EhFrame |
| //===----------------------------------------------------------------------===// |
| EhFrame::EhFrame() |
| : m_pSection(NULL), m_pSectionData(NULL) { |
| } |
| |
| EhFrame::EhFrame(LDSection& pSection) |
| : m_pSection(&pSection), |
| m_pSectionData(NULL) { |
| m_pSectionData = SectionData::Create(pSection); |
| } |
| |
| EhFrame::~EhFrame() |
| { |
| // Since all CIEs, FDEs and regular fragments are stored in iplist, iplist |
| // will delete the fragments and we do not need to handle with it. |
| } |
| |
| EhFrame* EhFrame::Create(LDSection& pSection) |
| { |
| EhFrame* result = g_EhFrameFactory->allocate(); |
| new (result) EhFrame(pSection); |
| return result; |
| } |
| |
| void EhFrame::Destroy(EhFrame*& pSection) |
| { |
| pSection->~EhFrame(); |
| g_EhFrameFactory->deallocate(pSection); |
| pSection = NULL; |
| } |
| |
| void EhFrame::Clear() |
| { |
| g_EhFrameFactory->clear(); |
| } |
| |
| const LDSection& EhFrame::getSection() const |
| { |
| assert(NULL != m_pSection); |
| return *m_pSection; |
| } |
| |
| LDSection& EhFrame::getSection() |
| { |
| assert(NULL != m_pSection); |
| return *m_pSection; |
| } |
| |
| void EhFrame::addFragment(RegionFragment& pFrag) |
| { |
| uint32_t offset = 0; |
| if (!m_pSectionData->empty()) |
| offset = m_pSectionData->back().getOffset() + m_pSectionData->back().size(); |
| |
| m_pSectionData->getFragmentList().push_back(&pFrag); |
| pFrag.setOffset(offset); |
| } |
| |
| void EhFrame::addCIE(EhFrame::CIE& pCIE) |
| { |
| m_CIEs.push_back(&pCIE); |
| addFragment(pCIE); |
| } |
| |
| void EhFrame::addFDE(EhFrame::FDE& pFDE) |
| { |
| m_FDEs.push_back(&pFDE); |
| addFragment(pFDE); |
| } |
| |
| EhFrame& EhFrame::merge(EhFrame& pOther) |
| { |
| ObjectBuilder::MoveSectionData(pOther.getSectionData(), *m_pSectionData); |
| |
| m_CIEs.reserve(pOther.numOfCIEs() + m_CIEs.size()); |
| for (cie_iterator cie = pOther.cie_begin(); cie != pOther.cie_end(); ++cie) |
| m_CIEs.push_back(*cie); |
| |
| m_FDEs.reserve(pOther.numOfFDEs() + m_FDEs.size()); |
| for (fde_iterator fde = pOther.fde_begin(); fde != pOther.fde_end(); ++fde) |
| m_FDEs.push_back(*fde); |
| |
| pOther.m_CIEs.clear(); |
| pOther.m_FDEs.clear(); |
| return *this; |
| } |
| |