1 /*
2 * Copyright 2010-2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "bcc/Linker.h"
18 #include "bcc/Support/LinkerConfig.h"
19 #include "bcc/Support/MemoryFactory.h"
20 #include "bcc/Support/Log.h"
21
22 #include <llvm/Support/ELF.h>
23
24 #include <mcld/MC/MCLDDriver.h>
25 #include <mcld/MC/InputTree.h>
26 #include <mcld/MC/MCLinker.h>
27 #include <mcld/MC/InputTree.h>
28 #include <mcld/LD/LDSection.h>
29 #include <mcld/LD/LDContext.h>
30 #include <mcld/Target/TargetLDBackend.h>
31 #include <mcld/Support/Path.h>
32 #include <mcld/Support/MemoryArea.h>
33 #include <mcld/Support/FileHandle.h>
34 #include <mcld/Support/MemoryAreaFactory.h>
35 #include <mcld/Support/TargetRegistry.h>
36
37 using namespace bcc;
38
GetErrorString(enum Linker::ErrorCode pErrCode)39 const char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode) {
40 static const char* ErrorString[] = {
41 /* kSuccess */
42 "Successfully compiled.",
43 /* kDoubleConfig */
44 "Configure Linker twice.",
45 /* kCreateBackend */
46 "Cannot create backend.",
47 /* kDelegateLDInfo */
48 "Cannot get linker information",
49 /* kFindNameSpec */
50 "Cannot find -lnamespec",
51 /* kOpenNameSpec */
52 "Cannot open -lnamespec",
53 /* kOpenObjectFile */
54 "Cannot open object file",
55 /* kNotConfig */
56 "Linker::config() is not called",
57 /* kNotSetUpOutput */
58 "Linker::setOutput() is not called before add input files",
59 /* kOpenOutput */
60 "Cannot open output file",
61 /* kReadSections */
62 "Cannot read sections",
63 /* kReadSymbols */
64 "Cannot read symbols",
65 /* kAddAdditionalSymbols */
66 "Cannot add standard and target symbols",
67 /* kMaxErrorCode */
68 "(Unknown error code)"
69 };
70
71 if (pErrCode > kMaxErrorCode) {
72 pErrCode = kMaxErrorCode;
73 }
74
75 return ErrorString[ static_cast<size_t>(pErrCode) ];
76 }
77
78 //===----------------------------------------------------------------------===//
79 // Linker
80 //===----------------------------------------------------------------------===//
Linker()81 Linker::Linker()
82 : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
83 mRoot(NULL), mShared(false) {
84 }
85
Linker(const LinkerConfig & pConfig)86 Linker::Linker(const LinkerConfig& pConfig)
87 : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
88 mRoot(NULL), mShared(false) {
89
90 const std::string &triple = pConfig.getTriple();
91
92 enum ErrorCode err = config(pConfig);
93 if (kSuccess != err) {
94 ALOGE("%s (%s)", GetErrorString(err), triple.c_str());
95 return;
96 }
97
98 return;
99 }
100
~Linker()101 Linker::~Linker() {
102 delete mDriver;
103 delete mBackend;
104 delete mMemAreaFactory;
105 delete mRoot;
106 }
107
extractFiles(const LinkerConfig & pConfig)108 enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
109 mLDInfo = const_cast<mcld::MCLDInfo*>(pConfig.getLDInfo());
110 if (mLDInfo == NULL) {
111 return kDelegateLDInfo;
112 }
113
114 mRoot = new mcld::InputTree::iterator(mLDInfo->inputs().root());
115 mShared = pConfig.isShared();
116 mSOName = pConfig.getSOName();
117
118 return kSuccess;
119 }
120
config(const LinkerConfig & pConfig)121 enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
122 if (mLDInfo != NULL) {
123 return kDoubleConfig;
124 }
125
126 extractFiles(pConfig);
127
128 mBackend = pConfig.getTarget()->createLDBackend(pConfig.getTriple());
129 if (mBackend == NULL) {
130 return kCreateBackend;
131 }
132
133 mMemAreaFactory = new MemoryFactory();
134
135 mDriver = new mcld::MCLDDriver(*mLDInfo, *mBackend, *mMemAreaFactory);
136
137 mDriver->initMCLinker();
138
139 return kSuccess;
140 }
141
advanceRoot()142 void Linker::advanceRoot() {
143 if (mRoot->isRoot()) {
144 mRoot->move<mcld::TreeIteratorBase::Leftward>();
145 } else {
146 mRoot->move<mcld::TreeIteratorBase::Rightward>();
147 }
148 return;
149 }
150
openFile(const mcld::sys::fs::Path & pPath,enum Linker::ErrorCode pCode,mcld::Input & pInput)151 enum Linker::ErrorCode Linker::openFile(const mcld::sys::fs::Path& pPath,
152 enum Linker::ErrorCode pCode,
153 mcld::Input& pInput) {
154 mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pPath,
155 mcld::FileHandle::ReadOnly);
156
157 if (input_memory->handler()->isGood()) {
158 pInput.setMemArea(input_memory);
159 } else {
160 return pCode;
161 }
162
163 mcld::LDContext *input_context = mLDInfo->contextFactory().produce(pPath);
164 pInput.setContext(input_context);
165 return kSuccess;
166 }
167
addNameSpec(const std::string & pNameSpec)168 enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
169 mcld::sys::fs::Path* path = NULL;
170 // find out the real path of the namespec.
171 if (mLDInfo->attrFactory().constraint().isSharedSystem()) {
172 // In the system with shared object support, we can find both archive
173 // and shared object.
174
175 if (mLDInfo->attrFactory().last().isStatic()) {
176 // with --static, we must search an archive.
177 path = mLDInfo->options().directories().find(pNameSpec,
178 mcld::Input::Archive);
179 }
180 else {
181 // otherwise, with --Bdynamic, we can find either an archive or a
182 // shared object.
183 path = mLDInfo->options().directories().find(pNameSpec,
184 mcld::Input::DynObj);
185 }
186 }
187 else {
188 // In the system without shared object support, we only look for an
189 // archive.
190 path = mLDInfo->options().directories().find(pNameSpec,
191 mcld::Input::Archive);
192 }
193
194 if (NULL == path)
195 return kFindNameSpec;
196
197 mcld::Input* input = mLDInfo->inputFactory().produce(pNameSpec, *path,
198 mcld::Input::Unknown);
199 mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
200
201 advanceRoot();
202
203 return openFile(*path, kOpenNameSpec, *input);
204 }
205
206 /// addObject - Add a object file by the filename.
addObject(const std::string & pObjectPath)207 enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
208 mcld::Input* input = mLDInfo->inputFactory().produce(pObjectPath,
209 pObjectPath,
210 mcld::Input::Unknown);
211
212 mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
213
214 advanceRoot();
215
216 return openFile(pObjectPath, kOpenObjectFile, *input);
217 }
218
219 /// addObject - Add a piece of memory. The memory is of ELF format.
addObject(void * pMemory,size_t pSize)220 enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
221
222 mcld::Input* input = mLDInfo->inputFactory().produce("memory object",
223 "NAN",
224 mcld::Input::Unknown);
225
226 mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
227
228 advanceRoot();
229
230 mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
231 input->setMemArea(input_memory);
232
233 mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
234 input->setContext(input_context);
235
236 return kSuccess;
237 }
238
addCode(void * pMemory,size_t pSize)239 enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
240 mcld::Input* input = mLDInfo->inputFactory().produce("code object",
241 "NAN",
242 mcld::Input::External);
243
244 mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
245
246 advanceRoot();
247
248 mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
249 input->setMemArea(input_memory);
250
251 mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
252 input->setContext(input_context);
253
254 // FIXME: So far, MCLinker must set up output before add input files.
255 // set up LDContext
256 if (mDriver->hasInitLinker()) {
257 return kNotConfig;
258 }
259
260 if (!mLDInfo->output().hasContext()) {
261 return kNotSetUpOutput;
262 }
263
264 // create NULL section
265 mcld::LDSection& null =
266 mDriver->getLinker()->createSectHdr("",
267 mcld::LDFileFormat::Null,
268 llvm::ELF::SHT_NULL,
269 0);
270
271 null.setSize(0);
272 null.setOffset(0);
273 null.setIndex(0);
274 null.setInfo(0);
275 null.setAlign(0);
276
277 input_context->getSectionTable().push_back(&null);
278
279 // create .text section
280 mcld::LDSection& text = mDriver->getLinker()->createSectHdr(".text",
281 mcld::LDFileFormat::Regular,
282 llvm::ELF::SHT_PROGBITS,
283 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR);
284
285 text.setSize(pSize);
286 text.setOffset(0x0);
287 text.setIndex(1);
288 text.setInfo(0);
289 text.setAlign(1);
290
291 input_context->getSectionTable().push_back(&text);
292
293 return kSuccess;
294 }
295
setOutput(const std::string & pPath)296 enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
297 if (mLDInfo->output().hasContext()) {
298 return kDoubleConfig;
299 }
300
301 // ----- initialize output file ----- //
302
303 mcld::FileHandle::Permission perm = 0755;
304
305 mcld::MemoryArea* out_area = mMemAreaFactory->produce(
306 pPath,
307 mcld::FileHandle::ReadWrite |
308 mcld::FileHandle::Truncate |
309 mcld::FileHandle::Create,
310 perm);
311
312 if (!out_area->handler()->isGood()) {
313 return kOpenOutput;
314 }
315
316 if (mShared) {
317 mLDInfo->output().setType(mcld::Output::DynObj);
318 } else {
319 mLDInfo->output().setType(mcld::Output::Exec);
320 }
321
322 mLDInfo->output().setSOName(mSOName);
323 mLDInfo->output().setMemArea(out_area);
324 mLDInfo->output().setContext(mLDInfo->contextFactory().produce(pPath));
325
326 // FIXME: We must initialize MCLinker before setOutput, and initialize
327 // standard sections here. This is because we have to build the section
328 // map before input files using it.
329 if (!mDriver->hasInitLinker()) {
330 return kNotConfig;
331 }
332
333 mDriver->initStdSections();
334
335 return kSuccess;
336 }
337
setOutput(int pFileHandler)338 enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
339 if (mLDInfo->output().hasContext()) {
340 return kDoubleConfig;
341 }
342
343 // ----- initialize output file ----- //
344 mcld::MemoryArea* out_area = mMemAreaFactory->produce(pFileHandler);
345
346 mLDInfo->output().setType(mcld::Output::DynObj);
347 mLDInfo->output().setMemArea(out_area);
348 mLDInfo->output().setContext(mLDInfo->contextFactory().produce());
349
350 // FIXME: We must initialize MCLinker before setOutput, and initialize
351 // standard sections here. This is because we have to build the section
352 // map before input files using it.
353 if (!mDriver->hasInitLinker()) {
354 return kNotConfig;
355 }
356
357 mDriver->initStdSections();
358
359 return kSuccess;
360 }
361
link()362 enum Linker::ErrorCode Linker::link() {
363 mDriver->normalize();
364
365 if (!mDriver->mergeSections()) {
366 return kReadSections;
367 }
368
369 if (!mDriver->addStandardSymbols() || !mDriver->addTargetSymbols()) {
370 return kAddAdditionalSymbols;
371 }
372
373 mDriver->readRelocations();
374 mDriver->prelayout();
375 mDriver->layout();
376 mDriver->postlayout();
377 mDriver->finalizeSymbolValue();
378 mDriver->relocation();
379 mDriver->emitOutput();
380 mDriver->postProcessing();
381
382 return kSuccess;
383 }
384
385