1//===- ObjectBuilder.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#include <mcld/Object/ObjectBuilder.h>
10
11#include <mcld/Module.h>
12#include <mcld/LinkerScript.h>
13#include <mcld/IRBuilder.h>
14#include <mcld/Object/SectionMap.h>
15#include <mcld/LD/LDSection.h>
16#include <mcld/LD/SectionData.h>
17#include <mcld/LD/EhFrame.h>
18#include <mcld/Fragment/AlignFragment.h>
19#include <mcld/Fragment/NullFragment.h>
20#include <mcld/Fragment/FillFragment.h>
21
22#include <llvm/Support/Casting.h>
23
24using namespace mcld;
25
26//===----------------------------------------------------------------------===//
27// ObjectBuilder
28//===----------------------------------------------------------------------===//
29ObjectBuilder::ObjectBuilder(Module& pTheModule)
30  : m_Module(pTheModule) {
31}
32
33/// CreateSection - create an output section.
34LDSection* ObjectBuilder::CreateSection(const std::string& pName,
35                                        LDFileFormat::Kind pKind,
36                                        uint32_t pType,
37                                        uint32_t pFlag,
38                                        uint32_t pAlign)
39{
40  // try to get one from output LDSection
41  SectionMap::const_mapping pair =
42    m_Module.getScript().sectionMap().find("*", pName);
43
44  std::string output_name = (pair.first == NULL) ? pName : pair.first->name();
45
46  LDSection* output_sect = m_Module.getSection(output_name);
47  if (NULL == output_sect) {
48    output_sect = LDSection::Create(pName, pKind, pType, pFlag);
49    output_sect->setAlign(pAlign);
50    m_Module.getSectionTable().push_back(output_sect);
51  }
52  return output_sect;
53}
54
55/// MergeSection - merge the pInput section to the pOutput section
56LDSection* ObjectBuilder::MergeSection(const Input& pInputFile,
57                                       LDSection& pInputSection)
58{
59  SectionMap::mapping pair =
60    m_Module.getScript().sectionMap().find(pInputFile.path().native(),
61                                           pInputSection.name());
62
63  if (pair.first != NULL && pair.first->isDiscard()) {
64    pInputSection.setKind(LDFileFormat::Ignore);
65    return NULL;
66  }
67
68  std::string output_name = (pair.first == NULL) ?
69                            pInputSection.name() : pair.first->name();
70  LDSection* target = m_Module.getSection(output_name);
71
72  if (NULL == target) {
73    target = LDSection::Create(output_name,
74                               pInputSection.kind(),
75                               pInputSection.type(),
76                               pInputSection.flag());
77    target->setAlign(pInputSection.align());
78    m_Module.getSectionTable().push_back(target);
79  }
80
81  switch (target->kind()) {
82    case LDFileFormat::EhFrame: {
83      EhFrame* eh_frame = NULL;
84      if (target->hasEhFrame())
85        eh_frame = target->getEhFrame();
86      else
87        eh_frame = IRBuilder::CreateEhFrame(*target);
88
89      eh_frame->merge(pInputFile, *pInputSection.getEhFrame());
90      UpdateSectionAlign(*target, pInputSection);
91      return target;
92    }
93    default: {
94      if (!target->hasSectionData())
95        IRBuilder::CreateSectionData(*target);
96
97      SectionData* data = NULL;
98      if (pair.first != NULL) {
99        assert(pair.second != NULL);
100        data = pair.second->getSection()->getSectionData();
101      } else {
102        // orphan section
103        data = target->getSectionData();
104      }
105
106      if (MoveSectionData(*pInputSection.getSectionData(), *data)) {
107        UpdateSectionAlign(*target, pInputSection);
108        return target;
109      }
110      return NULL;
111    }
112  }
113  return target;
114}
115
116/// MoveSectionData - move the fragments of pTO section data to pTo
117bool ObjectBuilder::MoveSectionData(SectionData& pFrom, SectionData& pTo)
118{
119  assert(&pFrom != &pTo && "Cannot move section data to itself!");
120
121  uint64_t offset = pTo.getSection().size();
122  AlignFragment* align = NULL;
123  if (pFrom.getSection().align() > 1) {
124    // if the align constraint is larger than 1, append an alignment
125    align = new AlignFragment(pFrom.getSection().align(), // alignment
126                              0x0, // the filled value
127                              1u,  // the size of filled value
128                              pFrom.getSection().align() - 1 // max bytes to emit
129                              );
130    align->setOffset(offset);
131    align->setParent(&pTo);
132    pTo.getFragmentList().push_back(align);
133    offset += align->size();
134  }
135
136  // move fragments from pFrom to pTO
137  SectionData::FragmentListType& from_list = pFrom.getFragmentList();
138  SectionData::FragmentListType& to_list = pTo.getFragmentList();
139  SectionData::FragmentListType::iterator frag, fragEnd = from_list.end();
140  for (frag = from_list.begin(); frag != fragEnd; ++frag) {
141    frag->setParent(&pTo);
142    frag->setOffset(offset);
143    offset += frag->size();
144  }
145  to_list.splice(to_list.end(), from_list);
146
147  // set up pTo's header
148  pTo.getSection().setSize(offset);
149
150  return true;
151}
152
153/// UpdateSectionAlign - update alignment for input section
154void ObjectBuilder::UpdateSectionAlign(LDSection& pTo, const LDSection& pFrom)
155{
156  if (pFrom.align() > pTo.align())
157    pTo.setAlign(pFrom.align());
158}
159
160/// UpdateSectionAlign - update alignment for input section
161void ObjectBuilder::UpdateSectionAlign(LDSection& pSection,
162                                       uint32_t pAlignConstraint)
163{
164  if (pSection.align() < pAlignConstraint)
165    pSection.setAlign(pAlignConstraint);
166}
167
168/// AppendFragment - To append pFrag to the given SectionData pSD.
169uint64_t ObjectBuilder::AppendFragment(Fragment& pFrag,
170                                       SectionData& pSD,
171                                       uint32_t pAlignConstraint)
172{
173  // get initial offset.
174  uint64_t offset = 0;
175  if (!pSD.empty())
176    offset = pSD.back().getOffset() + pSD.back().size();
177
178  AlignFragment* align = NULL;
179  if (pAlignConstraint > 1) {
180    // if the align constraint is larger than 1, append an alignment
181    align = new AlignFragment(pAlignConstraint, // alignment
182                              0x0, // the filled value
183                              1u,  // the size of filled value
184                              pAlignConstraint - 1 // max bytes to emit
185                              );
186    align->setOffset(offset);
187    align->setParent(&pSD);
188    pSD.getFragmentList().push_back(align);
189    offset += align->size();
190  }
191
192  // append the fragment
193  pFrag.setParent(&pSD);
194  pFrag.setOffset(offset);
195  pSD.getFragmentList().push_back(&pFrag);
196
197  // append the null fragment
198  offset += pFrag.size();
199  NullFragment* null = new NullFragment(&pSD);
200  null->setOffset(offset);
201
202  if (NULL != align)
203    return align->size() + pFrag.size();
204  else
205    return pFrag.size();
206}
207
208