blob: 2dbdf405447d67f643cbfaea5c3254a4347449cd [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
Zonr Changc09dee62012-04-12 17:15:30 +080026#include "BCCContextImpl.h"
Logan4dcd6792011-02-28 05:12:00 +080027#include "DebugHelper.h"
Logan04329712011-01-06 06:10:57 +080028#include "FileHandle.h"
Daniel Malea094881f2011-12-14 17:39:16 -050029#include "GDBJITRegistrar.h"
Logancf3e5212010-12-29 01:44:55 +080030#include "ScriptCompiled.h"
Logan9a5f8682011-01-07 06:09:57 +080031#include "ScriptCached.h"
32#include "Sha1Helper.h"
Logan474cbd22011-01-31 01:47:44 +080033#include "SourceInfo.h"
Logancf3e5212010-12-29 01:44:55 +080034
Logan89eb47f2011-01-07 10:45:16 +080035#include <errno.h>
Logan474cbd22011-01-31 01:47:44 +080036#include <sys/stat.h>
37#include <sys/types.h>
Bhanu Chetlapallieb4509b2012-01-08 20:42:56 -080038#include <unistd.h>
Logancf3e5212010-12-29 01:44:55 +080039
Logan89eb47f2011-01-07 10:45:16 +080040#include <new>
41#include <string.h>
Logan033f46e2011-01-06 05:51:24 +080042#include <cutils/properties.h>
43
Loganecf4cbd2011-01-06 05:34:11 +080044namespace {
45
Logan033f46e2011-01-06 05:51:24 +080046bool getBooleanProp(const char *str) {
Loganf340bf72011-01-14 17:51:40 +080047 char buf[PROPERTY_VALUE_MAX];
48 property_get(str, buf, "0");
49 return strcmp(buf, "0") != 0;
Logan033f46e2011-01-06 05:51:24 +080050}
51
Loganecf4cbd2011-01-06 05:34:11 +080052} // namespace anonymous
53
Logancf3e5212010-12-29 01:44:55 +080054namespace bcc {
55
56Script::~Script() {
Logan35849002011-01-15 07:30:43 +080057 switch (mStatus) {
58 case ScriptStatus::Compiled:
Logancf3e5212010-12-29 01:44:55 +080059 delete mCompiled;
Logan35849002011-01-15 07:30:43 +080060 break;
61
Logan35849002011-01-15 07:30:43 +080062 case ScriptStatus::Cached:
Shih-wei Liaoc4cf6542011-01-13 01:43:01 -080063 delete mCached;
Logan35849002011-01-15 07:30:43 +080064 break;
Logan35849002011-01-15 07:30:43 +080065
66 default:
67 break;
Logancf3e5212010-12-29 01:44:55 +080068 }
Logan474cbd22011-01-31 01:47:44 +080069
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080070 for (size_t i = 0; i < 2; ++i) {
Logan474cbd22011-01-31 01:47:44 +080071 delete mSourceList[i];
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -080072 }
Logancf3e5212010-12-29 01:44:55 +080073}
74
75
Logan474cbd22011-01-31 01:47:44 +080076int Script::addSourceBC(size_t idx,
77 char const *resName,
78 const char *bitcode,
79 size_t bitcodeSize,
80 unsigned long flags) {
Shih-wei Liao898c5a92011-05-18 07:02:39 -070081
82 if (!resName) {
83 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000084 ALOGE("Invalid argument: resName = NULL\n");
Shih-wei Liao898c5a92011-05-18 07:02:39 -070085 return 1;
86 }
87
Loganecf4cbd2011-01-06 05:34:11 +080088 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +080089 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +000090 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +080091 return 1;
92 }
93
Logan474cbd22011-01-31 01:47:44 +080094 if (!bitcode) {
95 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +000096 ALOGE("Invalid argument: bitcode = NULL\n");
Logan474cbd22011-01-31 01:47:44 +080097 return 1;
98 }
99
Stephen Hinesb67c9e72012-03-22 11:02:48 -0700100 bcinfo::BitcodeWrapper wrapper(bitcode, bitcodeSize);
Stephen Hinesb67c9e72012-03-22 11:02:48 -0700101
Logan474cbd22011-01-31 01:47:44 +0800102 mSourceList[idx] = SourceInfo::createFromBuffer(resName,
103 bitcode, bitcodeSize,
104 flags);
105
106 if (!mSourceList[idx]) {
107 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000108 ALOGE("Out of memory while adding source bitcode\n");
Logan474cbd22011-01-31 01:47:44 +0800109 return 1;
110 }
111
Loganecf4cbd2011-01-06 05:34:11 +0800112 return 0;
Logancf3e5212010-12-29 01:44:55 +0800113}
114
115
Logan474cbd22011-01-31 01:47:44 +0800116int Script::addSourceModule(size_t idx,
117 llvm::Module *module,
118 unsigned long flags) {
Logancf3e5212010-12-29 01:44:55 +0800119 if (mStatus != ScriptStatus::Unknown) {
120 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000121 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800122 return 1;
123 }
124
Logan474cbd22011-01-31 01:47:44 +0800125 if (!module) {
126 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000127 ALOGE("Invalid argument: module = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800128 return 1;
129 }
130
131 mSourceList[idx] = SourceInfo::createFromModule(module, flags);
132
133 if (!mSourceList[idx]) {
134 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000135 ALOGE("Out of memory when add source module\n");
Logan474cbd22011-01-31 01:47:44 +0800136 return 1;
137 }
138
Loganecf4cbd2011-01-06 05:34:11 +0800139 return 0;
Logancf3e5212010-12-29 01:44:55 +0800140}
141
142
Logan474cbd22011-01-31 01:47:44 +0800143int Script::addSourceFile(size_t idx,
144 char const *path,
145 unsigned long flags) {
Logan3133c412011-01-06 06:15:40 +0800146 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800147 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000148 ALOGE("Bad operation: Adding source after bccPrepareExecutable\n");
Logancf3e5212010-12-29 01:44:55 +0800149 return 1;
150 }
151
Logan474cbd22011-01-31 01:47:44 +0800152 if (!path) {
153 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000154 ALOGE("Invalid argument: path = NULL\n");
Logan474cbd22011-01-31 01:47:44 +0800155 return 1;
156 }
157
158 struct stat sb;
159 if (stat(path, &sb) != 0) {
160 mErrorCode = BCC_INVALID_VALUE;
Steve Block10c14122012-01-08 10:15:06 +0000161 ALOGE("File not found: %s\n", path);
Logan474cbd22011-01-31 01:47:44 +0800162 return 1;
163 }
164
165 mSourceList[idx] = SourceInfo::createFromFile(path, flags);
166
167 if (!mSourceList[idx]) {
168 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000169 ALOGE("Out of memory while adding source file\n");
Logan474cbd22011-01-31 01:47:44 +0800170 return 1;
171 }
172
Logan3133c412011-01-06 06:15:40 +0800173 return 0;
Logancf3e5212010-12-29 01:44:55 +0800174}
175
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800176int Script::prepareRelocatable(char const *objPath,
Shih-wei Liao6a60f4e2012-01-17 02:58:40 -0800177 llvm::Reloc::Model RelocModel,
178 unsigned long flags) {
Zonr Chang2fcbd022012-01-06 21:04:31 +0800179 CompilerOption option;
Shih-wei Liao8afed382012-01-10 15:57:24 +0800180 option.RelocModelOpt = RelocModel;
Zonr Chang2fcbd022012-01-06 21:04:31 +0800181 option.LoadAfterCompile = false;
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800182
Zonr Chang2fcbd022012-01-06 21:04:31 +0800183 int status = internalCompile(option);
Joseph Wen34c600a2011-07-25 17:59:17 -0700184 if (status != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000185 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800186 return status;
187 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800188
189 FileHandle objFile;
190 if (objFile.open(objPath, OpenMode::Write) < 0) {
191 ALOGE("Failed to open %s for write.\n", objPath);
192 return 1;
Joseph Wen34c600a2011-07-25 17:59:17 -0700193 }
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800194
195 if (static_cast<size_t>(objFile.write(getELF(),
196 getELFSize())) != getELFSize()) {
197 objFile.close();
198 ::unlink(objPath);
199 ALOGE("Unable to write ELF to file %s.\n", objPath);
200 return false;
201 }
202
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800203 mObjectType = ScriptObject::Relocatable;
204
Shih-wei Liaod8ed6a92012-03-03 01:44:29 -0800205 return 0;
Joseph Wen34c600a2011-07-25 17:59:17 -0700206}
207
Logancf3e5212010-12-29 01:44:55 +0800208
Shih-wei Liao69341742012-03-03 01:45:36 -0800209int Script::prepareSharedObject(char const *objPath,
Shih-wei Liaoa471ebb2012-02-05 00:49:58 -0800210 char const *dsoPath,
211 unsigned long flags) {
212 // TODO: Support cached shared object.
213 return 1;
214}
215
216
Logan Chien311c26f2011-07-11 14:30:34 +0800217int Script::prepareExecutable(char const *cacheDir,
218 char const *cacheName,
219 unsigned long flags) {
Loganecf4cbd2011-01-06 05:34:11 +0800220 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800221 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000222 ALOGE("Invalid operation: %s\n", __func__);
Logancf3e5212010-12-29 01:44:55 +0800223 return 1;
224 }
225
Stephen Hines0e567862012-03-11 20:26:40 -0700226 int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
Loganecf4cbd2011-01-06 05:34:11 +0800227
Stephen Hinese0918ac2012-03-01 23:28:09 -0800228 if (status != 0) {
229 CompilerOption option;
230 status = internalCompile(option);
Stephen Hinese0918ac2012-03-01 23:28:09 -0800231
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800232 if (status != 0) {
233 ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
234 return status;
235 }
236
237 status = writeCache();
238 if (status != 0) {
239 ALOGE("Failed to write the cache for %s\n", cacheName);
240 return status;
241 }
Stephen Hines27b35102011-05-11 17:58:48 -0700242 }
Daniel Malea094881f2011-12-14 17:39:16 -0500243
244 // FIXME: Registration can be conditional on the presence of debug metadata
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800245 registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
246
Shih-wei Liao8454a3a2012-03-03 01:50:08 -0800247 mObjectType = ScriptObject::Executable;
248
Stephen Hines27b35102011-05-11 17:58:48 -0700249 return status;
Logan033f46e2011-01-06 05:51:24 +0800250}
251
Zonr Chang743dd712012-01-19 10:13:52 +0800252int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
Zonr Chang743dd712012-01-19 10:13:52 +0800253 bool checkOnly) {
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800254 if ((cacheDir == NULL) || (cacheName == NULL)) {
Zonr Chang743dd712012-01-19 10:13:52 +0800255 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800256 }
Zonr Chang743dd712012-01-19 10:13:52 +0800257
258 // Set cache file Name
259 mCacheName = cacheName;
260
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800261 // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
Zonr Chang743dd712012-01-19 10:13:52 +0800262 mCacheDir = cacheDir;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800263 if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
Zonr Chang743dd712012-01-19 10:13:52 +0800264 mCacheDir.push_back('/');
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800265 }
Zonr Chang743dd712012-01-19 10:13:52 +0800266
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800267 if (!isCacheable()) {
Logan033f46e2011-01-06 05:51:24 +0800268 return 1;
Shih-wei Liao32ef88b2012-02-04 23:33:11 -0800269 }
Logan04329712011-01-06 06:10:57 +0800270
Zonr Chang4ea08862012-01-17 17:26:49 +0800271 std::string objPath = getCachedObjectPath();
272 std::string infoPath = getCacheInfoPath();
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700273
Logan Chien311c26f2011-07-11 14:30:34 +0800274 FileHandle objFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700275 if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800276 // Unable to open the executable file in read mode.
Logan04329712011-01-06 06:10:57 +0800277 return 1;
278 }
279
Logan Chien311c26f2011-07-11 14:30:34 +0800280 FileHandle infoFile;
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700281 if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
Logan Chien03a2e302011-07-13 21:46:32 +0800282 // Unable to open the metadata information file in read mode.
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700283 return 1;
284 }
285
286 MCCacheReader reader;
287
288 // Register symbol lookup function
289 if (mpExtSymbolLookupFn) {
290 reader.registerSymbolCallback(mpExtSymbolLookupFn,
291 mpExtSymbolLookupFnContext);
292 }
Logan04329712011-01-06 06:10:57 +0800293
Logan9a5f8682011-01-07 06:09:57 +0800294 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700295 reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700296 reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logan9a5f8682011-01-07 06:09:57 +0800297
Logan474cbd22011-01-31 01:47:44 +0800298 for (size_t i = 0; i < 2; ++i) {
299 if (mSourceList[i]) {
300 mSourceList[i]->introDependency(reader);
301 }
Logan9a5f8682011-01-07 06:09:57 +0800302 }
303
Joseph Wen34c600a2011-07-25 17:59:17 -0700304 if (checkOnly)
Joseph Wen49281042011-07-26 10:04:09 -0700305 return !reader.checkCacheFile(&objFile, &infoFile, this);
Joseph Wen34c600a2011-07-25 17:59:17 -0700306
Logan9a5f8682011-01-07 06:09:57 +0800307 // Read cache file
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700308 ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700309
Logan04329712011-01-06 06:10:57 +0800310 if (!cached) {
Logan42598052011-01-26 22:41:13 +0800311 mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
Logan04329712011-01-06 06:10:57 +0800312 return 1;
313 }
314
315 mCached = cached;
316 mStatus = ScriptStatus::Cached;
Logan033f46e2011-01-06 05:51:24 +0800317
Loganf3c83ce2011-01-07 06:36:33 +0800318 // Dirty hack for libRS.
319 // TODO(all): This dirty hack should be removed in the future.
Shih-wei Liao8eb5fe92011-02-01 04:17:38 -0800320 if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
Loganf3c83ce2011-01-07 06:36:33 +0800321 mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
322 }
323
Loganf7f0ac52011-01-07 03:53:43 +0800324 return 0;
Logan033f46e2011-01-06 05:51:24 +0800325}
326
Shih-wei Liao9e81e372012-01-17 16:38:40 -0800327int Script::internalCompile(const CompilerOption &option) {
Logan033f46e2011-01-06 05:51:24 +0800328 // Create the ScriptCompiled object
Nowar Gu09b6c1c2011-05-24 23:49:07 +0800329 mCompiled = new (std::nothrow) ScriptCompiled(this);
Loganecf4cbd2011-01-06 05:34:11 +0800330
331 if (!mCompiled) {
332 mErrorCode = BCC_OUT_OF_MEMORY;
Steve Block10c14122012-01-08 10:15:06 +0000333 ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
Loganecf4cbd2011-01-06 05:34:11 +0800334 return 1;
335 }
336
337 mStatus = ScriptStatus::Compiled;
338
Logan033f46e2011-01-06 05:51:24 +0800339 // Register symbol lookup function
Loganecf4cbd2011-01-06 05:34:11 +0800340 if (mpExtSymbolLookupFn) {
341 mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
342 mpExtSymbolLookupFnContext);
343 }
344
Zonr Changdf3fee42012-01-10 15:58:36 +0800345 if (!mSourceList[0]) {
346 ALOGE("Source bitcode is not set.\n");
Logan474cbd22011-01-31 01:47:44 +0800347 return 1;
348 }
349
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800350 // Parse Source bitcode file (if necessary)
Zonr Changc09dee62012-04-12 17:15:30 +0800351 if (mSourceList[0]->prepareModule(mContext.mImpl->mLLVMContext) != 0) {
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800352 ALOGE("Unable to setup source module\n");
Zonr Changdf3fee42012-01-10 15:58:36 +0800353 return 1;
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800354 }
355
356 // Parse Library bitcode file (if necessary)
357 if (mSourceList[1]) {
Zonr Changc09dee62012-04-12 17:15:30 +0800358 if (mSourceList[1]->prepareModule(mContext.mImpl->mLLVMContext) != 0) {
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800359 ALOGE("Unable to setup library module\n");
360 return 1;
361 }
362 }
Zonr Changdf3fee42012-01-10 15:58:36 +0800363
364 // Set the main source module
365 if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000366 ALOGE("Unable to read source module\n");
Logan474cbd22011-01-31 01:47:44 +0800367 return 1;
Loganecf4cbd2011-01-06 05:34:11 +0800368 }
369
Logan3133c412011-01-06 06:15:40 +0800370 // Link the source module with the library module
Shih-wei Liaod88c0d12012-01-17 20:32:58 -0800371 if (mSourceList[1]) {
Zonr Changdf3fee42012-01-10 15:58:36 +0800372 if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000373 ALOGE("Unable to link library module\n");
Logan04329712011-01-06 06:10:57 +0800374 return 1;
375 }
376 }
Loganecf4cbd2011-01-06 05:34:11 +0800377
Logan3133c412011-01-06 06:15:40 +0800378 // Compile and JIT the code
Zonr Chang2fcbd022012-01-06 21:04:31 +0800379 if (mCompiled->compile(option) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000380 ALOGE("Unable to compile.\n");
Logan04329712011-01-06 06:10:57 +0800381 return 1;
382 }
383
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800384 return 0;
385}
386
387int Script::writeCache() {
Stephen Hines3e36c692012-03-05 12:39:45 -0800388 // Not compiled script or encountered error during the compilation.
Shih-wei Liaoa0ed34e2012-03-03 01:33:30 -0800389 if ((mStatus != ScriptStatus::Compiled) ||
390 (getCompilerErrorMessage() == NULL))
391 return 1;
392
Logan42598052011-01-26 22:41:13 +0800393 // Note: If we re-compile the script because the cached context slot not
394 // available, then we don't have to write the cache.
395
396 // Note: If the address of the context is not in the context slot, then
397 // we don't have to cache it.
398
Stephen Hines9ddeb6b2012-03-11 18:41:03 -0700399 if (isCacheable()) {
Logan42598052011-01-26 22:41:13 +0800400
Zonr Chang4ea08862012-01-17 17:26:49 +0800401 std::string objPath = getCachedObjectPath();
402 std::string infoPath = getCacheInfoPath();
Logan Chien311c26f2011-07-11 14:30:34 +0800403
Jeff Brown937a0bc2011-01-26 23:20:14 -0800404 // Remove the file if it already exists before writing the new file.
405 // The old file may still be mapped elsewhere in memory and we do not want
406 // to modify its contents. (The same script may be running concurrently in
407 // the same process or a different process!)
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700408 ::unlink(objPath.c_str());
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700409 ::unlink(infoPath.c_str());
Jeff Brown937a0bc2011-01-26 23:20:14 -0800410
Logan Chien03a2e302011-07-13 21:46:32 +0800411 FileHandle objFile;
412 FileHandle infoFile;
413
414 if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
415 infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700416
Logan Chien311c26f2011-07-11 14:30:34 +0800417 MCCacheWriter writer;
Logana27a83f2011-01-07 10:25:48 +0800418
Joseph Wen2ca6e572011-06-24 14:12:23 -0700419#ifdef TARGET_BUILD
Logana2e15af2011-01-07 11:46:08 +0800420 // Dependencies
Joseph Wen2ca6e572011-06-24 14:12:23 -0700421 writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
Joseph Wen76919072011-07-07 23:06:15 -0700422 writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
Logane1323992011-01-12 04:47:13 +0800423#endif
Logana2e15af2011-01-07 11:46:08 +0800424
Logan474cbd22011-01-31 01:47:44 +0800425 for (size_t i = 0; i < 2; ++i) {
Logan825c3b22011-02-28 05:05:48 +0800426 if (mSourceList[i]) {
427 mSourceList[i]->introDependency(writer);
428 }
Logana2e15af2011-01-07 11:46:08 +0800429 }
430
Logana27a83f2011-01-07 10:25:48 +0800431 // libRS is threadable dirty hack
432 // TODO: This should be removed in the future
433 uint32_t libRS_threadable = 0;
434 if (mpExtSymbolLookupFn) {
Logan89eb47f2011-01-07 10:45:16 +0800435 libRS_threadable =
436 (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
437 "__isThreadable");
Logana27a83f2011-01-07 10:25:48 +0800438 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700439
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700440 if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700441 objFile.truncate();
442 objFile.close();
Logana27a83f2011-01-07 10:25:48 +0800443
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700444 if (unlink(objPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000445 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700446 objPath.c_str(), strerror(errno));
Logan89eb47f2011-01-07 10:45:16 +0800447 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700448
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700449 infoFile.truncate();
450 infoFile.close();
451
452 if (unlink(infoPath.c_str()) != 0) {
Steve Block10c14122012-01-08 10:15:06 +0000453 ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700454 infoPath.c_str(), strerror(errno));
455 }
Logan89eb47f2011-01-07 10:45:16 +0800456 }
457 }
Logan04329712011-01-06 06:10:57 +0800458 }
Logan04329712011-01-06 06:10:57 +0800459
460 return 0;
Logancf3e5212010-12-29 01:44:55 +0800461}
462
463
464char const *Script::getCompilerErrorMessage() {
465 if (mStatus != ScriptStatus::Compiled) {
466 mErrorCode = BCC_INVALID_OPERATION;
467 return NULL;
468 }
469
470 return mCompiled->getCompilerErrorMessage();
471}
472
473
474void *Script::lookup(const char *name) {
Logan89eb47f2011-01-07 10:45:16 +0800475 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700476 case ScriptStatus::Compiled: {
477 return mCompiled->lookup(name);
478 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700479
Shih-wei Liaod50be322011-07-01 22:53:31 -0700480 case ScriptStatus::Cached: {
481 return mCached->lookup(name);
482 }
Logan89eb47f2011-01-07 10:45:16 +0800483
Shih-wei Liaod50be322011-07-01 22:53:31 -0700484 default: {
485 mErrorCode = BCC_INVALID_OPERATION;
486 return NULL;
487 }
Logancf3e5212010-12-29 01:44:55 +0800488 }
Logancf3e5212010-12-29 01:44:55 +0800489}
490
491
Loganbe79ada2011-01-13 01:33:45 +0800492size_t Script::getExportVarCount() const {
Logan89eb47f2011-01-07 10:45:16 +0800493 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700494 case ScriptStatus::Compiled: {
495 return mCompiled->getExportVarCount();
496 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700497
Shih-wei Liaod50be322011-07-01 22:53:31 -0700498 case ScriptStatus::Cached: {
499 return mCached->getExportVarCount();
500 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700501
Shih-wei Liaod50be322011-07-01 22:53:31 -0700502 default: {
503 return 0;
504 }
Loganbe79ada2011-01-13 01:33:45 +0800505 }
506}
507
508
509size_t Script::getExportFuncCount() const {
510 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700511 case ScriptStatus::Compiled: {
512 return mCompiled->getExportFuncCount();
513 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700514
Shih-wei Liaod50be322011-07-01 22:53:31 -0700515 case ScriptStatus::Cached: {
516 return mCached->getExportFuncCount();
517 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700518
Shih-wei Liaod50be322011-07-01 22:53:31 -0700519 default: {
520 return 0;
521 }
Loganbe79ada2011-01-13 01:33:45 +0800522 }
523}
524
525
Stephen Hinescc366e52012-02-21 17:22:04 -0800526size_t Script::getExportForEachCount() const {
527 switch (mStatus) {
528 case ScriptStatus::Compiled: {
529 return mCompiled->getExportForEachCount();
530 }
531
Stephen Hinescc366e52012-02-21 17:22:04 -0800532 case ScriptStatus::Cached: {
533 return mCached->getExportForEachCount();
534 }
Stephen Hinescc366e52012-02-21 17:22:04 -0800535
536 default: {
537 return 0;
538 }
539 }
540}
541
542
Loganbe79ada2011-01-13 01:33:45 +0800543size_t Script::getPragmaCount() const {
544 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700545 case ScriptStatus::Compiled: {
546 return mCompiled->getPragmaCount();
547 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700548
Shih-wei Liaod50be322011-07-01 22:53:31 -0700549 case ScriptStatus::Cached: {
550 return mCached->getPragmaCount();
551 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700552
Shih-wei Liaod50be322011-07-01 22:53:31 -0700553 default: {
554 return 0;
555 }
Loganbe79ada2011-01-13 01:33:45 +0800556 }
557}
558
559
560size_t Script::getFuncCount() const {
561 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700562 case ScriptStatus::Compiled: {
563 return mCompiled->getFuncCount();
564 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700565
Shih-wei Liaod50be322011-07-01 22:53:31 -0700566 case ScriptStatus::Cached: {
567 return mCached->getFuncCount();
568 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700569
Shih-wei Liaod50be322011-07-01 22:53:31 -0700570 default: {
571 return 0;
572 }
Loganbe79ada2011-01-13 01:33:45 +0800573 }
574}
575
576
Stephen Hines071288a2011-01-27 14:38:26 -0800577size_t Script::getObjectSlotCount() const {
578 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700579 case ScriptStatus::Compiled: {
580 return mCompiled->getObjectSlotCount();
581 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700582
Shih-wei Liaod50be322011-07-01 22:53:31 -0700583 case ScriptStatus::Cached: {
584 return mCached->getObjectSlotCount();
585 }
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700586
Shih-wei Liaod50be322011-07-01 22:53:31 -0700587 default: {
588 return 0;
589 }
Stephen Hines071288a2011-01-27 14:38:26 -0800590 }
591}
592
593
Loganbe79ada2011-01-13 01:33:45 +0800594void Script::getExportVarList(size_t varListSize, void **varList) {
595 switch (mStatus) {
596#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700597 case ScriptStatus::STATUS: \
598 m##STATUS->getExportVarList(varListSize, varList); \
599 break;
Logancf3e5212010-12-29 01:44:55 +0800600
Shih-wei Liaod50be322011-07-01 22:53:31 -0700601 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800602
Shih-wei Liaod50be322011-07-01 22:53:31 -0700603 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800604#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800605
Shih-wei Liaod50be322011-07-01 22:53:31 -0700606 default: {
607 mErrorCode = BCC_INVALID_OPERATION;
608 }
Logan89eb47f2011-01-07 10:45:16 +0800609 }
Logancf3e5212010-12-29 01:44:55 +0800610}
611
Joseph Wenf36637f2011-07-06 18:27:12 -0700612void Script::getExportVarNameList(std::vector<std::string> &varList) {
613 switch (mStatus) {
614 case ScriptStatus::Compiled: {
615 return mCompiled->getExportVarNameList(varList);
616 }
617
618 default: {
619 mErrorCode = BCC_INVALID_OPERATION;
620 }
621 }
622}
623
Logancf3e5212010-12-29 01:44:55 +0800624
Loganbe79ada2011-01-13 01:33:45 +0800625void Script::getExportFuncList(size_t funcListSize, void **funcList) {
Logan89eb47f2011-01-07 10:45:16 +0800626 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800627#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700628 case ScriptStatus::STATUS: \
629 m##STATUS->getExportFuncList(funcListSize, funcList); \
630 break;
Logancf3e5212010-12-29 01:44:55 +0800631
Shih-wei Liaod50be322011-07-01 22:53:31 -0700632 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800633
Shih-wei Liaod50be322011-07-01 22:53:31 -0700634 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800635#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800636
Shih-wei Liaod50be322011-07-01 22:53:31 -0700637 default: {
638 mErrorCode = BCC_INVALID_OPERATION;
639 }
Logan89eb47f2011-01-07 10:45:16 +0800640 }
Logancf3e5212010-12-29 01:44:55 +0800641}
642
Joseph Wenf36637f2011-07-06 18:27:12 -0700643void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
644 switch (mStatus) {
645 case ScriptStatus::Compiled: {
646 return mCompiled->getExportFuncNameList(funcList);
647 }
648
649 default: {
650 mErrorCode = BCC_INVALID_OPERATION;
651 }
652 }
653}
654
Stephen Hinescc366e52012-02-21 17:22:04 -0800655void Script::getExportForEachList(size_t funcListSize, void **funcList) {
656 switch (mStatus) {
657#define DELEGATE(STATUS) \
658 case ScriptStatus::STATUS: \
659 m##STATUS->getExportForEachList(funcListSize, funcList); \
660 break;
661
Stephen Hinescc366e52012-02-21 17:22:04 -0800662 DELEGATE(Cached);
Stephen Hinescc366e52012-02-21 17:22:04 -0800663
664 DELEGATE(Compiled);
665#undef DELEGATE
666
667 default: {
668 mErrorCode = BCC_INVALID_OPERATION;
669 }
670 }
671}
672
673void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
674 switch (mStatus) {
675 case ScriptStatus::Compiled: {
676 return mCompiled->getExportForEachNameList(forEachList);
677 }
678
679 default: {
680 mErrorCode = BCC_INVALID_OPERATION;
681 }
682 }
683}
Logancf3e5212010-12-29 01:44:55 +0800684
Loganbe79ada2011-01-13 01:33:45 +0800685void Script::getPragmaList(size_t pragmaListSize,
686 char const **keyList,
687 char const **valueList) {
Logan89eb47f2011-01-07 10:45:16 +0800688 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800689#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700690 case ScriptStatus::STATUS: \
691 m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
692 break;
Logancf3e5212010-12-29 01:44:55 +0800693
Shih-wei Liaod50be322011-07-01 22:53:31 -0700694 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800695
Shih-wei Liaod50be322011-07-01 22:53:31 -0700696 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800697#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800698
Shih-wei Liaod50be322011-07-01 22:53:31 -0700699 default: {
700 mErrorCode = BCC_INVALID_OPERATION;
701 }
Logan89eb47f2011-01-07 10:45:16 +0800702 }
Logancf3e5212010-12-29 01:44:55 +0800703}
704
705
Loganf340bf72011-01-14 17:51:40 +0800706void Script::getFuncInfoList(size_t funcInfoListSize,
707 FuncInfo *funcInfoList) {
Logan89eb47f2011-01-07 10:45:16 +0800708 switch (mStatus) {
Loganbe79ada2011-01-13 01:33:45 +0800709#define DELEGATE(STATUS) \
Shih-wei Liaod50be322011-07-01 22:53:31 -0700710 case ScriptStatus::STATUS: \
711 m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
712 break;
Logancf3e5212010-12-29 01:44:55 +0800713
Shih-wei Liaod50be322011-07-01 22:53:31 -0700714 DELEGATE(Cached);
Logan35849002011-01-15 07:30:43 +0800715
Shih-wei Liaod50be322011-07-01 22:53:31 -0700716 DELEGATE(Compiled);
Loganbe79ada2011-01-13 01:33:45 +0800717#undef DELEGATE
Logan89eb47f2011-01-07 10:45:16 +0800718
Shih-wei Liaod50be322011-07-01 22:53:31 -0700719 default: {
720 mErrorCode = BCC_INVALID_OPERATION;
721 }
Logan89eb47f2011-01-07 10:45:16 +0800722 }
Logancf3e5212010-12-29 01:44:55 +0800723}
724
Stephen Hines071288a2011-01-27 14:38:26 -0800725
726void Script::getObjectSlotList(size_t objectSlotListSize,
727 uint32_t *objectSlotList) {
728 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700729#define DELEGATE(STATUS) \
730 case ScriptStatus::STATUS: \
731 m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
732 break;
Stephen Hines071288a2011-01-27 14:38:26 -0800733
Shih-wei Liaod50be322011-07-01 22:53:31 -0700734 DELEGATE(Cached);
Stephen Hines071288a2011-01-27 14:38:26 -0800735
Shih-wei Liaod50be322011-07-01 22:53:31 -0700736 DELEGATE(Compiled);
Stephen Hines071288a2011-01-27 14:38:26 -0800737#undef DELEGATE
738
Shih-wei Liaod50be322011-07-01 22:53:31 -0700739 default: {
740 mErrorCode = BCC_INVALID_OPERATION;
741 }
Stephen Hines071288a2011-01-27 14:38:26 -0800742 }
743}
744
745
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800746int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
Logancf3e5212010-12-29 01:44:55 +0800747 mpExtSymbolLookupFn = pFn;
748 mpExtSymbolLookupFnContext = pContext;
749
Logan7d2219f2011-01-06 06:19:25 +0800750 if (mStatus != ScriptStatus::Unknown) {
Logancf3e5212010-12-29 01:44:55 +0800751 mErrorCode = BCC_INVALID_OPERATION;
Steve Block10c14122012-01-08 10:15:06 +0000752 ALOGE("Invalid operation: %s\n", __func__);
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800753 return 1;
Logancf3e5212010-12-29 01:44:55 +0800754 }
Shih-wei Liaoce82d492011-01-20 12:34:03 -0800755 return 0;
Logancf3e5212010-12-29 01:44:55 +0800756}
Shih-wei Liaob65410d2011-06-19 11:11:48 -0700757
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800758bool Script::isCacheable() const {
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800759 if (getBooleanProp("debug.bcc.nocache")) {
760 // Android system environment property: Disables the cache mechanism by
761 // setting "debug.bcc.nocache". So we will not load the cache file any
762 // way.
763 return false;
764 }
765
766 if (mCacheDir.empty() || mCacheName.empty()) {
767 // The application developer has not specified the cachePath, so
768 // we don't know where to open the cache file.
769 return false;
770 }
771
772 return true;
Shih-wei Liaoabc7f512012-01-18 00:34:07 -0800773}
774
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700775size_t Script::getELFSize() const {
776 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700777 case ScriptStatus::Compiled: {
778 return mCompiled->getELFSize();
779 }
Stephen Hines0e567862012-03-11 20:26:40 -0700780
Daniel Malea094881f2011-12-14 17:39:16 -0500781 case ScriptStatus::Cached: {
782 return mCached->getELFSize();
783 }
Stephen Hines0e567862012-03-11 20:26:40 -0700784
Shih-wei Liaod50be322011-07-01 22:53:31 -0700785 default: {
786 return 0;
787 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700788 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700789}
790
791const char *Script::getELF() const {
792 switch (mStatus) {
Shih-wei Liaod50be322011-07-01 22:53:31 -0700793 case ScriptStatus::Compiled: {
794 return mCompiled->getELF();
795 }
Stephen Hines0e567862012-03-11 20:26:40 -0700796
Daniel Malea094881f2011-12-14 17:39:16 -0500797 case ScriptStatus::Cached: {
798 return mCached->getELF();
799 }
Stephen Hines0e567862012-03-11 20:26:40 -0700800
Shih-wei Liaod50be322011-07-01 22:53:31 -0700801 default: {
802 return NULL;
803 }
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700804 }
805}
Logancf3e5212010-12-29 01:44:55 +0800806
807} // namespace bcc