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