• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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