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