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
DeviceBitcodeCompiler(const std::string & working_dir,const std::string & sysroot)41 DeviceBitcodeCompiler::DeviceBitcodeCompiler(const std::string &working_dir, const std::string &sysroot)
42 : BitcodeCompiler(CURRENT_ABI, sysroot, working_dir, false/*!savetemps*/) {}
43
cleanupPost()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
parseLDFlags(BitcodeInfo & info,const std::string & orig_str)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
getBitcodeFiles()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
prepareToolchain()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
copyRuntime(const BitcodeInfo & info)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
removeIntermediateFile(const std::string & path)221 void DeviceBitcodeCompiler::removeIntermediateFile(const std::string &path) {
222 runCmd(std::string("rm -f ") + path);
223 }
224