blob: 87d6e1dd01fda25cd23be81a983756809ae58e59 [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"
Stephen Hinesb67c9e72012-03-22 11:02:48 -070020#include "bcinfo/BitcodeWrapper.h"
Logan35849002011-01-15 07:30:43 +080021
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070022#include "MCCacheReader.h"
23#include "MCCacheWriter.h"
Zonr Chang2fcbd022012-01-06 21:04:31 +080024#include "CompilerOption.h"
Logan Chiend2a5f302011-07-19 20:32:25 +080025
Logan4dcd6792011-02-28 05:12:00 +080026#include "DebugHelper.h"
Logan04329712011-01-06 06:10:57 +080027#include "FileHandle.h"
Daniel Malea094881f2011-12-14 17:39:16 -050028#include "GDBJITRegistrar.h"
Logancf3e5212010-12-29 01:44:55 +080029#include "ScriptCompiled.h"
Logan9a5f8682011-01-07 06:09:57 +080030#include "ScriptCached.h"
31#include "Sha1Helper.h"
Logan474cbd22011-01-31 01:47:44 +080032#include "SourceInfo.h"
Logancf3e5212010-12-29 01:44:55 +080033
Logan89eb47f2011-01-07 10:45:16 +080034#include <errno.h>
Logan474cbd22011-01-31 01:47:44 +080035#include <sys/stat.h>
36#include <sys/types.h>
Bhanu Chetlapallieb4509b2012-01-08 20:42:56 -080037#include <unistd.h>
Logancf3e5212010-12-29 01:44:55 +080038
Logan89eb47f2011-01-07 10:45:16 +080039#include <new>
40#include <string.h>
Logan033f46e2011-01-06 05:51:24 +080041#include <cutils/properties.h>
42
Loganecf4cbd2011-01-06 05:34:11 +080043namespace {
44
Logan033f46e2011-01-06 05:51:24 +080045bool getBooleanProp(const char *str) {
Loganf340bf72011-01-14 17:51:40 +080046 char buf[PROPERTY_VALUE_MAX];
47 property_get(str, buf, "0");
48 return strcmp(buf, "0") != 0;
Logan033f46e2011-01-06 05:51:24 +080049}
50
Loganecf4cbd2011-01-06 05:34:11 +080051} // namespace anonymous
52
Logancf3e5212010-12-29 01:44:55 +080053namespace bcc {
54
55Script::~Script() {
Logan35849002011-01-15 07:30:43 +080056 switch (mStatus) {
57 case ScriptStatus::Compiled:
Logancf3e5212010-12-29 01:44:55 +080058 delete mCompiled;
Logan35849002011-01-15 07:30:43 +080059 break;
60
Logan35849002011-01-15 07:30:43 +080061 case ScriptStatus::Cached:
Shih-wei Liaoc4cf6542011-01-13 01:43:01 -080062 delete mCached;
Logan35849002011-01-15 07:30:43 +080063 break;
Logan35849002011-01-15 07:30:43 +080064
65 default:
66 break;
Logancf3e5212010-12-29 01:44:55 +080067 }
Logan474cbd22011-01-31 01:47:44 +080068
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080069 for (size_t i = 0; i < 2; ++i) {
Logan474cbd22011-01-31 01:47:44 +080070 delete mSourceList[i];
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080071 }
Logancf3e5212010-12-29 01:44:55 +080072}
73
74
Logan474cbd22011-01-31 01:47:44 +080075int Script::addSourceBC(size_t idx,
76 char const *resName,
77 const char *bitcode,
78 size_t bitcodeSize,
79 unsigned long flags) {
Shih-wei Liao898c5a92011-05-18 07:02:39 -070080
81 if (!resName) {
82 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000083 ALOGE("Invalid argument: resName = NULL\n");
Shih-wei Liao898c5a92011-05-18 07:02:39 -070084 return 1;
85 }
86
Loganecf4cbd2011-01-06 05:34:11 +080087 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +080088 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +000089 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +080090 return 1;
91 }
92
Logan474cbd22011-01-31 01:47:44 +080093 if (!bitcode) {
94 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000095 ALOGE("Invalid argument: bitcode = NULL\n");
Logan474cbd22011-01-31 01:47:44 +080096 return 1;
97 }
98
Stephen Hinesb67c9e72012-03-22 11:02:48 -070099 bcinfo::BitcodeWrapper wrapper(bitcode, bitcodeSize);
100 mCompilerVersion = wrapper.getCompilerVersion();
101 mOptimizationLevel = wrapper.getOptimizationLevel();
102
Logan474cbd22011-01-31 01:47:44 +0800103 mSourceList[idx] = SourceInfo::createFromBuffer(resName,
104 bitcode, bitcodeSize,
105 flags);
106
107 if (!mSourceList[idx]) {
108 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000109 ALOGE("Out of memory while adding source bitcode\n");
Logan474cbd22011-01-31 01:47:44 +0800110 return 1;
111 }
112
Loganecf4cbd2011-01-06 05:34:11 +0800113 return 0;
Logancf3e5212010-12-29 01:44:55 +0800114}
115
116
Logan474cbd22011-01-31 01:47:44 +0800117int Script::addSourceModule(size_t idx,
118 llvm::Module *module,
119 unsigned long flags) {
Logancf3e5212010-12-29 01:44:55 +0800120 if (mStatus != ScriptStatus::Unknown) {
121 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000122 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800123 return 1;
124 }
125
Logan474cbd22011-01-31 01:47:44 +0800126 if (!module) {
127 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000128 ALOGE("Invalid argument: module = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800129 return 1;
130 }
131
132 mSourceList[idx] = SourceInfo::createFromModule(module, flags);
133
134 if (!mSourceList[idx]) {
135 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000136 ALOGE("Out of memory when add source module\n");
Logan474cbd22011-01-31 01:47:44 +0800137 return 1;
138 }
139
Loganecf4cbd2011-01-06 05:34:11 +0800140 return 0;
Logancf3e5212010-12-29 01:44:55 +0800141}
142
143
Logan474cbd22011-01-31 01:47:44 +0800144int Script::addSourceFile(size_t idx,
145 char const *path,
146 unsigned long flags) {
Logan3133c412011-01-06 06:15:40 +0800147 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800148 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000149 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800150 return 1;
151 }
152
Logan474cbd22011-01-31 01:47:44 +0800153 if (!path) {
154 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000155 ALOGE("Invalid argument: path = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800156 return 1;
157 }
158
159 struct stat sb;
160 if (stat(path, &sb) != 0) {
161 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000162 ALOGE("File not found: %s\n", path);
Logan474cbd22011-01-31 01:47:44 +0800163 return 1;
164 }
165
166 mSourceList[idx] = SourceInfo::createFromFile(path, flags);
167
168 if (!mSourceList[idx]) {
169 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000170 ALOGE("Out of memory while adding source file\n");
Logan474cbd22011-01-31 01:47:44 +0800171 return 1;
172 }
173
Logan3133c412011-01-06 06:15:40 +0800174 return 0;
Logancf3e5212010-12-29 01:44:55 +0800175}
176
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800177int Script::prepareRelocatable(char const *objPath,
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -0800178 llvm::Reloc::Model RelocModel,
179 unsigned long flags) {
Zonr Chang2fcbd022012-01-06 21:04:31 +0800180 CompilerOption option;
Shih-wei Liao8afed382012-01-10 15:57:24 +0800181 option.RelocModelOpt = RelocModel;
Zonr Chang2fcbd022012-01-06 21:04:31 +0800182 option.LoadAfterCompile = false;
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800183
Zonr Chang2fcbd022012-01-06 21:04:31 +0800184 int status = internalCompile(option);
Joseph Wen34c600a2011-07-25 17:59:17 -0700185 if (status != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000186 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800187 return status;
188 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800189
190 FileHandle objFile;
191 if (objFile.open(objPath, OpenMode::Write) < 0) {
192 ALOGE("Failed to open %s for write.\n", objPath);
193 return 1;
Joseph Wen34c600a2011-07-25 17:59:17 -0700194 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800195
196 if (static_cast<size_t>(objFile.write(getELF(),
197 getELFSize())) != getELFSize()) {
198 objFile.close();
199 ::unlink(objPath);
200 ALOGE("Unable to write ELF to file %s.\n", objPath);
201 return false;
202 }
203
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800204 mObjectType = ScriptObject::Relocatable;
205
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800206 return 0;
Joseph Wen34c600a2011-07-25 17:59:17 -0700207}
208
Logancf3e5212010-12-29 01:44:55 +0800209
Shih-wei Liao69341742012-03-03 01:45:36 -0800210int Script::prepareSharedObject(char const *objPath,
Shih-wei Liaoa471ebb2012-02-05 00:49:58 -0800211 char const *dsoPath,
212 unsigned long flags) {
213 // TODO: Support cached shared object.
214 return 1;
215}
216
217
Logan Chien311c26f2011-07-11 14:30:34 +0800218int Script::prepareExecutable(char const *cacheDir,
219 char const *cacheName,
220 unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +0800221 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800222 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000223 ALOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800224 return 1;
225 }
226
Stephen Hines0e567862012-03-11 20:26:40 -0700227 int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
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
Zonr Chang743dd712012-01-19 10:13:52 +0800253int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
Zonr Chang743dd712012-01-19 10:13:52 +0800254 bool checkOnly) {
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800255 if ((cacheDir == NULL) || (cacheName == NULL)) {
Zonr Chang743dd712012-01-19 10:13:52 +0800256 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800257 }
Zonr Chang743dd712012-01-19 10:13:52 +0800258
259 // Set cache file Name
260 mCacheName = cacheName;
261
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800262 // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
Zonr Chang743dd712012-01-19 10:13:52 +0800263 mCacheDir = cacheDir;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800264 if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
Zonr Chang743dd712012-01-19 10:13:52 +0800265 mCacheDir.push_back('/');
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800266 }
Zonr Chang743dd712012-01-19 10:13:52 +0800267
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800268 if (!isCacheable()) {
Logan033f46e2011-01-06 05:51:24 +0800269 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800270 }
Logan04329712011-01-06 06:10:57 +0800271
Zonr Chang4ea08862012-01-17 17:26:49 +0800272 std::string objPath = getCachedObjectPath();
273 std::string infoPath = getCacheInfoPath();
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700274
Logan Chien311c26f2011-07-11 14:30:34 +0800275 FileHandle objFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700276 if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800277 // Unable to open the executable file in read mode.
Logan04329712011-01-06 06:10:57 +0800278 return 1;
279 }
280
Logan Chien311c26f2011-07-11 14:30:34 +0800281 FileHandle infoFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700282 if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800283 // Unable to open the metadata information file in read mode.
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700284 return 1;
285 }
286
287 MCCacheReader reader;
288
289 // Register symbol lookup function
290 if (mpExtSymbolLookupFn) {
291 reader.registerSymbolCallback(mpExtSymbolLookupFn,
292 mpExtSymbolLookupFnContext);
293 }
Logan04329712011-01-06 06:10:57 +0800294
Logan9a5f8682011-01-07 06:09:57 +0800295 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700296 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700297 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logan9a5f8682011-01-07 06:09:57 +0800298
Logan474cbd22011-01-31 01:47:44 +0800299 for (size_t i = 0; i < 2; ++i) {
300 if (mSourceList[i]) {
301 mSourceList[i]->introDependency(reader);
302 }
Logan9a5f8682011-01-07 06:09:57 +0800303 }
304
Joseph Wen34c600a2011-07-25 17:59:17 -0700305 if (checkOnly)
Joseph Wen49281042011-07-26 10:04:09 -0700306 return !reader.checkCacheFile(&objFile, &infoFile, this);
Joseph Wen34c600a2011-07-25 17:59:17 -0700307
Logan9a5f8682011-01-07 06:09:57 +0800308 // Read cache file
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700309 ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700310
Logan04329712011-01-06 06:10:57 +0800311 if (!cached) {
Logan42598052011-01-26 22:41:13 +0800312 mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
Logan04329712011-01-06 06:10:57 +0800313 return 1;
314 }
315
316 mCached = cached;
317 mStatus = ScriptStatus::Cached;
Logan033f46e2011-01-06 05:51:24 +0800318
Loganf3c83ce2011-01-07 06:36:33 +0800319 // Dirty hack for libRS.
320 // TODO(all): This dirty hack should be removed in the future.
Shih-wei Liao8eb5fe92011-02-01 04:17:38 -0800321 if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
Loganf3c83ce2011-01-07 06:36:33 +0800322 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
323 }
324
Loganf7f0ac52011-01-07 03:53:43 +0800325 return 0;
Logan033f46e2011-01-06 05:51:24 +0800326}
327
Shih-wei Liao9e81e372012-01-17 16:38:40 -0800328int Script::internalCompile(const CompilerOption &option) {
Logan033f46e2011-01-06 05:51:24 +0800329 // Create the ScriptCompiled object
Nowar Gu09b6c1c2011-05-24 23:49:07 +0800330 mCompiled = new (std::nothrow) ScriptCompiled(this);
Loganecf4cbd2011-01-06 05:34:11 +0800331
332 if (!mCompiled) {
333 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000334 ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
Loganecf4cbd2011-01-06 05:34:11 +0800335 return 1;
336 }
337
338 mStatus = ScriptStatus::Compiled;
339
Logan033f46e2011-01-06 05:51:24 +0800340 // Register symbol lookup function
Loganecf4cbd2011-01-06 05:34:11 +0800341 if (mpExtSymbolLookupFn) {
342 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
343 mpExtSymbolLookupFnContext);
344 }
345
Zonr Changdf3fee42012-01-10 15:58:36 +0800346 if (!mSourceList[0]) {
347 ALOGE("Source bitcode is not set.\n");
Logan474cbd22011-01-31 01:47:44 +0800348 return 1;
349 }
350
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800351 // Parse Source bitcode file (if necessary)
352 if (mSourceList[0]->prepareModule() != 0) {
353 ALOGE("Unable to setup source module\n");
Zonr Changdf3fee42012-01-10 15:58:36 +0800354 return 1;
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800355 }
356
357 // Parse Library bitcode file (if necessary)
358 if (mSourceList[1]) {
359 if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
360 ALOGE("Unable to setup library module\n");
361 return 1;
362 }
363 }
Zonr Changdf3fee42012-01-10 15:58:36 +0800364
365 // Set the main source module
366 if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000367 ALOGE("Unable to read source module\n");
Logan474cbd22011-01-31 01:47:44 +0800368 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800369 }
370
Logan3133c412011-01-06 06:15:40 +0800371 // Link the source module with the library module
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800372 if (mSourceList[1]) {
Zonr Changdf3fee42012-01-10 15:58:36 +0800373 if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000374 ALOGE("Unable to link library module\n");
Logan04329712011-01-06 06:10:57 +0800375 return 1;
376 }
377 }
Loganecf4cbd2011-01-06 05:34:11 +0800378
Logan3133c412011-01-06 06:15:40 +0800379 // Compile and JIT the code
Zonr Chang2fcbd022012-01-06 21:04:31 +0800380 if (mCompiled->compile(option) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000381 ALOGE("Unable to compile.\n");
Logan04329712011-01-06 06:10:57 +0800382 return 1;
383 }
384
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800385 return 0;
386}
387
388int Script::writeCache() {
Stephen Hines3e36c692012-03-05 12:39:45 -0800389 // Not compiled script or encountered error during the compilation.
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800390 if ((mStatus != ScriptStatus::Compiled) ||
391 (getCompilerErrorMessage() == NULL))
392 return 1;
393
Logan42598052011-01-26 22:41:13 +0800394 // Note: If we re-compile the script because the cached context slot not
395 // available, then we don't have to write the cache.
396
397 // Note: If the address of the context is not in the context slot, then
398 // we don't have to cache it.
399
Stephen Hines9ddeb6b2012-03-11 18:41:03 -0700400 if (isCacheable()) {
Logan42598052011-01-26 22:41:13 +0800401
Zonr Chang4ea08862012-01-17 17:26:49 +0800402 std::string objPath = getCachedObjectPath();
403 std::string infoPath = getCacheInfoPath();
Logan Chien311c26f2011-07-11 14:30:34 +0800404
Jeff Brown937a0bc2011-01-26 23:20:14 -0800405 // Remove the file if it already exists before writing the new file.
406 // The old file may still be mapped elsewhere in memory and we do not want
407 // to modify its contents. (The same script may be running concurrently in
408 // the same process or a different process!)
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700409 ::unlink(objPath.c_str());
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700410 ::unlink(infoPath.c_str());
Jeff Brown937a0bc2011-01-26 23:20:14 -0800411
Logan Chien03a2e302011-07-13 21:46:32 +0800412 FileHandle objFile;
413 FileHandle infoFile;
414
415 if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
416 infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700417
Logan Chien311c26f2011-07-11 14:30:34 +0800418 MCCacheWriter writer;
Logana27a83f2011-01-07 10:25:48 +0800419
Joseph Wen2ca6e572011-06-24 14:12:23 -0700420#ifdef TARGET_BUILD
Logana2e15af2011-01-07 11:46:08 +0800421 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700422 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700423 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logane1323992011-01-12 04:47:13 +0800424#endif
Logana2e15af2011-01-07 11:46:08 +0800425
Logan474cbd22011-01-31 01:47:44 +0800426 for (size_t i = 0; i < 2; ++i) {
Logan825c3b22011-02-28 05:05:48 +0800427 if (mSourceList[i]) {
428 mSourceList[i]->introDependency(writer);
429 }
Logana2e15af2011-01-07 11:46:08 +0800430 }
431
Logana27a83f2011-01-07 10:25:48 +0800432 // libRS is threadable dirty hack
433 // TODO: This should be removed in the future
434 uint32_t libRS_threadable = 0;
435 if (mpExtSymbolLookupFn) {
Logan89eb47f2011-01-07 10:45:16 +0800436 libRS_threadable =
437 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
438 "__isThreadable");
Logana27a83f2011-01-07 10:25:48 +0800439 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700440
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700441 if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700442 objFile.truncate();
443 objFile.close();
Logana27a83f2011-01-07 10:25:48 +0800444
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700445 if (unlink(objPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000446 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700447 objPath.c_str(), strerror(errno));
Logan89eb47f2011-01-07 10:45:16 +0800448 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700449
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700450 infoFile.truncate();
451 infoFile.close();
452
453 if (unlink(infoPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000454 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700455 infoPath.c_str(), strerror(errno));
456 }
Logan89eb47f2011-01-07 10:45:16 +0800457 }
458 }
Logan04329712011-01-06 06:10:57 +0800459 }
Logan04329712011-01-06 06:10:57 +0800460
461 return 0;
Logancf3e5212010-12-29 01:44:55 +0800462}
463
464
465char const *Script::getCompilerErrorMessage() {
466 if (mStatus != ScriptStatus::Compiled) {
467 mErrorCode = BCC_INVALID_OPERATION;
468 return NULL;
469 }
470
471 return mCompiled->getCompilerErrorMessage();
472}
473
474
475void *Script::lookup(const char *name) {
Logan89eb47f2011-01-07 10:45:16 +0800476 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700477 case ScriptStatus::Compiled: {
478 return mCompiled->lookup(name);
479 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700480
Shih-wei Liaod50be322011-07-01 22:53:31 -0700481 case ScriptStatus::Cached: {
482 return mCached->lookup(name);
483 }
Logan89eb47f2011-01-07 10:45:16 +0800484
Shih-wei Liaod50be322011-07-01 22:53:31 -0700485 default: {
486 mErrorCode = BCC_INVALID_OPERATION;
487 return NULL;
488 }
Logancf3e5212010-12-29 01:44:55 +0800489 }
Logancf3e5212010-12-29 01:44:55 +0800490}
491
492
Loganbe79ada2011-01-13 01:33:45 +0800493size_t Script::getExportVarCount() const {
Logan89eb47f2011-01-07 10:45:16 +0800494 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700495 case ScriptStatus::Compiled: {
496 return mCompiled->getExportVarCount();
497 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700498
Shih-wei Liaod50be322011-07-01 22:53:31 -0700499 case ScriptStatus::Cached: {
500 return mCached->getExportVarCount();
501 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700502
Shih-wei Liaod50be322011-07-01 22:53:31 -0700503 default: {
504 return 0;
505 }
Loganbe79ada2011-01-13 01:33:45 +0800506 }
507}
508
509
510size_t Script::getExportFuncCount() const {
511 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700512 case ScriptStatus::Compiled: {
513 return mCompiled->getExportFuncCount();
514 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700515
Shih-wei Liaod50be322011-07-01 22:53:31 -0700516 case ScriptStatus::Cached: {
517 return mCached->getExportFuncCount();
518 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700519
Shih-wei Liaod50be322011-07-01 22:53:31 -0700520 default: {
521 return 0;
522 }
Loganbe79ada2011-01-13 01:33:45 +0800523 }
524}
525
526
Stephen Hinescc366e52012-02-21 17:22:04 -0800527size_t Script::getExportForEachCount() const {
528 switch (mStatus) {
529 case ScriptStatus::Compiled: {
530 return mCompiled->getExportForEachCount();
531 }
532
Stephen Hinescc366e52012-02-21 17:22:04 -0800533 case ScriptStatus::Cached: {
534 return mCached->getExportForEachCount();
535 }
Stephen Hinescc366e52012-02-21 17:22:04 -0800536
537 default: {
538 return 0;
539 }
540 }
541}
542
543
Loganbe79ada2011-01-13 01:33:45 +0800544size_t Script::getPragmaCount() const {
545 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700546 case ScriptStatus::Compiled: {
547 return mCompiled->getPragmaCount();
548 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700549
Shih-wei Liaod50be322011-07-01 22:53:31 -0700550 case ScriptStatus::Cached: {
551 return mCached->getPragmaCount();
552 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700553
Shih-wei Liaod50be322011-07-01 22:53:31 -0700554 default: {
555 return 0;
556 }
Loganbe79ada2011-01-13 01:33:45 +0800557 }
558}
559
560
561size_t Script::getFuncCount() const {
562 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700563 case ScriptStatus::Compiled: {
564 return mCompiled->getFuncCount();
565 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700566
Shih-wei Liaod50be322011-07-01 22:53:31 -0700567 case ScriptStatus::Cached: {
568 return mCached->getFuncCount();
569 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700570
Shih-wei Liaod50be322011-07-01 22:53:31 -0700571 default: {
572 return 0;
573 }
Loganbe79ada2011-01-13 01:33:45 +0800574 }
575}
576
577
Stephen Hines071288a2011-01-27 14:38:26 -0800578size_t Script::getObjectSlotCount() const {
579 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700580 case ScriptStatus::Compiled: {
581 return mCompiled->getObjectSlotCount();
582 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700583
Shih-wei Liaod50be322011-07-01 22:53:31 -0700584 case ScriptStatus::Cached: {
585 return mCached->getObjectSlotCount();
586 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700587
Shih-wei Liaod50be322011-07-01 22:53:31 -0700588 default: {
589 return 0;
590 }
Stephen Hines071288a2011-01-27 14:38:26 -0800591 }
592}
593
594
Loganbe79ada2011-01-13 01:33:45 +0800595void Script::getExportVarList(size_t varListSize, void **varList) {
596 switch (mStatus) {
597#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700598 case ScriptStatus::STATUS: \
599 m##STATUS->getExportVarList(varListSize, varList); \
600 break;
Logancf3e5212010-12-29 01:44:55 +0800601
Shih-wei Liaod50be322011-07-01 22:53:31 -0700602 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800603
Shih-wei Liaod50be322011-07-01 22:53:31 -0700604 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800605#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800606
Shih-wei Liaod50be322011-07-01 22:53:31 -0700607 default: {
608 mErrorCode = BCC_INVALID_OPERATION;
609 }
Logan89eb47f2011-01-07 10:45:16 +0800610 }
Logancf3e5212010-12-29 01:44:55 +0800611}
612
Joseph Wenf36637f2011-07-06 18:27:12 -0700613void Script::getExportVarNameList(std::vector<std::string> &varList) {
614 switch (mStatus) {
615 case ScriptStatus::Compiled: {
616 return mCompiled->getExportVarNameList(varList);
617 }
618
619 default: {
620 mErrorCode = BCC_INVALID_OPERATION;
621 }
622 }
623}
624
Logancf3e5212010-12-29 01:44:55 +0800625
Loganbe79ada2011-01-13 01:33:45 +0800626void Script::getExportFuncList(size_t funcListSize, void **funcList) {
Logan89eb47f2011-01-07 10:45:16 +0800627 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800628#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700629 case ScriptStatus::STATUS: \
630 m##STATUS->getExportFuncList(funcListSize, funcList); \
631 break;
Logancf3e5212010-12-29 01:44:55 +0800632
Shih-wei Liaod50be322011-07-01 22:53:31 -0700633 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800634
Shih-wei Liaod50be322011-07-01 22:53:31 -0700635 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800636#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800637
Shih-wei Liaod50be322011-07-01 22:53:31 -0700638 default: {
639 mErrorCode = BCC_INVALID_OPERATION;
640 }
Logan89eb47f2011-01-07 10:45:16 +0800641 }
Logancf3e5212010-12-29 01:44:55 +0800642}
643
Joseph Wenf36637f2011-07-06 18:27:12 -0700644void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
645 switch (mStatus) {
646 case ScriptStatus::Compiled: {
647 return mCompiled->getExportFuncNameList(funcList);
648 }
649
650 default: {
651 mErrorCode = BCC_INVALID_OPERATION;
652 }
653 }
654}
655
Stephen Hinescc366e52012-02-21 17:22:04 -0800656void Script::getExportForEachList(size_t funcListSize, void **funcList) {
657 switch (mStatus) {
658#define DELEGATE(STATUS) \
659 case ScriptStatus::STATUS: \
660 m##STATUS->getExportForEachList(funcListSize, funcList); \
661 break;
662
Stephen Hinescc366e52012-02-21 17:22:04 -0800663 DELEGATE(Cached);
Stephen Hinescc366e52012-02-21 17:22:04 -0800664
665 DELEGATE(Compiled);
666#undef DELEGATE
667
668 default: {
669 mErrorCode = BCC_INVALID_OPERATION;
670 }
671 }
672}
673
674void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
675 switch (mStatus) {
676 case ScriptStatus::Compiled: {
677 return mCompiled->getExportForEachNameList(forEachList);
678 }
679
680 default: {
681 mErrorCode = BCC_INVALID_OPERATION;
682 }
683 }
684}
Logancf3e5212010-12-29 01:44:55 +0800685
Loganbe79ada2011-01-13 01:33:45 +0800686void Script::getPragmaList(size_t pragmaListSize,
687 char const **keyList,
688 char const **valueList) {
Logan89eb47f2011-01-07 10:45:16 +0800689 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800690#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700691 case ScriptStatus::STATUS: \
692 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
693 break;
Logancf3e5212010-12-29 01:44:55 +0800694
Shih-wei Liaod50be322011-07-01 22:53:31 -0700695 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800696
Shih-wei Liaod50be322011-07-01 22:53:31 -0700697 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800698#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800699
Shih-wei Liaod50be322011-07-01 22:53:31 -0700700 default: {
701 mErrorCode = BCC_INVALID_OPERATION;
702 }
Logan89eb47f2011-01-07 10:45:16 +0800703 }
Logancf3e5212010-12-29 01:44:55 +0800704}
705
706
Loganf340bf72011-01-14 17:51:40 +0800707void Script::getFuncInfoList(size_t funcInfoListSize,
708 FuncInfo *funcInfoList) {
Logan89eb47f2011-01-07 10:45:16 +0800709 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800710#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700711 case ScriptStatus::STATUS: \
712 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
713 break;
Logancf3e5212010-12-29 01:44:55 +0800714
Shih-wei Liaod50be322011-07-01 22:53:31 -0700715 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800716
Shih-wei Liaod50be322011-07-01 22:53:31 -0700717 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800718#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800719
Shih-wei Liaod50be322011-07-01 22:53:31 -0700720 default: {
721 mErrorCode = BCC_INVALID_OPERATION;
722 }
Logan89eb47f2011-01-07 10:45:16 +0800723 }
Logancf3e5212010-12-29 01:44:55 +0800724}
725
Stephen Hines071288a2011-01-27 14:38:26 -0800726
727void Script::getObjectSlotList(size_t objectSlotListSize,
728 uint32_t *objectSlotList) {
729 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700730#define DELEGATE(STATUS) \
731 case ScriptStatus::STATUS: \
732 m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
733 break;
Stephen Hines071288a2011-01-27 14:38:26 -0800734
Shih-wei Liaod50be322011-07-01 22:53:31 -0700735 DELEGATE(Cached);
Stephen Hines071288a2011-01-27 14:38:26 -0800736
Shih-wei Liaod50be322011-07-01 22:53:31 -0700737 DELEGATE(Compiled);
Stephen Hines071288a2011-01-27 14:38:26 -0800738#undef DELEGATE
739
Shih-wei Liaod50be322011-07-01 22:53:31 -0700740 default: {
741 mErrorCode = BCC_INVALID_OPERATION;
742 }
Stephen Hines071288a2011-01-27 14:38:26 -0800743 }
744}
745
746
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800747int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
Logancf3e5212010-12-29 01:44:55 +0800748 mpExtSymbolLookupFn = pFn;
749 mpExtSymbolLookupFnContext = pContext;
750
Logan7d2219f2011-01-06 06:19:25 +0800751 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800752 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000753 ALOGE("Invalid operation: %s\n", __func__);
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800754 return 1;
Logancf3e5212010-12-29 01:44:55 +0800755 }
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800756 return 0;
Logancf3e5212010-12-29 01:44:55 +0800757}
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700758
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800759bool Script::isCacheable() const {
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800760 if (getBooleanProp("debug.bcc.nocache")) {
761 // Android system environment property: Disables the cache mechanism by
762 // setting "debug.bcc.nocache". So we will not load the cache file any
763 // way.
764 return false;
765 }
766
767 if (mCacheDir.empty() || mCacheName.empty()) {
768 // The application developer has not specified the cachePath, so
769 // we don't know where to open the cache file.
770 return false;
771 }
772
773 return true;
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800774}
775
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700776size_t Script::getELFSize() const {
777 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700778 case ScriptStatus::Compiled: {
779 return mCompiled->getELFSize();
780 }
Stephen Hines0e567862012-03-11 20:26:40 -0700781
Daniel Malea094881f2011-12-14 17:39:16 -0500782 case ScriptStatus::Cached: {
783 return mCached->getELFSize();
784 }
Stephen Hines0e567862012-03-11 20:26:40 -0700785
Shih-wei Liaod50be322011-07-01 22:53:31 -0700786 default: {
787 return 0;
788 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700789 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700790}
791
792const char *Script::getELF() const {
793 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700794 case ScriptStatus::Compiled: {
795 return mCompiled->getELF();
796 }
Stephen Hines0e567862012-03-11 20:26:40 -0700797
Daniel Malea094881f2011-12-14 17:39:16 -0500798 case ScriptStatus::Cached: {
799 return mCached->getELF();
800 }
Stephen Hines0e567862012-03-11 20:26:40 -0700801
Shih-wei Liaod50be322011-07-01 22:53:31 -0700802 default: {
803 return NULL;
804 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700805 }
806}
Logancf3e5212010-12-29 01:44:55 +0800807
808} // namespace bcc