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