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