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