• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- Layout.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_LAYOUT_H
10 #define MCLD_LAYOUT_H
11 #ifdef ENABLE_UNITTEST
12 #include <gtest.h>
13 #endif
14 #include <llvm/ADT/ilist.h>
15 #include <llvm/ADT/ilist_node.h>
16 #include <llvm/ADT/DenseMap.h>
17 #include <llvm/MC/MCAssembler.h>
18 #include <mcld/MC/MCFragmentRef.h>
19 #include <mcld/Support/GCFactory.h>
20 #include <mcld/LD/LDSection.h>
21 #include <map>
22 
23 namespace mcld
24 {
25 class MCLinker;
26 class Output;
27 class TargetLDBackend;
28 
29 /** \class Layout
30  *  \brief Layout maintains the mapping between sections and fragments.
31  *
32  *  MCLinker is a fragment-based linker. But readers and target backends
33  *  still need section information. Layout is used to maintain the mapping
34  *  between sections and fragments. Layout helps readers and target backends
35  *  get the input or output section information from a fragment.
36  */
37 class Layout
38 {
39 public:
40   typedef std::vector<LDSection*> SectionOrder;
41   typedef SectionOrder::iterator sect_iterator;
42   typedef SectionOrder::const_iterator const_sect_iterator;
43 
44 public:
45   /// constructor
46   Layout();
47 
48   /// destructor
49   ~Layout();
50 
51   /// getInputLDSection - give a MCFragment, return the corresponding input
52   /// LDSection*
53   ///
54   /// @return return NULL if the fragment is not found in input
55   LDSection* getInputLDSection(const llvm::MCFragment& pFrag);
56 
57   /// getInputLDSection - give a MCFragment, return the corresponding input
58   /// LDSection*
59   ///
60   /// @return return NULL if the fragment is not found in input
61   const LDSection* getInputLDSection(const llvm::MCFragment& pFrag) const;
62 
63   /// getFragmentRef - give a LDSection in input file and an offset, return
64   /// the fragment reference.
65   ///
66   /// @param pInputSection - the given input section
67   /// @param pOffset - the offset, cannot be larger than this input section.
68   /// @return if found, return the fragment. Otherwise, return NULL.
69   MCFragmentRef*
70   getFragmentRef(const LDSection& pInputSection, uint64_t pOffset);
71 
72   /// getFragmentRef - give a fragment and a big offset, return the fragment
73   /// reference in the section data.
74   ///
75   /// @param pFrag - the given fragment
76   /// @param pBigOffset - the offset, can be larger than the fragment, but can
77   ///                     not larger than this input section.
78   /// @return if found, return the fragment. Otherwise, return NULL.
79   MCFragmentRef*
80   getFragmentRef(const llvm::MCFragment& pFrag, uint64_t pBigOffset);
81 
82   /// getOutputOffset - Get the offset of the given fragment inside the
83   /// the output's MCSectionData.
84   uint64_t getOutputOffset(const llvm::MCFragment& pFrag);
85 
86   /// getOutputOffset - Get the offset of the given fragment inside the
87   /// the output's MCSectionData.
88   uint64_t getOutputOffset(const llvm::MCFragment& pFrag) const;
89 
90   /// getOutputOffset - Get the offset of the given fragment inside
91   /// the output's MCSectionData.
92   ///
93   /// @return return -1 if the fragment is not found in output's MCSectionData.
94 
95   uint64_t getOutputOffset(const MCFragmentRef& pFragRef);
96   /// getOutputOffset - Get the offset of the given fragment inside
97   /// the output's MCSectionData.
98   ///
99   /// @return return -1 if the fragment is not found in output's MCSectionData.
100   uint64_t getOutputOffset(const MCFragmentRef& pFragRef) const;
101 
102   /// getOutputLDSection - give a MCFragment, return the corresponding output
103   /// LDSection*
104   ///
105   /// @return return NULL if the fragment is not found in the output
106   LDSection* getOutputLDSection(const llvm::MCFragment& pFrag);
107 
108   /// getOutputLDSection - give a MCFragment, return the corresponding output
109   /// LDSection*
110   ///
111   /// @return return NULL if the fragment is not found in the output
112   const LDSection* getOutputLDSection(const llvm::MCFragment& pFrag) const;
113 
114   // -----  modifiers  ----- //
115   bool layout(Output& pOutput, const TargetLDBackend& pBackend);
116 
117   /// addInputRange
118   void addInputRange(const llvm::MCSectionData& pSD,
119                      const LDSection& pInputHdr);
120 
121   /// appendFragment - append the given MCFragment to the given MCSectionData,
122   /// and insert a MCAlignFragment to preserve the required align constraint if
123   /// needed
124   /// @return return the inserted size, i.e., the size of pFrag and alignment
125   /// size if any
126   uint64_t appendFragment(llvm::MCFragment& pFrag,
127                           llvm::MCSectionData& pSD,
128                           uint32_t pAlignConstraint = 1);
129 private:
130   /** \class Range
131    *  \brief Range is a <input's LDSection, previous rear fragment> pair
132    */
133   struct Range : public llvm::ilist_node<Range>
134   {
135   public:
136     Range();
137     Range(const LDSection& pHeader);
138     ~Range();
139 
140   public:
141     LDSection* header;
142     llvm::MCFragment* prevRear;
143   };
144 
145   typedef llvm::iplist<Range> RangeList;
146 
147   typedef std::map<const llvm::MCSectionData*, RangeList*> SDRangeMap;
148 
149   typedef GCFactory<MCFragmentRef, 0> FragRefFactory;
150 
151 private:
isFirstRange(const Range & pRange)152   inline bool isFirstRange(const Range& pRange) const
153   { return (NULL == pRange.prevRear); }
154 
isLastRange(const Range & pRange)155   inline bool isLastRange(const Range& pRange) const
156   { return (NULL == pRange.getNextNode()); }
157 
isEmptyRange(const Range & pRange)158   inline bool isEmptyRange(const Range& pRange) const
159   {
160     if (isFirstRange(pRange)) {
161       if (!pRange.header->hasSectionData() ||
162           pRange.header->getSectionData()->getFragmentList().empty())
163         return true;
164       else
165         return false;
166     }
167     return (NULL == pRange.prevRear->getNextNode());
168   }
169 
170   // get the front fragment in the range.
getFront(Range & pRange)171   inline llvm::MCFragment* getFront(Range& pRange) const
172   {
173     if (!pRange.header->hasSectionData())
174       return NULL;
175     if (pRange.header->getSectionData()->getFragmentList().empty())
176       return NULL;
177 
178     if (isFirstRange(pRange))
179       return &pRange.header->getSectionData()->getFragmentList().front();
180 
181     if (isEmptyRange(pRange))
182       return NULL;
183 
184     return pRange.prevRear->getNextNode();
185   }
186 
getFront(const Range & pRange)187   inline const llvm::MCFragment* getFront(const Range& pRange) const
188   {
189     if (!pRange.header->hasSectionData())
190       return NULL;
191     if (pRange.header->getSectionData()->getFragmentList().empty())
192       return NULL;
193 
194     if (isFirstRange(pRange))
195       return &pRange.header->getSectionData()->getFragmentList().front();
196 
197     if (isEmptyRange(pRange))
198       return NULL;
199 
200     return pRange.prevRear->getNextNode();
201   }
202 
203   // get the rear fragment in the range.
getRear(Range & pRange)204   inline llvm::MCFragment* getRear(Range& pRange) const
205   {
206     if (!pRange.header->hasSectionData())
207       return NULL;
208     if (pRange.header->getSectionData()->getFragmentList().empty())
209       return NULL;
210 
211     if (isLastRange(pRange)) {
212       if (isEmptyRange(pRange))
213         return NULL;
214       return &pRange.header->getSectionData()->getFragmentList().back();
215     }
216     return pRange.getNextNode()->prevRear;
217   }
218 
getRear(const Range & pRange)219   inline const llvm::MCFragment* getRear(const Range& pRange) const
220   {
221     if (!pRange.header->hasSectionData())
222       return NULL;
223     if (pRange.header->getSectionData()->getFragmentList().empty())
224       return NULL;
225 
226     if (isLastRange(pRange)) {
227       if (isEmptyRange(pRange))
228         return NULL;
229       return &pRange.header->getSectionData()->getFragmentList().back();
230     }
231     return pRange.getNextNode()->prevRear;
232   }
233 
234   MCFragmentRef* getFragmentRef(Range &pRange, uint64_t pOffset);
235 
236   MCFragmentRef* getFragmentRef(llvm::MCFragment& pFront,
237                                 llvm::MCFragment& pRear,
238                                 uint64_t pOffset);
239 
hasLayoutOrder(const llvm::MCFragment & pFragment)240   bool hasLayoutOrder(const llvm::MCFragment& pFragment) const
241   { return (pFragment.getLayoutOrder() != ~(0U)); }
242 
hasLayoutOffset(const llvm::MCFragment & pFragment)243   bool hasLayoutOffset(const llvm::MCFragment& pFragment) const
244   { return (pFragment.Offset != ~UINT64_C(0)); }
245 
246   bool isValidOffset(const llvm::MCFragment& pFrag, uint64_t pTargetOffset) const;
247 
248   void setFragmentLayoutOrder(llvm::MCFragment* pFragment);
249 
250   void setFragmentLayoutOffset(llvm::MCFragment* pFragment);
251 
252   /// sortSectionOrder - perform sorting on m_SectionOrder to get final layout
253   /// ordering
254   void sortSectionOrder(const Output& pOutput,
255                         const TargetLDBackend& pBackend);
256 
257 private:
258   /// a vector to describe the order of sections
259   SectionOrder m_SectionOrder;
260 
261   /// the map from MCSectionData* to its own RangeList.
262   SDRangeMap m_SDRangeMap;
263 
264   FragRefFactory m_FragRefFactory;
265 };
266 
267 } // namespace of mcld
268 
269 #endif
270