//===- 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_EHFRAME_H_ #define MCLD_LD_EHFRAME_H_ #include "mcld/Config/Config.h" #include "mcld/Fragment/RegionFragment.h" #include "mcld/LD/SectionData.h" #include "mcld/Support/Allocators.h" #include "mcld/Support/Compiler.h" #include #include #include #include namespace mcld { class Input; class LDSection; class Relocation; /** \class EhFrame * \brief EhFrame represents .eh_frame section */ class EhFrame { private: friend class Chunk; EhFrame(); explicit EhFrame(LDSection& pSection); ~EhFrame(); public: enum RecordType { RECORD_UNKNOWN, RECORD_INPUT, RECORD_GENERATED }; class CIE; class FDE; typedef std::vector CIEList; typedef CIEList::iterator cie_iterator; typedef CIEList::const_iterator const_cie_iterator; typedef std::list FDEList; typedef FDEList::iterator fde_iterator; typedef FDEList::const_iterator const_fde_iterator; typedef std::map CIEMap; // A super class of CIE and FDE, containing the same part class Record : public RegionFragment { public: explicit Record(llvm::StringRef pRegion); virtual ~Record(); const llvm::StringRef getRegion() const { return RegionFragment::getRegion(); } llvm::StringRef getRegion() { return RegionFragment::getRegion(); } virtual RecordType getRecordType() const { return RECORD_UNKNOWN; } private: DISALLOW_COPY_AND_ASSIGN(Record); }; /** \class CIE * \brief Common Information Entry. * The CIE structure refers to LSB Core Spec 4.1, chap.10.6. Exception * Frames. */ class CIE : public Record { public: explicit CIE(llvm::StringRef pRegion); ~CIE(); virtual RecordType getRecordType() const { return RECORD_INPUT; } void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; } uint8_t getFDEEncode() const { return m_FDEEncode; } void setMergeable(bool pVal = true) { m_Mergeable = pVal; } virtual bool getMergeable() const { return m_Mergeable; } void setRelocation(const Relocation& pReloc) { m_pReloc = &pReloc; } const Relocation* getRelocation() const { return m_pReloc; } void setPersonalityOffset(uint64_t pOffset) { m_PersonalityOffset = pOffset; } uint64_t getPersonalityOffset() const { return m_PersonalityOffset; } void setPersonalityName(const std::string& pStr) { m_PersonalityName = pStr; } const std::string& getPersonalityName() const { return m_PersonalityName; } void setAugmentationData(const std::string& pStr) { m_AugmentationData = pStr; } const std::string& getAugmentationData() const { return m_AugmentationData; } void add(FDE& pFDE) { m_FDEs.push_back(&pFDE); } void remove(FDE& pFDE) { m_FDEs.remove(&pFDE); } void clearFDEs() { m_FDEs.clear(); } size_t numOfFDEs() const { return m_FDEs.size(); } const_fde_iterator begin() const { return m_FDEs.begin(); } fde_iterator begin() { return m_FDEs.begin(); } const_fde_iterator end() const { return m_FDEs.end(); } fde_iterator end() { return m_FDEs.end(); } private: uint8_t m_FDEEncode; bool m_Mergeable; const Relocation* m_pReloc; uint64_t m_PersonalityOffset; std::string m_PersonalityName; std::string m_AugmentationData; FDEList m_FDEs; }; /** \class FDE * \brief Frame Description Entry * The FDE structure refers to LSB Core Spec 4.1, chap.10.6. Exception * Frames. */ class FDE : public Record { public: FDE(llvm::StringRef pRegion, CIE& pCIE); ~FDE(); void setCIE(CIE& pCIE); const CIE& getCIE() const { return *m_pCIE; } CIE& getCIE() { return *m_pCIE; } private: CIE* m_pCIE; // Referenced CIE may change when merging. }; // These are created for PLT class GeneratedCIE : public CIE { public: explicit GeneratedCIE(llvm::StringRef pRegion); ~GeneratedCIE(); virtual RecordType getRecordType() const { return RECORD_GENERATED; } virtual bool getMergeable() const { return true; } }; class GeneratedFDE : public FDE { public: GeneratedFDE(llvm::StringRef pRegion, CIE& pCIE); ~GeneratedFDE(); virtual RecordType getRecordType() const { return RECORD_GENERATED; } }; 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(const Input& pInput, EhFrame& pInFrame); const LDSection& getSection() const; LDSection& getSection(); const SectionData* getSectionData() const { return m_pSectionData; } SectionData* getSectionData() { return m_pSectionData; } // ----- fragment ----- // void addFragment(Fragment& pFrag); /// addCIE - add a CIE entry in EhFrame void addCIE(CIE& pCIE, bool pAlsoAddFragment = true); /// addFDE - add a FDE entry in EhFrame void addFDE(FDE& pFDE, bool pAlsoAddFragment = true); // ----- 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(); } bool emptyCIEs() const { return m_CIEs.empty(); } size_t numOfCIEs() const { return m_CIEs.size(); } size_t numOfFDEs() const; const CIEMap& getCIEMap() const { return m_FoundCIEs; } CIEMap& getCIEMap() { return m_FoundCIEs; } public: size_t computeOffsetSize(); /// getDataStartOffset - Get the offset after length and ID field. /// The offset is 8byte for 32b, and 16byte for 64b. /// We can just use "BITCLASS/4" to represent offset. template static size_t getDataStartOffset() { return BITCLASS / 4; } private: // We needs to check if it is mergeable and check personality name // before merging them. The important note is we must do this after // ALL readSections done, that is the reason why we don't check this // immediately when reading. void setupAttributes(const LDSection* reloc_sect); void removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocEhFrameSect); private: void removeAndUpdateCIEForFDE(EhFrame& pInFrame, CIE& pInCIE, CIE& pOutCIE, const LDSection* reloc_sect); void moveInputFragments(EhFrame& pInFrame); void moveInputFragments(EhFrame& pInFrame, CIE& pInCIE, CIE* pOutCIE = 0); private: LDSection* m_pSection; SectionData* m_pSectionData; // Each eh_frame has a list of CIE, and each CIE has a list of FDE // pointing to the CIE itself. This is used by management when we are // processing eh_frame merge. // However, don't forget we need to handle the Fragments inside SectionData // correctly since they are truly used when output emission. CIEList m_CIEs; // We need this map to find the corresponding CIE for FDE. Not all FDE point // to the nearest CIE. CIEMap m_FoundCIEs; private: DISALLOW_COPY_AND_ASSIGN(EhFrame); }; bool operator==(const EhFrame::CIE&, const EhFrame::CIE&); } // namespace mcld #endif // MCLD_LD_EHFRAME_H_