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 
25 namespace mcld {
26 
27 //===----------------------------------------------------------------------===//
28 // ObjectBuilder
29 //===----------------------------------------------------------------------===//
ObjectBuilder(Module & pTheModule)30 ObjectBuilder::ObjectBuilder(Module& pTheModule) : m_Module(pTheModule) {
31 }
32 
33 /// CreateSection - create an output section.
CreateSection(const std::string & pName,LDFileFormat::Kind pKind,uint32_t pType,uint32_t pFlag,uint32_t pAlign)34 LDSection* 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
MergeSection(const Input & pInputFile,LDSection & pInputSection)55 LDSection* 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
MoveSectionData(SectionData & pFrom,SectionData & pTo)130 bool 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
UpdateSectionAlign(LDSection & pTo,const LDSection & pFrom)166 void 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
UpdateSectionAlign(LDSection & pSection,uint32_t pAlignConstraint)172 void 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.
AppendFragment(Fragment & pFrag,SectionData & pSD,uint32_t pAlignConstraint)179 uint64_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