Home | History | Annotate | Download | only in device
      1 /*
      2  * Copyright 2013, 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 <dirent.h>
     18 #include <fcntl.h>
     19 #include <unistd.h>
     20 #include <sstream>
     21 #include <sys/stat.h>
     22 #if ENABLE_PARALLEL_LLVM_CG
     23 #include <cpu-features.h>
     24 #endif
     25 #include "Abcc_device.h"
     26 using namespace abcc;
     27 
     28 #if defined(__arm__) && defined(__ARM_ARCH_7A__)
     29 # define CURRENT_ABI  "armeabi-v7a"
     30 #elif defined(__arm__)
     31 # define CURRENT_ABI  "armeabi"
     32 #elif defined(__i386__)
     33 # define CURRENT_ABI  "x86"
     34 #elif defined(__mips__)
     35 # define CURRENT_ABI  "mips"
     36 #else
     37 # error "Unsupport target abi"
     38 #endif
     39 
     40 
     41 DeviceBitcodeCompiler::DeviceBitcodeCompiler(const std::string &working_dir, const std::string &sysroot)
     42   : BitcodeCompiler(CURRENT_ABI, sysroot, working_dir, false/*!savetemps*/) {}
     43 
     44 void DeviceBitcodeCompiler::cleanupPost() {
     45   ReturnCode ret = mRet;
     46   std::string cmd("echo ");
     47   if (ret == RET_OK)
     48     cmd += "0";
     49   else
     50     cmd += "255";
     51   cmd += " > " + mWorkingDir + "/compile_result";
     52   runCmd(cmd);
     53 
     54   if (ret == RET_OK) {
     55     cmd = "rm -f " + mWorkingDir + "/compile_log";
     56     runCmd(cmd);
     57   }
     58   cmd = "chmod 0755 " + mWorkingDir + "/*";
     59   runCmd(cmd);
     60   mRet = ret; // Restore execution return code
     61 }
     62 
     63 int DeviceBitcodeCompiler::parseLDFlags(BitcodeInfo &info, const std::string &orig_str) {
     64   std::stringstream ss(orig_str);
     65   std::string str;
     66   while (ss >> str) {
     67     if (str.find("--sysroot") != std::string::npos) {
     68       continue;
     69     }
     70     if (str == "-o") {
     71       ss >> str;
     72       continue;
     73     }
     74     if (str == "-soname") {
     75       ss >> str;
     76       info.mSOName = str;
     77       continue;
     78     }
     79     if (str == "-shared") {
     80       info.mShared = true;
     81       info.mOutPath += ".so";
     82       continue;
     83     }
     84 
     85     // Parse -lxxx
     86     if (str.size() > 2 &&
     87         str.substr(0, 2) == "-l") {
     88       info.mLDLibs.push_back(str.substr(2));
     89       info.mLDLibsStr += " " + str;
     90       continue;
     91     }
     92 
     93     // Some other flags, like --no-undefined, -z now, -z noexecstack, ...
     94     info.mLDFlags += str + " ";
     95   } // while
     96   return 0;
     97 }
     98 
     99 void DeviceBitcodeCompiler::getBitcodeFiles() {
    100   std::vector<std::string> bc_files,lib_files;
    101   DIR *dp = opendir(mWorkingDir.c_str());
    102   if (!dp) {
    103     mRet = RET_FAIL_PREPARE_BITCODE;
    104     return;
    105   }
    106 
    107   struct dirent *entry = 0;
    108   while ((entry = readdir(dp)) != 0) {
    109     std::string filename(entry->d_name);
    110     std::string full_path = mWorkingDir + "/" + filename;
    111     if (filename == "." || filename == "..")
    112       continue;
    113 
    114     std::string libpath = mSysroot + "/usr/lib/" + filename.substr(0, filename.rfind('.')) + ".so";
    115     struct stat buf;
    116     if (stat(libpath.c_str(), &buf) == 0) {
    117       // This file has the same name in our runtime library pool.  Add to deletion list.
    118       lib_files.push_back(full_path);
    119       continue;
    120     }
    121 
    122     int fd = open(full_path.c_str(), O_RDONLY);
    123     if (fd < 0) {
    124       LOGV("Error opening file: %s (Ignored)", full_path.c_str());
    125       continue;
    126     }
    127 
    128     unsigned char buffer[4];
    129     read(fd, buffer, 4);
    130     close(fd);
    131     int magic = BitcodeInfo::transferBytesToNumLe(buffer, 4);
    132 
    133     if (magic != 0x0b17c0de) {
    134       LOGV("Found file %s magic: %x, but we need a wrapped bitcode.", full_path.c_str(), magic);
    135       continue;
    136     }
    137 
    138     LOGV("Push_back a bitcode: %s", full_path.c_str());
    139     bc_files.push_back(full_path);
    140   } // while
    141   closedir(dp);
    142 
    143   if (bc_files.empty()) {
    144     LOGV("No bitcodes needs to compile");
    145     return;
    146   }
    147 
    148   if (returnCode() != RET_OK) {
    149     LOGV("Cannot get bitcode files from directory: %s", mWorkingDir.c_str());
    150     return;
    151   }
    152 
    153   // Reomve lib file
    154   for (std::vector<std::string>::const_iterator i = lib_files.begin(),
    155        e = lib_files.end(); i != e; ++i) {
    156       std::string cmd = "rm -f " + *i;
    157       runCmd(cmd.c_str());
    158   }
    159 
    160   for (std::vector<std::string>::const_iterator i = bc_files.begin(),
    161        e = bc_files.end(); i != e; ++i) {
    162     BitcodeInfo bcinfo(*i);
    163     if (bcinfo.readWrapper(*this) != 0) {
    164       LOGE("Cannot read wrapper for bitcode %s", i->c_str());
    165       mRet = RET_FAIL_PREPARE_BITCODE;
    166       return;
    167     }
    168     mBitcodeFiles.push_back(bcinfo);
    169   }
    170 }
    171 
    172 void DeviceBitcodeCompiler::prepareToolchain() {
    173   // le32-none-ndk-translate
    174   std::string cmd = std::string("LD_LIBRARY_PATH=") + mSysroot + "/usr/lib";
    175   cmd += " " + mSysroot + "/usr/bin/le32-none-ndk-translate";
    176   mExecutableToolsPath[(unsigned)CMD_TRANSLATE] = cmd;
    177 
    178   // llc
    179   cmd = std::string("LD_LIBRARY_PATH=") + mSysroot + "/usr/lib";
    180   cmd += " " + mSysroot + "/usr/bin/llc";
    181 #ifdef ENABLE_PARALLEL_LLVM_CG
    182   std::ostringstream stream;
    183   stream << android_getCpuCount();
    184   cmd += " -thread=" + stream.str();
    185 #endif
    186   mExecutableToolsPath[(unsigned)CMD_COMPILE] = cmd;
    187 
    188   // ld.mcld
    189   cmd = std::string("LD_LIBRARY_PATH=") + mSysroot + "/usr/lib";
    190   cmd += " " + mSysroot + "/usr/bin/ld.mcld";
    191   cmd += " -L" + mWorkingDir;
    192   cmd += " -L" + mSysroot + "/usr/lib";
    193   cmd += " -L/system/lib";
    194   mExecutableToolsPath[(unsigned)CMD_LINK] = cmd;
    195 
    196   cmd = " @" + mSysroot + "/usr/lib/libportable.wrap " + mSysroot + "/usr/lib/libportable.a";
    197   cmd += " " + mSysroot + "/usr/lib/libcompiler_rt_static.a";
    198   cmd += " " + mSysroot + "/usr/lib/libgccunwind.a";
    199   cmd += " -ldl";
    200   mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME] = cmd;
    201 }
    202 
    203 void DeviceBitcodeCompiler::copyRuntime(const BitcodeInfo &info) {
    204 
    205   std::stringstream ss(info.mLDLibsStr);
    206   std::string deplib;
    207   while (ss >> deplib) {
    208     if (deplib.substr(0, 2) == "-l") {
    209       std::string libname = "lib" + deplib.substr(2) + ".so";
    210       std::string libpath = mSysroot + "/usr/lib/" + libname;
    211       struct stat buf;
    212       if (stat(libpath.c_str(), &buf) == 0) {
    213         // Found!
    214         LOGV("Copy runtime library: %s", libname.c_str());
    215         runCmd("cp -f " + libpath + " " + mWorkingDir + "/" + libname);
    216       }
    217     }
    218   }
    219 }
    220 
    221 void DeviceBitcodeCompiler::removeIntermediateFile(const std::string &path) {
    222   runCmd(std::string("rm -f ") + path);
    223 }
    224