1 //===- EhFrame.h ----------------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef MCLD_LD_EHFRAME_H 10 #define MCLD_LD_EHFRAME_H 11 12 #include <mcld/Config/Config.h> 13 #include <mcld/Fragment/RegionFragment.h> 14 #include <mcld/LD/SectionData.h> 15 #include <mcld/Support/Allocators.h> 16 17 #include <llvm/ADT/StringRef.h> 18 #include <list> 19 #include <map> 20 #include <set> 21 #include <vector> 22 23 namespace mcld { 24 25 class Input; 26 class Module; 27 class LDSection; 28 class ObjectLinker; 29 class Relocation; 30 31 /** \class EhFrame 32 * \brief EhFrame represents .eh_frame section 33 */ 34 class EhFrame 35 { 36 private: 37 friend class Chunk<EhFrame, MCLD_SECTIONS_PER_INPUT>; 38 39 EhFrame(); 40 explicit EhFrame(LDSection& pSection); 41 42 ~EhFrame(); 43 44 EhFrame(const EhFrame&); // DO NOT IMPLEMENT 45 EhFrame& operator=(const EhFrame&); // DO NOT IMPLEMENT 46 47 public: 48 enum RecordType { 49 RECORD_UNKNOWN, 50 RECORD_INPUT, 51 RECORD_GENERATED 52 }; 53 54 class CIE; 55 class FDE; 56 57 typedef std::vector<CIE*> CIEList; 58 typedef CIEList::iterator cie_iterator; 59 typedef CIEList::const_iterator const_cie_iterator; 60 61 typedef std::list<FDE*> FDEList; 62 typedef FDEList::iterator fde_iterator; 63 typedef FDEList::const_iterator const_fde_iterator; 64 65 typedef std::map</*offset*/size_t, CIE*> CIEMap; 66 67 // A super class of CIE and FDE, containing the same part 68 class Record : public RegionFragment 69 { 70 public: 71 Record(llvm::StringRef pRegion); 72 virtual ~Record(); 73 getRegion()74 const llvm::StringRef getRegion() const { return RegionFragment::getRegion(); } getRegion()75 llvm::StringRef getRegion() { return RegionFragment::getRegion(); } getRecordType()76 virtual RecordType getRecordType() const { return RECORD_UNKNOWN; } 77 78 private: 79 Record(const Record&); // DO NOT IMPLEMENT 80 Record& operator=(const Record&); // DO NOT IMPLEMENT 81 }; 82 83 /** \class CIE 84 * \brief Common Information Entry. 85 * The CIE structure refers to LSB Core Spec 4.1, chap.10.6. Exception Frames. 86 */ 87 class CIE : public Record 88 { 89 public: 90 CIE(llvm::StringRef pRegion); 91 ~CIE(); 92 getRecordType()93 virtual RecordType getRecordType() const { return RECORD_INPUT; } 94 setFDEEncode(uint8_t pEncode)95 void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; } getFDEEncode()96 uint8_t getFDEEncode() const { return m_FDEEncode; } 97 98 void setMergeable(bool pVal = true) { m_Mergeable = pVal; } getMergeable()99 virtual bool getMergeable() const { return m_Mergeable; } 100 setRelocation(const Relocation & pReloc)101 void setRelocation(const Relocation& pReloc) { m_pReloc = &pReloc; } getRelocation()102 const Relocation* getRelocation() const { return m_pReloc; } 103 setPersonalityOffset(uint64_t pOffset)104 void setPersonalityOffset(uint64_t pOffset) { m_PersonalityOffset = pOffset; } getPersonalityOffset()105 uint64_t getPersonalityOffset() const { return m_PersonalityOffset; } 106 setPersonalityName(const std::string & pStr)107 void setPersonalityName(const std::string& pStr) { m_PersonalityName = pStr; } getPersonalityName()108 const std::string& getPersonalityName() const { return m_PersonalityName; } 109 setAugmentationData(const std::string & pStr)110 void setAugmentationData(const std::string& pStr) { m_AugmentationData = pStr; } getAugmentationData()111 const std::string& getAugmentationData() const { return m_AugmentationData; } 112 add(FDE & pFDE)113 void add(FDE& pFDE) { m_FDEs.push_back(&pFDE); } remove(FDE & pFDE)114 void remove(FDE& pFDE) { m_FDEs.remove(&pFDE); } clearFDEs()115 void clearFDEs() { m_FDEs.clear(); } numOfFDEs()116 size_t numOfFDEs() const { return m_FDEs.size(); } 117 begin()118 const_fde_iterator begin() const { return m_FDEs.begin(); } begin()119 fde_iterator begin() { return m_FDEs.begin(); } end()120 const_fde_iterator end() const { return m_FDEs.end(); } end()121 fde_iterator end() { return m_FDEs.end(); } 122 123 private: 124 uint8_t m_FDEEncode; 125 bool m_Mergeable; 126 const Relocation* m_pReloc; 127 uint64_t m_PersonalityOffset; 128 std::string m_PersonalityName; 129 std::string m_AugmentationData; 130 FDEList m_FDEs; 131 }; 132 133 /** \class FDE 134 * \brief Frame Description Entry 135 * The FDE structure refers to LSB Core Spec 4.1, chap.10.6. Exception Frames. 136 */ 137 class FDE : public Record 138 { 139 public: 140 FDE(llvm::StringRef pRegion, CIE& pCIE); 141 ~FDE(); 142 143 void setCIE(CIE& pCIE); getCIE()144 const CIE& getCIE() const { return *m_pCIE; } getCIE()145 CIE& getCIE() { return *m_pCIE; } 146 147 private: 148 CIE* m_pCIE; // Referenced CIE may change when merging. 149 }; 150 151 // These are created for PLT 152 class GeneratedCIE : public CIE 153 { 154 public: 155 GeneratedCIE(llvm::StringRef pRegion); 156 ~GeneratedCIE(); 157 getRecordType()158 virtual RecordType getRecordType() const { return RECORD_GENERATED; } getMergeable()159 virtual bool getMergeable() const { return true; } 160 }; 161 162 class GeneratedFDE : public FDE 163 { 164 public: 165 GeneratedFDE(llvm::StringRef pRegion, CIE& pCIE); 166 ~GeneratedFDE(); 167 getRecordType()168 virtual RecordType getRecordType() const { return RECORD_GENERATED; } 169 }; 170 171 public: 172 static EhFrame* Create(LDSection& pSection); 173 174 static void Destroy(EhFrame*& pSection); 175 176 static void Clear(); 177 178 /// merge - move all data from pOther to this object. 179 EhFrame& merge(const Input& pInput, EhFrame& pInFrame); 180 181 const LDSection& getSection() const; 182 LDSection& getSection(); 183 getSectionData()184 const SectionData* getSectionData() const { return m_pSectionData; } getSectionData()185 SectionData* getSectionData() { return m_pSectionData; } 186 187 // ----- fragment ----- // 188 void addFragment(Fragment& pFrag); 189 190 /// addCIE - add a CIE entry in EhFrame 191 void addCIE(CIE& pCIE, bool pAlsoAddFragment = true); 192 193 /// addFDE - add a FDE entry in EhFrame 194 void addFDE(FDE& pFDE, bool pAlsoAddFragment = true); 195 196 // ----- CIE ----- // cie_begin()197 const_cie_iterator cie_begin() const { return m_CIEs.begin(); } cie_begin()198 cie_iterator cie_begin() { return m_CIEs.begin(); } cie_end()199 const_cie_iterator cie_end () const { return m_CIEs.end(); } cie_end()200 cie_iterator cie_end () { return m_CIEs.end(); } 201 cie_front()202 const CIE& cie_front() const { return *m_CIEs.front(); } cie_front()203 CIE& cie_front() { return *m_CIEs.front(); } cie_back()204 const CIE& cie_back () const { return *m_CIEs.back(); } cie_back()205 CIE& cie_back () { return *m_CIEs.back(); } 206 emptyCIEs()207 bool emptyCIEs() const { return m_CIEs.empty(); } numOfCIEs()208 size_t numOfCIEs() const { return m_CIEs.size(); } 209 size_t numOfFDEs() const; 210 getCIEMap()211 const CIEMap& getCIEMap() const { return m_FoundCIEs; } getCIEMap()212 CIEMap& getCIEMap() { return m_FoundCIEs; } 213 214 public: 215 size_t computeOffsetSize(); 216 217 /// getDataStartOffset - Get the offset after length and ID field. 218 /// The offset is 8byte for 32b, and 16byte for 64b. 219 /// We can just use "BITCLASS/4" to represent offset. 220 template <size_t BITCLASS> getDataStartOffset()221 static size_t getDataStartOffset() { return BITCLASS / 4; } 222 223 private: 224 // We needs to check if it is mergeable and check personality name 225 // before merging them. The important note is we must do this after 226 // ALL readSections done, that is the reason why we don't check this 227 // immediately when reading. 228 void setupAttributes(const LDSection* reloc_sect); 229 void removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocEhFrameSect); 230 231 private: 232 void removeAndUpdateCIEForFDE(EhFrame& pInFrame, CIE& pInCIE, CIE& pOutCIE, 233 const LDSection* reloc_sect); 234 void moveInputFragments(EhFrame& pInFrame); 235 void moveInputFragments(EhFrame& pInFrame, CIE& pInCIE, CIE* pOutCIE = 0); 236 237 private: 238 LDSection* m_pSection; 239 SectionData* m_pSectionData; 240 241 // Each eh_frame has a list of CIE, and each CIE has a list of FDE 242 // pointing to the CIE itself. This is used by management when we are 243 // processing eh_frame merge. 244 // However, don't forget we need to handle the Fragments inside SectionData 245 // correctly since they are truly used when output emission. 246 CIEList m_CIEs; 247 248 // We need this map to find the corresponding CIE for FDE. Not all FDE point 249 // to the nearest CIE. 250 CIEMap m_FoundCIEs; 251 }; 252 253 bool operator==(const EhFrame::CIE&, const EhFrame::CIE&); 254 255 } // namespace of mcld 256 257 #endif 258 259