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