blob: 445d07554adbacfbd1d2e037206be4193e84de1a [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
Logan35849002011-01-15 07:30:43 +080060 case ScriptStatus::Cached:
Shih-wei Liaoc4cf6542011-01-13 01:43:01 -080061 delete mCached;
Logan35849002011-01-15 07:30:43 +080062 break;
Logan35849002011-01-15 07:30:43 +080063
64 default:
65 break;
Logancf3e5212010-12-29 01:44:55 +080066 }
Logan474cbd22011-01-31 01:47:44 +080067
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080068 for (size_t i = 0; i < 2; ++i) {
Logan474cbd22011-01-31 01:47:44 +080069 delete mSourceList[i];
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080070 }
Logancf3e5212010-12-29 01:44:55 +080071}
72
73
Logan474cbd22011-01-31 01:47:44 +080074int Script::addSourceBC(size_t idx,
75 char const *resName,
76 const char *bitcode,
77 size_t bitcodeSize,
78 unsigned long flags) {
Shih-wei Liao898c5a92011-05-18 07:02:39 -070079
80 if (!resName) {
81 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000082 ALOGE("Invalid argument: resName = NULL\n");
Shih-wei Liao898c5a92011-05-18 07:02:39 -070083 return 1;
84 }
85
Loganecf4cbd2011-01-06 05:34:11 +080086 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +080087 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +000088 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +080089 return 1;
90 }
91
Logan474cbd22011-01-31 01:47:44 +080092 if (!bitcode) {
93 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000094 ALOGE("Invalid argument: bitcode = NULL\n");
Logan474cbd22011-01-31 01:47:44 +080095 return 1;
96 }
97
98 mSourceList[idx] = SourceInfo::createFromBuffer(resName,
99 bitcode, bitcodeSize,
100 flags);
101
102 if (!mSourceList[idx]) {
103 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000104 ALOGE("Out of memory while adding source bitcode\n");
Logan474cbd22011-01-31 01:47:44 +0800105 return 1;
106 }
107
Loganecf4cbd2011-01-06 05:34:11 +0800108 return 0;
Logancf3e5212010-12-29 01:44:55 +0800109}
110
111
Logan474cbd22011-01-31 01:47:44 +0800112int Script::addSourceModule(size_t idx,
113 llvm::Module *module,
114 unsigned long flags) {
Logancf3e5212010-12-29 01:44:55 +0800115 if (mStatus != ScriptStatus::Unknown) {
116 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000117 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800118 return 1;
119 }
120
Logan474cbd22011-01-31 01:47:44 +0800121 if (!module) {
122 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000123 ALOGE("Invalid argument: module = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800124 return 1;
125 }
126
127 mSourceList[idx] = SourceInfo::createFromModule(module, flags);
128
129 if (!mSourceList[idx]) {
130 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000131 ALOGE("Out of memory when add source module\n");
Logan474cbd22011-01-31 01:47:44 +0800132 return 1;
133 }
134
Loganecf4cbd2011-01-06 05:34:11 +0800135 return 0;
Logancf3e5212010-12-29 01:44:55 +0800136}
137
138
Logan474cbd22011-01-31 01:47:44 +0800139int Script::addSourceFile(size_t idx,
140 char const *path,
141 unsigned long flags) {
Logan3133c412011-01-06 06:15:40 +0800142 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800143 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000144 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800145 return 1;
146 }
147
Logan474cbd22011-01-31 01:47:44 +0800148 if (!path) {
149 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000150 ALOGE("Invalid argument: path = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800151 return 1;
152 }
153
154 struct stat sb;
155 if (stat(path, &sb) != 0) {
156 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000157 ALOGE("File not found: %s\n", path);
Logan474cbd22011-01-31 01:47:44 +0800158 return 1;
159 }
160
161 mSourceList[idx] = SourceInfo::createFromFile(path, flags);
162
163 if (!mSourceList[idx]) {
164 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000165 ALOGE("Out of memory while adding source file\n");
Logan474cbd22011-01-31 01:47:44 +0800166 return 1;
167 }
168
Logan3133c412011-01-06 06:15:40 +0800169 return 0;
Logancf3e5212010-12-29 01:44:55 +0800170}
171
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800172int Script::prepareRelocatable(char const *objPath,
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -0800173 llvm::Reloc::Model RelocModel,
174 unsigned long flags) {
Zonr Chang2fcbd022012-01-06 21:04:31 +0800175 CompilerOption option;
Shih-wei Liao8afed382012-01-10 15:57:24 +0800176 option.RelocModelOpt = RelocModel;
Zonr Chang2fcbd022012-01-06 21:04:31 +0800177 option.LoadAfterCompile = false;
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800178
Zonr Chang2fcbd022012-01-06 21:04:31 +0800179 int status = internalCompile(option);
Joseph Wen34c600a2011-07-25 17:59:17 -0700180 if (status != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000181 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800182 return status;
183 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800184
185 FileHandle objFile;
186 if (objFile.open(objPath, OpenMode::Write) < 0) {
187 ALOGE("Failed to open %s for write.\n", objPath);
188 return 1;
Joseph Wen34c600a2011-07-25 17:59:17 -0700189 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800190
191 if (static_cast<size_t>(objFile.write(getELF(),
192 getELFSize())) != getELFSize()) {
193 objFile.close();
194 ::unlink(objPath);
195 ALOGE("Unable to write ELF to file %s.\n", objPath);
196 return false;
197 }
198
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800199 mObjectType = ScriptObject::Relocatable;
200
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800201 return 0;
Joseph Wen34c600a2011-07-25 17:59:17 -0700202}
203
Logancf3e5212010-12-29 01:44:55 +0800204
Shih-wei Liao69341742012-03-03 01:45:36 -0800205int Script::prepareSharedObject(char const *objPath,
Shih-wei Liaoa471ebb2012-02-05 00:49:58 -0800206 char const *dsoPath,
207 unsigned long flags) {
208 // TODO: Support cached shared object.
209 return 1;
210}
211
212
Logan Chien311c26f2011-07-11 14:30:34 +0800213int Script::prepareExecutable(char const *cacheDir,
214 char const *cacheName,
215 unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +0800216 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800217 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000218 ALOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800219 return 1;
220 }
221
Stephen Hines0e567862012-03-11 20:26:40 -0700222 int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
Loganecf4cbd2011-01-06 05:34:11 +0800223
Stephen Hinese0918ac2012-03-01 23:28:09 -0800224 if (status != 0) {
225 CompilerOption option;
226 status = internalCompile(option);
Stephen Hinese0918ac2012-03-01 23:28:09 -0800227
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800228 if (status != 0) {
229 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
230 return status;
231 }
232
233 status = writeCache();
234 if (status != 0) {
235 ALOGE("Failed to write the cache for %s\n", cacheName);
236 return status;
237 }
Stephen Hines27b35102011-05-11 17:58:48 -0700238 }
Daniel Malea094881f2011-12-14 17:39:16 -0500239
240 // FIXME: Registration can be conditional on the presence of debug metadata
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800241 registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
242
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800243 mObjectType = ScriptObject::Executable;
244
Stephen Hines27b35102011-05-11 17:58:48 -0700245 return status;
Logan033f46e2011-01-06 05:51:24 +0800246}
247
Zonr Chang743dd712012-01-19 10:13:52 +0800248int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
Zonr Chang743dd712012-01-19 10:13:52 +0800249 bool checkOnly) {
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800250 if ((cacheDir == NULL) || (cacheName == NULL)) {
Zonr Chang743dd712012-01-19 10:13:52 +0800251 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800252 }
Zonr Chang743dd712012-01-19 10:13:52 +0800253
254 // Set cache file Name
255 mCacheName = cacheName;
256
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800257 // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
Zonr Chang743dd712012-01-19 10:13:52 +0800258 mCacheDir = cacheDir;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800259 if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
Zonr Chang743dd712012-01-19 10:13:52 +0800260 mCacheDir.push_back('/');
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800261 }
Zonr Chang743dd712012-01-19 10:13:52 +0800262
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800263 if (!isCacheable()) {
Logan033f46e2011-01-06 05:51:24 +0800264 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800265 }
Logan04329712011-01-06 06:10:57 +0800266
Zonr Chang4ea08862012-01-17 17:26:49 +0800267 std::string objPath = getCachedObjectPath();
268 std::string infoPath = getCacheInfoPath();
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700269
Logan Chien311c26f2011-07-11 14:30:34 +0800270 FileHandle objFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700271 if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800272 // Unable to open the executable file in read mode.
Logan04329712011-01-06 06:10:57 +0800273 return 1;
274 }
275
Logan Chien311c26f2011-07-11 14:30:34 +0800276 FileHandle infoFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700277 if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800278 // Unable to open the metadata information file in read mode.
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700279 return 1;
280 }
281
282 MCCacheReader reader;
283
284 // Register symbol lookup function
285 if (mpExtSymbolLookupFn) {
286 reader.registerSymbolCallback(mpExtSymbolLookupFn,
287 mpExtSymbolLookupFnContext);
288 }
Logan04329712011-01-06 06:10:57 +0800289
Logan9a5f8682011-01-07 06:09:57 +0800290 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700291 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700292 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logan9a5f8682011-01-07 06:09:57 +0800293
Logan474cbd22011-01-31 01:47:44 +0800294 for (size_t i = 0; i < 2; ++i) {
295 if (mSourceList[i]) {
296 mSourceList[i]->introDependency(reader);
297 }
Logan9a5f8682011-01-07 06:09:57 +0800298 }
299
Joseph Wen34c600a2011-07-25 17:59:17 -0700300 if (checkOnly)
Joseph Wen49281042011-07-26 10:04:09 -0700301 return !reader.checkCacheFile(&objFile, &infoFile, this);
Joseph Wen34c600a2011-07-25 17:59:17 -0700302
Logan9a5f8682011-01-07 06:09:57 +0800303 // Read cache file
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700304 ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700305
Logan04329712011-01-06 06:10:57 +0800306 if (!cached) {
Logan42598052011-01-26 22:41:13 +0800307 mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
Logan04329712011-01-06 06:10:57 +0800308 return 1;
309 }
310
311 mCached = cached;
312 mStatus = ScriptStatus::Cached;
Logan033f46e2011-01-06 05:51:24 +0800313
Loganf3c83ce2011-01-07 06:36:33 +0800314 // Dirty hack for libRS.
315 // TODO(all): This dirty hack should be removed in the future.
Shih-wei Liao8eb5fe92011-02-01 04:17:38 -0800316 if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
Loganf3c83ce2011-01-07 06:36:33 +0800317 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
318 }
319
Loganf7f0ac52011-01-07 03:53:43 +0800320 return 0;
Logan033f46e2011-01-06 05:51:24 +0800321}
322
Shih-wei Liao9e81e372012-01-17 16:38:40 -0800323int Script::internalCompile(const CompilerOption &option) {
Logan033f46e2011-01-06 05:51:24 +0800324 // Create the ScriptCompiled object
Nowar Gu09b6c1c2011-05-24 23:49:07 +0800325 mCompiled = new (std::nothrow) ScriptCompiled(this);
Loganecf4cbd2011-01-06 05:34:11 +0800326
327 if (!mCompiled) {
328 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000329 ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
Loganecf4cbd2011-01-06 05:34:11 +0800330 return 1;
331 }
332
333 mStatus = ScriptStatus::Compiled;
334
Logan033f46e2011-01-06 05:51:24 +0800335 // Register symbol lookup function
Loganecf4cbd2011-01-06 05:34:11 +0800336 if (mpExtSymbolLookupFn) {
337 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
338 mpExtSymbolLookupFnContext);
339 }
340
Zonr Changdf3fee42012-01-10 15:58:36 +0800341 if (!mSourceList[0]) {
342 ALOGE("Source bitcode is not set.\n");
Logan474cbd22011-01-31 01:47:44 +0800343 return 1;
344 }
345
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800346 // Parse Source bitcode file (if necessary)
347 if (mSourceList[0]->prepareModule() != 0) {
348 ALOGE("Unable to setup source module\n");
Zonr Changdf3fee42012-01-10 15:58:36 +0800349 return 1;
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800350 }
351
352 // Parse Library bitcode file (if necessary)
353 if (mSourceList[1]) {
354 if (mSourceList[1]->prepareModule(mSourceList[0]->getContext()) != 0) {
355 ALOGE("Unable to setup library module\n");
356 return 1;
357 }
358 }
Zonr Changdf3fee42012-01-10 15:58:36 +0800359
360 // Set the main source module
361 if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000362 ALOGE("Unable to read source module\n");
Logan474cbd22011-01-31 01:47:44 +0800363 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800364 }
365
Logan3133c412011-01-06 06:15:40 +0800366 // Link the source module with the library module
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800367 if (mSourceList[1]) {
Zonr Changdf3fee42012-01-10 15:58:36 +0800368 if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000369 ALOGE("Unable to link library module\n");
Logan04329712011-01-06 06:10:57 +0800370 return 1;
371 }
372 }
Loganecf4cbd2011-01-06 05:34:11 +0800373
Logan3133c412011-01-06 06:15:40 +0800374 // Compile and JIT the code
Zonr Chang2fcbd022012-01-06 21:04:31 +0800375 if (mCompiled->compile(option) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000376 ALOGE("Unable to compile.\n");
Logan04329712011-01-06 06:10:57 +0800377 return 1;
378 }
379
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800380 return 0;
381}
382
383int Script::writeCache() {
Stephen Hines3e36c692012-03-05 12:39:45 -0800384 // Not compiled script or encountered error during the compilation.
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800385 if ((mStatus != ScriptStatus::Compiled) ||
386 (getCompilerErrorMessage() == NULL))
387 return 1;
388
Logan42598052011-01-26 22:41:13 +0800389 // Note: If we re-compile the script because the cached context slot not
390 // available, then we don't have to write the cache.
391
392 // Note: If the address of the context is not in the context slot, then
393 // we don't have to cache it.
394
Stephen Hines9ddeb6b2012-03-11 18:41:03 -0700395 if (isCacheable()) {
Logan42598052011-01-26 22:41:13 +0800396
Zonr Chang4ea08862012-01-17 17:26:49 +0800397 std::string objPath = getCachedObjectPath();
398 std::string infoPath = getCacheInfoPath();
Logan Chien311c26f2011-07-11 14:30:34 +0800399
Jeff Brown937a0bc2011-01-26 23:20:14 -0800400 // Remove the file if it already exists before writing the new file.
401 // The old file may still be mapped elsewhere in memory and we do not want
402 // to modify its contents. (The same script may be running concurrently in
403 // the same process or a different process!)
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700404 ::unlink(objPath.c_str());
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700405 ::unlink(infoPath.c_str());
Jeff Brown937a0bc2011-01-26 23:20:14 -0800406
Logan Chien03a2e302011-07-13 21:46:32 +0800407 FileHandle objFile;
408 FileHandle infoFile;
409
410 if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
411 infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700412
Logan Chien311c26f2011-07-11 14:30:34 +0800413 MCCacheWriter writer;
Logana27a83f2011-01-07 10:25:48 +0800414
Joseph Wen2ca6e572011-06-24 14:12:23 -0700415#ifdef TARGET_BUILD
Logana2e15af2011-01-07 11:46:08 +0800416 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700417 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700418 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logane1323992011-01-12 04:47:13 +0800419#endif
Logana2e15af2011-01-07 11:46:08 +0800420
Logan474cbd22011-01-31 01:47:44 +0800421 for (size_t i = 0; i < 2; ++i) {
Logan825c3b22011-02-28 05:05:48 +0800422 if (mSourceList[i]) {
423 mSourceList[i]->introDependency(writer);
424 }
Logana2e15af2011-01-07 11:46:08 +0800425 }
426
Logana27a83f2011-01-07 10:25:48 +0800427 // libRS is threadable dirty hack
428 // TODO: This should be removed in the future
429 uint32_t libRS_threadable = 0;
430 if (mpExtSymbolLookupFn) {
Logan89eb47f2011-01-07 10:45:16 +0800431 libRS_threadable =
432 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
433 "__isThreadable");
Logana27a83f2011-01-07 10:25:48 +0800434 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700435
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700436 if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700437 objFile.truncate();
438 objFile.close();
Logana27a83f2011-01-07 10:25:48 +0800439
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700440 if (unlink(objPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000441 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700442 objPath.c_str(), strerror(errno));
Logan89eb47f2011-01-07 10:45:16 +0800443 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700444
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700445 infoFile.truncate();
446 infoFile.close();
447
448 if (unlink(infoPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000449 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700450 infoPath.c_str(), strerror(errno));
451 }
Logan89eb47f2011-01-07 10:45:16 +0800452 }
453 }
Logan04329712011-01-06 06:10:57 +0800454 }
Logan04329712011-01-06 06:10:57 +0800455
456 return 0;
Logancf3e5212010-12-29 01:44:55 +0800457}
458
459
460char const *Script::getCompilerErrorMessage() {
461 if (mStatus != ScriptStatus::Compiled) {
462 mErrorCode = BCC_INVALID_OPERATION;
463 return NULL;
464 }
465
466 return mCompiled->getCompilerErrorMessage();
467}
468
469
470void *Script::lookup(const char *name) {
Logan89eb47f2011-01-07 10:45:16 +0800471 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700472 case ScriptStatus::Compiled: {
473 return mCompiled->lookup(name);
474 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700475
Shih-wei Liaod50be322011-07-01 22:53:31 -0700476 case ScriptStatus::Cached: {
477 return mCached->lookup(name);
478 }
Logan89eb47f2011-01-07 10:45:16 +0800479
Shih-wei Liaod50be322011-07-01 22:53:31 -0700480 default: {
481 mErrorCode = BCC_INVALID_OPERATION;
482 return NULL;
483 }
Logancf3e5212010-12-29 01:44:55 +0800484 }
Logancf3e5212010-12-29 01:44:55 +0800485}
486
487
Loganbe79ada2011-01-13 01:33:45 +0800488size_t Script::getExportVarCount() const {
Logan89eb47f2011-01-07 10:45:16 +0800489 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700490 case ScriptStatus::Compiled: {
491 return mCompiled->getExportVarCount();
492 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700493
Shih-wei Liaod50be322011-07-01 22:53:31 -0700494 case ScriptStatus::Cached: {
495 return mCached->getExportVarCount();
496 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700497
Shih-wei Liaod50be322011-07-01 22:53:31 -0700498 default: {
499 return 0;
500 }
Loganbe79ada2011-01-13 01:33:45 +0800501 }
502}
503
504
505size_t Script::getExportFuncCount() const {
506 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700507 case ScriptStatus::Compiled: {
508 return mCompiled->getExportFuncCount();
509 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700510
Shih-wei Liaod50be322011-07-01 22:53:31 -0700511 case ScriptStatus::Cached: {
512 return mCached->getExportFuncCount();
513 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700514
Shih-wei Liaod50be322011-07-01 22:53:31 -0700515 default: {
516 return 0;
517 }
Loganbe79ada2011-01-13 01:33:45 +0800518 }
519}
520
521
Stephen Hinescc366e52012-02-21 17:22:04 -0800522size_t Script::getExportForEachCount() const {
523 switch (mStatus) {
524 case ScriptStatus::Compiled: {
525 return mCompiled->getExportForEachCount();
526 }
527
Stephen Hinescc366e52012-02-21 17:22:04 -0800528 case ScriptStatus::Cached: {
529 return mCached->getExportForEachCount();
530 }
Stephen Hinescc366e52012-02-21 17:22:04 -0800531
532 default: {
533 return 0;
534 }
535 }
536}
537
538
Loganbe79ada2011-01-13 01:33:45 +0800539size_t Script::getPragmaCount() const {
540 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700541 case ScriptStatus::Compiled: {
542 return mCompiled->getPragmaCount();
543 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700544
Shih-wei Liaod50be322011-07-01 22:53:31 -0700545 case ScriptStatus::Cached: {
546 return mCached->getPragmaCount();
547 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700548
Shih-wei Liaod50be322011-07-01 22:53:31 -0700549 default: {
550 return 0;
551 }
Loganbe79ada2011-01-13 01:33:45 +0800552 }
553}
554
555
556size_t Script::getFuncCount() const {
557 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700558 case ScriptStatus::Compiled: {
559 return mCompiled->getFuncCount();
560 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700561
Shih-wei Liaod50be322011-07-01 22:53:31 -0700562 case ScriptStatus::Cached: {
563 return mCached->getFuncCount();
564 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700565
Shih-wei Liaod50be322011-07-01 22:53:31 -0700566 default: {
567 return 0;
568 }
Loganbe79ada2011-01-13 01:33:45 +0800569 }
570}
571
572
Stephen Hines071288a2011-01-27 14:38:26 -0800573size_t Script::getObjectSlotCount() const {
574 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700575 case ScriptStatus::Compiled: {
576 return mCompiled->getObjectSlotCount();
577 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700578
Shih-wei Liaod50be322011-07-01 22:53:31 -0700579 case ScriptStatus::Cached: {
580 return mCached->getObjectSlotCount();
581 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700582
Shih-wei Liaod50be322011-07-01 22:53:31 -0700583 default: {
584 return 0;
585 }
Stephen Hines071288a2011-01-27 14:38:26 -0800586 }
587}
588
589
Loganbe79ada2011-01-13 01:33:45 +0800590void Script::getExportVarList(size_t varListSize, void **varList) {
591 switch (mStatus) {
592#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700593 case ScriptStatus::STATUS: \
594 m##STATUS->getExportVarList(varListSize, varList); \
595 break;
Logancf3e5212010-12-29 01:44:55 +0800596
Shih-wei Liaod50be322011-07-01 22:53:31 -0700597 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800598
Shih-wei Liaod50be322011-07-01 22:53:31 -0700599 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800600#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800601
Shih-wei Liaod50be322011-07-01 22:53:31 -0700602 default: {
603 mErrorCode = BCC_INVALID_OPERATION;
604 }
Logan89eb47f2011-01-07 10:45:16 +0800605 }
Logancf3e5212010-12-29 01:44:55 +0800606}
607
Joseph Wenf36637f2011-07-06 18:27:12 -0700608void Script::getExportVarNameList(std::vector<std::string> &varList) {
609 switch (mStatus) {
610 case ScriptStatus::Compiled: {
611 return mCompiled->getExportVarNameList(varList);
612 }
613
614 default: {
615 mErrorCode = BCC_INVALID_OPERATION;
616 }
617 }
618}
619
Logancf3e5212010-12-29 01:44:55 +0800620
Loganbe79ada2011-01-13 01:33:45 +0800621void Script::getExportFuncList(size_t funcListSize, void **funcList) {
Logan89eb47f2011-01-07 10:45:16 +0800622 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800623#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700624 case ScriptStatus::STATUS: \
625 m##STATUS->getExportFuncList(funcListSize, funcList); \
626 break;
Logancf3e5212010-12-29 01:44:55 +0800627
Shih-wei Liaod50be322011-07-01 22:53:31 -0700628 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800629
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::getExportFuncNameList(std::vector<std::string> &funcList) {
640 switch (mStatus) {
641 case ScriptStatus::Compiled: {
642 return mCompiled->getExportFuncNameList(funcList);
643 }
644
645 default: {
646 mErrorCode = BCC_INVALID_OPERATION;
647 }
648 }
649}
650
Stephen Hinescc366e52012-02-21 17:22:04 -0800651void Script::getExportForEachList(size_t funcListSize, void **funcList) {
652 switch (mStatus) {
653#define DELEGATE(STATUS) \
654 case ScriptStatus::STATUS: \
655 m##STATUS->getExportForEachList(funcListSize, funcList); \
656 break;
657
Stephen Hinescc366e52012-02-21 17:22:04 -0800658 DELEGATE(Cached);
Stephen Hinescc366e52012-02-21 17:22:04 -0800659
660 DELEGATE(Compiled);
661#undef DELEGATE
662
663 default: {
664 mErrorCode = BCC_INVALID_OPERATION;
665 }
666 }
667}
668
669void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
670 switch (mStatus) {
671 case ScriptStatus::Compiled: {
672 return mCompiled->getExportForEachNameList(forEachList);
673 }
674
675 default: {
676 mErrorCode = BCC_INVALID_OPERATION;
677 }
678 }
679}
Logancf3e5212010-12-29 01:44:55 +0800680
Loganbe79ada2011-01-13 01:33:45 +0800681void Script::getPragmaList(size_t pragmaListSize,
682 char const **keyList,
683 char const **valueList) {
Logan89eb47f2011-01-07 10:45:16 +0800684 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800685#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700686 case ScriptStatus::STATUS: \
687 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
688 break;
Logancf3e5212010-12-29 01:44:55 +0800689
Shih-wei Liaod50be322011-07-01 22:53:31 -0700690 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800691
Shih-wei Liaod50be322011-07-01 22:53:31 -0700692 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800693#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800694
Shih-wei Liaod50be322011-07-01 22:53:31 -0700695 default: {
696 mErrorCode = BCC_INVALID_OPERATION;
697 }
Logan89eb47f2011-01-07 10:45:16 +0800698 }
Logancf3e5212010-12-29 01:44:55 +0800699}
700
701
Loganf340bf72011-01-14 17:51:40 +0800702void Script::getFuncInfoList(size_t funcInfoListSize,
703 FuncInfo *funcInfoList) {
Logan89eb47f2011-01-07 10:45:16 +0800704 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800705#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700706 case ScriptStatus::STATUS: \
707 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
708 break;
Logancf3e5212010-12-29 01:44:55 +0800709
Shih-wei Liaod50be322011-07-01 22:53:31 -0700710 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800711
Shih-wei Liaod50be322011-07-01 22:53:31 -0700712 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800713#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800714
Shih-wei Liaod50be322011-07-01 22:53:31 -0700715 default: {
716 mErrorCode = BCC_INVALID_OPERATION;
717 }
Logan89eb47f2011-01-07 10:45:16 +0800718 }
Logancf3e5212010-12-29 01:44:55 +0800719}
720
Stephen Hines071288a2011-01-27 14:38:26 -0800721
722void Script::getObjectSlotList(size_t objectSlotListSize,
723 uint32_t *objectSlotList) {
724 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700725#define DELEGATE(STATUS) \
726 case ScriptStatus::STATUS: \
727 m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
728 break;
Stephen Hines071288a2011-01-27 14:38:26 -0800729
Shih-wei Liaod50be322011-07-01 22:53:31 -0700730 DELEGATE(Cached);
Stephen Hines071288a2011-01-27 14:38:26 -0800731
Shih-wei Liaod50be322011-07-01 22:53:31 -0700732 DELEGATE(Compiled);
Stephen Hines071288a2011-01-27 14:38:26 -0800733#undef DELEGATE
734
Shih-wei Liaod50be322011-07-01 22:53:31 -0700735 default: {
736 mErrorCode = BCC_INVALID_OPERATION;
737 }
Stephen Hines071288a2011-01-27 14:38:26 -0800738 }
739}
740
741
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800742int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
Logancf3e5212010-12-29 01:44:55 +0800743 mpExtSymbolLookupFn = pFn;
744 mpExtSymbolLookupFnContext = pContext;
745
Logan7d2219f2011-01-06 06:19:25 +0800746 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800747 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000748 ALOGE("Invalid operation: %s\n", __func__);
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800749 return 1;
Logancf3e5212010-12-29 01:44:55 +0800750 }
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800751 return 0;
Logancf3e5212010-12-29 01:44:55 +0800752}
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700753
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800754bool Script::isCacheable() const {
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800755 if (getBooleanProp("debug.bcc.nocache")) {
756 // Android system environment property: Disables the cache mechanism by
757 // setting "debug.bcc.nocache". So we will not load the cache file any
758 // way.
759 return false;
760 }
761
762 if (mCacheDir.empty() || mCacheName.empty()) {
763 // The application developer has not specified the cachePath, so
764 // we don't know where to open the cache file.
765 return false;
766 }
767
768 return true;
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800769}
770
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700771size_t Script::getELFSize() const {
772 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700773 case ScriptStatus::Compiled: {
774 return mCompiled->getELFSize();
775 }
Stephen Hines0e567862012-03-11 20:26:40 -0700776
Daniel Malea094881f2011-12-14 17:39:16 -0500777 case ScriptStatus::Cached: {
778 return mCached->getELFSize();
779 }
Stephen Hines0e567862012-03-11 20:26:40 -0700780
Shih-wei Liaod50be322011-07-01 22:53:31 -0700781 default: {
782 return 0;
783 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700784 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700785}
786
787const char *Script::getELF() const {
788 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700789 case ScriptStatus::Compiled: {
790 return mCompiled->getELF();
791 }
Stephen Hines0e567862012-03-11 20:26:40 -0700792
Daniel Malea094881f2011-12-14 17:39:16 -0500793 case ScriptStatus::Cached: {
794 return mCached->getELF();
795 }
Stephen Hines0e567862012-03-11 20:26:40 -0700796
Shih-wei Liaod50be322011-07-01 22:53:31 -0700797 default: {
798 return NULL;
799 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700800 }
801}
Logancf3e5212010-12-29 01:44:55 +0800802
803} // namespace bcc