Home | History | Annotate | Download | only in Support
      1 //===- LinkerConfig.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/Support/LinkerConfig.h"
     11 #include "alone/Support/Log.h"
     12 
     13 #include <llvm/Support/Signals.h>
     14 
     15 #include <mcld/MC/MCLDDirectory.h>
     16 #include <mcld/MC/ZOption.h>
     17 #include <mcld/LD/TextDiagnosticPrinter.h>
     18 #include <mcld/Support/Path.h>
     19 #include <mcld/Support/MsgHandling.h>
     20 #include <mcld/Support/raw_ostream.h>
     21 
     22 using namespace alone;
     23 
     24 LinkerConfig::LinkerConfig(const std::string &pTriple)
     25   : mTriple(pTriple), mSOName(), mTarget(NULL), mLDConfig(NULL),
     26     mLDScript(NULL), mDiagLineInfo(NULL), mDiagPrinter(NULL) {
     27 
     28   initializeTarget();
     29   initializeLDScript();
     30   initializeLDInfo();
     31   initializeDiagnostic();
     32 }
     33 
     34 LinkerConfig::~LinkerConfig() {
     35   delete mLDConfig;
     36 
     37   if (mDiagPrinter->getNumErrors() != 0) {
     38     // If here, the program failed ungracefully. Run the interrupt handlers to
     39     // ensure any other cleanups (e.g., files that registered by
     40     // RemoveFileOnSignal(...)) getting done before exit.
     41     llvm::sys::RunInterruptHandlers();
     42   }
     43   mDiagPrinter->finish();
     44 
     45   delete mLDScript;
     46   delete mDiagLineInfo;
     47   delete mDiagPrinter;
     48 }
     49 
     50 bool LinkerConfig::initializeTarget() {
     51   std::string error;
     52   mTarget = mcld::TargetRegistry::lookupTarget(mTriple, error);
     53   if (NULL != mTarget) {
     54     return true;
     55   } else {
     56     ALOGE("Cannot initialize mcld::Target for given triple '%s'! (%s)\n",
     57           mTriple.c_str(), error.c_str());
     58     return false;
     59   }
     60 }
     61 
     62 bool LinkerConfig::initializeLDInfo() {
     63   if (NULL != mLDConfig) {
     64     ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
     65           mTriple.c_str());
     66     return false;
     67   }
     68 
     69   mLDConfig = new mcld::LinkerConfig(getTriple());
     70   mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
     71 
     72   struct NameMap {
     73     const char* from;
     74     const char* to;
     75   };
     76 
     77   static const NameMap map[] =
     78   {
     79     {".text", ".text"},
     80     {".rodata", ".rodata"},
     81     {".data.rel.ro.local", ".data.rel.ro.local"},
     82     {".data.rel.ro", ".data.rel.ro"},
     83     {".data", ".data"},
     84     {".bss", ".bss"},
     85     {".tdata", ".tdata"},
     86     {".tbss", ".tbss"},
     87     {".init_array", ".init_array"},
     88     {".fini_array", ".fini_array"},
     89     // TODO: Support DT_INIT_ARRAY for all constructors?
     90     {".ctors", ".ctors"},
     91     {".dtors", ".dtors"},
     92     // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
     93     // sections would be handled differently.
     94     {".sdata2", ".sdata"},
     95     {".sbss2", ".sbss"},
     96     {".sdata", ".sdata"},
     97     {".sbss", ".sbss"},
     98     {".lrodata", ".lrodata"},
     99     {".ldata", ".ldata"},
    100     {".lbss", ".lbss"},
    101     {".gcc_except_table", ".gcc_except_table"},
    102     {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
    103     {".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
    104     {".gnu.linkonce.r", ".rodata"},
    105     {".gnu.linkonce.d", ".data"},
    106     {".gnu.linkonce.b", ".bss"},
    107     {".gnu.linkonce.sb2", ".sbss"},
    108     {".gnu.linkonce.sb", ".sbss"},
    109     {".gnu.linkonce.s2", ".sdata"},
    110     {".gnu.linkonce.s", ".sdata"},
    111     {".gnu.linkonce.wi", ".debug_info"},
    112     {".gnu.linkonce.td", ".tdata"},
    113     {".gnu.linkonce.tb", ".tbss"},
    114     {".gnu.linkonce.t", ".text"},
    115     {".gnu.linkonce.lr", ".lrodata"},
    116     {".gnu.linkonce.lb", ".lbss"},
    117     {".gnu.linkonce.l", ".ldata"},
    118   };
    119 
    120   if (mLDConfig->codeGenType() != mcld::LinkerConfig::Object) {
    121     const unsigned int map_size =  (sizeof(map) / sizeof(map[0]) );
    122     for (unsigned int i = 0; i < map_size; ++i) {
    123       bool exist = false;
    124       mLDScript->sectionMap().append(map[i].from,
    125                                                map[i].to,
    126                                                exist);
    127     }
    128   }
    129   return true;
    130 }
    131 
    132 bool LinkerConfig::initializeLDScript() {
    133   mLDScript = new mcld::LinkerScript();
    134   return true;
    135 }
    136 
    137 bool LinkerConfig::initializeDiagnostic() {
    138   // Set up MsgHandler.
    139   mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDConfig);
    140 
    141   mcld::InitializeDiagnosticEngine(*mLDConfig, mDiagPrinter);
    142 
    143   mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
    144 
    145   mcld::getDiagnosticEngine().setLineInfo(*mDiagLineInfo);
    146   return true;
    147 }
    148 
    149 bool LinkerConfig::isShared() const {
    150   return (mcld::LinkerConfig::DynObj == mLDConfig->codeGenType());
    151 }
    152 
    153 void LinkerConfig::setShared(bool pEnable) {
    154   if (pEnable)
    155     mLDConfig->setCodeGenType(mcld::LinkerConfig::DynObj);
    156   else
    157     mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
    158   return;
    159 }
    160 
    161 void LinkerConfig::setBsymbolic(bool pEnable) {
    162   mLDConfig->options().setBsymbolic(pEnable);
    163   return;
    164 }
    165 
    166 void LinkerConfig::setDefineCommon(bool pEnable) {
    167   mLDConfig->options().setDefineCommon(pEnable);
    168   return;
    169 }
    170 
    171 void LinkerConfig::setSOName(const std::string &pSOName) {
    172   mLDConfig->options().setSOName(pSOName);
    173   return;
    174 }
    175 
    176 void LinkerConfig::setDyld(const std::string &pDyld) {
    177   mLDConfig->options().setDyld(pDyld);
    178   return;
    179 }
    180 
    181 void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
    182   mLDScript->setSysroot(mcld::sys::fs::Path(pSysRoot));
    183   return;
    184 }
    185 
    186 void LinkerConfig::setZOption(unsigned int pOptions) {
    187   mcld::ZOption option;
    188   if (pOptions & kCombReloc) {
    189     option.setKind(mcld::ZOption::CombReloc);
    190     mLDConfig->options().addZOption(option);
    191   }
    192   else {
    193     option.setKind(mcld::ZOption::NoCombReloc);
    194     mLDConfig->options().addZOption(option);
    195   }
    196 
    197   if (pOptions & kDefs) {
    198     option.setKind(mcld::ZOption::Defs);
    199     mLDConfig->options().addZOption(option);
    200   }
    201 
    202   if (pOptions & kExecStack) {
    203     option.setKind(mcld::ZOption::ExecStack);
    204     mLDConfig->options().addZOption(option);
    205   }
    206   else {
    207     option.setKind(mcld::ZOption::NoExecStack);
    208     mLDConfig->options().addZOption(option);
    209   }
    210 
    211   if (pOptions & kInitFirst) {
    212     option.setKind(mcld::ZOption::InitFirst);
    213     mLDConfig->options().addZOption(option);
    214   }
    215 
    216   if (pOptions & kInterPose) {
    217     option.setKind(mcld::ZOption::InterPose);
    218     mLDConfig->options().addZOption(option);
    219   }
    220 
    221   if (pOptions & kLoadFltr) {
    222     option.setKind(mcld::ZOption::LoadFltr);
    223     mLDConfig->options().addZOption(option);
    224   }
    225 
    226   if (pOptions & kMulDefs) {
    227     option.setKind(mcld::ZOption::MulDefs);
    228     mLDConfig->options().addZOption(option);
    229   }
    230 
    231   if (pOptions & kNoCopyReloc) {
    232     option.setKind(mcld::ZOption::NoCopyReloc);
    233     mLDConfig->options().addZOption(option);
    234   }
    235 
    236   if (pOptions & kNoDefaultLib) {
    237     option.setKind(mcld::ZOption::NoDefaultLib);
    238     mLDConfig->options().addZOption(option);
    239   }
    240 
    241   if (pOptions & kNoDelete) {
    242     option.setKind(mcld::ZOption::NoDelete);
    243     mLDConfig->options().addZOption(option);
    244   }
    245 
    246   if (pOptions & kNoDLOpen) {
    247     option.setKind(mcld::ZOption::NoDLOpen);
    248     mLDConfig->options().addZOption(option);
    249   }
    250 
    251   if (pOptions & kNoDump) {
    252     option.setKind(mcld::ZOption::NoDump);
    253     mLDConfig->options().addZOption(option);
    254   }
    255 
    256   if (pOptions & kRelro) {
    257     option.setKind(mcld::ZOption::Relro);
    258     mLDConfig->options().addZOption(option);
    259   }
    260   else {
    261     option.setKind(mcld::ZOption::NoRelro);
    262     mLDConfig->options().addZOption(option);
    263   }
    264 
    265   if (pOptions & kLazy) {
    266     option.setKind(mcld::ZOption::Lazy);
    267     mLDConfig->options().addZOption(option);
    268   }
    269   else {
    270     option.setKind(mcld::ZOption::Now);
    271     mLDConfig->options().addZOption(option);
    272   }
    273 
    274   if (pOptions & kOrigin) {
    275     option.setKind(mcld::ZOption::Origin);
    276     mLDConfig->options().addZOption(option);
    277   }
    278 }
    279 
    280 void LinkerConfig::addWrap(const std::string &pWrapSymbol) {
    281   bool exist = false;
    282 
    283   // Add wname -> __wrap_wname.
    284   mcld::StringEntry<llvm::StringRef>* to_wrap =
    285                mLDScript->renameMap().insert(pWrapSymbol, exist);
    286 
    287   std::string to_wrap_str = "__wrap_" + pWrapSymbol;
    288   to_wrap->setValue(to_wrap_str);
    289 
    290   if (exist) {
    291     mcld::warning(mcld::diag::rewrap) << pWrapSymbol << to_wrap_str;
    292   }
    293 
    294   // Add __real_wname -> wname.
    295   std::string from_real_str = "__real_" + pWrapSymbol;
    296   mcld::StringEntry<llvm::StringRef>* from_real =
    297              mLDScript->renameMap().insert(from_real_str, exist);
    298   from_real->setValue(pWrapSymbol);
    299 
    300   if (exist) {
    301     mcld::warning(mcld::diag::rewrap) << pWrapSymbol << from_real_str;
    302   }
    303 
    304   return;
    305 }
    306 
    307 void LinkerConfig::addPortable(const std::string &pPortableSymbol) {
    308   bool exist = false;
    309 
    310   // Add pname -> pname_portable.
    311   mcld::StringEntry<llvm::StringRef>* to_port =
    312                 mLDScript->renameMap().insert(pPortableSymbol, exist);
    313 
    314   std::string to_port_str = pPortableSymbol + "_portable";
    315   to_port->setValue(to_port_str);
    316 
    317   if (exist) {
    318     mcld::warning(mcld::diag::rewrap) << pPortableSymbol << to_port_str;
    319 }
    320 
    321   // Add __real_pname -> pname.
    322   std::string from_real_str = "__real_" + pPortableSymbol;
    323   mcld::StringEntry<llvm::StringRef>* from_real =
    324            mLDScript->renameMap().insert(from_real_str, exist);
    325 
    326   from_real->setValue(pPortableSymbol);
    327 
    328   if (exist) {
    329     mcld::warning(mcld::diag::rewrap) << pPortableSymbol << from_real_str;
    330   }
    331 
    332   return;
    333 }
    334 
    335 void LinkerConfig::addSearchDir(const std::string &pDirPath) {
    336   // SearchDirs will remove the created MCLDDirectory.
    337   if (!mLDScript->directories().insert(pDirPath)) {
    338     mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
    339   }
    340 }
    341