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