Home | History | Annotate | Download | only in Core
      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/Log.h"
     13 
     14 #include <llvm/Support/ELF.h>
     15 
     16 #include <mcld/Module.h>
     17 #include <mcld/IRBuilder.h>
     18 #include <mcld/MC/MCLDInput.h>
     19 #include <mcld/Linker.h>
     20 #include <mcld/LD/LDSection.h>
     21 #include <mcld/LD/LDContext.h>
     22 #include <mcld/Support/Path.h>
     23 
     24 using namespace alone;
     25 
     26 const char* Linker::GetErrorString(enum Linker::ErrorCode pErrCode) {
     27   static const char* ErrorString[] = {
     28     /* kSuccess */
     29     "Successfully compiled.",
     30     /* kDoubleConfig */
     31     "Configure Linker twice.",
     32     /* kDelegateLDInfo */
     33     "Cannot get linker information",
     34     /* kFindNameSpec */
     35     "Cannot find -lnamespec",
     36     /* kOpenObjectFile */
     37     "Cannot open object file",
     38     /* kNotConfig */
     39     "Linker::config() is not called",
     40     /* kNotSetUpOutput */
     41     "Linker::setOutput() is not called before add input files",
     42     /* kOpenOutput */
     43     "Cannot open output file",
     44     /* kReadSections */
     45     "Cannot read sections",
     46     /* kReadSymbols */
     47     "Cannot read symbols",
     48     /* kAddAdditionalSymbols */
     49     "Cannot add standard and target symbols",
     50     /* kMaxErrorCode */
     51     "(Unknown error code)"
     52   };
     53 
     54   if (pErrCode > kMaxErrorCode) {
     55     pErrCode = kMaxErrorCode;
     56   }
     57 
     58   return ErrorString[ static_cast<size_t>(pErrCode) ];
     59 }
     60 
     61 //===----------------------------------------------------------------------===//
     62 // Linker
     63 //===----------------------------------------------------------------------===//
     64 Linker::Linker()
     65   : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
     66     mOutputHandler(-1) {
     67 }
     68 
     69 Linker::Linker(const LinkerConfig& pConfig)
     70   : mLDConfig(NULL), mModule(NULL), mLinker(NULL), mBuilder(NULL),
     71     mOutputHandler(-1) {
     72 
     73   const std::string &triple = pConfig.getTriple();
     74 
     75   enum ErrorCode err = config(pConfig);
     76   if (kSuccess != err) {
     77     ALOGE("%s (%s)", GetErrorString(err), triple.c_str());
     78     return;
     79   }
     80 
     81   return;
     82 }
     83 
     84 Linker::~Linker() {
     85   delete mModule;
     86   delete mLinker;
     87   delete mBuilder;
     88 }
     89 
     90 enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
     91   mLDConfig = pConfig.getLDConfig();
     92   if (mLDConfig == NULL) {
     93     return kDelegateLDInfo;
     94   }
     95   return kSuccess;
     96 }
     97 
     98 enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
     99   if (mLDConfig != NULL) {
    100     return kDoubleConfig;
    101   }
    102 
    103   extractFiles(pConfig);
    104 
    105   mModule = new mcld::Module(mLDConfig->options().soname());
    106 
    107   mBuilder = new mcld::IRBuilder(*mModule, *mLDConfig);
    108 
    109   mLinker = new mcld::Linker();
    110 
    111   mLinker->config(const_cast<mcld::LinkerConfig&>(*mLDConfig));
    112 
    113   return kSuccess;
    114 }
    115 
    116 enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
    117   mcld::Input* input = mBuilder->ReadInput(pNameSpec);
    118   if (NULL == input)
    119     return kFindNameSpec;
    120   return kSuccess;
    121 }
    122 
    123 /// addObject - Add a object file by the filename.
    124 enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
    125   mcld::Input* input = mBuilder->ReadInput(pObjectPath, pObjectPath);
    126   if (NULL == input)
    127     return kOpenObjectFile;
    128   return kSuccess;
    129 }
    130 
    131 /// addObject - Add a piece of memory. The memory is of ELF format.
    132 enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
    133   mcld::Input* input = mBuilder->ReadInput("NAN", pMemory, pSize);
    134   if (NULL == input)
    135     return kOpenMemory;
    136   return kSuccess;
    137 }
    138 
    139 enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
    140   mcld::Input* input = mBuilder->CreateInput("NAN", "NAN", mcld::Input::Object);
    141   mcld::LDSection* sect = mBuilder->CreateELFHeader(*input, ".text",
    142                                 llvm::ELF::SHT_PROGBITS,
    143                                 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
    144                                 0x1);
    145   mcld::SectionData* data = mBuilder->CreateSectionData(*sect);
    146   mcld::Fragment* frag = mBuilder->CreateRegion(pMemory, pSize);
    147   mBuilder->AppendFragment(*frag, *data);
    148   return kSuccess;
    149 }
    150 
    151 enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
    152   mOutputPath = pPath;
    153   return kSuccess;
    154 }
    155 
    156 enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
    157   mOutputHandler = pFileHandler;
    158   return kSuccess;
    159 }
    160 
    161 enum Linker::ErrorCode Linker::link() {
    162   mLinker->link(*mModule, *mBuilder);
    163   if (!mOutputPath.empty()) {
    164     mLinker->emit(mOutputPath);
    165     return kSuccess;
    166   }
    167 
    168   if (-1 != mOutputHandler) {
    169     mLinker->emit(mOutputHandler);
    170     return kSuccess;
    171   }
    172   return kNotSetUpOutput;
    173 }
    174 
    175