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