• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- Layout.cpp ---------------------------------------------------------===//
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 
10 #include <mcld/LD/Layout.h>
11 
12 #include <cassert>
13 
14 #include <llvm/ADT/Twine.h>
15 
16 #include <mcld/ADT/SizeTraits.h>
17 #include <mcld/LD/LDContext.h>
18 #include <mcld/LD/LDFileFormat.h>
19 #include <mcld/LD/LDSection.h>
20 #include <mcld/LD/Fragment.h>
21 #include <mcld/LD/FillFragment.h>
22 #include <mcld/LD/AlignFragment.h>
23 #include <mcld/MC/MCLinker.h>
24 #include <mcld/MC/MCLDInfo.h>
25 #include <mcld/Support/MsgHandling.h>
26 #include <mcld/Target/TargetLDBackend.h>
27 
28 using namespace mcld;
29 
30 //===----------------------------------------------------------------------===//
31 // Range
32 //===----------------------------------------------------------------------===//
Range()33 Layout::Range::Range()
34   : header(NULL),
35     prevRear(NULL) {
36 }
37 
Range(const LDSection & pHdr)38 Layout::Range::Range(const LDSection& pHdr)
39   : header(const_cast<LDSection*>(&pHdr)),
40     prevRear(NULL) {
41 }
42 
~Range()43 Layout::Range::~Range()
44 {
45 }
46 
47 //===----------------------------------------------------------------------===//
48 // Layout
49 //===----------------------------------------------------------------------===//
Layout()50 Layout::Layout()
51   : m_FragRefFactory(32) /** magic number **/ {
52 }
53 
~Layout()54 Layout::~Layout()
55 {
56 }
57 
setFragmentLayoutOrder(Fragment * pFrag)58 void Layout::setFragmentLayoutOrder(Fragment* pFrag)
59 {
60   if (NULL == pFrag)
61     return;
62 
63   /// find the most-recent fragment whose order was set.
64   Fragment* first = pFrag;
65   while (!hasLayoutOrder(*first)) {
66     if (NULL == first->getPrevNode())
67       break;
68     first = first->getPrevNode();
69   }
70 
71   /// set all layout order
72 
73   // find the first fragment who has no order.
74   // find the last order of the fragment
75   unsigned int layout_order = 0;
76   Fragment* frag_not_set = NULL;
77   if (NULL == first->getPrevNode()) {
78     layout_order = 0;
79     frag_not_set = first;
80   }
81   else {
82     layout_order = first->getLayoutOrder();
83     frag_not_set = first->getNextNode();
84   }
85 
86   // for all fragments that has no order, set up its order
87   while(NULL != frag_not_set) {
88     frag_not_set->setLayoutOrder(layout_order);
89     ++layout_order;
90     frag_not_set = frag_not_set->getNextNode();
91   }
92 }
93 
94 /// setFragmentLayoutOffset - set the fragment's layout offset. This function
95 /// also set up the layout offsets of all the fragments in the same range.
96 /// If the offset of the fragment was set before, return immediately.
setFragmentLayoutOffset(Fragment * pFrag)97 void Layout::setFragmentLayoutOffset(Fragment* pFrag)
98 {
99   if (NULL == pFrag)
100     return;
101 
102   // find the most-recent fragment whose offset was set.
103   Fragment* first = pFrag;
104 
105   while (!hasLayoutOffset(*first)) {
106     if (NULL == first->getPrevNode())
107       break;
108     first = first->getPrevNode();
109   }
110 
111   // set all layout order
112   uint64_t offset = 0;
113   Fragment* frag_not_set = NULL;
114   if (NULL == first->getPrevNode()) {
115     offset = 0;
116     frag_not_set = first;
117   }
118   else {
119     offset = first->getOffset();
120     offset += computeFragmentSize(*this, *first);
121     frag_not_set = first->getNextNode();
122   }
123 
124   while(NULL != frag_not_set) {
125     frag_not_set->setOffset(offset);
126     offset += computeFragmentSize(*this, *frag_not_set);
127     frag_not_set = frag_not_set->getNextNode();
128   }
129 }
130 
131 /// addInputRange
132 ///   1. add a new range <pInputHdr, previous rear fragment>
133 ///   2. compute the layout order of all previous ranges.
134 ///   2. compute the layout offset of all previous ranges.
addInputRange(const SectionData & pSD,const LDSection & pInputHdr)135 void Layout::addInputRange(const SectionData& pSD,
136                            const LDSection& pInputHdr)
137 {
138   RangeList* range_list = NULL;
139 
140   // get or create the range_list
141   if (pSD.getFragmentList().empty() || 0 == m_SDRangeMap.count(&pSD)) {
142     range_list = new RangeList();
143     m_SDRangeMap[&pSD] = range_list;
144   }
145   else {
146     range_list = m_SDRangeMap[&pSD];
147   }
148 
149   // make a range and push it into the range list
150   Range* range = new Range(pInputHdr);
151   range_list->push_back(range);
152 
153   // set up previous rear of the range.
154   // FIXME: in current design, we can not add a range before finishing adding
155   // fragments in the previous range. If the limitation keeps, we can set
156   // prevRear to the last fragment in the SectionData simply.
157   //
158   // if the pSD's fragment list is empty, the range.prevRear keeps NULL.
159   if (!pSD.getFragmentList().empty()) {
160     range->prevRear =
161                   const_cast<Fragment*>(&pSD.getFragmentList().back());
162   }
163 
164   // compute the layout order of the previous range.
165   if (!isFirstRange(*range)) {
166     setFragmentLayoutOrder(range->prevRear);
167     setFragmentLayoutOffset(range->prevRear);
168   }
169 }
170 
171 /// appendFragment - append the given Fragment to the given SectionData,
172 /// and insert a MCAlignFragment to preserve the required align constraint if
173 /// needed
appendFragment(Fragment & pFrag,SectionData & pSD,uint32_t pAlignConstraint)174 uint64_t Layout::appendFragment(Fragment& pFrag,
175                                 SectionData& pSD,
176                                 uint32_t pAlignConstraint)
177 {
178   // insert MCAlignFragment into SectionData first if needed
179   AlignFragment* align_frag = NULL;
180   if (pAlignConstraint > 1) {
181     align_frag = new AlignFragment(pAlignConstraint, // alignment
182                                    0x0, // the filled value
183                                    1u,  // the size of filled value
184                                    pAlignConstraint - 1, // max bytes to emit
185                                    &pSD);
186   }
187 
188   // append the fragment to the SectionData
189   pFrag.setParent(&pSD);
190   pSD.getFragmentList().push_back(&pFrag);
191 
192   // update the alignment of associated output LDSection if needed
193   LDSection* output_sect = getOutputLDSection(pFrag);
194   assert(NULL != output_sect);
195   if (pAlignConstraint > output_sect->align())
196     output_sect->setAlign(pAlignConstraint);
197 
198   // compute the fragment order and offset
199   setFragmentLayoutOrder(&pFrag);
200   setFragmentLayoutOffset(&pFrag);
201 
202   if (NULL != align_frag)
203     return pFrag.getOffset() - align_frag->getOffset() + computeFragmentSize(*this, pFrag);
204   else
205     return computeFragmentSize(*this, pFrag);
206 }
207 
208 /// getInputLDSection - give a Fragment, return the corresponding input
209 /// LDSection*
210 LDSection*
getInputLDSection(const Fragment & pFrag)211 Layout::getInputLDSection(const Fragment& pFrag)
212 {
213   const SectionData* sect_data = pFrag.getParent();
214   // check the SectionData
215   if (NULL == sect_data) {
216     llvm::report_fatal_error(llvm::Twine("the fragment does not belong to") +
217                              llvm::Twine(" any SectionData.\n"));
218   }
219 
220   // check the SectionData's range list
221   if (0 == m_SDRangeMap.count(sect_data)) {
222     llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
223                              llvm::Twine("the input's SectionData is not ") +
224                              llvm::Twine("registered in the Layout.\nPlease ") +
225                              llvm::Twine("use MCLinker::getOrCreateSectData() ") +
226                              llvm::Twine("to get input's SectionData.\n"));
227   }
228 
229   RangeList* range_list = m_SDRangeMap[sect_data];
230   // the fragment who has the layout order is not in the last range.
231   if (hasLayoutOrder(pFrag)) {
232     Range range = range_list->back();
233     if (isFirstRange(range)) {
234       return range.header;
235     }
236     while(range.prevRear->getLayoutOrder() > pFrag.getLayoutOrder()) {
237       if (NULL != range.getPrevNode())
238         range = *range.getPrevNode();
239       else
240         return NULL;
241     }
242     return range.header;
243   }
244   // the fragment who has no layout order should be in the last range
245   else {
246     if (range_list->empty())
247       return NULL;
248     return range_list->back().header;
249   }
250 }
251 
252 /// getInputLDSection - give a Fragment, return the corresponding input
253 /// LDSection*
254 const LDSection*
getInputLDSection(const Fragment & pFrag) const255 Layout::getInputLDSection(const Fragment& pFrag) const
256 {
257   const SectionData* sect_data = pFrag.getParent();
258   // check the SectionData
259   if (NULL == sect_data) {
260     llvm::report_fatal_error(llvm::Twine("the fragment does not belong to") +
261                              llvm::Twine(" any SectionData.\n"));
262   }
263 
264   // check the SectionData's range list
265   if (0 == m_SDRangeMap.count(sect_data)) {
266     llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
267                              llvm::Twine("the input's SectionData is not ") +
268                              llvm::Twine("registered in the Layout.\nPlease ") +
269                              llvm::Twine("use MCLinker::getOrCreateSectData() ") +
270                              llvm::Twine("to get input's SectionData.\n"));
271   }
272 
273   SDRangeMap::const_iterator range_list_iter = m_SDRangeMap.find(sect_data);
274   const RangeList* range_list = range_list_iter->second;
275   // the fragment who has the layout order is not in the last range.
276   if (hasLayoutOrder(pFrag)) {
277     Range range = range_list->back();
278     if (isFirstRange(range)) {
279       return range.header;
280     }
281     while(range.prevRear->getLayoutOrder() > pFrag.getLayoutOrder()) {
282       if (NULL != range.getPrevNode())
283         range = *range.getPrevNode();
284       else
285         return NULL;
286     }
287     return range.header;
288   }
289   // the fragment who has no layout order should be in the last range
290   else {
291     if (range_list->empty())
292       return NULL;
293     return range_list->back().header;
294   }
295 }
296 
297 /// getOutputLDSection
getOutputLDSection(const Fragment & pFrag)298 LDSection* Layout::getOutputLDSection(const Fragment& pFrag)
299 {
300   SectionData* sect_data = pFrag.getParent();
301   if (NULL == sect_data)
302     return NULL;
303 
304   return const_cast<LDSection*>(&sect_data->getSection());
305 }
306 
307 /// getOutputLDSection
getOutputLDSection(const Fragment & pFrag) const308 const LDSection* Layout::getOutputLDSection(const Fragment& pFrag) const
309 {
310   const SectionData* sect_data = pFrag.getParent();
311   if (NULL == sect_data)
312     return NULL;
313 
314   return &sect_data->getSection();
315 }
316 
317 /// getFragmentRef - assume the ragne exist, find the fragment reference
getFragmentRef(Layout::Range & pRange,uint64_t pOffset)318 FragmentRef* Layout::getFragmentRef(Layout::Range& pRange, uint64_t pOffset)
319 {
320   if (isEmptyRange(pRange))
321     return NULL;
322 
323   Fragment* front = getFront(pRange);
324   if (NULL == front)
325     return NULL;
326 
327   Fragment* rear = getRear(pRange);
328   if (NULL == rear)
329     return NULL;
330 
331   return getFragmentRef(*front, *rear, pOffset);
332 }
333 
334 // @param pFront is the first fragment in the range.
335 // @param pRear is the last fragment in the range.
336 // @pOffset is the offset started from pFront.
337 FragmentRef*
getFragmentRef(Fragment & pFront,Fragment & pRear,uint64_t pOffset)338 Layout::getFragmentRef(Fragment& pFront, Fragment& pRear, uint64_t pOffset)
339 {
340   Fragment* front = &pFront;
341   Fragment* rear  = &pRear;
342 
343   if (!hasLayoutOffset(*rear)) {
344     // compute layout order, offset
345     setFragmentLayoutOrder(rear);
346     setFragmentLayoutOffset(rear);
347   }
348 
349   // compute the offset from overall start fragment.
350   uint64_t target_offset = pFront.getOffset() + pOffset;
351 
352   // from front to rear, find the offset which is as large as possible
353   // but smaller than the target_offset.
354   while (front != rear) {
355     if (Fragment::Alignment == front->getKind()) {
356       // alignment fragments were not counted in target_offset.
357       // Count in the size of alignment fragmen in target_offset here.
358       uint64_t align_size = 0x0;
359       if (NULL == front->getNextNode()) {
360         // If the alignment fragment is the last fragment, increase
361         // the target_offset by the alignment fragment's size.
362         align_size = computeFragmentSize(*this, *front);
363       }
364       else {
365         // If the alignment fragment is not the last fragment, the alignment
366         // fragment's size is the distance between the two fragment.
367         align_size = front->getNextNode()->getOffset() - front->getOffset();
368       }
369       target_offset += align_size;
370       front = front->getNextNode();
371       continue;
372     }
373 
374     if (target_offset >= front->getNextNode()->getOffset()) {
375       front = front->getNextNode();
376     }
377     else {
378       // found
379       FragmentRef* result = m_FragRefFactory.allocate();
380       new (result) FragmentRef(*front, target_offset - front->getOffset());
381       return result;
382     }
383   }
384 
385   if (front == rear) {
386     if (Fragment::Alignment == front->getKind())
387       return NULL;
388 
389     if (!isValidOffset(*front, target_offset))
390       return NULL;
391 
392     FragmentRef* result = m_FragRefFactory.allocate();
393     new (result) FragmentRef(*front, target_offset - front->getOffset());
394     return result;
395   }
396   return NULL;
397 }
398 
399 /// getFragmentRef - give a LDSection in input file and an offset, return
400 /// the fragment reference.
401 FragmentRef*
getFragmentRef(const LDSection & pInputSection,uint64_t pOffset)402 Layout::getFragmentRef(const LDSection& pInputSection, uint64_t pOffset)
403 {
404   // find out which SectionData covers the range of input section header
405   const SectionData* sect_data = pInputSection.getSectionData();
406 
407   // check range list
408   if (0 == m_SDRangeMap.count(sect_data))
409     return NULL;
410 
411   if (sect_data->getFragmentList().empty())
412     return NULL;
413 
414   RangeList* range_list = m_SDRangeMap[sect_data];
415 
416   // find out the specific part in SectionData range
417   RangeList::iterator range, rangeEnd = range_list->end();
418   for (range = range_list->begin(); range != rangeEnd; ++range) {
419     // found the range
420     if (&pInputSection == range->header) {
421       break;
422     }
423   }
424 
425   // range not found
426   if (range == rangeEnd) {
427     fatal(diag::err_section_not_laid_out) << pInputSection.name();
428   }
429 
430   return getFragmentRef(*range, pOffset);
431 }
432 
433 /// getFragmentRef - give a fragment and a big offset, return the fragment
434 /// reference in the section data.
435 ///
436 /// @param pFrag - the given fragment
437 /// @param pBigOffset - the offset, can be larger than the fragment, but can
438 ///                     not larger than this input section.
439 /// @return if found, return the fragment. Otherwise, return NULL.
440 FragmentRef*
getFragmentRef(const Fragment & pFrag,uint64_t pBigOffset)441 Layout::getFragmentRef(const Fragment& pFrag, uint64_t pBigOffset)
442 {
443   if (!hasLayoutOffset(pFrag)) {
444     // compute layout order, offset
445     setFragmentLayoutOrder(const_cast<Fragment*>(&pFrag));
446     setFragmentLayoutOffset(const_cast<Fragment*>(&pFrag));
447   }
448 
449   // find out which SectionData covers the range of input section header
450   const SectionData* sect_data = pFrag.getParent();
451 
452   // check range list
453   if (0 == m_SDRangeMap.count(sect_data)) {
454     llvm::report_fatal_error(llvm::Twine("SectionData has no") +
455                              llvm::Twine(" correponding range list.\n"));
456   }
457 
458   if (sect_data->getFragmentList().empty())
459     return NULL;
460 
461   RangeList* range_list = m_SDRangeMap[sect_data];
462 
463   // find out the specific part in SectionData range
464   uint64_t target_offset = pBigOffset + pFrag.getOffset();
465 
466   RangeList::iterator range, rangeEnd = range_list->end();
467   for (range = range_list->begin(); range != rangeEnd; ++range) {
468     if (isEmptyRange(*range))
469       continue;
470     if (getRear(*range)->getOffset() >= target_offset) {
471       break;
472     }
473   }
474 
475   // range not found
476   if (range == rangeEnd) {
477     llvm::report_fatal_error(llvm::Twine("the offset is too big that") +
478                              llvm::Twine(" never be in the range list.\n"));
479   }
480 
481   return getFragmentRef(*range, pBigOffset);
482 }
483 
getOutputOffset(const Fragment & pFrag)484 uint64_t Layout::getOutputOffset(const Fragment& pFrag)
485 {
486   if (!hasLayoutOffset(pFrag)) {
487     // compute layout order, offset
488     setFragmentLayoutOrder(const_cast<Fragment*>(&pFrag));
489     setFragmentLayoutOffset(const_cast<Fragment*>(&pFrag));
490   }
491   return pFrag.getOffset();
492 }
493 
getOutputOffset(const Fragment & pFrag) const494 uint64_t Layout::getOutputOffset(const Fragment& pFrag) const
495 {
496   if (!hasLayoutOffset(pFrag)) {
497     llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
498                              llvm::Twine("the function ") +
499                              llvm::Twine(__func__) +
500                              llvm::Twine(" can not be used before layout().\n"));
501   }
502   return pFrag.getOffset();
503 }
504 
getOutputOffset(const FragmentRef & pFragRef)505 uint64_t Layout::getOutputOffset(const FragmentRef& pFragRef)
506 {
507   return getOutputOffset(*(pFragRef.frag())) + pFragRef.offset();
508 }
509 
getOutputOffset(const FragmentRef & pFragRef) const510 uint64_t Layout::getOutputOffset(const FragmentRef& pFragRef) const
511 {
512   return getOutputOffset(*(pFragRef.frag())) + pFragRef.offset();
513 }
514 
sortSectionOrder(const Output & pOutput,const TargetLDBackend & pBackend,const MCLDInfo & pInfo)515 void Layout::sortSectionOrder(const Output& pOutput,
516                               const TargetLDBackend& pBackend,
517                               const MCLDInfo& pInfo)
518 {
519   typedef std::pair<LDSection*, unsigned int> SectOrder;
520   typedef std::vector<SectOrder > SectListTy;
521   SectListTy sect_list;
522   // get section order from backend
523   for (size_t index = 0; index < m_SectionOrder.size(); ++index)
524     sect_list.push_back(std::make_pair(
525                     m_SectionOrder[index],
526                     pBackend.getSectionOrder(pOutput, *m_SectionOrder[index], pInfo)));
527 
528   // simple insertion sort should be fine for general cases such as so and exec
529   for (unsigned int i = 1; i < sect_list.size(); ++i) {
530     SectOrder order = sect_list[i];
531     int j = i - 1;
532     while (j >= 0 && sect_list[j].second > order.second) {
533       sect_list[j + 1] = sect_list[j];
534       --j;
535     }
536     sect_list[j + 1] = order;
537   }
538 
539   // update the sorted ordering to m_SectionOrder
540   m_SectionOrder.clear();
541   for (size_t index = 0; index < sect_list.size(); ++index) {
542     m_SectionOrder.push_back(sect_list[index].first);
543   }
544 }
545 
546 /// layout - layout the sections
547 ///   1. finalize fragment offset
548 ///   2. compute section order
549 ///   3. finalize section offset
layout(Output & pOutput,const TargetLDBackend & pBackend,const MCLDInfo & pInfo)550 bool Layout::layout(Output& pOutput,
551                     const TargetLDBackend& pBackend,
552                     const MCLDInfo& pInfo)
553 {
554   // determine what sections in output context will go into final output, and
555   // push the needed sections into m_SectionOrder for later processing
556   assert(pOutput.hasContext());
557   LDContext& output_context = *pOutput.context();
558   LDContext::sect_iterator it, itEnd = output_context.sectEnd();
559   for (it = output_context.sectBegin(); it != itEnd; ++it) {
560     // calculate 1. all fragment offset, and 2. the section order
561     LDSection* sect = *it;
562 
563     switch (sect->kind()) {
564       // ignore if there is no SectionData for certain section kinds
565       case LDFileFormat::Regular:
566       case LDFileFormat::Target:
567       case LDFileFormat::MetaData:
568       case LDFileFormat::BSS:
569       case LDFileFormat::Debug:
570       case LDFileFormat::EhFrame:
571       case LDFileFormat::GCCExceptTable:
572         if (0 != sect->size()) {
573           if (NULL != sect->getSectionData() &&
574               !sect->getSectionData()->getFragmentList().empty()) {
575             // make sure that all fragments are valid
576             Fragment& frag = sect->getSectionData()->getFragmentList().back();
577             setFragmentLayoutOrder(&frag);
578             setFragmentLayoutOffset(&frag);
579           }
580           m_SectionOrder.push_back(sect);
581         }
582         break;
583       // take NULL directly
584       case LDFileFormat::Null:
585         m_SectionOrder.push_back(sect);
586         break;
587       // ignore if section size is 0
588       case LDFileFormat::NamePool:
589       case LDFileFormat::Relocation:
590       case LDFileFormat::Note:
591       case LDFileFormat::EhFrameHdr:
592         if (0 != sect->size())
593           m_SectionOrder.push_back(sect);
594         break;
595       case LDFileFormat::Group:
596         if (MCLDFile::Object == pOutput.type()) {
597           //TODO: support incremental linking
598           ;
599         }
600         break;
601       case LDFileFormat::Version:
602         if (0 != sect->size()) {
603           m_SectionOrder.push_back(sect);
604           warning(diag::warn_unsupported_symbolic_versioning) << sect->name();
605         }
606         break;
607       default:
608         if (0 != sect->size()) {
609           error(diag::err_unsupported_section) << sect->name() << sect->kind();
610         }
611         break;
612     }
613   }
614 
615   // perform sorting on m_SectionOrder to get a ordering for final layout
616   sortSectionOrder(pOutput, pBackend, pInfo);
617 
618   // Backend defines the section start offset for section 1.
619   uint64_t offset = pBackend.sectionStartOffset();
620 
621   for (size_t index = 1; index < m_SectionOrder.size(); ++index) {
622     // compute the section offset and handle alignment also. And ignore section 0
623     // (NULL in ELF/COFF), and MachO starts from section 1.
624 
625     if (LDFileFormat::BSS != m_SectionOrder[index - 1]->kind()) {
626       // we should not preserve file space for the BSS section.
627       offset += m_SectionOrder[index - 1]->size();
628     }
629 
630     alignAddress(offset, m_SectionOrder[index]->align());
631     m_SectionOrder[index]->setOffset(offset);
632   }
633 
634   // FIXME: Currently Writer bases on the section table in output context to
635   // write out sections, so we have to update its content..
636   output_context.getSectionTable().clear();
637   for (size_t index = 0; index < m_SectionOrder.size(); ++index) {
638     output_context.getSectionTable().push_back(m_SectionOrder[index]);
639     // after sorting, update the correct output section indices
640     m_SectionOrder[index]->setIndex(index);
641   }
642   return true;
643 }
644 
isValidOffset(const Fragment & pFrag,uint64_t pTargetOffset) const645 bool Layout::isValidOffset(const Fragment& pFrag, uint64_t pTargetOffset) const
646 {
647   uint64_t size = computeFragmentSize(*this, pFrag);
648   if (0x0 == size)
649     return (pTargetOffset == pFrag.getOffset());
650 
651   if (NULL != pFrag.getNextNode())
652     return (pTargetOffset >= pFrag.getOffset() && pTargetOffset < pFrag.getNextNode()->getOffset());
653 
654   return (pTargetOffset >= pFrag.getOffset() && pTargetOffset < (pFrag.getOffset() + size));
655 }
656 
657