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 <sstream>
18 #include "Abcc_host.h"
19 using namespace abcc;
20
21 bool kVerbose = false;
22
HostBitcodeCompiler(const std::string & abi,const std::string & sysroot,const std::string & toolchain_bin,const std::string & input,const std::string & output,const std::string & working_dir,const std::string & platform,const bool savetemps,bool bit32)23 HostBitcodeCompiler::HostBitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &toolchain_bin,
24 const std::string &input, const std::string &output, const std::string &working_dir,
25 const std::string &platform, const bool savetemps, bool bit32)
26 : BitcodeCompiler(abi, sysroot, working_dir, savetemps), mIn(input), mOut(output),
27 mNDKDir(""), mPlatform(platform), mToolchainBinPath(toolchain_bin) {
28 initRuntimePath();
29 }
30
HostBitcodeCompiler(const std::string & abi,const std::string & sysroot,const std::string & ndk_dir,const std::string & toolchain_bin,const std::string & input,const std::string & output,const std::string & working_dir,const std::string & platform,const bool savetemps,bool bit32)31 HostBitcodeCompiler::HostBitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &ndk_dir, const std::string &toolchain_bin,
32 const std::string &input, const std::string &output, const std::string &working_dir,
33 const std::string &platform, const bool savetemps, bool bit32)
34 : BitcodeCompiler(abi, sysroot, working_dir, savetemps), mIn(input), mOut(output),
35 mNDKDir(ndk_dir), mPlatform(platform), mToolchainBinPath(toolchain_bin) {
36 initRuntimePath();
37 }
38
initRuntimePath()39 void HostBitcodeCompiler::initRuntimePath() {
40 mRuntimePath.clear();
41
42 mRuntimePath.insert(std::make_pair("gabi++_static", getGAbixxPath() + "/libgabi++_static.a"));
43 mRuntimePath.insert(std::make_pair("gabi++_shared", getGAbixxPath() + "/libgabi++_shared.so"));
44 mRuntimePath.insert(std::make_pair("compiler_rt_static", getCompilerRTPath() + "/libcompiler_rt_static.a"));
45 mRuntimePath.insert(std::make_pair("portable", getLibPortablePath() + "/libportable.a"));
46 mRuntimePath.insert(std::make_pair("portable.wrap", getLibPortablePath() + "/libportable.wrap"));
47 mRuntimePath.insert(std::make_pair("gccunwind", getGCCUnwindPath() + "/libgccunwind.a"));
48 }
49
getRuntimePath(const std::string & libname)50 const std::string HostBitcodeCompiler::getRuntimePath(const std::string &libname) {
51 if (mRuntimePath.count(libname)) {
52 return mRuntimePath.find(libname)->second;
53 }
54 return "";
55 }
56
parseLDFlags(BitcodeInfo & info,const std::string & orig_str)57 int HostBitcodeCompiler::parseLDFlags(BitcodeInfo &info, const std::string &orig_str) {
58 // Follow traditional clang/gcc use, add -lgccunwind (-lgcc) before local libs
59 info.mLDLocalLibsStr += " " + getRuntimePath("gccunwind");
60
61 std::stringstream ss(orig_str);
62 std::string str;
63 while (ss >> str) {
64 if (str.find("--sysroot") != std::string::npos) {
65 continue;
66 }
67 if (str == "-o") {
68 ss >> str;
69 continue;
70 }
71 if (str == "-soname") {
72 ss >> str;
73 info.mSOName = str;
74 continue;
75 }
76 if (str == "-shared") {
77 info.mShared = true;
78 info.mOutPath += ".so";
79 continue;
80 }
81
82 if (str == "-static") {
83 info.mStatic = true;
84 }
85
86 if (str.size() > 2 &&
87 str.substr(str.size() - 2) == ".a") {
88 if (str.size() > 6 &&
89 str.substr(0, /*leng*/6) == "./obj/") {
90 info.mLDLocalLibsStr += " " + str;
91 } else {
92 info.mLDLibs.push_back(str);
93 info.mLDLibsStr += " " + str;
94 }
95 continue;
96 }
97 if (str.size() > 3 &&
98 str.substr(str.size() - 3) == ".so") {
99 if (str.size() > 6 &&
100 str.substr(0, /*leng*/6) == "./obj/") {
101 info.mLDLocalLibsStr += " " + str;
102 } else {
103 info.mLDLibs.push_back(str);
104 info.mLDLibsStr += " " + str;
105 }
106 continue;
107 }
108
109 // Parse -lxxx
110 if (str.size() > 2 &&
111 str.substr(0, 2) == "-l") {
112 std::string runtime_path = getRuntimePath(str.substr(2));
113 if (!runtime_path.empty()) {
114 info.mLDLibsStr += " " + runtime_path;
115 }
116 else {
117 info.mLDLibs.push_back(str.substr(2));
118 info.mLDLibsStr += " " + str;
119 }
120 continue;
121 }
122
123 // Some other flags, like --no-undefined, -z now, -z noexecstack, ...
124 info.mLDFlags += str + " ";
125 } // while
126
127 size_t first_dash_l = info.mLDLibsStr.find(" -l");
128 if (first_dash_l == 0u) {
129 info.mLDLibsStr += " " + getRuntimePath("gccunwind");
130 } else if (first_dash_l == std::string::npos) {
131 info.mLDLibsStr = getRuntimePath("gccunwind") + info.mLDLibsStr;
132 } else {
133 info.mLDLibsStr = info.mLDLibsStr.substr(0, first_dash_l)
134 + " " + getRuntimePath("gccunwind")
135 + info.mLDLibsStr.substr(first_dash_l,
136 info.mLDLibsStr.size() - first_dash_l);
137 }
138 return 0;
139 }
140
getBitcodeFiles()141 void HostBitcodeCompiler::getBitcodeFiles() {
142 BitcodeInfo bcinfo(mIn);
143 if (bcinfo.readWrapper(*this) != 0) {
144 LOGE("Cannot read wrapper for bitcode %s", mIn.c_str());
145 mRet = RET_FAIL_PREPARE_BITCODE;
146 return;
147 }
148
149 bcinfo.mOutPath = mOut;
150 mBitcodeFiles.push_back(bcinfo);
151 }
152
prepareToolchain()153 void HostBitcodeCompiler::prepareToolchain() {
154 std::string cmd;
155 // le32-none-ndk-translate
156 if (mAbi == TargetAbi::ARM64_V8A || mAbi == TargetAbi::X86_64 ||
157 mAbi == TargetAbi::MIPS64)
158 cmd = getToolchainBinPath() + "/le64-none-ndk-translate";
159 else
160 cmd = getToolchainBinPath() + "/le32-none-ndk-translate";
161 mExecutableToolsPath[(unsigned)CMD_TRANSLATE] = cmd;
162
163 // llc
164 cmd = getToolchainBinPath() + "/llc";
165 mExecutableToolsPath[(unsigned)CMD_COMPILE] = cmd;
166
167 // ld.mcld
168 cmd = getToolchainBinPath() + "/ld.mcld";
169 if (mAbi == TargetAbi::MIPS64) {
170 cmd = getToolchainBinPath() + "/../../../../mips64el-linux-android-4.8/prebuilt/linux-x86/bin/mips64el-linux-android-ld";
171 }
172
173 if (mAbi == TargetAbi::X86_64) {
174 cmd += " -L" + mSysroot + "/usr/lib64";
175 } else {
176 cmd += " -L" + mSysroot + "/usr/lib";
177 }
178 mExecutableToolsPath[(unsigned)CMD_LINK] = cmd;
179
180 cmd = " @" + getRuntimePath("portable.wrap") + " " + getRuntimePath("portable");
181 cmd += " " + getRuntimePath("compiler_rt_static");
182 cmd += " " + getRuntimePath("gccunwind");
183 mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME] = cmd;
184 }
185
copyRuntime(const BitcodeInfo & info)186 void HostBitcodeCompiler::copyRuntime(const BitcodeInfo &info) {
187 }
188
removeIntermediateFile(const std::string & path)189 void HostBitcodeCompiler::removeIntermediateFile(const std::string &path) {
190 if (!kVerbose)
191 runCmd(std::string("rm -f ") + path);
192 }
193
getToolchainBinPath() const194 const std::string HostBitcodeCompiler::getToolchainBinPath() const {
195 return mToolchainBinPath;
196 }
197
getCompilerRTPath() const198 const std::string HostBitcodeCompiler::getCompilerRTPath() const {
199 if (!mNDKDir.empty())
200 return std::string(mNDKDir) + "/sources/android/compiler-rt/libs/" + (const char*)mAbi;
201 else
202 return mSysroot + "/usr/lib";
203 }
204
getGAbixxPath() const205 const std::string HostBitcodeCompiler::getGAbixxPath() const {
206 if (!mNDKDir.empty())
207 return std::string(mNDKDir) + "/sources/cxx-stl/gabi++/libs/" + (const char*)mAbi;
208 else
209 return mSysroot + "/usr/lib";
210 }
211
getLibPortablePath() const212 const std::string HostBitcodeCompiler::getLibPortablePath() const {
213 if (!mNDKDir.empty())
214 return std::string(mNDKDir) + "/sources/android/libportable/libs/" + (const char*)mAbi;
215 else
216 return mSysroot + "/usr/lib";
217 }
218
getGCCUnwindPath() const219 const std::string HostBitcodeCompiler::getGCCUnwindPath() const {
220 if (!mNDKDir.empty())
221 return std::string(mNDKDir) + "/sources/android/gccunwind/libs/" + (const char*)mAbi;
222 else
223 return mSysroot + "/usr/lib";
224 }
225