12abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include "rsCpuExecutable.h"
22abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include "rsCppUtils.h"
32abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
42abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <fstream>
52abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <set>
62abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <memory>
72abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
82abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifdef RS_COMPATIBILITY_LIB
92abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <stdio.h>
102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <sys/stat.h>
112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <unistd.h>
122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#else
132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include "bcc/Config/Config.h"
142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif
152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <dlfcn.h>
172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ninamespace android {
192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ninamespace renderscript {
202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ninamespace {
222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Check if a path exists and attempt to create it if it doesn't.
242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic bool ensureCacheDirExists(const char *path) {
252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (access(path, R_OK | W_OK | X_OK) == 0) {
262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // Done if we can rwx the directory
272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return true;
282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (mkdir(path, 0700) == 0) {
302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return true;
312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return false;
332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Copy the file named \p srcFile to \p dstFile.
362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Return 0 on success and -1 if anything wasn't copied.
372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic int copyFile(const char *dstFile, const char *srcFile) {
382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::ifstream srcStream(srcFile);
392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!srcStream) {
402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not verify or read source file: %s", srcFile);
412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return -1;
422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::ofstream dstStream(dstFile);
442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!dstStream) {
452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not verify or write destination file: %s", dstFile);
462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return -1;
472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    dstStream << srcStream.rdbuf();
492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!dstStream) {
502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not write destination file: %s", dstFile);
512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return -1;
522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    srcStream.close();
552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    dstStream.close();
562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return 0;
582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic std::string findSharedObjectName(const char *cacheDir,
612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                                        const char *resName) {
622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_SERVER
632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string scriptSOName(cacheDir);
642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#if defined(RS_COMPATIBILITY_LIB) && !defined(__LP64__)
652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t cutPos = scriptSOName.rfind("cache");
662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (cutPos != std::string::npos) {
672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        scriptSOName.erase(cutPos);
682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    } else {
692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    scriptSOName.append("/lib/librs.");
722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#else
732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    scriptSOName.append("/librs.");
742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif // RS_COMPATIBILITY_LIB
752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#else
772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string scriptSOName("lib");
782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif // RS_SERVER
792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    scriptSOName.append(resName);
802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    scriptSOName.append(".so");
812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return scriptSOName;
832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}  // anonymous namespace
862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Niconst char* SharedLibraryUtils::LD_EXE_PATH = "/system/bin/ld.mc";
882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Niconst char* SharedLibraryUtils::RS_CACHE_DIR = "com.android.renderscript.cache";
892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_COMPATIBILITY_LIB
912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
92d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Samsbool SharedLibraryUtils::createSharedLibrary(const char *driverName,
93d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams                                             const char *cacheDir,
94d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams                                             const char *resName) {
952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string sharedLibName = findSharedObjectName(cacheDir, resName);
962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string objFileName = cacheDir;
972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    objFileName.append("/");
982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    objFileName.append(resName);
992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    objFileName.append(".o");
100d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams    // Should be something like "libRSDriver.so".
101d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams    std::string linkDriverName = driverName;
102d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams    // Remove ".so" and replace "lib" with "-l".
103d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams    // This will leave us with "-lRSDriver" instead.
104d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams    linkDriverName.erase(linkDriverName.length() - 3);
105d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams    linkDriverName.replace(0, 3, "-l");
1062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    const char *compiler_rt = SYSLIBPATH"/libcompiler_rt.so";
108c2be413317efcc44e3b282fd38fca3334c11777ePirama Arumuga Nainar    const char *mTriple = "-mtriple=" DEFAULT_TARGET_TRIPLE_STRING;
109c2be413317efcc44e3b282fd38fca3334c11777ePirama Arumuga Nainar    const char *libPath = "--library-path=" SYSLIBPATH;
11021732f493bd56ed83fb27f8823a66910ecbcf870Pirama Arumuga Nainar    const char *vendorLibPath = "--library-path=" SYSLIBPATH_VENDOR;
111c2be413317efcc44e3b282fd38fca3334c11777ePirama Arumuga Nainar
1122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::vector<const char *> args = {
1132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        LD_EXE_PATH,
1142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        "-shared",
1152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        "-nostdlib",
11621732f493bd56ed83fb27f8823a66910ecbcf870Pirama Arumuga Nainar        compiler_rt, mTriple, vendorLibPath, libPath,
117d97617a0a736b4dadcf978bfc1fa0aef0d4d50d3Jason Sams        linkDriverName.c_str(), "-lm", "-lc",
1182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        objFileName.c_str(),
1192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        "-o", sharedLibName.c_str(),
1202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        nullptr
1212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    };
1222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1232fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar    return rsuExecuteCommand(LD_EXE_PATH, args.size()-1, args.data());
1242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
1262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif  // RS_COMPATIBILITY_LIB
1282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Niconst char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc";
1302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nivoid* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir,
1322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                                            const char *resName,
1339844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni                                            const char *nativeLibDir,
1349844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni                                            bool* alreadyLoaded) {
1352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    void *loaded = nullptr;
1362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#if defined(RS_COMPATIBILITY_LIB) && defined(__LP64__)
1382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string scriptSOName = findSharedObjectName(nativeLibDir, resName);
1392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#else
1402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string scriptSOName = findSharedObjectName(cacheDir, resName);
1412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif
1422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // We should check if we can load the library from the standard app
1442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // location for shared libraries first.
1459844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName, alreadyLoaded);
1462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (loaded == nullptr) {
1482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Unable to open shared library (%s): %s",
1492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni              scriptSOName.c_str(), dlerror());
1502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifdef RS_COMPATIBILITY_LIB
1522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // One final attempt to find the library in "/system/lib".
1532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // We do this to allow bundled applications to use the compatibility
1542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // library fallback path. Those applications don't have a private
1552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // library path, so they need to install to the system directly.
1562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // Note that this is really just a testing path.
1572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        std::string scriptSONameSystem("/system/lib/librs.");
1582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        scriptSONameSystem.append(resName);
1592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        scriptSONameSystem.append(".so");
1602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
1612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                              resName);
1622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (loaded == nullptr) {
1632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Unable to open system shared library (%s): %s",
1642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  scriptSONameSystem.c_str(), dlerror());
1652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
1662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif
1672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
1682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return loaded;
1702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
1712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1729844cffc8af28c4829012bc0c48f85d04b671f88Yang NiString8 SharedLibraryUtils::getRandomString(size_t len) {
1739844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    char buf[len + 1];
1749844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    for (size_t i = 0; i < len; i++) {
1759844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        uint32_t r = arc4random() & 0xffff;
1769844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        r %= 62;
1779844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        if (r < 26) {
1789844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni            // lowercase
1799844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni            buf[i] = 'a' + r;
1809844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        } else if (r < 52) {
1819844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni            // uppercase
1829844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni            buf[i] = 'A' + (r - 26);
1839844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        } else {
1849844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni            // Use a number
1859844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni            buf[i] = '0' + (r - 52);
1869844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        }
1879844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    }
1889844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    buf[len] = '\0';
1899844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    return String8(buf);
1909844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni}
1919844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni
1922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nivoid* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir,
1939844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni                                       const char *resName, bool *alreadyLoaded) {
1942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Keep track of which .so libraries have been loaded. Once a library is
1952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // in the set (per-process granularity), we must instead make a copy of
1962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // the original shared object (randomly named .so file) and load that one
1972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // instead. If we don't do this, we end up aliasing global data between
1982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // the various Script instances (which are supposed to be completely
1992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // independent).
2002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    static std::set<std::string> LoadedLibraries;
2012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    void *loaded = nullptr;
2032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Skip everything if we don't even have the original library available.
2052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (access(origName, F_OK) != 0) {
2062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
2072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Common path is that we have not loaded this Script/library before.
2102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
2119844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        if (alreadyLoaded != nullptr) {
2129844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni            *alreadyLoaded = false;
2139844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        }
2142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
2152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (loaded) {
2162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            LoadedLibraries.insert(origName);
2172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
2182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return loaded;
2192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2219844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    if (alreadyLoaded != nullptr) {
2229844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni        *alreadyLoaded = true;
2239844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    }
2249844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni
2252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string newName(cacheDir);
2262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Append RS_CACHE_DIR only if it is not found in cacheDir
2282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // In driver mode, RS_CACHE_DIR is already appended to cacheDir.
2292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (newName.find(RS_CACHE_DIR) == std::string::npos) {
2302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        newName.append("/");
2312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        newName.append(RS_CACHE_DIR);
2322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        newName.append("/");
2332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!ensureCacheDirExists(newName.c_str())) {
2362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not verify or create cache dir: %s", cacheDir);
2372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
2382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Construct an appropriately randomized filename for the copy.
2412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    newName.append("librs.");
2422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    newName.append(resName);
2432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    newName.append("#");
2449844cffc8af28c4829012bc0c48f85d04b671f88Yang Ni    newName.append(getRandomString(6).string());  // 62^6 potential filename variants.
2452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    newName.append(".so");
2462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    int r = copyFile(newName.c_str(), origName);
2482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (r != 0) {
2492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not create copy %s -> %s", origName, newName.c_str());
2502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
2512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
2532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    r = unlink(newName.c_str());
2542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (r != 0) {
2552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not unlink copy %s", newName.c_str());
2562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (loaded) {
2582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        LoadedLibraries.insert(newName.c_str());
2592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return loaded;
2622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
2632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define MAXLINE 500
2652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define MAKE_STR_HELPER(S) #S
2662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define MAKE_STR(S) MAKE_STR_HELPER(S)
2672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_VAR_STR "exportVarCount: "
2682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_FUNC_STR "exportFuncCount: "
2692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_FOREACH_STR "exportForEachCount: "
2702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define OBJECT_SLOT_STR "objectSlotCount: "
2712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define PRAGMA_STR "pragmaCount: "
2722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define THREADABLE_STR "isThreadable: "
273aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar#define CHECKSUM_STR "buildChecksum: "
2742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Copy up to a newline or size chars from str -> s, updating str
2762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Returns s when successful and nullptr when '\0' is finally reached.
2772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic char* strgets(char *s, int size, const char **ppstr) {
2782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
2792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
2802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    int i;
2832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (i = 0; i < (size - 1); i++) {
2842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        s[i] = **ppstr;
2852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        (*ppstr)++;
2862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (s[i] == '\0') {
2872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            return s;
2882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        } else if (s[i] == '\n') {
2892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            s[i+1] = '\0';
2902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            return s;
2912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
2922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // size has been exceeded.
2952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    s[i] = '\0';
2962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return s;
2982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
2992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3002abfcc6d129fe3defddef4540aa95cc445c03a7aYang NiScriptExecutable* ScriptExecutable::createFromSharedObject(
301cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    Context* RSContext, void* sharedObj, uint32_t expectedChecksum) {
3022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    char line[MAXLINE];
3032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t varCount = 0;
3052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t funcCount = 0;
3062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t forEachCount = 0;
3072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t objectSlotCount = 0;
3082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t pragmaCount = 0;
3092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bool isThreadable = true;
3102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    void** fieldAddress = nullptr;
3122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bool* fieldIsObject = nullptr;
313062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    char** fieldName = nullptr;
3142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    InvokeFunc_t* invokeFunctions = nullptr;
3152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    ForEachFunc_t* forEachFunctions = nullptr;
3162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    uint32_t* forEachSignatures = nullptr;
3172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    const char ** pragmaKeys = nullptr;
3182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    const char ** pragmaValues = nullptr;
319cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    uint32_t checksum = 0;
3202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3210e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    const char *rsInfo = (const char *) dlsym(sharedObj, kRsInfo);
322a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    int numEntries = 0;
3230e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    const int *rsGlobalEntries = (const int *) dlsym(sharedObj, kRsGlobalEntries);
3240e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    const char **rsGlobalNames = (const char **) dlsym(sharedObj, kRsGlobalNames);
3250e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    const void **rsGlobalAddresses = (const void **) dlsym(sharedObj, kRsGlobalAddresses);
3260e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    const size_t *rsGlobalSizes = (const size_t *) dlsym(sharedObj, kRsGlobalSizes);
3270e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    const uint32_t *rsGlobalProperties = (const uint32_t *) dlsym(sharedObj, kRsGlobalProperties);
3282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
3302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
3312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
3332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export var count!: %s", line);
3342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
3352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    fieldAddress = new void*[varCount];
3382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (fieldAddress == nullptr) {
3392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
3402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    fieldIsObject = new bool[varCount];
3432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (fieldIsObject == nullptr) {
3442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
3452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
347062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    fieldName = new char*[varCount];
348062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    if (fieldName == nullptr) {
349062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        goto error;
350062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
351062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
3522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < varCount; ++i) {
3532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
3542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
3552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *c = strrchr(line, '\n');
3572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (c) {
3582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            *c = '\0';
3592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        void* addr = dlsym(sharedObj, line);
3612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (addr == nullptr) {
3622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Failed to find variable address for %s: %s",
3632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  line, dlerror());
3642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // Not a critical error if we don't find a global variable.
3652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        fieldAddress[i] = addr;
3672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        fieldIsObject[i] = false;
368062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        fieldName[i] = new char[strlen(line)+1];
369062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        strcpy(fieldName[i], line);
3702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
3732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
3742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
3762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export func count!: %s", line);
3772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
3782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    invokeFunctions = new InvokeFunc_t[funcCount];
3812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (invokeFunctions == nullptr) {
3822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
3832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < funcCount; ++i) {
3862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
3872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
3882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *c = strrchr(line, '\n');
3902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (c) {
3912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            *c = '\0';
3922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        invokeFunctions[i] = (InvokeFunc_t) dlsym(sharedObj, line);
3952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (invokeFunctions[i] == nullptr) {
3962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Failed to get function address for %s(): %s",
3972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  line, dlerror());
3982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
3992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
4062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export forEach count!: %s", line);
4072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    forEachFunctions = new ForEachFunc_t[forEachCount];
4112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (forEachFunctions == nullptr) {
4122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    forEachSignatures = new uint32_t[forEachCount];
4162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (forEachSignatures == nullptr) {
4172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < forEachCount; ++i) {
4212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        unsigned int tmpSig = 0;
4222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char tmpName[MAXLINE];
4232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
4282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                   &tmpSig, tmpName) != 2) {
4292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni          ALOGE("Invalid export forEach!: %s", line);
4302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni          goto error;
4312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // Lookup the expanded ForEach kernel.
4342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
4352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachSignatures[i] = tmpSig;
4362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachFunctions[i] =
4372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            (ForEachFunc_t) dlsym(sharedObj, tmpName);
438062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (i != 0 && forEachFunctions[i] == nullptr &&
439062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            strcmp(tmpName, "root.expand")) {
4402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // Ignore missing root.expand functions.
4412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // root() is always specified at location 0.
4422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Failed to find forEach function address for %s: %s",
4432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  tmpName, dlerror());
4442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
4522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid object slot count!: %s", line);
4532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < objectSlotCount; ++i) {
4572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        uint32_t varNum = 0;
4582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (sscanf(line, "%u", &varNum) != 1) {
4622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Invalid object slot!: %s", line);
4632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (varNum < varCount) {
4672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            fieldIsObject[varNum] = true;
4682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_COMPATIBILITY_LIB
4722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Do not attempt to read pragmas or isThreadable flag in compat lib path.
4732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Neither is applicable for compat lib
4742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, PRAGMA_STR "%zu", &pragmaCount) != 1) {
4802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid pragma count!: %s", line);
4812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    pragmaKeys = new const char*[pragmaCount];
4852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (pragmaKeys == nullptr) {
4862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    pragmaValues = new const char*[pragmaCount];
4902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (pragmaValues == nullptr) {
4912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bzero(pragmaKeys, sizeof(char*) * pragmaCount);
4952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bzero(pragmaValues, sizeof(char*) * pragmaCount);
4962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < pragmaCount; ++i) {
4982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Unable to read pragma at index %zu!", i);
5002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
5012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
5022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char key[MAXLINE];
5032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char value[MAXLINE] = ""; // initialize in case value is empty
5042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // pragmas can just have a key and no value.  Only check to make sure
5062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // that the key is not empty
5072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (sscanf(line, "%" MAKE_STR(MAXLINE) "s - %" MAKE_STR(MAXLINE) "s",
5082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                   key, value) == 0 ||
5092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            strlen(key) == 0)
5102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        {
5112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Invalid pragma value!: %s", line);
5122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
5142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
5152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *pKey = new char[strlen(key)+1];
5172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        strcpy(pKey, key);
5182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        pragmaKeys[i] = pKey;
5192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *pValue = new char[strlen(value)+1];
5212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        strcpy(pValue, value);
5222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        pragmaValues[i] = pValue;
5232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        //ALOGE("Pragma %zu: Key: '%s' Value: '%s'", i, pKey, pValue);
5242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
5272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
5282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    char tmpFlag[4];
5312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, THREADABLE_STR "%4s", tmpFlag) != 1) {
5322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid threadable flag!: %s", line);
5332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
5342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strcmp(tmpFlag, "yes") == 0) {
5362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        isThreadable = true;
5372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    } else if (strcmp(tmpFlag, "no") == 0) {
5382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        isThreadable = false;
5392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    } else {
5402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid threadable flag!: %s", tmpFlag);
5412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
5422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
544aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    if (strgets(line, MAXLINE, &rsInfo) != nullptr) {
545cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        if (sscanf(line, CHECKSUM_STR "%08x", &checksum) != 1) {
546aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            ALOGE("Invalid checksum flag!: %s", line);
547aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            goto error;
548aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        }
549062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    } else {
550062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        ALOGE("Missing checksum in shared obj file");
551aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        goto error;
552aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    }
553aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
554cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    if (expectedChecksum != 0 && checksum != expectedChecksum) {
555cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        ALOGE("Found invalid checksum.  Expected %08x, got %08x\n",
556cb17015fed6b11a5028f31cc804a3847e379945dYang Ni              expectedChecksum, checksum);
557cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        goto error;
558cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    }
559cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
5602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif  // RS_COMPATIBILITY_LIB
5612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
562a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    // Read in information about mutable global variables provided by bcc's
563a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    // RSGlobalInfoPass
564a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    if (rsGlobalEntries) {
565a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines        numEntries = *rsGlobalEntries;
566a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines        if (numEntries > 0) {
567a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines            rsAssert(rsGlobalNames);
568a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines            rsAssert(rsGlobalAddresses);
569a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines            rsAssert(rsGlobalSizes);
5700e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines            rsAssert(rsGlobalProperties);
571a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines        }
572a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    } else {
573a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines        ALOGD("Missing .rs.global_entries from shared object");
574a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    }
575a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines
5762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return new ScriptExecutable(
577062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        RSContext, fieldAddress, fieldIsObject, fieldName, varCount,
5782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        invokeFunctions, funcCount,
5792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachFunctions, forEachSignatures, forEachCount,
5802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        pragmaKeys, pragmaValues, pragmaCount,
5810e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines        rsGlobalNames, rsGlobalAddresses, rsGlobalSizes, rsGlobalProperties,
5820e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines        numEntries, isThreadable, checksum);
5832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nierror:
5852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_COMPATIBILITY_LIB
587aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
5882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t idx = 0; idx < pragmaCount; ++idx) {
5892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        delete [] pragmaKeys[idx];
5902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        delete [] pragmaValues[idx];
5912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] pragmaValues;
5942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] pragmaKeys;
5952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif  // RS_COMPATIBILITY_LIB
5962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] forEachSignatures;
5982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] forEachFunctions;
599062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
6002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] invokeFunctions;
601062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
602062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (size_t i = 0; i < varCount; i++) {
603062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        delete[] fieldName[i];
604062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
605062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    delete[] fieldName;
6062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] fieldIsObject;
6072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] fieldAddress;
6082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return nullptr;
6102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
6112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
612062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nivoid* ScriptExecutable::getFieldAddress(const char* name) const {
613062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    // TODO: improve this by using a hash map.
614062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (size_t i = 0; i < mExportedVarCount; i++) {
615062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (strcmp(name, mFieldName[i]) == 0) {
616062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return mFieldAddress[i];
617062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
618062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
619062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    return nullptr;
620062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni}
621062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
622a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hinesbool ScriptExecutable::dumpGlobalInfo() const {
623a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    ALOGE("Globals: %p %p %p", mGlobalAddresses, mGlobalSizes, mGlobalNames);
6240e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    ALOGE("P   - Pointer");
6250e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    ALOGE(" C  - Constant");
6260e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines    ALOGE("  S - Static");
627a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    for (int i = 0; i < mGlobalEntries; i++) {
628a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines        ALOGE("Global[%d]: %p %zu %s", i, mGlobalAddresses[i], mGlobalSizes[i],
629a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines              mGlobalNames[i]);
6300e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines        uint32_t properties = mGlobalProperties[i];
6310e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines        ALOGE("%c%c%c Type: %u",
6320e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines              isGlobalPointer(properties)  ? 'P' : ' ',
6330e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines              isGlobalConstant(properties) ? 'C' : ' ',
6340e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines              isGlobalStatic(properties)   ? 'S' : ' ',
6350e5d9f637a9ed4207582edb51e200912d8bf54cbStephen Hines              getGlobalRsType(properties));
636a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    }
637a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines    return true;
638a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines}
639a874c96bef8428131b83345dd92f37d8ce246d4eStephen Hines
6402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}  // namespace renderscript
6412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}  // namespace android
642