• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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