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                    const_cast<mcld::LinkerScript&>(*pConfig.getLDScript()));
    107 
    108   mBuilder = new mcld::IRBuilder(*mModule, *mLDConfig);
    109 
    110   mLinker = new mcld::Linker();
    111 
    112   mLinker->emulate(const_cast<mcld::LinkerScript&>(*pConfig.getLDScript()),
    113                    const_cast<mcld::LinkerConfig&>(*mLDConfig));
    114 
    115   return kSuccess;
    116 }
    117 
    118 enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
    119   mcld::Input* input = mBuilder->ReadInput(pNameSpec);
    120   if (NULL == input)
    121     return kFindNameSpec;
    122   return kSuccess;
    123 }
    124 
    125 /// addObject - Add a object file by the filename.
    126 enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
    127   mcld::Input* input = mBuilder->ReadInput(pObjectPath, pObjectPath);
    128   if (NULL == input)
    129     return kOpenObjectFile;
    130   return kSuccess;
    131 }
    132 
    133 /// addObject - Add a piece of memory. The memory is of ELF format.
    134 enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
    135   mcld::Input* input = mBuilder->ReadInput("NAN", pMemory, pSize);
    136   if (NULL == input)
    137     return kOpenMemory;
    138   return kSuccess;
    139 }
    140 
    141 enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
    142   mcld::Input* input = mBuilder->CreateInput("NAN", "NAN", mcld::Input::Object);
    143   mcld::LDSection* sect = mBuilder->CreateELFHeader(*input, ".text",
    144                                 llvm::ELF::SHT_PROGBITS,
    145                                 llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
    146                                 0x1);
    147   mcld::SectionData* data = mBuilder->CreateSectionData(*sect);
    148   mcld::Fragment* frag = mBuilder->CreateRegion(pMemory, pSize);
    149   mBuilder->AppendFragment(*frag, *data);
    150   return kSuccess;
    151 }
    152 
    153 enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
    154   mOutputPath = pPath;
    155   return kSuccess;
    156 }
    157 
    158 enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
    159   mOutputHandler = pFileHandler;
    160   return kSuccess;
    161 }
    162 
    163 enum Linker::ErrorCode Linker::link() {
    164   mLinker->link(*mModule, *mBuilder);
    165   if (!mOutputPath.empty()) {
    166     mLinker->emit(mOutputPath);
    167     return kSuccess;
    168   }
    169 
    170   if (-1 != mOutputHandler) {
    171     mLinker->emit(mOutputHandler);
    172     return kSuccess;
    173   }
    174   return kNotSetUpOutput;
    175 }
    176 
    177