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