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