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