1 #include "rsCpuExecutable.h"
2 #include "rsCppUtils.h"
3
4 #include <fstream>
5 #include <set>
6 #include <memory>
7
8 #ifdef RS_COMPATIBILITY_LIB
9 #include <stdio.h>
10 #include <sys/stat.h>
11 #include <unistd.h>
12 #else
13 #include "bcc/Config/Config.h"
14 #endif
15
16 #include <dlfcn.h>
17
18 namespace android {
19 namespace renderscript {
20
21 namespace {
22
23 // Check if a path exists and attempt to create it if it doesn't.
ensureCacheDirExists(const char * path)24 static bool ensureCacheDirExists(const char *path) {
25 if (access(path, R_OK | W_OK | X_OK) == 0) {
26 // Done if we can rwx the directory
27 return true;
28 }
29 if (mkdir(path, 0700) == 0) {
30 return true;
31 }
32 return false;
33 }
34
35 // Copy the file named \p srcFile to \p dstFile.
36 // Return 0 on success and -1 if anything wasn't copied.
copyFile(const char * dstFile,const char * srcFile)37 static int copyFile(const char *dstFile, const char *srcFile) {
38 std::ifstream srcStream(srcFile);
39 if (!srcStream) {
40 ALOGE("Could not verify or read source file: %s", srcFile);
41 return -1;
42 }
43 std::ofstream dstStream(dstFile);
44 if (!dstStream) {
45 ALOGE("Could not verify or write destination file: %s", dstFile);
46 return -1;
47 }
48 dstStream << srcStream.rdbuf();
49 if (!dstStream) {
50 ALOGE("Could not write destination file: %s", dstFile);
51 return -1;
52 }
53
54 srcStream.close();
55 dstStream.close();
56
57 return 0;
58 }
59
findSharedObjectName(const char * cacheDir,const char * resName)60 static std::string findSharedObjectName(const char *cacheDir,
61 const char *resName) {
62 #ifndef RS_SERVER
63 std::string scriptSOName(cacheDir);
64 #if defined(RS_COMPATIBILITY_LIB) && !defined(__LP64__)
65 size_t cutPos = scriptSOName.rfind("cache");
66 if (cutPos != std::string::npos) {
67 scriptSOName.erase(cutPos);
68 } else {
69 ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
70 }
71 scriptSOName.append("/lib/librs.");
72 #else
73 scriptSOName.append("/librs.");
74 #endif // RS_COMPATIBILITY_LIB
75
76 #else
77 std::string scriptSOName("lib");
78 #endif // RS_SERVER
79 scriptSOName.append(resName);
80 scriptSOName.append(".so");
81
82 return scriptSOName;
83 }
84
85 } // anonymous namespace
86
87 const char* SharedLibraryUtils::LD_EXE_PATH = "/system/bin/ld.mc";
88 const char* SharedLibraryUtils::RS_CACHE_DIR = "com.android.renderscript.cache";
89
90 #ifndef RS_COMPATIBILITY_LIB
91
createSharedLibrary(const char * driverName,const char * cacheDir,const char * resName)92 bool SharedLibraryUtils::createSharedLibrary(const char *driverName,
93 const char *cacheDir,
94 const char *resName) {
95 std::string sharedLibName = findSharedObjectName(cacheDir, resName);
96 std::string objFileName = cacheDir;
97 objFileName.append("/");
98 objFileName.append(resName);
99 objFileName.append(".o");
100 // Should be something like "libRSDriver.so".
101 std::string linkDriverName = driverName;
102 // Remove ".so" and replace "lib" with "-l".
103 // This will leave us with "-lRSDriver" instead.
104 linkDriverName.erase(linkDriverName.length() - 3);
105 linkDriverName.replace(0, 3, "-l");
106
107 const char *compiler_rt = SYSLIBPATH"/libcompiler_rt.so";
108 const char *mTriple = "-mtriple=" DEFAULT_TARGET_TRIPLE_STRING;
109 const char *libPath = "--library-path=" SYSLIBPATH;
110 const char *vendorLibPath = "--library-path=" SYSLIBPATH_VENDOR;
111
112 std::vector<const char *> args = {
113 LD_EXE_PATH,
114 "-shared",
115 "-nostdlib",
116 compiler_rt, mTriple, vendorLibPath, libPath,
117 linkDriverName.c_str(), "-lm", "-lc",
118 objFileName.c_str(),
119 "-o", sharedLibName.c_str(),
120 nullptr
121 };
122
123 return rsuExecuteCommand(LD_EXE_PATH, args.size()-1, args.data());
124
125 }
126
127 #endif // RS_COMPATIBILITY_LIB
128
129 const char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc";
130
loadSharedLibrary(const char * cacheDir,const char * resName,const char * nativeLibDir,bool * alreadyLoaded)131 void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir,
132 const char *resName,
133 const char *nativeLibDir,
134 bool* alreadyLoaded) {
135 void *loaded = nullptr;
136
137 #if defined(RS_COMPATIBILITY_LIB) && defined(__LP64__)
138 std::string scriptSOName = findSharedObjectName(nativeLibDir, resName);
139 #else
140 std::string scriptSOName = findSharedObjectName(cacheDir, resName);
141 #endif
142
143 // We should check if we can load the library from the standard app
144 // location for shared libraries first.
145 loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName, alreadyLoaded);
146
147 if (loaded == nullptr) {
148 ALOGE("Unable to open shared library (%s): %s",
149 scriptSOName.c_str(), dlerror());
150
151 #ifdef RS_COMPATIBILITY_LIB
152 // One final attempt to find the library in "/system/lib".
153 // We do this to allow bundled applications to use the compatibility
154 // library fallback path. Those applications don't have a private
155 // library path, so they need to install to the system directly.
156 // Note that this is really just a testing path.
157 std::string scriptSONameSystem("/system/lib/librs.");
158 scriptSONameSystem.append(resName);
159 scriptSONameSystem.append(".so");
160 loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
161 resName);
162 if (loaded == nullptr) {
163 ALOGE("Unable to open system shared library (%s): %s",
164 scriptSONameSystem.c_str(), dlerror());
165 }
166 #endif
167 }
168
169 return loaded;
170 }
171
getRandomString(size_t len)172 String8 SharedLibraryUtils::getRandomString(size_t len) {
173 char buf[len + 1];
174 for (size_t i = 0; i < len; i++) {
175 uint32_t r = arc4random() & 0xffff;
176 r %= 62;
177 if (r < 26) {
178 // lowercase
179 buf[i] = 'a' + r;
180 } else if (r < 52) {
181 // uppercase
182 buf[i] = 'A' + (r - 26);
183 } else {
184 // Use a number
185 buf[i] = '0' + (r - 52);
186 }
187 }
188 buf[len] = '\0';
189 return String8(buf);
190 }
191
loadSOHelper(const char * origName,const char * cacheDir,const char * resName,bool * alreadyLoaded)192 void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir,
193 const char *resName, bool *alreadyLoaded) {
194 // Keep track of which .so libraries have been loaded. Once a library is
195 // in the set (per-process granularity), we must instead make a copy of
196 // the original shared object (randomly named .so file) and load that one
197 // instead. If we don't do this, we end up aliasing global data between
198 // the various Script instances (which are supposed to be completely
199 // independent).
200 static std::set<std::string> LoadedLibraries;
201
202 void *loaded = nullptr;
203
204 // Skip everything if we don't even have the original library available.
205 if (access(origName, F_OK) != 0) {
206 return nullptr;
207 }
208
209 // Common path is that we have not loaded this Script/library before.
210 if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
211 if (alreadyLoaded != nullptr) {
212 *alreadyLoaded = false;
213 }
214 loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
215 if (loaded) {
216 LoadedLibraries.insert(origName);
217 }
218 return loaded;
219 }
220
221 if (alreadyLoaded != nullptr) {
222 *alreadyLoaded = true;
223 }
224
225 std::string newName(cacheDir);
226
227 // Append RS_CACHE_DIR only if it is not found in cacheDir
228 // In driver mode, RS_CACHE_DIR is already appended to cacheDir.
229 if (newName.find(RS_CACHE_DIR) == std::string::npos) {
230 newName.append("/");
231 newName.append(RS_CACHE_DIR);
232 newName.append("/");
233 }
234
235 if (!ensureCacheDirExists(newName.c_str())) {
236 ALOGE("Could not verify or create cache dir: %s", cacheDir);
237 return nullptr;
238 }
239
240 // Construct an appropriately randomized filename for the copy.
241 newName.append("librs.");
242 newName.append(resName);
243 newName.append("#");
244 newName.append(getRandomString(6).string()); // 62^6 potential filename variants.
245 newName.append(".so");
246
247 int r = copyFile(newName.c_str(), origName);
248 if (r != 0) {
249 ALOGE("Could not create copy %s -> %s", origName, newName.c_str());
250 return nullptr;
251 }
252 loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
253 r = unlink(newName.c_str());
254 if (r != 0) {
255 ALOGE("Could not unlink copy %s", newName.c_str());
256 }
257 if (loaded) {
258 LoadedLibraries.insert(newName.c_str());
259 }
260
261 return loaded;
262 }
263
264 // MAXLINESTR must be compatible with operator '#' in C macro.
265 #define MAXLINESTR 499
266 // MAXLINE must be (MAXLINESTR + 1), representing the size of a C string
267 // containing MAXLINESTR non-null chars plus a null.
268 #define MAXLINE (MAXLINESTR + 1)
269 #define MAKE_STR_HELPER(S) #S
270 #define MAKE_STR(S) MAKE_STR_HELPER(S)
271 #define EXPORT_VAR_STR "exportVarCount: "
272 #define EXPORT_FUNC_STR "exportFuncCount: "
273 #define EXPORT_FOREACH_STR "exportForEachCount: "
274 #define EXPORT_REDUCE_STR "exportReduceCount: "
275 #define OBJECT_SLOT_STR "objectSlotCount: "
276 #define PRAGMA_STR "pragmaCount: "
277 #define THREADABLE_STR "isThreadable: "
278 #define CHECKSUM_STR "buildChecksum: "
279
280 // Copy up to a newline or size chars from str -> s, updating str
281 // Returns s when successful and nullptr when '\0' is finally reached.
strgets(char * s,int size,const char ** ppstr)282 static char* strgets(char *s, int size, const char **ppstr) {
283 if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
284 return nullptr;
285 }
286
287 int i;
288 for (i = 0; i < (size - 1); i++) {
289 s[i] = **ppstr;
290 (*ppstr)++;
291 if (s[i] == '\0') {
292 return s;
293 } else if (s[i] == '\n') {
294 s[i+1] = '\0';
295 return s;
296 }
297 }
298
299 // size has been exceeded.
300 s[i] = '\0';
301
302 return s;
303 }
304
createFromSharedObject(void * sharedObj,uint32_t expectedChecksum)305 ScriptExecutable* ScriptExecutable::createFromSharedObject(
306 void* sharedObj, uint32_t expectedChecksum) {
307 char line[MAXLINE];
308
309 size_t varCount = 0;
310 size_t funcCount = 0;
311 size_t forEachCount = 0;
312 size_t reduceCount = 0;
313 size_t objectSlotCount = 0;
314 size_t pragmaCount = 0;
315 bool isThreadable = true;
316
317 void** fieldAddress = nullptr;
318 bool* fieldIsObject = nullptr;
319 char** fieldName = nullptr;
320 InvokeFunc_t* invokeFunctions = nullptr;
321 ForEachFunc_t* forEachFunctions = nullptr;
322 uint32_t* forEachSignatures = nullptr;
323 ReduceDescription* reduceDescriptions = nullptr;
324 const char ** pragmaKeys = nullptr;
325 const char ** pragmaValues = nullptr;
326 uint32_t checksum = 0;
327
328 const char *rsInfo = (const char *) dlsym(sharedObj, kRsInfo);
329 int numEntries = 0;
330 const int *rsGlobalEntries = (const int *) dlsym(sharedObj, kRsGlobalEntries);
331 const char **rsGlobalNames = (const char **) dlsym(sharedObj, kRsGlobalNames);
332 const void **rsGlobalAddresses = (const void **) dlsym(sharedObj, kRsGlobalAddresses);
333 const size_t *rsGlobalSizes = (const size_t *) dlsym(sharedObj, kRsGlobalSizes);
334 const uint32_t *rsGlobalProperties = (const uint32_t *) dlsym(sharedObj, kRsGlobalProperties);
335
336 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
337 return nullptr;
338 }
339 if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
340 ALOGE("Invalid export var count!: %s", line);
341 return nullptr;
342 }
343
344 fieldAddress = new void*[varCount];
345 if (fieldAddress == nullptr) {
346 return nullptr;
347 }
348
349 fieldIsObject = new bool[varCount];
350 if (fieldIsObject == nullptr) {
351 goto error;
352 }
353
354 fieldName = new char*[varCount];
355 if (fieldName == nullptr) {
356 goto error;
357 }
358
359 for (size_t i = 0; i < varCount; ++i) {
360 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
361 goto error;
362 }
363 char *c = strrchr(line, '\n');
364 if (c) {
365 *c = '\0';
366 }
367 void* addr = dlsym(sharedObj, line);
368 if (addr == nullptr) {
369 ALOGE("Failed to find variable address for %s: %s",
370 line, dlerror());
371 // Not a critical error if we don't find a global variable.
372 }
373 fieldAddress[i] = addr;
374 fieldIsObject[i] = false;
375 fieldName[i] = new char[strlen(line)+1];
376 strcpy(fieldName[i], line);
377 }
378
379 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
380 goto error;
381 }
382 if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
383 ALOGE("Invalid export func count!: %s", line);
384 goto error;
385 }
386
387 invokeFunctions = new InvokeFunc_t[funcCount];
388 if (invokeFunctions == nullptr) {
389 goto error;
390 }
391
392 for (size_t i = 0; i < funcCount; ++i) {
393 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
394 goto error;
395 }
396 char *c = strrchr(line, '\n');
397 if (c) {
398 *c = '\0';
399 }
400
401 invokeFunctions[i] = (InvokeFunc_t) dlsym(sharedObj, line);
402 if (invokeFunctions[i] == nullptr) {
403 ALOGE("Failed to get function address for %s(): %s",
404 line, dlerror());
405 goto error;
406 }
407 }
408
409 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
410 goto error;
411 }
412 if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
413 ALOGE("Invalid export forEach count!: %s", line);
414 goto error;
415 }
416
417 forEachFunctions = new ForEachFunc_t[forEachCount];
418 if (forEachFunctions == nullptr) {
419 goto error;
420 }
421
422 forEachSignatures = new uint32_t[forEachCount];
423 if (forEachSignatures == nullptr) {
424 goto error;
425 }
426
427 for (size_t i = 0; i < forEachCount; ++i) {
428 unsigned int tmpSig = 0;
429 char tmpName[MAXLINE];
430
431 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
432 goto error;
433 }
434 if (sscanf(line, "%u - %" MAKE_STR(MAXLINESTR) "s",
435 &tmpSig, tmpName) != 2) {
436 ALOGE("Invalid export forEach!: %s", line);
437 goto error;
438 }
439
440 // Lookup the expanded ForEach kernel.
441 strncat(tmpName, ".expand", MAXLINESTR-strlen(tmpName));
442 forEachSignatures[i] = tmpSig;
443 forEachFunctions[i] =
444 (ForEachFunc_t) dlsym(sharedObj, tmpName);
445 if (i != 0 && forEachFunctions[i] == nullptr &&
446 strcmp(tmpName, "root.expand")) {
447 // Ignore missing root.expand functions.
448 // root() is always specified at location 0.
449 ALOGE("Failed to find forEach function address for %s(): %s",
450 tmpName, dlerror());
451 goto error;
452 }
453 }
454
455 // Read general reduce kernels
456 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
457 goto error;
458 }
459 if (sscanf(line, EXPORT_REDUCE_STR "%zu", &reduceCount) != 1) {
460 ALOGE("Invalid export reduce new count!: %s", line);
461 goto error;
462 }
463
464 reduceDescriptions = new ReduceDescription[reduceCount];
465 if (reduceDescriptions == nullptr) {
466 goto error;
467 }
468
469 for (size_t i = 0; i < reduceCount; ++i) {
470 static const char kNoName[] = ".";
471
472 unsigned int tmpSig = 0;
473 size_t tmpSize = 0;
474 char tmpNameReduce[MAXLINE];
475 char tmpNameInitializer[MAXLINE];
476 char tmpNameAccumulator[MAXLINE];
477 char tmpNameCombiner[MAXLINE];
478 char tmpNameOutConverter[MAXLINE];
479 char tmpNameHalter[MAXLINE];
480
481 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
482 goto error;
483 }
484 #define DELIMNAME " - %" MAKE_STR(MAXLINESTR) "s"
485 if (sscanf(line, "%u - %zu" DELIMNAME DELIMNAME DELIMNAME DELIMNAME DELIMNAME DELIMNAME,
486 &tmpSig, &tmpSize, tmpNameReduce, tmpNameInitializer, tmpNameAccumulator,
487 tmpNameCombiner, tmpNameOutConverter, tmpNameHalter) != 8) {
488 ALOGE("Invalid export reduce new!: %s", line);
489 goto error;
490 }
491 #undef DELIMNAME
492
493 // For now, we expect
494 // - Reduce and Accumulator names
495 // - optional Initializer, Combiner, and OutConverter name
496 // - no Halter name
497 if (!strcmp(tmpNameReduce, kNoName) ||
498 !strcmp(tmpNameAccumulator, kNoName)) {
499 ALOGE("Expected reduce and accumulator names!: %s", line);
500 goto error;
501 }
502 if (strcmp(tmpNameHalter, kNoName)) {
503 ALOGE("Did not expect halter name!: %s", line);
504 goto error;
505 }
506
507 // The current implementation does not use the signature
508 // or reduce name.
509
510 reduceDescriptions[i].accumSize = tmpSize;
511
512 // Process the (optional) initializer.
513 if (strcmp(tmpNameInitializer, kNoName)) {
514 // Lookup the original user-written initializer.
515 if (!(reduceDescriptions[i].initFunc =
516 (ReduceInitializerFunc_t) dlsym(sharedObj, tmpNameInitializer))) {
517 ALOGE("Failed to find initializer function address for %s(): %s",
518 tmpNameInitializer, dlerror());
519 goto error;
520 }
521 } else {
522 reduceDescriptions[i].initFunc = nullptr;
523 }
524
525 // Lookup the expanded accumulator.
526 strncat(tmpNameAccumulator, ".expand", MAXLINESTR-strlen(tmpNameAccumulator));
527 if (!(reduceDescriptions[i].accumFunc =
528 (ReduceAccumulatorFunc_t) dlsym(sharedObj, tmpNameAccumulator))) {
529 ALOGE("Failed to find accumulator function address for %s(): %s",
530 tmpNameAccumulator, dlerror());
531 goto error;
532 }
533
534 // Process the (optional) combiner.
535 if (strcmp(tmpNameCombiner, kNoName)) {
536 // Lookup the original user-written combiner.
537 if (!(reduceDescriptions[i].combFunc =
538 (ReduceCombinerFunc_t) dlsym(sharedObj, tmpNameCombiner))) {
539 ALOGE("Failed to find combiner function address for %s(): %s",
540 tmpNameCombiner, dlerror());
541 goto error;
542 }
543 } else {
544 reduceDescriptions[i].combFunc = nullptr;
545 }
546
547 // Process the (optional) outconverter.
548 if (strcmp(tmpNameOutConverter, kNoName)) {
549 // Lookup the original user-written outconverter.
550 if (!(reduceDescriptions[i].outFunc =
551 (ReduceOutConverterFunc_t) dlsym(sharedObj, tmpNameOutConverter))) {
552 ALOGE("Failed to find outconverter function address for %s(): %s",
553 tmpNameOutConverter, dlerror());
554 goto error;
555 }
556 } else {
557 reduceDescriptions[i].outFunc = nullptr;
558 }
559 }
560
561 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
562 goto error;
563 }
564 if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
565 ALOGE("Invalid object slot count!: %s", line);
566 goto error;
567 }
568
569 for (size_t i = 0; i < objectSlotCount; ++i) {
570 uint32_t varNum = 0;
571 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
572 goto error;
573 }
574 if (sscanf(line, "%u", &varNum) != 1) {
575 ALOGE("Invalid object slot!: %s", line);
576 goto error;
577 }
578
579 if (varNum < varCount) {
580 fieldIsObject[varNum] = true;
581 }
582 }
583
584 #ifndef RS_COMPATIBILITY_LIB
585 // Do not attempt to read pragmas or isThreadable flag in compat lib path.
586 // Neither is applicable for compat lib
587
588 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
589 goto error;
590 }
591
592 if (sscanf(line, PRAGMA_STR "%zu", &pragmaCount) != 1) {
593 ALOGE("Invalid pragma count!: %s", line);
594 goto error;
595 }
596
597 pragmaKeys = new const char*[pragmaCount];
598 if (pragmaKeys == nullptr) {
599 goto error;
600 }
601
602 pragmaValues = new const char*[pragmaCount];
603 if (pragmaValues == nullptr) {
604 goto error;
605 }
606
607 bzero(pragmaKeys, sizeof(char*) * pragmaCount);
608 bzero(pragmaValues, sizeof(char*) * pragmaCount);
609
610 for (size_t i = 0; i < pragmaCount; ++i) {
611 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
612 ALOGE("Unable to read pragma at index %zu!", i);
613 goto error;
614 }
615 char key[MAXLINE];
616 char value[MAXLINE] = ""; // initialize in case value is empty
617
618 // pragmas can just have a key and no value. Only check to make sure
619 // that the key is not empty
620 if (sscanf(line, "%" MAKE_STR(MAXLINESTR) "s - %" MAKE_STR(MAXLINESTR) "s",
621 key, value) == 0 ||
622 strlen(key) == 0)
623 {
624 ALOGE("Invalid pragma value!: %s", line);
625
626 goto error;
627 }
628
629 char *pKey = new char[strlen(key)+1];
630 strcpy(pKey, key);
631 pragmaKeys[i] = pKey;
632
633 char *pValue = new char[strlen(value)+1];
634 strcpy(pValue, value);
635 pragmaValues[i] = pValue;
636 //ALOGE("Pragma %zu: Key: '%s' Value: '%s'", i, pKey, pValue);
637 }
638
639 if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
640 goto error;
641 }
642
643 char tmpFlag[4];
644 if (sscanf(line, THREADABLE_STR "%3s", tmpFlag) != 1) {
645 ALOGE("Invalid threadable flag!: %s", line);
646 goto error;
647 }
648 if (strcmp(tmpFlag, "yes") == 0) {
649 isThreadable = true;
650 } else if (strcmp(tmpFlag, "no") == 0) {
651 isThreadable = false;
652 } else {
653 ALOGE("Invalid threadable flag!: %s", tmpFlag);
654 goto error;
655 }
656
657 if (strgets(line, MAXLINE, &rsInfo) != nullptr) {
658 if (sscanf(line, CHECKSUM_STR "%08x", &checksum) != 1) {
659 ALOGE("Invalid checksum flag!: %s", line);
660 goto error;
661 }
662 } else {
663 ALOGE("Missing checksum in shared obj file");
664 goto error;
665 }
666
667 if (expectedChecksum != 0 && checksum != expectedChecksum) {
668 ALOGE("Found invalid checksum. Expected %08x, got %08x\n",
669 expectedChecksum, checksum);
670 goto error;
671 }
672
673 #endif // RS_COMPATIBILITY_LIB
674
675 // Read in information about mutable global variables provided by bcc's
676 // RSGlobalInfoPass
677 if (rsGlobalEntries) {
678 numEntries = *rsGlobalEntries;
679 if (numEntries > 0) {
680 rsAssert(rsGlobalNames);
681 rsAssert(rsGlobalAddresses);
682 rsAssert(rsGlobalSizes);
683 rsAssert(rsGlobalProperties);
684 }
685 }
686
687 return new ScriptExecutable(
688 fieldAddress, fieldIsObject, fieldName, varCount,
689 invokeFunctions, funcCount,
690 forEachFunctions, forEachSignatures, forEachCount,
691 reduceDescriptions, reduceCount,
692 pragmaKeys, pragmaValues, pragmaCount,
693 rsGlobalNames, rsGlobalAddresses, rsGlobalSizes, rsGlobalProperties,
694 numEntries, isThreadable, checksum);
695
696 error:
697
698 #ifndef RS_COMPATIBILITY_LIB
699
700 for (size_t idx = 0; idx < pragmaCount; ++idx) {
701 delete [] pragmaKeys[idx];
702 delete [] pragmaValues[idx];
703 }
704
705 delete[] pragmaValues;
706 delete[] pragmaKeys;
707 #endif // RS_COMPATIBILITY_LIB
708
709 delete[] forEachSignatures;
710 delete[] forEachFunctions;
711
712 delete[] invokeFunctions;
713
714 for (size_t i = 0; i < varCount; i++) {
715 delete[] fieldName[i];
716 }
717 delete[] fieldName;
718 delete[] fieldIsObject;
719 delete[] fieldAddress;
720
721 return nullptr;
722 }
723
getFieldAddress(const char * name) const724 void* ScriptExecutable::getFieldAddress(const char* name) const {
725 // TODO: improve this by using a hash map.
726 for (size_t i = 0; i < mExportedVarCount; i++) {
727 if (strcmp(name, mFieldName[i]) == 0) {
728 return mFieldAddress[i];
729 }
730 }
731 return nullptr;
732 }
733
dumpGlobalInfo() const734 bool ScriptExecutable::dumpGlobalInfo() const {
735 ALOGE("Globals: %p %p %p", mGlobalAddresses, mGlobalSizes, mGlobalNames);
736 ALOGE("P - Pointer");
737 ALOGE(" C - Constant");
738 ALOGE(" S - Static");
739 for (int i = 0; i < mGlobalEntries; i++) {
740 ALOGE("Global[%d]: %p %zu %s", i, mGlobalAddresses[i], mGlobalSizes[i],
741 mGlobalNames[i]);
742 uint32_t properties = mGlobalProperties[i];
743 ALOGE("%c%c%c Type: %u",
744 isGlobalPointer(properties) ? 'P' : ' ',
745 isGlobalConstant(properties) ? 'C' : ' ',
746 isGlobalStatic(properties) ? 'S' : ' ',
747 getGlobalRsType(properties));
748 }
749 return true;
750 }
751
752 } // namespace renderscript
753 } // namespace android
754