//===- EhFrame.h ----------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_LD_EH_FRAME_H
#define MCLD_LD_EH_FRAME_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/Config/Config.h>
#include <mcld/Fragment/RegionFragment.h>
#include <mcld/Fragment/NullFragment.h>
#include <mcld/Support/Allocators.h>
#include <vector>
namespace mcld {
class LDSection;
class SectionData;
/** \class EhFrame
* \brief EhFrame represents .eh_frame section
*/
class EhFrame
{
private:
friend class Chunk<EhFrame, MCLD_SECTIONS_PER_INPUT>;
EhFrame();
explicit EhFrame(LDSection& pSection);
~EhFrame();
EhFrame(const EhFrame&); // DO NOT IMPLEMENT
EhFrame& operator=(const EhFrame&); // DO NOT IMPLEMENT
public:
/** \class CIE
* \brief Common Information Entry.
* The CIE structure refers to LSB Core Spec 4.1, chap.10.6. Exception Frames.
*/
class CIE : public RegionFragment
{
public:
CIE(MemoryRegion& pRegion);
void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; }
uint8_t getFDEEncode() const { return m_FDEEncode; }
private:
uint8_t m_FDEEncode;
};
/** \class FDE
* \brief Frame Description Entry
* The FDE structure refers to LSB Core Spec 4.1, chap.10.6. Exception Frames.
*/
class FDE : public RegionFragment
{
public:
FDE(MemoryRegion& pRegion,
const CIE& pCIE,
uint32_t pDataStart);
const CIE& getCIE() const { return m_CIE; }
uint32_t getDataStart() const { return m_DataStart; }
private:
const CIE& m_CIE;
uint32_t m_DataStart;
};
typedef std::vector<CIE*> CIEList;
// cie_iterator and const_cie_iterator must be a kind of random access iterator
typedef CIEList::iterator cie_iterator;
typedef CIEList::const_iterator const_cie_iterator;
typedef std::vector<FDE*> FDEList;
// fde_iterator and const_fde_iterator must be a kind of random access iterator
typedef FDEList::iterator fde_iterator;
typedef FDEList::const_iterator const_fde_iterator;
public:
static EhFrame* Create(LDSection& pSection);
static void Destroy(EhFrame*& pSection);
static void Clear();
/// merge - move all data from pOther to this object.
EhFrame& merge(EhFrame& pOther);
const LDSection& getSection() const;
LDSection& getSection();
const SectionData* getSectionData() const { return m_pSectionData; }
SectionData* getSectionData() { return m_pSectionData; }
// ----- fragment ----- //
/// addFragment - when we start treating CIEs and FDEs as regular fragments,
/// we call this function instead of addCIE() and addFDE().
void addFragment(RegionFragment& pFrag);
void addFragment(NullFragment& pFrag);
/// addCIE - add a CIE entry in EhFrame
void addCIE(CIE& pCIE);
/// addFDE - add a FDE entry in EhFrame
void addFDE(FDE& pFDE);
// ----- CIE ----- //
const_cie_iterator cie_begin() const { return m_CIEs.begin(); }
cie_iterator cie_begin() { return m_CIEs.begin(); }
const_cie_iterator cie_end () const { return m_CIEs.end(); }
cie_iterator cie_end () { return m_CIEs.end(); }
const CIE& cie_front() const { return *m_CIEs.front(); }
CIE& cie_front() { return *m_CIEs.front(); }
const CIE& cie_back () const { return *m_CIEs.back(); }
CIE& cie_back () { return *m_CIEs.back(); }
size_t numOfCIEs() const { return m_CIEs.size(); }
// ----- FDE ----- //
const_fde_iterator fde_begin() const { return m_FDEs.begin(); }
fde_iterator fde_begin() { return m_FDEs.begin(); }
const_fde_iterator fde_end () const { return m_FDEs.end(); }
fde_iterator fde_end () { return m_FDEs.end(); }
const FDE& fde_front() const { return *m_FDEs.front(); }
FDE& fde_front() { return *m_FDEs.front(); }
const FDE& fde_back () const { return *m_FDEs.back(); }
FDE& fde_back () { return *m_FDEs.back(); }
size_t numOfFDEs() const { return m_FDEs.size(); }
private:
LDSection* m_pSection;
SectionData* m_pSectionData;
CIEList m_CIEs;
FDEList m_FDEs;
};
} // namespace of mcld
#endif