blob: 760dfe6ae9c70e5ecefca5d8fff6a8bd609d74c6 [file] [log] [blame]
Logancf3e5212010-12-29 01:44:55 +08001/*
2 * copyright 2010, 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#define LOG_TAG "bcc"
18#include <cutils/log.h>
19
20#include "Script.h"
21
Loganf7f0ac52011-01-07 03:53:43 +080022#include "CacheReader.h"
Logan89eb47f2011-01-07 10:45:16 +080023#include "CacheWriter.h"
Logan04329712011-01-06 06:10:57 +080024#include "FileHandle.h"
Logancf3e5212010-12-29 01:44:55 +080025#include "ScriptCompiled.h"
Logan9a5f8682011-01-07 06:09:57 +080026#include "ScriptCached.h"
27#include "Sha1Helper.h"
Logancf3e5212010-12-29 01:44:55 +080028
Logan89eb47f2011-01-07 10:45:16 +080029#include <errno.h>
Logancf3e5212010-12-29 01:44:55 +080030
Logan89eb47f2011-01-07 10:45:16 +080031#include <new>
32#include <string.h>
Logan033f46e2011-01-06 05:51:24 +080033#include <cutils/properties.h>
34
Logan89eb47f2011-01-07 10:45:16 +080035
Loganecf4cbd2011-01-06 05:34:11 +080036namespace {
37
Logan033f46e2011-01-06 05:51:24 +080038bool getBooleanProp(const char *str) {
Loganf340bf72011-01-14 17:51:40 +080039 char buf[PROPERTY_VALUE_MAX];
40 property_get(str, buf, "0");
41 return strcmp(buf, "0") != 0;
Logan033f46e2011-01-06 05:51:24 +080042}
43
Loganecf4cbd2011-01-06 05:34:11 +080044} // namespace anonymous
45
Logancf3e5212010-12-29 01:44:55 +080046namespace bcc {
47
48Script::~Script() {
49 if (mStatus == ScriptStatus::Compiled) {
50 delete mCompiled;
Shih-wei Liaoc4cf6542011-01-13 01:43:01 -080051 } else if (mStatus == ScriptStatus::Cached) {
52 delete mCached;
Logancf3e5212010-12-29 01:44:55 +080053 }
54}
55
56
Loganf340bf72011-01-14 17:51:40 +080057int Script::readBC(char const *resName,
58 const char *bitcode,
Logancf3e5212010-12-29 01:44:55 +080059 size_t bitcodeSize,
Loganf340bf72011-01-14 17:51:40 +080060 unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +080061 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +080062 mErrorCode = BCC_INVALID_OPERATION;
Loganecf4cbd2011-01-06 05:34:11 +080063 LOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +080064 return 1;
65 }
66
Loganecf4cbd2011-01-06 05:34:11 +080067 sourceBC = bitcode;
68 sourceResName = resName;
69 sourceSize = bitcodeSize;
Loganecf4cbd2011-01-06 05:34:11 +080070 return 0;
Logancf3e5212010-12-29 01:44:55 +080071}
72
73
Loganf340bf72011-01-14 17:51:40 +080074int Script::readModule(char const *resName,
75 llvm::Module *module,
76 unsigned long flags) {
Logancf3e5212010-12-29 01:44:55 +080077 if (mStatus != ScriptStatus::Unknown) {
78 mErrorCode = BCC_INVALID_OPERATION;
Loganecf4cbd2011-01-06 05:34:11 +080079 LOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +080080 return 1;
81 }
82
Loganecf4cbd2011-01-06 05:34:11 +080083 sourceModule = module;
84 return 0;
Logancf3e5212010-12-29 01:44:55 +080085}
86
87
Loganf340bf72011-01-14 17:51:40 +080088int Script::linkBC(char const *resName,
89 const char *bitcode,
90 size_t bitcodeSize,
91 unsigned long flags) {
Logan3133c412011-01-06 06:15:40 +080092 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +080093 mErrorCode = BCC_INVALID_OPERATION;
Logan3133c412011-01-06 06:15:40 +080094 LOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +080095 return 1;
96 }
97
Logan3133c412011-01-06 06:15:40 +080098 libraryBC = bitcode;
99 librarySize = bitcodeSize;
Shih-wei Liaoc4cf6542011-01-13 01:43:01 -0800100 LOGI("libraryBC = %x, librarySize = %d", libraryBC, librarySize);
Logan3133c412011-01-06 06:15:40 +0800101 return 0;
Logancf3e5212010-12-29 01:44:55 +0800102}
103
104
Loganf340bf72011-01-14 17:51:40 +0800105int Script::prepareExecutable(char const *cachePath, unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +0800106 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800107 mErrorCode = BCC_INVALID_OPERATION;
Loganecf4cbd2011-01-06 05:34:11 +0800108 LOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800109 return 1;
110 }
111
Loganecf4cbd2011-01-06 05:34:11 +0800112 // Load Cache File
Loganf340bf72011-01-14 17:51:40 +0800113 mCachePath = cachePath;
114 if (cachePath && internalLoadCache() == 0) {
Logan033f46e2011-01-06 05:51:24 +0800115 return 0;
116 }
Loganecf4cbd2011-01-06 05:34:11 +0800117
Logan033f46e2011-01-06 05:51:24 +0800118 return internalCompile();
119}
120
121
122int Script::internalLoadCache() {
123 if (getBooleanProp("debug.bcc.nocache")) {
124 // Android system environment property disable the cache mechanism by
125 // setting "debug.bcc.nocache". So we will not load the cache file any
126 // way.
127 return 1;
128 }
129
Loganf340bf72011-01-14 17:51:40 +0800130 if (!mCachePath) {
131 // The application developer has not specify the cachePath, so
Logan04329712011-01-06 06:10:57 +0800132 // we don't know where to open the cache file.
133 return 1;
Logan033f46e2011-01-06 05:51:24 +0800134 }
Logan04329712011-01-06 06:10:57 +0800135
Loganf340bf72011-01-14 17:51:40 +0800136 // If we are going to use the cache file. We have to calculate sha1sum
137 // first (no matter we can open the file now or not.)
Logana2e15af2011-01-07 11:46:08 +0800138 if (sourceBC) {
Logana2e15af2011-01-07 11:46:08 +0800139 calcSHA1(sourceSHA1, sourceBC, sourceSize);
140 }
141
Loganf340bf72011-01-14 17:51:40 +0800142 //if (libraryBC) {
143 // calcSHA1(librarySHA1, libraryBC, librarySize);
144 //}
145
Logan04329712011-01-06 06:10:57 +0800146 FileHandle file;
147
Loganf340bf72011-01-14 17:51:40 +0800148 if (file.open(mCachePath, OpenMode::Read) < 0) {
Logan04329712011-01-06 06:10:57 +0800149 // Unable to open the cache file in read mode.
150 return 1;
151 }
152
Logane7eb7732011-01-07 07:11:56 +0800153 CacheReader reader;
Logan04329712011-01-06 06:10:57 +0800154
Logan9a5f8682011-01-07 06:09:57 +0800155 // Dependencies
Logane1323992011-01-12 04:47:13 +0800156#if defined(USE_LIBBCC_SHA1SUM)
Logan9a5f8682011-01-07 06:09:57 +0800157 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC, sha1LibBCC);
Logane1323992011-01-12 04:47:13 +0800158#endif
159
Logan9a5f8682011-01-07 06:09:57 +0800160 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
161
162 if (sourceBC) {
Logan9a5f8682011-01-07 06:09:57 +0800163 reader.addDependency(BCC_APK_RESOURCE, sourceResName, sourceSHA1);
164 }
165
Loganf340bf72011-01-14 17:51:40 +0800166 //if (libraryBC) {
167 // reader.addDependency(BCC_APK_RESOURCE, libraryResName, librarySHA1);
168 //}
169
Logan9a5f8682011-01-07 06:09:57 +0800170 // Read cache file
Logane7eb7732011-01-07 07:11:56 +0800171 ScriptCached *cached = reader.readCacheFile(&file, this);
Logan04329712011-01-06 06:10:57 +0800172 if (!cached) {
173 return 1;
174 }
175
176 mCached = cached;
177 mStatus = ScriptStatus::Cached;
Logan033f46e2011-01-06 05:51:24 +0800178
Loganf3c83ce2011-01-07 06:36:33 +0800179 // Dirty hack for libRS.
180 // TODO(all): This dirty hack should be removed in the future.
181 if (cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
182 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
183 }
184
Loganf7f0ac52011-01-07 03:53:43 +0800185 return 0;
Logan033f46e2011-01-06 05:51:24 +0800186}
187
188
189int Script::internalCompile() {
190 // Create the ScriptCompiled object
Loganecf4cbd2011-01-06 05:34:11 +0800191 mCompiled = new (nothrow) ScriptCompiled(this);
192
193 if (!mCompiled) {
194 mErrorCode = BCC_OUT_OF_MEMORY;
195 LOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
196 return 1;
197 }
198
199 mStatus = ScriptStatus::Compiled;
200
Logan033f46e2011-01-06 05:51:24 +0800201 // Register symbol lookup function
Loganecf4cbd2011-01-06 05:34:11 +0800202 if (mpExtSymbolLookupFn) {
203 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
204 mpExtSymbolLookupFnContext);
205 }
206
Logan033f46e2011-01-06 05:51:24 +0800207 // Setup the source bitcode / module
Loganecf4cbd2011-01-06 05:34:11 +0800208 if (sourceBC) {
Loganf340bf72011-01-14 17:51:40 +0800209 if (mCompiled->readBC(sourceResName, sourceBC, sourceSize, 0) != 0) {
Logan65719812011-01-07 11:17:14 +0800210 LOGE("Unable to readBC, bitcode=%p, size=%lu\n",
211 sourceBC, (unsigned long)sourceSize);
Logan033f46e2011-01-06 05:51:24 +0800212 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800213 }
Shih-wei Liaoefbd0ed2011-01-07 06:36:25 -0800214 LOGI("Load sourceBC\n");
Loganecf4cbd2011-01-06 05:34:11 +0800215 } else if (sourceModule) {
Loganf340bf72011-01-14 17:51:40 +0800216 if (mCompiled->readModule(NULL, sourceModule, 0) != 0) {
Logan033f46e2011-01-06 05:51:24 +0800217 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800218 }
Shih-wei Liaoefbd0ed2011-01-07 06:36:25 -0800219 LOGI("Load sourceModule\n");
Loganecf4cbd2011-01-06 05:34:11 +0800220 }
221
Logan3133c412011-01-06 06:15:40 +0800222 // Link the source module with the library module
Logan04329712011-01-06 06:10:57 +0800223 if (libraryBC) {
Loganf340bf72011-01-14 17:51:40 +0800224 if (mCompiled->linkBC(NULL, libraryBC, librarySize, 0) != 0) {
Logan04329712011-01-06 06:10:57 +0800225 return 1;
226 }
Logan65719812011-01-07 11:17:14 +0800227
228 LOGE("Load Library\n");
Logan04329712011-01-06 06:10:57 +0800229 }
Loganecf4cbd2011-01-06 05:34:11 +0800230
Logan3133c412011-01-06 06:15:40 +0800231 // Compile and JIT the code
Logan04329712011-01-06 06:10:57 +0800232 if (mCompiled->compile() != 0) {
Logan65719812011-01-07 11:17:14 +0800233 LOGE("Unable to compile.\n");
Logan04329712011-01-06 06:10:57 +0800234 return 1;
235 }
236
237 // TODO(logan): Write the cache out
Loganf340bf72011-01-14 17:51:40 +0800238 if (mCachePath && !getBooleanProp("debug.bcc.nocache")) {
Logan89eb47f2011-01-07 10:45:16 +0800239 FileHandle file;
Logan04329712011-01-06 06:10:57 +0800240
Loganf340bf72011-01-14 17:51:40 +0800241 if (file.open(mCachePath, OpenMode::Write) >= 0) {
Logan04329712011-01-06 06:10:57 +0800242 CacheWriter writer;
Logana27a83f2011-01-07 10:25:48 +0800243
Logana2e15af2011-01-07 11:46:08 +0800244 // Dependencies
Logane1323992011-01-12 04:47:13 +0800245#if defined(USE_LIBBCC_SHA1SUM)
Logana2e15af2011-01-07 11:46:08 +0800246 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC, sha1LibBCC);
Logane1323992011-01-12 04:47:13 +0800247#endif
Logana2e15af2011-01-07 11:46:08 +0800248 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
249
250 if (sourceBC) {
251 writer.addDependency(BCC_APK_RESOURCE, sourceResName, sourceSHA1);
252 }
253
Logana27a83f2011-01-07 10:25:48 +0800254 // libRS is threadable dirty hack
255 // TODO: This should be removed in the future
256 uint32_t libRS_threadable = 0;
257 if (mpExtSymbolLookupFn) {
Logan89eb47f2011-01-07 10:45:16 +0800258 libRS_threadable =
259 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
260 "__isThreadable");
Logana27a83f2011-01-07 10:25:48 +0800261 }
262
Logan89eb47f2011-01-07 10:45:16 +0800263 if (!writer.writeCacheFile(&file, this, libRS_threadable)) {
264 file.truncate();
265 file.close();
Logana27a83f2011-01-07 10:25:48 +0800266
Loganf340bf72011-01-14 17:51:40 +0800267 if (unlink(mCachePath) != 0) {
Logan89eb47f2011-01-07 10:45:16 +0800268 LOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Loganf340bf72011-01-14 17:51:40 +0800269 mCachePath, strerror(errno));
Logan89eb47f2011-01-07 10:45:16 +0800270 }
271 }
272 }
Logan04329712011-01-06 06:10:57 +0800273 }
Logan04329712011-01-06 06:10:57 +0800274
275 return 0;
Logancf3e5212010-12-29 01:44:55 +0800276}
277
278
279char const *Script::getCompilerErrorMessage() {
280 if (mStatus != ScriptStatus::Compiled) {
281 mErrorCode = BCC_INVALID_OPERATION;
282 return NULL;
283 }
284
285 return mCompiled->getCompilerErrorMessage();
286}
287
288
289void *Script::lookup(const char *name) {
Logan89eb47f2011-01-07 10:45:16 +0800290 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800291 case ScriptStatus::Compiled: return mCompiled->lookup(name);
292 case ScriptStatus::Cached: return mCached->lookup(name);
Logan89eb47f2011-01-07 10:45:16 +0800293
294 default:
Logancf3e5212010-12-29 01:44:55 +0800295 mErrorCode = BCC_INVALID_OPERATION;
296 return NULL;
297 }
Logancf3e5212010-12-29 01:44:55 +0800298}
299
300
Loganbe79ada2011-01-13 01:33:45 +0800301size_t Script::getExportVarCount() const {
Logan89eb47f2011-01-07 10:45:16 +0800302 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800303 case ScriptStatus::Compiled: return mCompiled->getExportVarCount();
304 case ScriptStatus::Cached: return mCached->getExportVarCount();
305 default: return 0;
306 }
307}
308
309
310size_t Script::getExportFuncCount() const {
311 switch (mStatus) {
312 case ScriptStatus::Compiled: return mCompiled->getExportFuncCount();
313 case ScriptStatus::Cached: return mCached->getExportFuncCount();
314 default: return 0;
315 }
316}
317
318
319size_t Script::getPragmaCount() const {
320 switch (mStatus) {
321 case ScriptStatus::Compiled: return mCompiled->getPragmaCount();
322 case ScriptStatus::Cached: return mCached->getPragmaCount();
323 default: return 0;
324 }
325}
326
327
328size_t Script::getFuncCount() const {
329 switch (mStatus) {
330 case ScriptStatus::Compiled: return mCompiled->getFuncCount();
331 case ScriptStatus::Cached: return mCached->getFuncCount();
332 default: return 0;
333 }
334}
335
336
337void Script::getExportVarList(size_t varListSize, void **varList) {
338 switch (mStatus) {
339#define DELEGATE(STATUS) \
340 case ScriptStatus::STATUS: \
341 m##STATUS->getExportVarList(varListSize, varList); \
Logan89eb47f2011-01-07 10:45:16 +0800342 break;
Logancf3e5212010-12-29 01:44:55 +0800343
Loganbe79ada2011-01-13 01:33:45 +0800344 DELEGATE(Cached);
345 DELEGATE(Compiled);
346#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800347
348 default:
349 mErrorCode = BCC_INVALID_OPERATION;
350 }
Logancf3e5212010-12-29 01:44:55 +0800351}
352
353
Loganbe79ada2011-01-13 01:33:45 +0800354void Script::getExportFuncList(size_t funcListSize, void **funcList) {
Logan89eb47f2011-01-07 10:45:16 +0800355 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800356#define DELEGATE(STATUS) \
357 case ScriptStatus::STATUS: \
358 m##STATUS->getExportFuncList(funcListSize, funcList); \
Logan89eb47f2011-01-07 10:45:16 +0800359 break;
Logancf3e5212010-12-29 01:44:55 +0800360
Loganbe79ada2011-01-13 01:33:45 +0800361 DELEGATE(Cached);
362 DELEGATE(Compiled);
363#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800364
365 default:
366 mErrorCode = BCC_INVALID_OPERATION;
367 }
Logancf3e5212010-12-29 01:44:55 +0800368}
369
370
Loganbe79ada2011-01-13 01:33:45 +0800371void Script::getPragmaList(size_t pragmaListSize,
372 char const **keyList,
373 char const **valueList) {
Logan89eb47f2011-01-07 10:45:16 +0800374 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800375#define DELEGATE(STATUS) \
376 case ScriptStatus::STATUS: \
377 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
Logan89eb47f2011-01-07 10:45:16 +0800378 break;
Logancf3e5212010-12-29 01:44:55 +0800379
Loganbe79ada2011-01-13 01:33:45 +0800380 DELEGATE(Cached);
381 DELEGATE(Compiled);
382#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800383
384 default:
385 mErrorCode = BCC_INVALID_OPERATION;
386 }
Logancf3e5212010-12-29 01:44:55 +0800387}
388
389
Loganf340bf72011-01-14 17:51:40 +0800390void Script::getFuncInfoList(size_t funcInfoListSize,
391 FuncInfo *funcInfoList) {
Logan89eb47f2011-01-07 10:45:16 +0800392 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800393#define DELEGATE(STATUS) \
394 case ScriptStatus::STATUS: \
Loganf340bf72011-01-14 17:51:40 +0800395 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList);
Logan89eb47f2011-01-07 10:45:16 +0800396 break;
Logancf3e5212010-12-29 01:44:55 +0800397
Loganbe79ada2011-01-13 01:33:45 +0800398 DELEGATE(Cached);
399 DELEGATE(Compiled);
400#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800401
402 default:
403 mErrorCode = BCC_INVALID_OPERATION;
404 }
Logancf3e5212010-12-29 01:44:55 +0800405}
406
Logana27a83f2011-01-07 10:25:48 +0800407char *Script::getContext() {
408 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800409 case ScriptStatus::Cached: return mCached->getContext();
410 case ScriptStatus::Compiled: return mCompiled->getContext();
Logana27a83f2011-01-07 10:25:48 +0800411
412 default:
413 mErrorCode = BCC_INVALID_OPERATION;
Logan02286cb2011-01-07 00:30:47 +0800414 return NULL;
415 }
Logan02286cb2011-01-07 00:30:47 +0800416}
417
Logancf3e5212010-12-29 01:44:55 +0800418
Loganf340bf72011-01-14 17:51:40 +0800419void Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
Logancf3e5212010-12-29 01:44:55 +0800420 mpExtSymbolLookupFn = pFn;
421 mpExtSymbolLookupFnContext = pContext;
422
Logan7d2219f2011-01-06 06:19:25 +0800423 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800424 mErrorCode = BCC_INVALID_OPERATION;
Logan7d2219f2011-01-06 06:19:25 +0800425 LOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800426 }
Logancf3e5212010-12-29 01:44:55 +0800427}
428
429} // namespace bcc