blob: 11ef0e1f2c0fb72b05a12cbd51df0c0ebc777003 [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);
Stephen Hinesb67c9e72012-03-22 11:02:48 -0700100
Logan474cbd22011-01-31 01:47:44 +0800101 mSourceList[idx] = SourceInfo::createFromBuffer(resName,
102 bitcode, bitcodeSize,
103 flags);
104
105 if (!mSourceList[idx]) {
106 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000107 ALOGE("Out of memory while adding source bitcode\n");
Logan474cbd22011-01-31 01:47:44 +0800108 return 1;
109 }
110
Loganecf4cbd2011-01-06 05:34:11 +0800111 return 0;
Logancf3e5212010-12-29 01:44:55 +0800112}
113
114
Logan474cbd22011-01-31 01:47:44 +0800115int Script::addSourceModule(size_t idx,
116 llvm::Module *module,
117 unsigned long flags) {
Logancf3e5212010-12-29 01:44:55 +0800118 if (mStatus != ScriptStatus::Unknown) {
119 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000120 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800121 return 1;
122 }
123
Logan474cbd22011-01-31 01:47:44 +0800124 if (!module) {
125 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000126 ALOGE("Invalid argument: module = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800127 return 1;
128 }
129
130 mSourceList[idx] = SourceInfo::createFromModule(module, flags);
131
132 if (!mSourceList[idx]) {
133 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000134 ALOGE("Out of memory when add source module\n");
Logan474cbd22011-01-31 01:47:44 +0800135 return 1;
136 }
137
Loganecf4cbd2011-01-06 05:34:11 +0800138 return 0;
Logancf3e5212010-12-29 01:44:55 +0800139}
140
141
Logan474cbd22011-01-31 01:47:44 +0800142int Script::addSourceFile(size_t idx,
143 char const *path,
144 unsigned long flags) {
Logan3133c412011-01-06 06:15:40 +0800145 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800146 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000147 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800148 return 1;
149 }
150
Logan474cbd22011-01-31 01:47:44 +0800151 if (!path) {
152 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000153 ALOGE("Invalid argument: path = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800154 return 1;
155 }
156
157 struct stat sb;
158 if (stat(path, &sb) != 0) {
159 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000160 ALOGE("File not found: %s\n", path);
Logan474cbd22011-01-31 01:47:44 +0800161 return 1;
162 }
163
164 mSourceList[idx] = SourceInfo::createFromFile(path, flags);
165
166 if (!mSourceList[idx]) {
167 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000168 ALOGE("Out of memory while adding source file\n");
Logan474cbd22011-01-31 01:47:44 +0800169 return 1;
170 }
171
Logan3133c412011-01-06 06:15:40 +0800172 return 0;
Logancf3e5212010-12-29 01:44:55 +0800173}
174
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800175int Script::prepareRelocatable(char const *objPath,
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -0800176 llvm::Reloc::Model RelocModel,
177 unsigned long flags) {
Zonr Chang2fcbd022012-01-06 21:04:31 +0800178 CompilerOption option;
Shih-wei Liao8afed382012-01-10 15:57:24 +0800179 option.RelocModelOpt = RelocModel;
Zonr Chang2fcbd022012-01-06 21:04:31 +0800180 option.LoadAfterCompile = false;
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800181
Zonr Chang2fcbd022012-01-06 21:04:31 +0800182 int status = internalCompile(option);
Joseph Wen34c600a2011-07-25 17:59:17 -0700183 if (status != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000184 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800185 return status;
186 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800187
188 FileHandle objFile;
189 if (objFile.open(objPath, OpenMode::Write) < 0) {
190 ALOGE("Failed to open %s for write.\n", objPath);
191 return 1;
Joseph Wen34c600a2011-07-25 17:59:17 -0700192 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800193
194 if (static_cast<size_t>(objFile.write(getELF(),
195 getELFSize())) != getELFSize()) {
196 objFile.close();
197 ::unlink(objPath);
198 ALOGE("Unable to write ELF to file %s.\n", objPath);
199 return false;
200 }
201
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800202 mObjectType = ScriptObject::Relocatable;
203
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800204 return 0;
Joseph Wen34c600a2011-07-25 17:59:17 -0700205}
206
Logancf3e5212010-12-29 01:44:55 +0800207
Shih-wei Liao69341742012-03-03 01:45:36 -0800208int Script::prepareSharedObject(char const *objPath,
Shih-wei Liaoa471ebb2012-02-05 00:49:58 -0800209 char const *dsoPath,
210 unsigned long flags) {
211 // TODO: Support cached shared object.
212 return 1;
213}
214
215
Logan Chien311c26f2011-07-11 14:30:34 +0800216int Script::prepareExecutable(char const *cacheDir,
217 char const *cacheName,
218 unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +0800219 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800220 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000221 ALOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800222 return 1;
223 }
224
Stephen Hines0e567862012-03-11 20:26:40 -0700225 int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
Loganecf4cbd2011-01-06 05:34:11 +0800226
Stephen Hinese0918ac2012-03-01 23:28:09 -0800227 if (status != 0) {
228 CompilerOption option;
229 status = internalCompile(option);
Stephen Hinese0918ac2012-03-01 23:28:09 -0800230
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800231 if (status != 0) {
232 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
233 return status;
234 }
235
236 status = writeCache();
237 if (status != 0) {
238 ALOGE("Failed to write the cache for %s\n", cacheName);
239 return status;
240 }
Stephen Hines27b35102011-05-11 17:58:48 -0700241 }
Daniel Malea094881f2011-12-14 17:39:16 -0500242
243 // FIXME: Registration can be conditional on the presence of debug metadata
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800244 registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
245
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800246 mObjectType = ScriptObject::Executable;
247
Stephen Hines27b35102011-05-11 17:58:48 -0700248 return status;
Logan033f46e2011-01-06 05:51:24 +0800249}
250
Zonr Chang743dd712012-01-19 10:13:52 +0800251int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
Zonr Chang743dd712012-01-19 10:13:52 +0800252 bool checkOnly) {
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800253 if ((cacheDir == NULL) || (cacheName == NULL)) {
Zonr Chang743dd712012-01-19 10:13:52 +0800254 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800255 }
Zonr Chang743dd712012-01-19 10:13:52 +0800256
257 // Set cache file Name
258 mCacheName = cacheName;
259
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800260 // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
Zonr Chang743dd712012-01-19 10:13:52 +0800261 mCacheDir = cacheDir;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800262 if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
Zonr Chang743dd712012-01-19 10:13:52 +0800263 mCacheDir.push_back('/');
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800264 }
Zonr Chang743dd712012-01-19 10:13:52 +0800265
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800266 if (!isCacheable()) {
Logan033f46e2011-01-06 05:51:24 +0800267 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800268 }
Logan04329712011-01-06 06:10:57 +0800269
Zonr Chang4ea08862012-01-17 17:26:49 +0800270 std::string objPath = getCachedObjectPath();
271 std::string infoPath = getCacheInfoPath();
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700272
Logan Chien311c26f2011-07-11 14:30:34 +0800273 FileHandle objFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700274 if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800275 // Unable to open the executable file in read mode.
Logan04329712011-01-06 06:10:57 +0800276 return 1;
277 }
278
Logan Chien311c26f2011-07-11 14:30:34 +0800279 FileHandle infoFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700280 if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800281 // Unable to open the metadata information file in read mode.
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700282 return 1;
283 }
284
285 MCCacheReader reader;
286
287 // Register symbol lookup function
288 if (mpExtSymbolLookupFn) {
289 reader.registerSymbolCallback(mpExtSymbolLookupFn,
290 mpExtSymbolLookupFnContext);
291 }
Logan04329712011-01-06 06:10:57 +0800292
Logan9a5f8682011-01-07 06:09:57 +0800293 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700294 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700295 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logan9a5f8682011-01-07 06:09:57 +0800296
Logan474cbd22011-01-31 01:47:44 +0800297 for (size_t i = 0; i < 2; ++i) {
298 if (mSourceList[i]) {
299 mSourceList[i]->introDependency(reader);
300 }
Logan9a5f8682011-01-07 06:09:57 +0800301 }
302
Joseph Wen34c600a2011-07-25 17:59:17 -0700303 if (checkOnly)
Joseph Wen49281042011-07-26 10:04:09 -0700304 return !reader.checkCacheFile(&objFile, &infoFile, this);
Joseph Wen34c600a2011-07-25 17:59:17 -0700305
Logan9a5f8682011-01-07 06:09:57 +0800306 // Read cache file
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700307 ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700308
Logan04329712011-01-06 06:10:57 +0800309 if (!cached) {
Logan42598052011-01-26 22:41:13 +0800310 mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
Logan04329712011-01-06 06:10:57 +0800311 return 1;
312 }
313
314 mCached = cached;
315 mStatus = ScriptStatus::Cached;
Logan033f46e2011-01-06 05:51:24 +0800316
Loganf3c83ce2011-01-07 06:36:33 +0800317 // Dirty hack for libRS.
318 // TODO(all): This dirty hack should be removed in the future.
Shih-wei Liao8eb5fe92011-02-01 04:17:38 -0800319 if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
Loganf3c83ce2011-01-07 06:36:33 +0800320 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
321 }
322
Loganf7f0ac52011-01-07 03:53:43 +0800323 return 0;
Logan033f46e2011-01-06 05:51:24 +0800324}
325
Shih-wei Liao9e81e372012-01-17 16:38:40 -0800326int Script::internalCompile(const CompilerOption &option) {
Logan033f46e2011-01-06 05:51:24 +0800327 // Create the ScriptCompiled object
Nowar Gu09b6c1c2011-05-24 23:49:07 +0800328 mCompiled = new (std::nothrow) ScriptCompiled(this);
Loganecf4cbd2011-01-06 05:34:11 +0800329
330 if (!mCompiled) {
331 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000332 ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
Loganecf4cbd2011-01-06 05:34:11 +0800333 return 1;
334 }
335
336 mStatus = ScriptStatus::Compiled;
337
Logan033f46e2011-01-06 05:51:24 +0800338 // Register symbol lookup function
Loganecf4cbd2011-01-06 05:34:11 +0800339 if (mpExtSymbolLookupFn) {
340 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
341 mpExtSymbolLookupFnContext);
342 }
343
Zonr Changdf3fee42012-01-10 15:58:36 +0800344 if (!mSourceList[0]) {
345 ALOGE("Source bitcode is not set.\n");
Logan474cbd22011-01-31 01:47:44 +0800346 return 1;
347 }
348
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800349 // Parse Source bitcode file (if necessary)
350 if (mSourceList[0]->prepareModule() != 0) {
351 ALOGE("Unable to setup source module\n");
Zonr Changdf3fee42012-01-10 15:58:36 +0800352 return 1;
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800353 }
354
355 // Parse Library bitcode file (if necessary)
356 if (mSourceList[1]) {
357 if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
358 ALOGE("Unable to setup library module\n");
359 return 1;
360 }
361 }
Zonr Changdf3fee42012-01-10 15:58:36 +0800362
363 // Set the main source module
364 if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000365 ALOGE("Unable to read source module\n");
Logan474cbd22011-01-31 01:47:44 +0800366 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800367 }
368
Logan3133c412011-01-06 06:15:40 +0800369 // Link the source module with the library module
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800370 if (mSourceList[1]) {
Zonr Changdf3fee42012-01-10 15:58:36 +0800371 if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000372 ALOGE("Unable to link library module\n");
Logan04329712011-01-06 06:10:57 +0800373 return 1;
374 }
375 }
Loganecf4cbd2011-01-06 05:34:11 +0800376
Logan3133c412011-01-06 06:15:40 +0800377 // Compile and JIT the code
Zonr Chang2fcbd022012-01-06 21:04:31 +0800378 if (mCompiled->compile(option) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000379 ALOGE("Unable to compile.\n");
Logan04329712011-01-06 06:10:57 +0800380 return 1;
381 }
382
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800383 return 0;
384}
385
386int Script::writeCache() {
Stephen Hines3e36c692012-03-05 12:39:45 -0800387 // Not compiled script or encountered error during the compilation.
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800388 if ((mStatus != ScriptStatus::Compiled) ||
389 (getCompilerErrorMessage() == NULL))
390 return 1;
391
Logan42598052011-01-26 22:41:13 +0800392 // Note: If we re-compile the script because the cached context slot not
393 // available, then we don't have to write the cache.
394
395 // Note: If the address of the context is not in the context slot, then
396 // we don't have to cache it.
397
Stephen Hines9ddeb6b2012-03-11 18:41:03 -0700398 if (isCacheable()) {
Logan42598052011-01-26 22:41:13 +0800399
Zonr Chang4ea08862012-01-17 17:26:49 +0800400 std::string objPath = getCachedObjectPath();
401 std::string infoPath = getCacheInfoPath();
Logan Chien311c26f2011-07-11 14:30:34 +0800402
Jeff Brown937a0bc2011-01-26 23:20:14 -0800403 // Remove the file if it already exists before writing the new file.
404 // The old file may still be mapped elsewhere in memory and we do not want
405 // to modify its contents. (The same script may be running concurrently in
406 // the same process or a different process!)
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700407 ::unlink(objPath.c_str());
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700408 ::unlink(infoPath.c_str());
Jeff Brown937a0bc2011-01-26 23:20:14 -0800409
Logan Chien03a2e302011-07-13 21:46:32 +0800410 FileHandle objFile;
411 FileHandle infoFile;
412
413 if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
414 infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700415
Logan Chien311c26f2011-07-11 14:30:34 +0800416 MCCacheWriter writer;
Logana27a83f2011-01-07 10:25:48 +0800417
Joseph Wen2ca6e572011-06-24 14:12:23 -0700418#ifdef TARGET_BUILD
Logana2e15af2011-01-07 11:46:08 +0800419 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700420 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700421 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logane1323992011-01-12 04:47:13 +0800422#endif
Logana2e15af2011-01-07 11:46:08 +0800423
Logan474cbd22011-01-31 01:47:44 +0800424 for (size_t i = 0; i < 2; ++i) {
Logan825c3b22011-02-28 05:05:48 +0800425 if (mSourceList[i]) {
426 mSourceList[i]->introDependency(writer);
427 }
Logana2e15af2011-01-07 11:46:08 +0800428 }
429
Logana27a83f2011-01-07 10:25:48 +0800430 // libRS is threadable dirty hack
431 // TODO: This should be removed in the future
432 uint32_t libRS_threadable = 0;
433 if (mpExtSymbolLookupFn) {
Logan89eb47f2011-01-07 10:45:16 +0800434 libRS_threadable =
435 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
436 "__isThreadable");
Logana27a83f2011-01-07 10:25:48 +0800437 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700438
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700439 if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700440 objFile.truncate();
441 objFile.close();
Logana27a83f2011-01-07 10:25:48 +0800442
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700443 if (unlink(objPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000444 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700445 objPath.c_str(), strerror(errno));
Logan89eb47f2011-01-07 10:45:16 +0800446 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700447
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700448 infoFile.truncate();
449 infoFile.close();
450
451 if (unlink(infoPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000452 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700453 infoPath.c_str(), strerror(errno));
454 }
Logan89eb47f2011-01-07 10:45:16 +0800455 }
456 }
Logan04329712011-01-06 06:10:57 +0800457 }
Logan04329712011-01-06 06:10:57 +0800458
459 return 0;
Logancf3e5212010-12-29 01:44:55 +0800460}
461
462
463char const *Script::getCompilerErrorMessage() {
464 if (mStatus != ScriptStatus::Compiled) {
465 mErrorCode = BCC_INVALID_OPERATION;
466 return NULL;
467 }
468
469 return mCompiled->getCompilerErrorMessage();
470}
471
472
473void *Script::lookup(const char *name) {
Logan89eb47f2011-01-07 10:45:16 +0800474 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700475 case ScriptStatus::Compiled: {
476 return mCompiled->lookup(name);
477 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700478
Shih-wei Liaod50be322011-07-01 22:53:31 -0700479 case ScriptStatus::Cached: {
480 return mCached->lookup(name);
481 }
Logan89eb47f2011-01-07 10:45:16 +0800482
Shih-wei Liaod50be322011-07-01 22:53:31 -0700483 default: {
484 mErrorCode = BCC_INVALID_OPERATION;
485 return NULL;
486 }
Logancf3e5212010-12-29 01:44:55 +0800487 }
Logancf3e5212010-12-29 01:44:55 +0800488}
489
490
Loganbe79ada2011-01-13 01:33:45 +0800491size_t Script::getExportVarCount() const {
Logan89eb47f2011-01-07 10:45:16 +0800492 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700493 case ScriptStatus::Compiled: {
494 return mCompiled->getExportVarCount();
495 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700496
Shih-wei Liaod50be322011-07-01 22:53:31 -0700497 case ScriptStatus::Cached: {
498 return mCached->getExportVarCount();
499 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700500
Shih-wei Liaod50be322011-07-01 22:53:31 -0700501 default: {
502 return 0;
503 }
Loganbe79ada2011-01-13 01:33:45 +0800504 }
505}
506
507
508size_t Script::getExportFuncCount() const {
509 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700510 case ScriptStatus::Compiled: {
511 return mCompiled->getExportFuncCount();
512 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700513
Shih-wei Liaod50be322011-07-01 22:53:31 -0700514 case ScriptStatus::Cached: {
515 return mCached->getExportFuncCount();
516 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700517
Shih-wei Liaod50be322011-07-01 22:53:31 -0700518 default: {
519 return 0;
520 }
Loganbe79ada2011-01-13 01:33:45 +0800521 }
522}
523
524
Stephen Hinescc366e52012-02-21 17:22:04 -0800525size_t Script::getExportForEachCount() const {
526 switch (mStatus) {
527 case ScriptStatus::Compiled: {
528 return mCompiled->getExportForEachCount();
529 }
530
Stephen Hinescc366e52012-02-21 17:22:04 -0800531 case ScriptStatus::Cached: {
532 return mCached->getExportForEachCount();
533 }
Stephen Hinescc366e52012-02-21 17:22:04 -0800534
535 default: {
536 return 0;
537 }
538 }
539}
540
541
Loganbe79ada2011-01-13 01:33:45 +0800542size_t Script::getPragmaCount() const {
543 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700544 case ScriptStatus::Compiled: {
545 return mCompiled->getPragmaCount();
546 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700547
Shih-wei Liaod50be322011-07-01 22:53:31 -0700548 case ScriptStatus::Cached: {
549 return mCached->getPragmaCount();
550 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700551
Shih-wei Liaod50be322011-07-01 22:53:31 -0700552 default: {
553 return 0;
554 }
Loganbe79ada2011-01-13 01:33:45 +0800555 }
556}
557
558
559size_t Script::getFuncCount() const {
560 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700561 case ScriptStatus::Compiled: {
562 return mCompiled->getFuncCount();
563 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700564
Shih-wei Liaod50be322011-07-01 22:53:31 -0700565 case ScriptStatus::Cached: {
566 return mCached->getFuncCount();
567 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700568
Shih-wei Liaod50be322011-07-01 22:53:31 -0700569 default: {
570 return 0;
571 }
Loganbe79ada2011-01-13 01:33:45 +0800572 }
573}
574
575
Stephen Hines071288a2011-01-27 14:38:26 -0800576size_t Script::getObjectSlotCount() const {
577 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700578 case ScriptStatus::Compiled: {
579 return mCompiled->getObjectSlotCount();
580 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700581
Shih-wei Liaod50be322011-07-01 22:53:31 -0700582 case ScriptStatus::Cached: {
583 return mCached->getObjectSlotCount();
584 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700585
Shih-wei Liaod50be322011-07-01 22:53:31 -0700586 default: {
587 return 0;
588 }
Stephen Hines071288a2011-01-27 14:38:26 -0800589 }
590}
591
592
Loganbe79ada2011-01-13 01:33:45 +0800593void Script::getExportVarList(size_t varListSize, void **varList) {
594 switch (mStatus) {
595#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700596 case ScriptStatus::STATUS: \
597 m##STATUS->getExportVarList(varListSize, varList); \
598 break;
Logancf3e5212010-12-29 01:44:55 +0800599
Shih-wei Liaod50be322011-07-01 22:53:31 -0700600 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800601
Shih-wei Liaod50be322011-07-01 22:53:31 -0700602 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800603#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800604
Shih-wei Liaod50be322011-07-01 22:53:31 -0700605 default: {
606 mErrorCode = BCC_INVALID_OPERATION;
607 }
Logan89eb47f2011-01-07 10:45:16 +0800608 }
Logancf3e5212010-12-29 01:44:55 +0800609}
610
Joseph Wenf36637f2011-07-06 18:27:12 -0700611void Script::getExportVarNameList(std::vector<std::string> &varList) {
612 switch (mStatus) {
613 case ScriptStatus::Compiled: {
614 return mCompiled->getExportVarNameList(varList);
615 }
616
617 default: {
618 mErrorCode = BCC_INVALID_OPERATION;
619 }
620 }
621}
622
Logancf3e5212010-12-29 01:44:55 +0800623
Loganbe79ada2011-01-13 01:33:45 +0800624void Script::getExportFuncList(size_t funcListSize, void **funcList) {
Logan89eb47f2011-01-07 10:45:16 +0800625 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800626#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700627 case ScriptStatus::STATUS: \
628 m##STATUS->getExportFuncList(funcListSize, funcList); \
629 break;
Logancf3e5212010-12-29 01:44:55 +0800630
Shih-wei Liaod50be322011-07-01 22:53:31 -0700631 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800632
Shih-wei Liaod50be322011-07-01 22:53:31 -0700633 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800634#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800635
Shih-wei Liaod50be322011-07-01 22:53:31 -0700636 default: {
637 mErrorCode = BCC_INVALID_OPERATION;
638 }
Logan89eb47f2011-01-07 10:45:16 +0800639 }
Logancf3e5212010-12-29 01:44:55 +0800640}
641
Joseph Wenf36637f2011-07-06 18:27:12 -0700642void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
643 switch (mStatus) {
644 case ScriptStatus::Compiled: {
645 return mCompiled->getExportFuncNameList(funcList);
646 }
647
648 default: {
649 mErrorCode = BCC_INVALID_OPERATION;
650 }
651 }
652}
653
Stephen Hinescc366e52012-02-21 17:22:04 -0800654void Script::getExportForEachList(size_t funcListSize, void **funcList) {
655 switch (mStatus) {
656#define DELEGATE(STATUS) \
657 case ScriptStatus::STATUS: \
658 m##STATUS->getExportForEachList(funcListSize, funcList); \
659 break;
660
Stephen Hinescc366e52012-02-21 17:22:04 -0800661 DELEGATE(Cached);
Stephen Hinescc366e52012-02-21 17:22:04 -0800662
663 DELEGATE(Compiled);
664#undef DELEGATE
665
666 default: {
667 mErrorCode = BCC_INVALID_OPERATION;
668 }
669 }
670}
671
672void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
673 switch (mStatus) {
674 case ScriptStatus::Compiled: {
675 return mCompiled->getExportForEachNameList(forEachList);
676 }
677
678 default: {
679 mErrorCode = BCC_INVALID_OPERATION;
680 }
681 }
682}
Logancf3e5212010-12-29 01:44:55 +0800683
Loganbe79ada2011-01-13 01:33:45 +0800684void Script::getPragmaList(size_t pragmaListSize,
685 char const **keyList,
686 char const **valueList) {
Logan89eb47f2011-01-07 10:45:16 +0800687 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800688#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700689 case ScriptStatus::STATUS: \
690 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
691 break;
Logancf3e5212010-12-29 01:44:55 +0800692
Shih-wei Liaod50be322011-07-01 22:53:31 -0700693 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800694
Shih-wei Liaod50be322011-07-01 22:53:31 -0700695 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800696#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800697
Shih-wei Liaod50be322011-07-01 22:53:31 -0700698 default: {
699 mErrorCode = BCC_INVALID_OPERATION;
700 }
Logan89eb47f2011-01-07 10:45:16 +0800701 }
Logancf3e5212010-12-29 01:44:55 +0800702}
703
704
Loganf340bf72011-01-14 17:51:40 +0800705void Script::getFuncInfoList(size_t funcInfoListSize,
706 FuncInfo *funcInfoList) {
Logan89eb47f2011-01-07 10:45:16 +0800707 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800708#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700709 case ScriptStatus::STATUS: \
710 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
711 break;
Logancf3e5212010-12-29 01:44:55 +0800712
Shih-wei Liaod50be322011-07-01 22:53:31 -0700713 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800714
Shih-wei Liaod50be322011-07-01 22:53:31 -0700715 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800716#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800717
Shih-wei Liaod50be322011-07-01 22:53:31 -0700718 default: {
719 mErrorCode = BCC_INVALID_OPERATION;
720 }
Logan89eb47f2011-01-07 10:45:16 +0800721 }
Logancf3e5212010-12-29 01:44:55 +0800722}
723
Stephen Hines071288a2011-01-27 14:38:26 -0800724
725void Script::getObjectSlotList(size_t objectSlotListSize,
726 uint32_t *objectSlotList) {
727 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700728#define DELEGATE(STATUS) \
729 case ScriptStatus::STATUS: \
730 m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
731 break;
Stephen Hines071288a2011-01-27 14:38:26 -0800732
Shih-wei Liaod50be322011-07-01 22:53:31 -0700733 DELEGATE(Cached);
Stephen Hines071288a2011-01-27 14:38:26 -0800734
Shih-wei Liaod50be322011-07-01 22:53:31 -0700735 DELEGATE(Compiled);
Stephen Hines071288a2011-01-27 14:38:26 -0800736#undef DELEGATE
737
Shih-wei Liaod50be322011-07-01 22:53:31 -0700738 default: {
739 mErrorCode = BCC_INVALID_OPERATION;
740 }
Stephen Hines071288a2011-01-27 14:38:26 -0800741 }
742}
743
744
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800745int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
Logancf3e5212010-12-29 01:44:55 +0800746 mpExtSymbolLookupFn = pFn;
747 mpExtSymbolLookupFnContext = pContext;
748
Logan7d2219f2011-01-06 06:19:25 +0800749 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800750 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000751 ALOGE("Invalid operation: %s\n", __func__);
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800752 return 1;
Logancf3e5212010-12-29 01:44:55 +0800753 }
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800754 return 0;
Logancf3e5212010-12-29 01:44:55 +0800755}
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700756
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800757bool Script::isCacheable() const {
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800758 if (getBooleanProp("debug.bcc.nocache")) {
759 // Android system environment property: Disables the cache mechanism by
760 // setting "debug.bcc.nocache". So we will not load the cache file any
761 // way.
762 return false;
763 }
764
765 if (mCacheDir.empty() || mCacheName.empty()) {
766 // The application developer has not specified the cachePath, so
767 // we don't know where to open the cache file.
768 return false;
769 }
770
771 return true;
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800772}
773
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700774size_t Script::getELFSize() const {
775 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700776 case ScriptStatus::Compiled: {
777 return mCompiled->getELFSize();
778 }
Stephen Hines0e567862012-03-11 20:26:40 -0700779
Daniel Malea094881f2011-12-14 17:39:16 -0500780 case ScriptStatus::Cached: {
781 return mCached->getELFSize();
782 }
Stephen Hines0e567862012-03-11 20:26:40 -0700783
Shih-wei Liaod50be322011-07-01 22:53:31 -0700784 default: {
785 return 0;
786 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700787 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700788}
789
790const char *Script::getELF() const {
791 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700792 case ScriptStatus::Compiled: {
793 return mCompiled->getELF();
794 }
Stephen Hines0e567862012-03-11 20:26:40 -0700795
Daniel Malea094881f2011-12-14 17:39:16 -0500796 case ScriptStatus::Cached: {
797 return mCached->getELF();
798 }
Stephen Hines0e567862012-03-11 20:26:40 -0700799
Shih-wei Liaod50be322011-07-01 22:53:31 -0700800 default: {
801 return NULL;
802 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700803 }
804}
Logancf3e5212010-12-29 01:44:55 +0800805
806} // namespace bcc