1 //===- SectLinker.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 //
10 // This file implements the SectLinker class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include <mcld/ADT/BinTree.h>
15 #include <mcld/CodeGen/SectLinker.h>
16 #include <mcld/CodeGen/SectLinkerOption.h>
17 #include <mcld/MC/MCLDInputTree.h>
18 #include <mcld/MC/MCLDDriver.h>
19 #include <mcld/Support/DerivedPositionDependentOptions.h>
20 #include <mcld/Support/FileSystem.h>
21 #include <mcld/Target/TargetLDBackend.h>
22
23 #include <llvm/Module.h>
24 #include <llvm/Support/ErrorHandling.h>
25 #include <llvm/Support/raw_ostream.h>
26
27 #include <algorithm>
28 #include <stack>
29 #include <string>
30
31 using namespace mcld;
32 using namespace llvm;
33
34 //===----------------------------------------------------------------------===//
35 // Forward declarations
36 char SectLinker::m_ID = 0;
37 static bool CompareOption(const PositionDependentOption* X,
38 const PositionDependentOption* Y);
39
40 //===----------------------------------------------------------------------===//
41 // SectLinker
SectLinker(SectLinkerOption & pOption,TargetLDBackend & pLDBackend)42 SectLinker::SectLinker(SectLinkerOption &pOption,
43 TargetLDBackend& pLDBackend)
44 : MachineFunctionPass(m_ID),
45 m_pOption(&pOption),
46 m_pLDBackend(&pLDBackend),
47 m_pLDDriver(NULL) { }
48
~SectLinker()49 SectLinker::~SectLinker()
50 {
51 delete m_pLDDriver;
52 // FIXME: current implementation can not change the order of delete.
53 //
54 // Instance of TargetLDBackend was created outside and is not managed by
55 // SectLinker. It should not be destroyed here and by SectLinker. However, in
56 // order to follow the LLVM convention - that is, the pass manages all the
57 // objects it used during the processing, we destroy the object of
58 // TargetLDBackend here.
59 delete m_pLDBackend;
60 }
61
doInitialization(Module & pM)62 bool SectLinker::doInitialization(Module &pM)
63 {
64 MCLDInfo &info = m_pOption->info();
65
66 // setup the output
67 info.output().setContext(info.contextFactory().produce(info.output().path()));
68
69 int mode = (Output::Object == info.output().type())? 0544 : 0755;
70 info.output().setMemArea(
71 info.memAreaFactory().produce(info.output().path(),
72 O_RDWR | O_CREAT | O_TRUNC,
73 mode));
74
75 // make sure output is openend successfully.
76 if (!info.output().hasMemArea())
77 report_fatal_error("output is not given on the command line\n");
78
79 if (!info.output().memArea()->isGood())
80 report_fatal_error("can not open output file :"+info.output().path().native());
81
82 // let the target override the target-specific parameters
83 addTargetOptions(pM, *m_pOption);
84
85 // ----- convert position dependent options into tree of input files ----- //
86 PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options();
87 std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption);
88 initializeInputTree(PosDepOpts);
89
90 // Now, all input arguments are prepared well, send it into MCLDDriver
91 m_pLDDriver = new MCLDDriver(info, *m_pLDBackend);
92
93 return false;
94 }
95
doFinalization(Module & pM)96 bool SectLinker::doFinalization(Module &pM)
97 {
98 const MCLDInfo &info = m_pOption->info();
99
100 // 3. - initialize output's standard segments and sections
101 if (!m_pLDDriver->initMCLinker())
102 return true;
103
104 // 4. - normalize the input tree
105 m_pLDDriver->normalize();
106
107 if (info.options().verbose()) {
108 outs() << "MCLinker (LLVM Sub-project) - ";
109 outs() << MCLDInfo::version();
110 outs() << "\n";
111 }
112
113 if (info.options().trace()) {
114 static int counter = 0;
115 outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
116 InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end();
117 for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) {
118 outs() << counter++ << " * " << (*input)->name();
119 switch((*input)->type()) {
120 case Input::Archive:
121 outs() << "\tarchive\t(";
122 break;
123 case Input::Object:
124 outs() << "\tobject\t(";
125 break;
126 case Input::DynObj:
127 outs() << "\tshared\t(";
128 break;
129 case Input::Script:
130 outs() << "\tscript\t(";
131 break;
132 default:
133 report_fatal_error("** Trace a unsupported file. It must be an internal bug!");
134 }
135 outs() << (*input)->path().c_str() << ")\n";
136 }
137 }
138
139 // 5. - check if we can do static linking and if we use split-stack.
140 if (!m_pLDDriver->linkable())
141 return true;
142
143
144 // 6. - read all sections
145 if (!m_pLDDriver->readSections() ||
146 !m_pLDDriver->mergeSections())
147 return true;
148
149 // 7. - read all symbol tables of input files and resolve them
150 if (!m_pLDDriver->readSymbolTables() ||
151 !m_pLDDriver->mergeSymbolTables())
152 return true;
153
154 // 7.a - add standard symbols and target-dependent symbols
155 // m_pLDDriver->addUndefSymbols();
156 if (!m_pLDDriver->addStandardSymbols() ||
157 !m_pLDDriver->addTargetSymbols())
158 return true;
159
160 // 8. - read all relocation entries from input files
161 m_pLDDriver->readRelocations();
162
163 // 9. - pre-layout
164 m_pLDDriver->prelayout();
165
166 // 10. - linear layout
167 m_pLDDriver->layout();
168
169 // 10.b - post-layout
170 m_pLDDriver->postlayout();
171
172 // 11. - finalize symbol value
173 m_pLDDriver->finalizeSymbolValue();
174
175 // 12. - apply relocations
176 m_pLDDriver->relocate();
177
178 // 13. - write out output
179 m_pLDDriver->emitOutput();
180
181 // 14. - post processing
182 m_pLDDriver->postProcessing();
183 return false;
184 }
185
runOnMachineFunction(MachineFunction & pF)186 bool SectLinker::runOnMachineFunction(MachineFunction& pF)
187 {
188 // basically, linkers do nothing during function is generated.
189 return false;
190 }
191
initializeInputTree(const PositionDependentOptions & pPosDepOptions) const192 void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const
193 {
194 if (pPosDepOptions.empty())
195 return;
196
197 MCLDInfo &info = m_pOption->info();
198 PositionDependentOptions::const_iterator cur_char = pPosDepOptions.begin();
199 if (1 == pPosDepOptions.size() &&
200 ((*cur_char)->type() != PositionDependentOption::INPUT_FILE &&
201 (*cur_char)->type() != PositionDependentOption::NAMESPEC))
202 return;
203
204 InputTree::Connector *prev_ward = &InputTree::Downward;
205
206 std::stack<InputTree::iterator> returnStack;
207 InputTree::iterator cur_node = info.inputs().root();
208
209 PositionDependentOptions::const_iterator charEnd = pPosDepOptions.end();
210 while (cur_char != charEnd ) {
211 switch ((*cur_char)->type()) {
212 case PositionDependentOption::BITCODE: {
213 // threat bitcode as a script in this version.
214 const BitcodeOption *bitcode_option =
215 static_cast<const BitcodeOption*>(*cur_char);
216 info.inputs().insert(cur_node,
217 *prev_ward,
218 bitcode_option->path()->native(),
219 *(bitcode_option->path()),
220 Input::Script);
221 info.setBitcode(**cur_node);
222 prev_ward->move(cur_node);
223 prev_ward = &InputTree::Afterward;
224 break;
225 }
226 case PositionDependentOption::INPUT_FILE: {
227 const InputFileOption *input_file_option =
228 static_cast<const InputFileOption*>(*cur_char);
229 info.inputs().insert(cur_node,
230 *prev_ward,
231 input_file_option->path()->native(),
232 *(input_file_option->path()));
233 prev_ward->move(cur_node);
234 prev_ward = &InputTree::Afterward;
235 break;
236 }
237 case PositionDependentOption::NAMESPEC: {
238 sys::fs::Path* path = 0;
239 const NamespecOption *namespec_option =
240 static_cast<const NamespecOption*>(*cur_char);
241 if (info.attrFactory().last().isStatic()) {
242 path = info.options().directories().find(namespec_option->namespec(),
243 Input::Archive);
244 }
245 else {
246 path = info.options().directories().find(namespec_option->namespec(),
247 Input::DynObj);
248 }
249
250 if (0 == path) {
251 llvm::report_fatal_error(std::string("Can't find namespec: ")+
252 namespec_option->namespec());
253 }
254 info.inputs().insert(cur_node,
255 *prev_ward,
256 namespec_option->namespec(),
257 *path);
258 prev_ward->move(cur_node);
259 prev_ward = &InputTree::Afterward;
260 break;
261 }
262 case PositionDependentOption::START_GROUP:
263 info.inputs().enterGroup(cur_node, *prev_ward);
264 prev_ward->move(cur_node);
265 returnStack.push(cur_node);
266 prev_ward = &InputTree::Downward;
267 break;
268 case PositionDependentOption::END_GROUP:
269 cur_node = returnStack.top();
270 returnStack.pop();
271 prev_ward = &InputTree::Afterward;
272 break;
273 case PositionDependentOption::WHOLE_ARCHIVE:
274 info.attrFactory().last().setWholeArchive();
275 break;
276 case PositionDependentOption::NO_WHOLE_ARCHIVE:
277 info.attrFactory().last().unsetWholeArchive();
278 break;
279 case PositionDependentOption::AS_NEEDED:
280 info.attrFactory().last().setAsNeeded();
281 break;
282 case PositionDependentOption::NO_AS_NEEDED:
283 info.attrFactory().last().unsetAsNeeded();
284 break;
285 case PositionDependentOption::ADD_NEEDED:
286 info.attrFactory().last().setAddNeeded();
287 break;
288 case PositionDependentOption::NO_ADD_NEEDED:
289 info.attrFactory().last().unsetAddNeeded();
290 break;
291 case PositionDependentOption::BSTATIC:
292 info.attrFactory().last().setStatic();
293 break;
294 case PositionDependentOption::BDYNAMIC:
295 info.attrFactory().last().setDynamic();
296 break;
297 default:
298 report_fatal_error("can not find the type of input file");
299 }
300 ++cur_char;
301 }
302
303 if (!returnStack.empty()) {
304 report_fatal_error("no matched --start-group and --end-group");
305 }
306 }
307
308 //===----------------------------------------------------------------------===//
309 // Non-member functions
CompareOption(const PositionDependentOption * X,const PositionDependentOption * Y)310 static bool CompareOption(const PositionDependentOption* X,
311 const PositionDependentOption* Y)
312 {
313 return (X->position() < Y->position());
314 }
315
316