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