Home | History | Annotate | Download | only in AndroidBitcode
      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/AndroidBitcode/ABCCompilerDriver.h"
     18 
     19 #include <llvm/IR/Module.h>
     20 #include <llvm/Pass.h>
     21 #include <llvm/Support/MemoryBuffer.h>
     22 #include <llvm/Support/raw_ostream.h>
     23 #include <mcld/Config/Config.h>
     24 
     25 #include "bcc/Config/Config.h"
     26 #include "bcc/Script.h"
     27 #include "bcc/Source.h"
     28 #include "bcc/Support/CompilerConfig.h"
     29 #include "bcc/Support/LinkerConfig.h"
     30 #include "bcc/Support/Log.h"
     31 #include "bcc/Support/OutputFile.h"
     32 #include "bcc/Support/TargetLinkerConfigs.h"
     33 #include "bcc/Support/TargetCompilerConfigs.h"
     34 
     35 #if defined(PROVIDE_ARM_CODEGEN)
     36 # include "ARM/ARMABCCompilerDriver.h"
     37 #endif
     38 #if defined(PROVIDE_MIPS_CODEGEN)
     39 # include "Mips/MipsABCCompilerDriver.h"
     40 #endif
     41 #if defined(PROVIDE_X86_CODEGEN)
     42 # include "X86/X86ABCCompilerDriver.h"
     43 #endif
     44 
     45 namespace bcc {
     46 
     47 ABCCompilerDriver::ABCCompilerDriver()
     48   : mContext(), mCompiler(*this), mLinker(),
     49     mCompilerConfig(NULL), mLinkerConfig(NULL), mAndroidSysroot("/") {
     50 }
     51 
     52 ABCCompilerDriver::~ABCCompilerDriver() {
     53   delete mCompilerConfig;
     54   delete mLinkerConfig;
     55 }
     56 
     57 bool ABCCompilerDriver::configCompiler() {
     58   if (mCompilerConfig != NULL) {
     59     return true;
     60   }
     61 
     62   mCompilerConfig = createCompilerConfig();
     63   if (mCompilerConfig == NULL) {
     64     ALOGE("Out of memory when create the compiler configuration!");
     65     return false;
     66   }
     67 
     68   // Set PIC mode for relocatables.
     69   mCompilerConfig->setRelocationModel(llvm::Reloc::PIC_);
     70 
     71   // Set optimization level to -O1.
     72   mCompilerConfig->setOptimizationLevel(llvm::CodeGenOpt::Less);
     73 
     74   Compiler::ErrorCode result = mCompiler.config(*mCompilerConfig);
     75 
     76   if (result != Compiler::kSuccess) {
     77     ALOGE("Failed to configure the compiler! (detail: %s)",
     78           Compiler::GetErrorString(result));
     79     return false;
     80   }
     81 
     82   return true;
     83 }
     84 
     85 bool ABCCompilerDriver::configLinker() {
     86   if (mLinkerConfig != NULL) {
     87     return true;
     88   }
     89 
     90   mLinkerConfig = createLinkerConfig();
     91   if (mLinkerConfig == NULL) {
     92     ALOGE("Out of memory when create the linker configuration!");
     93     return false;
     94   }
     95 
     96   // FIXME: how can we get the soname if input/output is file descriptor?
     97   mLinkerConfig->setSOName("");
     98 
     99   mLinkerConfig->setDyld("/system/bin/linker");
    100   mLinkerConfig->setSysRoot(mAndroidSysroot);
    101   mLinkerConfig->addSearchDir("=/system/lib");
    102 
    103   // Add non-portable function list. For each function X, linker will rename
    104   // it to X_portable. And X_portable" is implemented in libportable to solve
    105   // portable issues.
    106   const char **non_portable_func = getNonPortableList();
    107   if (non_portable_func != NULL) {
    108     while (*non_portable_func != NULL) {
    109       mLinkerConfig->addPortable(*non_portable_func);
    110       non_portable_func++;
    111     }
    112   }
    113 
    114   // -shared
    115   mLinkerConfig->setShared(true);
    116 
    117   // -Bsymbolic.
    118   mLinkerConfig->setBsymbolic(true);
    119 
    120   // Set kRelro for -z relro
    121   // Not set kExecStack for -z noexecstack
    122   // Not set kLazy for -z now
    123   mLinkerConfig->setZOption(LinkerConfig::kRelro);
    124 
    125   // Config the linker.
    126   Linker::ErrorCode result = mLinker.config(*mLinkerConfig);
    127   if (result != Linker::kSuccess) {
    128     ALOGE("Failed to configure the linker! (%s)",
    129           Linker::GetErrorString(result));
    130     return false;
    131   }
    132 
    133   return true;
    134 }
    135 
    136 //------------------------------------------------------------------------------
    137 
    138 Script *ABCCompilerDriver::prepareScript(int pInputFd) {
    139   Source *source = Source::CreateFromFd(mContext, pInputFd);
    140   if (source == NULL) {
    141     ALOGE("Failed to load LLVM module from file descriptor `%d'", pInputFd);
    142     return NULL;
    143   }
    144 
    145   Script *script = new (std::nothrow) Script(*source);
    146   if (script == NULL) {
    147     ALOGE("Out of memory when create script for file descriptor `%d'!",
    148           pInputFd);
    149     delete source;
    150     return NULL;
    151   }
    152 
    153   return script;
    154 }
    155 
    156 bool ABCCompilerDriver::compile(Script &pScript, llvm::raw_ostream &pOutput) {
    157   // Config the compiler.
    158   if (!configCompiler()) {
    159     return false;
    160   }
    161 
    162   // Run the compiler.
    163   Compiler::ErrorCode result = mCompiler.compile(pScript, pOutput);
    164   if (result != Compiler::kSuccess) {
    165     ALOGE("Fatal error during compilation (%s)!",
    166           Compiler::GetErrorString(result));
    167     return false;
    168   }
    169 
    170   return true;
    171 }
    172 
    173 bool ABCCompilerDriver::link(const Script &pScript,
    174                              const std::string &input_relocatable,
    175                              int pOutputFd) {
    176   // Config the linker.
    177   if (!configLinker()) {
    178     return false;
    179   }
    180 
    181   // Prepare output file.
    182   Linker::ErrorCode result = mLinker.setOutput(pOutputFd);
    183 
    184   if (result != Linker::kSuccess) {
    185     ALOGE("Failed to open the output file! (file descriptor `%d': %s)",
    186           pOutputFd, Linker::GetErrorString(result));
    187     return false;
    188   }
    189 
    190   mLinker.addObject(mAndroidSysroot + "/system/lib/crtbegin_so.o");
    191 
    192   // Prepare the relocatables.
    193   //
    194   // FIXME: Ugly const_cast here.
    195   mLinker.addObject(const_cast<char *>(input_relocatable.data()),
    196                     input_relocatable.size());
    197 
    198   // TODO: Refactor libbcc/runtime/ to libcompilerRT.so and use it.
    199   mLinker.addNameSpec("bcc");
    200 
    201   mLinker.addObject(mAndroidSysroot + "/system/lib/crtend_so.o");
    202 
    203   // Perform linking.
    204   result = mLinker.link();
    205   if (result != Linker::kSuccess) {
    206     ALOGE("Failed to link the shared object (detail: %s)",
    207           Linker::GetErrorString(result));
    208     return false;
    209   }
    210 
    211   return true;
    212 }
    213 
    214 //------------------------------------------------------------------------------
    215 
    216 ABCCompilerDriver *ABCCompilerDriver::Create(const std::string &pTriple) {
    217   std::string error;
    218   const llvm::Target *target =
    219       llvm::TargetRegistry::lookupTarget(pTriple, error);
    220 
    221   if (target == NULL) {
    222     ALOGE("Unsupported target '%s' (detail: %s)!", pTriple.c_str(),
    223           error.c_str());
    224     return NULL;
    225   }
    226 
    227   switch (llvm::Triple::getArchTypeForLLVMName(target->getName())) {
    228 #if defined(PROVIDE_ARM_CODEGEN)
    229     case llvm::Triple::arm: {
    230       return new ARMABCCompilerDriver(/* pInThumbMode */false);
    231     }
    232     case llvm::Triple::thumb: {
    233       return new ARMABCCompilerDriver(/* pInThumbMode */true);
    234     }
    235 #endif
    236 #if defined(PROVIDE_MIPS_CODEGEN)
    237     case llvm::Triple::mipsel: {
    238       return new MipsABCCompilerDriver();
    239     }
    240 #endif
    241 #if defined(PROVIDE_X86_CODEGEN)
    242     case llvm::Triple::x86: {
    243       return new X86ABCCompilerDriver();
    244     }
    245 #endif
    246     default: {
    247       ALOGE("Unknown architecture '%s' supplied in %s!", target->getName(),
    248             pTriple.c_str());
    249       break;
    250     }
    251   }
    252 
    253   return NULL;
    254 }
    255 
    256 bool ABCCompilerDriver::build(int pInputFd, int pOutputFd) {
    257   //===--------------------------------------------------------------------===//
    258   // Prepare the input.
    259   //===--------------------------------------------------------------------===//
    260   Script *script = prepareScript(pInputFd);
    261   if (script == NULL) {
    262     return false;
    263   }
    264 
    265   //===--------------------------------------------------------------------===//
    266   // Prepare the output.
    267   //===--------------------------------------------------------------------===//
    268   std::string output_relocatable;
    269   llvm::raw_ostream *output =
    270       new (std::nothrow) llvm::raw_string_ostream(output_relocatable);
    271   if (output == NULL) {
    272     ALOGE("Failed to prepare the output for compile the input from %d into "
    273           "relocatable object!", pInputFd);
    274     delete script;
    275     return false;
    276   }
    277 
    278   //===--------------------------------------------------------------------===//
    279   // Compile.
    280   //===--------------------------------------------------------------------===//
    281   if (!compile(*script, *output)) {
    282     delete output;
    283     delete script;
    284     return false;
    285   }
    286 
    287   //===--------------------------------------------------------------------===//
    288   // Close the output.
    289   //===--------------------------------------------------------------------===//
    290   delete output;
    291 
    292   //===--------------------------------------------------------------------===//
    293   // Link.
    294   //===--------------------------------------------------------------------===//
    295   if (!link(*script, output_relocatable, pOutputFd)) {
    296     delete script;
    297     return false;
    298   }
    299 
    300   //===--------------------------------------------------------------------===//
    301   // Clean up.
    302   //===--------------------------------------------------------------------===//
    303   delete script;
    304 
    305   return true;
    306 }
    307 
    308 } // namespace bcc
    309