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