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