• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 using namespace mcld;
25 
26 //===----------------------------------------------------------------------===//
27 // ObjectBuilder
28 //===----------------------------------------------------------------------===//
ObjectBuilder(Module & pTheModule)29 ObjectBuilder::ObjectBuilder(Module& pTheModule)
30   : 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 {
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
MergeSection(const Input & pInputFile,LDSection & pInputSection)56 LDSection* 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
MoveSectionData(SectionData & pFrom,SectionData & pTo)117 bool 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
UpdateSectionAlign(LDSection & pTo,const LDSection & pFrom)154 void 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
UpdateSectionAlign(LDSection & pSection,uint32_t pAlignConstraint)161 void 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.
AppendFragment(Fragment & pFrag,SectionData & pSD,uint32_t pAlignConstraint)169 uint64_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