blob: 3b67e04a11d311d7f8df2a7121d3e7a803b5358c [file] [log] [blame]
Logancf3e5212010-12-29 01:44:55 +08001/*
Stephen Hinescc366e52012-02-21 17:22:04 -08002 * copyright 2010-2012, the android open source project
Logancf3e5212010-12-29 01:44:55 +08003 *
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
Logancf3e5212010-12-29 01:44:55 +080017#include "Script.h"
18
Logan35849002011-01-15 07:30:43 +080019#include "Config.h"
20
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070021#include "MCCacheReader.h"
22#include "MCCacheWriter.h"
Zonr Chang2fcbd022012-01-06 21:04:31 +080023#include "CompilerOption.h"
Logan Chiend2a5f302011-07-19 20:32:25 +080024
Logan4dcd6792011-02-28 05:12:00 +080025#include "DebugHelper.h"
Logan04329712011-01-06 06:10:57 +080026#include "FileHandle.h"
Daniel Malea094881f2011-12-14 17:39:16 -050027#include "GDBJITRegistrar.h"
Logancf3e5212010-12-29 01:44:55 +080028#include "ScriptCompiled.h"
Logan9a5f8682011-01-07 06:09:57 +080029#include "ScriptCached.h"
30#include "Sha1Helper.h"
Logan474cbd22011-01-31 01:47:44 +080031#include "SourceInfo.h"
Logancf3e5212010-12-29 01:44:55 +080032
Logan89eb47f2011-01-07 10:45:16 +080033#include <errno.h>
Logan474cbd22011-01-31 01:47:44 +080034#include <sys/stat.h>
35#include <sys/types.h>
Bhanu Chetlapallieb4509b2012-01-08 20:42:56 -080036#include <unistd.h>
Logancf3e5212010-12-29 01:44:55 +080037
Logan89eb47f2011-01-07 10:45:16 +080038#include <new>
39#include <string.h>
Logan033f46e2011-01-06 05:51:24 +080040#include <cutils/properties.h>
41
Loganecf4cbd2011-01-06 05:34:11 +080042namespace {
43
Logan033f46e2011-01-06 05:51:24 +080044bool getBooleanProp(const char *str) {
Loganf340bf72011-01-14 17:51:40 +080045 char buf[PROPERTY_VALUE_MAX];
46 property_get(str, buf, "0");
47 return strcmp(buf, "0") != 0;
Logan033f46e2011-01-06 05:51:24 +080048}
49
Loganecf4cbd2011-01-06 05:34:11 +080050} // namespace anonymous
51
Logancf3e5212010-12-29 01:44:55 +080052namespace bcc {
53
54Script::~Script() {
Logan35849002011-01-15 07:30:43 +080055 switch (mStatus) {
56 case ScriptStatus::Compiled:
Logancf3e5212010-12-29 01:44:55 +080057 delete mCompiled;
Logan35849002011-01-15 07:30:43 +080058 break;
59
60#if USE_CACHE
61 case ScriptStatus::Cached:
Shih-wei Liaoc4cf6542011-01-13 01:43:01 -080062 delete mCached;
Logan35849002011-01-15 07:30:43 +080063 break;
64#endif
65
66 default:
67 break;
Logancf3e5212010-12-29 01:44:55 +080068 }
Logan474cbd22011-01-31 01:47:44 +080069
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080070 for (size_t i = 0; i < 2; ++i) {
Logan474cbd22011-01-31 01:47:44 +080071 delete mSourceList[i];
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080072 }
Logancf3e5212010-12-29 01:44:55 +080073}
74
75
Logan474cbd22011-01-31 01:47:44 +080076int Script::addSourceBC(size_t idx,
77 char const *resName,
78 const char *bitcode,
79 size_t bitcodeSize,
80 unsigned long flags) {
Shih-wei Liao898c5a92011-05-18 07:02:39 -070081
82 if (!resName) {
83 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000084 ALOGE("Invalid argument: resName = NULL\n");
Shih-wei Liao898c5a92011-05-18 07:02:39 -070085 return 1;
86 }
87
Loganecf4cbd2011-01-06 05:34:11 +080088 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +080089 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +000090 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +080091 return 1;
92 }
93
Logan474cbd22011-01-31 01:47:44 +080094 if (!bitcode) {
95 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000096 ALOGE("Invalid argument: bitcode = NULL\n");
Logan474cbd22011-01-31 01:47:44 +080097 return 1;
98 }
99
100 mSourceList[idx] = SourceInfo::createFromBuffer(resName,
101 bitcode, bitcodeSize,
102 flags);
103
104 if (!mSourceList[idx]) {
105 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000106 ALOGE("Out of memory while adding source bitcode\n");
Logan474cbd22011-01-31 01:47:44 +0800107 return 1;
108 }
109
Loganecf4cbd2011-01-06 05:34:11 +0800110 return 0;
Logancf3e5212010-12-29 01:44:55 +0800111}
112
113
Logan474cbd22011-01-31 01:47:44 +0800114int Script::addSourceModule(size_t idx,
115 llvm::Module *module,
116 unsigned long flags) {
Logancf3e5212010-12-29 01:44:55 +0800117 if (mStatus != ScriptStatus::Unknown) {
118 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000119 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800120 return 1;
121 }
122
Logan474cbd22011-01-31 01:47:44 +0800123 if (!module) {
124 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000125 ALOGE("Invalid argument: module = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800126 return 1;
127 }
128
129 mSourceList[idx] = SourceInfo::createFromModule(module, flags);
130
131 if (!mSourceList[idx]) {
132 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000133 ALOGE("Out of memory when add source module\n");
Logan474cbd22011-01-31 01:47:44 +0800134 return 1;
135 }
136
Loganecf4cbd2011-01-06 05:34:11 +0800137 return 0;
Logancf3e5212010-12-29 01:44:55 +0800138}
139
140
Logan474cbd22011-01-31 01:47:44 +0800141int Script::addSourceFile(size_t idx,
142 char const *path,
143 unsigned long flags) {
Logan3133c412011-01-06 06:15:40 +0800144 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800145 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000146 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800147 return 1;
148 }
149
Logan474cbd22011-01-31 01:47:44 +0800150 if (!path) {
151 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000152 ALOGE("Invalid argument: path = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800153 return 1;
154 }
155
156 struct stat sb;
157 if (stat(path, &sb) != 0) {
158 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000159 ALOGE("File not found: %s\n", path);
Logan474cbd22011-01-31 01:47:44 +0800160 return 1;
161 }
162
163 mSourceList[idx] = SourceInfo::createFromFile(path, flags);
164
165 if (!mSourceList[idx]) {
166 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000167 ALOGE("Out of memory while adding source file\n");
Logan474cbd22011-01-31 01:47:44 +0800168 return 1;
169 }
170
Logan3133c412011-01-06 06:15:40 +0800171 return 0;
Logancf3e5212010-12-29 01:44:55 +0800172}
173
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800174int Script::prepareRelocatable(char const *objPath,
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -0800175 llvm::Reloc::Model RelocModel,
176 unsigned long flags) {
Zonr Chang2fcbd022012-01-06 21:04:31 +0800177 CompilerOption option;
Shih-wei Liao8afed382012-01-10 15:57:24 +0800178 option.RelocModelOpt = RelocModel;
Zonr Chang2fcbd022012-01-06 21:04:31 +0800179 option.LoadAfterCompile = false;
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800180
Zonr Chang2fcbd022012-01-06 21:04:31 +0800181 int status = internalCompile(option);
Joseph Wen34c600a2011-07-25 17:59:17 -0700182 if (status != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000183 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800184 return status;
185 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800186
187 FileHandle objFile;
188 if (objFile.open(objPath, OpenMode::Write) < 0) {
189 ALOGE("Failed to open %s for write.\n", objPath);
190 return 1;
Joseph Wen34c600a2011-07-25 17:59:17 -0700191 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800192
193 if (static_cast<size_t>(objFile.write(getELF(),
194 getELFSize())) != getELFSize()) {
195 objFile.close();
196 ::unlink(objPath);
197 ALOGE("Unable to write ELF to file %s.\n", objPath);
198 return false;
199 }
200
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800201 mObjectType = ScriptObject::Relocatable;
202
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800203 return 0;
Joseph Wen34c600a2011-07-25 17:59:17 -0700204}
205
Logancf3e5212010-12-29 01:44:55 +0800206
Shih-wei Liao69341742012-03-03 01:45:36 -0800207int Script::prepareSharedObject(char const *objPath,
Shih-wei Liaoa471ebb2012-02-05 00:49:58 -0800208 char const *dsoPath,
209 unsigned long flags) {
210 // TODO: Support cached shared object.
211 return 1;
212}
213
214
Logan Chien311c26f2011-07-11 14:30:34 +0800215int Script::prepareExecutable(char const *cacheDir,
216 char const *cacheName,
217 unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +0800218 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800219 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000220 ALOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800221 return 1;
222 }
223
Daniel Malea094881f2011-12-14 17:39:16 -0500224 int status = -1;
Logan35849002011-01-15 07:30:43 +0800225#if USE_CACHE
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800226 status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
Logan35849002011-01-15 07:30:43 +0800227#endif
Loganecf4cbd2011-01-06 05:34:11 +0800228
Stephen Hinese0918ac2012-03-01 23:28:09 -0800229 if (status != 0) {
230 CompilerOption option;
231 status = internalCompile(option);
Stephen Hinese0918ac2012-03-01 23:28:09 -0800232
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800233 if (status != 0) {
234 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
235 return status;
236 }
237
238 status = writeCache();
239 if (status != 0) {
240 ALOGE("Failed to write the cache for %s\n", cacheName);
241 return status;
242 }
Stephen Hines27b35102011-05-11 17:58:48 -0700243 }
Daniel Malea094881f2011-12-14 17:39:16 -0500244
245 // FIXME: Registration can be conditional on the presence of debug metadata
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800246 registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
247
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800248 mObjectType = ScriptObject::Executable;
249
Stephen Hines27b35102011-05-11 17:58:48 -0700250 return status;
Logan033f46e2011-01-06 05:51:24 +0800251}
252
Logan35849002011-01-15 07:30:43 +0800253#if USE_CACHE
Zonr Chang743dd712012-01-19 10:13:52 +0800254int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
Zonr Chang743dd712012-01-19 10:13:52 +0800255 bool checkOnly) {
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800256 if ((cacheDir == NULL) || (cacheName == NULL)) {
Zonr Chang743dd712012-01-19 10:13:52 +0800257 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800258 }
Zonr Chang743dd712012-01-19 10:13:52 +0800259
260 // Set cache file Name
261 mCacheName = cacheName;
262
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800263 // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
Zonr Chang743dd712012-01-19 10:13:52 +0800264 mCacheDir = cacheDir;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800265 if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
Zonr Chang743dd712012-01-19 10:13:52 +0800266 mCacheDir.push_back('/');
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800267 }
Zonr Chang743dd712012-01-19 10:13:52 +0800268
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800269 if (!isCacheable()) {
Logan033f46e2011-01-06 05:51:24 +0800270 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800271 }
Logan04329712011-01-06 06:10:57 +0800272
Zonr Chang4ea08862012-01-17 17:26:49 +0800273 std::string objPath = getCachedObjectPath();
274 std::string infoPath = getCacheInfoPath();
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700275
Logan Chien311c26f2011-07-11 14:30:34 +0800276 FileHandle objFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700277 if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800278 // Unable to open the executable file in read mode.
Logan04329712011-01-06 06:10:57 +0800279 return 1;
280 }
281
Logan Chien311c26f2011-07-11 14:30:34 +0800282 FileHandle infoFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700283 if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800284 // Unable to open the metadata information file in read mode.
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700285 return 1;
286 }
287
Stephen Hines9ddeb6b2012-03-11 18:41:03 -0700288#if USE_MCJIT
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700289 MCCacheReader reader;
290
291 // Register symbol lookup function
292 if (mpExtSymbolLookupFn) {
293 reader.registerSymbolCallback(mpExtSymbolLookupFn,
294 mpExtSymbolLookupFnContext);
295 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700296#endif
Logan04329712011-01-06 06:10:57 +0800297
Logan9a5f8682011-01-07 06:09:57 +0800298 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700299 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700300 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logan9a5f8682011-01-07 06:09:57 +0800301
Logan474cbd22011-01-31 01:47:44 +0800302 for (size_t i = 0; i < 2; ++i) {
303 if (mSourceList[i]) {
304 mSourceList[i]->introDependency(reader);
305 }
Logan9a5f8682011-01-07 06:09:57 +0800306 }
307
Joseph Wen34c600a2011-07-25 17:59:17 -0700308 if (checkOnly)
Joseph Wen49281042011-07-26 10:04:09 -0700309 return !reader.checkCacheFile(&objFile, &infoFile, this);
Joseph Wen34c600a2011-07-25 17:59:17 -0700310
Logan9a5f8682011-01-07 06:09:57 +0800311 // Read cache file
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700312 ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700313
Logan04329712011-01-06 06:10:57 +0800314 if (!cached) {
Logan42598052011-01-26 22:41:13 +0800315 mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
Logan04329712011-01-06 06:10:57 +0800316 return 1;
317 }
318
319 mCached = cached;
320 mStatus = ScriptStatus::Cached;
Logan033f46e2011-01-06 05:51:24 +0800321
Loganf3c83ce2011-01-07 06:36:33 +0800322 // Dirty hack for libRS.
323 // TODO(all): This dirty hack should be removed in the future.
Shih-wei Liao8eb5fe92011-02-01 04:17:38 -0800324 if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
Loganf3c83ce2011-01-07 06:36:33 +0800325 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
326 }
327
Loganf7f0ac52011-01-07 03:53:43 +0800328 return 0;
Logan033f46e2011-01-06 05:51:24 +0800329}
Logan35849002011-01-15 07:30:43 +0800330#endif
Logan033f46e2011-01-06 05:51:24 +0800331
Shih-wei Liao9e81e372012-01-17 16:38:40 -0800332int Script::internalCompile(const CompilerOption &option) {
Logan033f46e2011-01-06 05:51:24 +0800333 // Create the ScriptCompiled object
Nowar Gu09b6c1c2011-05-24 23:49:07 +0800334 mCompiled = new (std::nothrow) ScriptCompiled(this);
Loganecf4cbd2011-01-06 05:34:11 +0800335
336 if (!mCompiled) {
337 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000338 ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
Loganecf4cbd2011-01-06 05:34:11 +0800339 return 1;
340 }
341
342 mStatus = ScriptStatus::Compiled;
343
Logan033f46e2011-01-06 05:51:24 +0800344 // Register symbol lookup function
Loganecf4cbd2011-01-06 05:34:11 +0800345 if (mpExtSymbolLookupFn) {
346 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
347 mpExtSymbolLookupFnContext);
348 }
349
Zonr Changdf3fee42012-01-10 15:58:36 +0800350 if (!mSourceList[0]) {
351 ALOGE("Source bitcode is not set.\n");
Logan474cbd22011-01-31 01:47:44 +0800352 return 1;
353 }
354
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800355 // Parse Source bitcode file (if necessary)
356 if (mSourceList[0]->prepareModule() != 0) {
357 ALOGE("Unable to setup source module\n");
Zonr Changdf3fee42012-01-10 15:58:36 +0800358 return 1;
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800359 }
360
361 // Parse Library bitcode file (if necessary)
362 if (mSourceList[1]) {
363 if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
364 ALOGE("Unable to setup library module\n");
365 return 1;
366 }
367 }
Zonr Changdf3fee42012-01-10 15:58:36 +0800368
369 // Set the main source module
370 if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000371 ALOGE("Unable to read source module\n");
Logan474cbd22011-01-31 01:47:44 +0800372 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800373 }
374
Logan3133c412011-01-06 06:15:40 +0800375 // Link the source module with the library module
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800376 if (mSourceList[1]) {
Zonr Changdf3fee42012-01-10 15:58:36 +0800377 if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000378 ALOGE("Unable to link library module\n");
Logan04329712011-01-06 06:10:57 +0800379 return 1;
380 }
381 }
Loganecf4cbd2011-01-06 05:34:11 +0800382
Logan3133c412011-01-06 06:15:40 +0800383 // Compile and JIT the code
Zonr Chang2fcbd022012-01-06 21:04:31 +0800384 if (mCompiled->compile(option) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000385 ALOGE("Unable to compile.\n");
Logan04329712011-01-06 06:10:57 +0800386 return 1;
387 }
388
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800389 return 0;
390}
391
392int Script::writeCache() {
Stephen Hines3e36c692012-03-05 12:39:45 -0800393 // Not compiled script or encountered error during the compilation.
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800394 if ((mStatus != ScriptStatus::Compiled) ||
395 (getCompilerErrorMessage() == NULL))
396 return 1;
397
Logan35849002011-01-15 07:30:43 +0800398#if USE_CACHE
Logan42598052011-01-26 22:41:13 +0800399 // Note: If we re-compile the script because the cached context slot not
400 // available, then we don't have to write the cache.
401
402 // Note: If the address of the context is not in the context slot, then
403 // we don't have to cache it.
404
Stephen Hines9ddeb6b2012-03-11 18:41:03 -0700405 if (isCacheable()) {
Logan42598052011-01-26 22:41:13 +0800406
Zonr Chang4ea08862012-01-17 17:26:49 +0800407 std::string objPath = getCachedObjectPath();
408 std::string infoPath = getCacheInfoPath();
Logan Chien311c26f2011-07-11 14:30:34 +0800409
Jeff Brown937a0bc2011-01-26 23:20:14 -0800410 // Remove the file if it already exists before writing the new file.
411 // The old file may still be mapped elsewhere in memory and we do not want
412 // to modify its contents. (The same script may be running concurrently in
413 // the same process or a different process!)
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700414 ::unlink(objPath.c_str());
Stephen Hines9ddeb6b2012-03-11 18:41:03 -0700415#if USE_MCJIT
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700416 ::unlink(infoPath.c_str());
417#endif
Jeff Brown937a0bc2011-01-26 23:20:14 -0800418
Logan Chien03a2e302011-07-13 21:46:32 +0800419 FileHandle objFile;
420 FileHandle infoFile;
421
422 if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
423 infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700424
Stephen Hines9ddeb6b2012-03-11 18:41:03 -0700425#if USE_MCJIT
Logan Chien311c26f2011-07-11 14:30:34 +0800426 MCCacheWriter writer;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700427#endif
Logana27a83f2011-01-07 10:25:48 +0800428
Joseph Wen2ca6e572011-06-24 14:12:23 -0700429#ifdef TARGET_BUILD
Logana2e15af2011-01-07 11:46:08 +0800430 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700431 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700432 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logane1323992011-01-12 04:47:13 +0800433#endif
Logana2e15af2011-01-07 11:46:08 +0800434
Logan474cbd22011-01-31 01:47:44 +0800435 for (size_t i = 0; i < 2; ++i) {
Logan825c3b22011-02-28 05:05:48 +0800436 if (mSourceList[i]) {
437 mSourceList[i]->introDependency(writer);
438 }
Logana2e15af2011-01-07 11:46:08 +0800439 }
440
Logana27a83f2011-01-07 10:25:48 +0800441 // libRS is threadable dirty hack
442 // TODO: This should be removed in the future
443 uint32_t libRS_threadable = 0;
444 if (mpExtSymbolLookupFn) {
Logan89eb47f2011-01-07 10:45:16 +0800445 libRS_threadable =
446 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
447 "__isThreadable");
Logana27a83f2011-01-07 10:25:48 +0800448 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700449
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700450 if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700451 objFile.truncate();
452 objFile.close();
Logana27a83f2011-01-07 10:25:48 +0800453
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700454 if (unlink(objPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000455 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700456 objPath.c_str(), strerror(errno));
Logan89eb47f2011-01-07 10:45:16 +0800457 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700458
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700459 infoFile.truncate();
460 infoFile.close();
461
462 if (unlink(infoPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000463 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700464 infoPath.c_str(), strerror(errno));
465 }
Logan89eb47f2011-01-07 10:45:16 +0800466 }
467 }
Logan04329712011-01-06 06:10:57 +0800468 }
Logan35849002011-01-15 07:30:43 +0800469#endif // USE_CACHE
Logan04329712011-01-06 06:10:57 +0800470
471 return 0;
Logancf3e5212010-12-29 01:44:55 +0800472}
473
474
475char const *Script::getCompilerErrorMessage() {
476 if (mStatus != ScriptStatus::Compiled) {
477 mErrorCode = BCC_INVALID_OPERATION;
478 return NULL;
479 }
480
481 return mCompiled->getCompilerErrorMessage();
482}
483
484
485void *Script::lookup(const char *name) {
Logan89eb47f2011-01-07 10:45:16 +0800486 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700487 case ScriptStatus::Compiled: {
488 return mCompiled->lookup(name);
489 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700490
Logan35849002011-01-15 07:30:43 +0800491#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700492 case ScriptStatus::Cached: {
493 return mCached->lookup(name);
494 }
Logan35849002011-01-15 07:30:43 +0800495#endif
Logan89eb47f2011-01-07 10:45:16 +0800496
Shih-wei Liaod50be322011-07-01 22:53:31 -0700497 default: {
498 mErrorCode = BCC_INVALID_OPERATION;
499 return NULL;
500 }
Logancf3e5212010-12-29 01:44:55 +0800501 }
Logancf3e5212010-12-29 01:44:55 +0800502}
503
504
Loganbe79ada2011-01-13 01:33:45 +0800505size_t Script::getExportVarCount() const {
Logan89eb47f2011-01-07 10:45:16 +0800506 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700507 case ScriptStatus::Compiled: {
508 return mCompiled->getExportVarCount();
509 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700510
Logan35849002011-01-15 07:30:43 +0800511#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700512 case ScriptStatus::Cached: {
513 return mCached->getExportVarCount();
514 }
Logan35849002011-01-15 07:30:43 +0800515#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700516
Shih-wei Liaod50be322011-07-01 22:53:31 -0700517 default: {
518 return 0;
519 }
Loganbe79ada2011-01-13 01:33:45 +0800520 }
521}
522
523
524size_t Script::getExportFuncCount() const {
525 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700526 case ScriptStatus::Compiled: {
527 return mCompiled->getExportFuncCount();
528 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700529
Logan35849002011-01-15 07:30:43 +0800530#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700531 case ScriptStatus::Cached: {
532 return mCached->getExportFuncCount();
533 }
Logan35849002011-01-15 07:30:43 +0800534#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700535
Shih-wei Liaod50be322011-07-01 22:53:31 -0700536 default: {
537 return 0;
538 }
Loganbe79ada2011-01-13 01:33:45 +0800539 }
540}
541
542
Stephen Hinescc366e52012-02-21 17:22:04 -0800543size_t Script::getExportForEachCount() const {
544 switch (mStatus) {
545 case ScriptStatus::Compiled: {
546 return mCompiled->getExportForEachCount();
547 }
548
549#if USE_CACHE
550 case ScriptStatus::Cached: {
551 return mCached->getExportForEachCount();
552 }
553#endif
554
555 default: {
556 return 0;
557 }
558 }
559}
560
561
Loganbe79ada2011-01-13 01:33:45 +0800562size_t Script::getPragmaCount() const {
563 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700564 case ScriptStatus::Compiled: {
565 return mCompiled->getPragmaCount();
566 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700567
Logan35849002011-01-15 07:30:43 +0800568#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700569 case ScriptStatus::Cached: {
570 return mCached->getPragmaCount();
571 }
Logan35849002011-01-15 07:30:43 +0800572#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700573
Shih-wei Liaod50be322011-07-01 22:53:31 -0700574 default: {
575 return 0;
576 }
Loganbe79ada2011-01-13 01:33:45 +0800577 }
578}
579
580
581size_t Script::getFuncCount() const {
582 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700583 case ScriptStatus::Compiled: {
584 return mCompiled->getFuncCount();
585 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700586
Logan35849002011-01-15 07:30:43 +0800587#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700588 case ScriptStatus::Cached: {
589 return mCached->getFuncCount();
590 }
Logan35849002011-01-15 07:30:43 +0800591#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700592
Shih-wei Liaod50be322011-07-01 22:53:31 -0700593 default: {
594 return 0;
595 }
Loganbe79ada2011-01-13 01:33:45 +0800596 }
597}
598
599
Stephen Hines071288a2011-01-27 14:38:26 -0800600size_t Script::getObjectSlotCount() const {
601 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700602 case ScriptStatus::Compiled: {
603 return mCompiled->getObjectSlotCount();
604 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700605
Stephen Hines071288a2011-01-27 14:38:26 -0800606#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700607 case ScriptStatus::Cached: {
608 return mCached->getObjectSlotCount();
609 }
Stephen Hines071288a2011-01-27 14:38:26 -0800610#endif
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700611
Shih-wei Liaod50be322011-07-01 22:53:31 -0700612 default: {
613 return 0;
614 }
Stephen Hines071288a2011-01-27 14:38:26 -0800615 }
616}
617
618
Loganbe79ada2011-01-13 01:33:45 +0800619void Script::getExportVarList(size_t varListSize, void **varList) {
620 switch (mStatus) {
621#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700622 case ScriptStatus::STATUS: \
623 m##STATUS->getExportVarList(varListSize, varList); \
624 break;
Logancf3e5212010-12-29 01:44:55 +0800625
Logan35849002011-01-15 07:30:43 +0800626#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700627 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800628#endif
629
Shih-wei Liaod50be322011-07-01 22:53:31 -0700630 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800631#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800632
Shih-wei Liaod50be322011-07-01 22:53:31 -0700633 default: {
634 mErrorCode = BCC_INVALID_OPERATION;
635 }
Logan89eb47f2011-01-07 10:45:16 +0800636 }
Logancf3e5212010-12-29 01:44:55 +0800637}
638
Joseph Wenf36637f2011-07-06 18:27:12 -0700639void Script::getExportVarNameList(std::vector<std::string> &varList) {
640 switch (mStatus) {
641 case ScriptStatus::Compiled: {
642 return mCompiled->getExportVarNameList(varList);
643 }
644
645 default: {
646 mErrorCode = BCC_INVALID_OPERATION;
647 }
648 }
649}
650
Logancf3e5212010-12-29 01:44:55 +0800651
Loganbe79ada2011-01-13 01:33:45 +0800652void Script::getExportFuncList(size_t funcListSize, void **funcList) {
Logan89eb47f2011-01-07 10:45:16 +0800653 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800654#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700655 case ScriptStatus::STATUS: \
656 m##STATUS->getExportFuncList(funcListSize, funcList); \
657 break;
Logancf3e5212010-12-29 01:44:55 +0800658
Logan35849002011-01-15 07:30:43 +0800659#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700660 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800661#endif
662
Shih-wei Liaod50be322011-07-01 22:53:31 -0700663 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800664#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800665
Shih-wei Liaod50be322011-07-01 22:53:31 -0700666 default: {
667 mErrorCode = BCC_INVALID_OPERATION;
668 }
Logan89eb47f2011-01-07 10:45:16 +0800669 }
Logancf3e5212010-12-29 01:44:55 +0800670}
671
Joseph Wenf36637f2011-07-06 18:27:12 -0700672void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
673 switch (mStatus) {
674 case ScriptStatus::Compiled: {
675 return mCompiled->getExportFuncNameList(funcList);
676 }
677
678 default: {
679 mErrorCode = BCC_INVALID_OPERATION;
680 }
681 }
682}
683
Stephen Hinescc366e52012-02-21 17:22:04 -0800684void Script::getExportForEachList(size_t funcListSize, void **funcList) {
685 switch (mStatus) {
686#define DELEGATE(STATUS) \
687 case ScriptStatus::STATUS: \
688 m##STATUS->getExportForEachList(funcListSize, funcList); \
689 break;
690
691#if USE_CACHE
692 DELEGATE(Cached);
693#endif
694
695 DELEGATE(Compiled);
696#undef DELEGATE
697
698 default: {
699 mErrorCode = BCC_INVALID_OPERATION;
700 }
701 }
702}
703
704void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
705 switch (mStatus) {
706 case ScriptStatus::Compiled: {
707 return mCompiled->getExportForEachNameList(forEachList);
708 }
709
710 default: {
711 mErrorCode = BCC_INVALID_OPERATION;
712 }
713 }
714}
Logancf3e5212010-12-29 01:44:55 +0800715
Loganbe79ada2011-01-13 01:33:45 +0800716void Script::getPragmaList(size_t pragmaListSize,
717 char const **keyList,
718 char const **valueList) {
Logan89eb47f2011-01-07 10:45:16 +0800719 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800720#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700721 case ScriptStatus::STATUS: \
722 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
723 break;
Logancf3e5212010-12-29 01:44:55 +0800724
Logan35849002011-01-15 07:30:43 +0800725#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700726 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800727#endif
728
Shih-wei Liaod50be322011-07-01 22:53:31 -0700729 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800730#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800731
Shih-wei Liaod50be322011-07-01 22:53:31 -0700732 default: {
733 mErrorCode = BCC_INVALID_OPERATION;
734 }
Logan89eb47f2011-01-07 10:45:16 +0800735 }
Logancf3e5212010-12-29 01:44:55 +0800736}
737
738
Loganf340bf72011-01-14 17:51:40 +0800739void Script::getFuncInfoList(size_t funcInfoListSize,
740 FuncInfo *funcInfoList) {
Logan89eb47f2011-01-07 10:45:16 +0800741 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800742#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700743 case ScriptStatus::STATUS: \
744 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
745 break;
Logancf3e5212010-12-29 01:44:55 +0800746
Logan35849002011-01-15 07:30:43 +0800747#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700748 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800749#endif
750
Shih-wei Liaod50be322011-07-01 22:53:31 -0700751 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800752#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800753
Shih-wei Liaod50be322011-07-01 22:53:31 -0700754 default: {
755 mErrorCode = BCC_INVALID_OPERATION;
756 }
Logan89eb47f2011-01-07 10:45:16 +0800757 }
Logancf3e5212010-12-29 01:44:55 +0800758}
759
Stephen Hines071288a2011-01-27 14:38:26 -0800760
761void Script::getObjectSlotList(size_t objectSlotListSize,
762 uint32_t *objectSlotList) {
763 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700764#define DELEGATE(STATUS) \
765 case ScriptStatus::STATUS: \
766 m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
767 break;
Stephen Hines071288a2011-01-27 14:38:26 -0800768
769#if USE_CACHE
Shih-wei Liaod50be322011-07-01 22:53:31 -0700770 DELEGATE(Cached);
Stephen Hines071288a2011-01-27 14:38:26 -0800771#endif
772
Shih-wei Liaod50be322011-07-01 22:53:31 -0700773 DELEGATE(Compiled);
Stephen Hines071288a2011-01-27 14:38:26 -0800774#undef DELEGATE
775
Shih-wei Liaod50be322011-07-01 22:53:31 -0700776 default: {
777 mErrorCode = BCC_INVALID_OPERATION;
778 }
Stephen Hines071288a2011-01-27 14:38:26 -0800779 }
780}
781
782
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800783int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
Logancf3e5212010-12-29 01:44:55 +0800784 mpExtSymbolLookupFn = pFn;
785 mpExtSymbolLookupFnContext = pContext;
786
Logan7d2219f2011-01-06 06:19:25 +0800787 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800788 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000789 ALOGE("Invalid operation: %s\n", __func__);
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800790 return 1;
Logancf3e5212010-12-29 01:44:55 +0800791 }
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800792 return 0;
Logancf3e5212010-12-29 01:44:55 +0800793}
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700794
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800795bool Script::isCacheable() const {
796#if USE_CACHE
797 if (getBooleanProp("debug.bcc.nocache")) {
798 // Android system environment property: Disables the cache mechanism by
799 // setting "debug.bcc.nocache". So we will not load the cache file any
800 // way.
801 return false;
802 }
803
804 if (mCacheDir.empty() || mCacheName.empty()) {
805 // The application developer has not specified the cachePath, so
806 // we don't know where to open the cache file.
807 return false;
808 }
809
810 return true;
811#else
812 return false;
813#endif
814}
815
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700816#if USE_MCJIT
817size_t Script::getELFSize() const {
818 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700819 case ScriptStatus::Compiled: {
820 return mCompiled->getELFSize();
821 }
Daniel Malea094881f2011-12-14 17:39:16 -0500822#if USE_CACHE
823 case ScriptStatus::Cached: {
824 return mCached->getELFSize();
825 }
826#endif
Shih-wei Liaod50be322011-07-01 22:53:31 -0700827 default: {
828 return 0;
829 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700830 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700831}
832
833const char *Script::getELF() const {
834 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700835 case ScriptStatus::Compiled: {
836 return mCompiled->getELF();
837 }
Daniel Malea094881f2011-12-14 17:39:16 -0500838#if USE_CACHE
839 case ScriptStatus::Cached: {
840 return mCached->getELF();
841 }
842#endif
Shih-wei Liaod50be322011-07-01 22:53:31 -0700843 default: {
844 return NULL;
845 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700846 }
847}
848#endif
Logancf3e5212010-12-29 01:44:55 +0800849
850} // namespace bcc