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
924c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hinesbool SharedLibraryUtils::createSharedLibrary(const char *driverName,
934c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines                                             const char *cacheDir,
944c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines                                             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");
1004c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    // Should be something like "libRSDriver.so".
1014c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    std::string linkDriverName = driverName;
1024c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    // Remove ".so" and replace "lib" with "-l".
1034c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    // This will leave us with "-lRSDriver" instead.
1044c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    linkDriverName.erase(linkDriverName.length() - 3);
1054c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    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;
110682672e36b05349bc4d9dee74e9fab73ce804183Pirama 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",
116682672e36b05349bc4d9dee74e9fab73ce804183Pirama Arumuga Nainar        compiler_rt, mTriple, vendorLibPath, libPath,
1174c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines        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,
1331efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni                                            const char *nativeLibDir,
1341efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang 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.
1451efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang 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
1721efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang NiString8 SharedLibraryUtils::getRandomString(size_t len) {
1731efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    char buf[len + 1];
1741efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    for (size_t i = 0; i < len; i++) {
1751efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        uint32_t r = arc4random() & 0xffff;
1761efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        r %= 62;
1771efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        if (r < 26) {
1781efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            // lowercase
1791efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            buf[i] = 'a' + r;
1801efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        } else if (r < 52) {
1811efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            // uppercase
1821efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            buf[i] = 'A' + (r - 26);
1831efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        } else {
1841efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            // Use a number
1851efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            buf[i] = '0' + (r - 52);
1861efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        }
1871efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    }
1881efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    buf[len] = '\0';
1891efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    return String8(buf);
1901efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni}
1911efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni
1922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nivoid* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir,
1931efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang 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()) {
2111efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        if (alreadyLoaded != nullptr) {
2121efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            *alreadyLoaded = false;
2131efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang 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
2211efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    if (alreadyLoaded != nullptr) {
2221efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        *alreadyLoaded = true;
2231efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    }
2241efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang 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("#");
2441efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang 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
264d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang// MAXLINESTR must be compatible with operator '#' in C macro.
265d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang#define MAXLINESTR 499
266d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang// MAXLINE must be (MAXLINESTR + 1), representing the size of a C string
267d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang// containing MAXLINESTR non-null chars plus a null.
268d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang#define MAXLINE (MAXLINESTR + 1)
2692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define MAKE_STR_HELPER(S) #S
2702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define MAKE_STR(S) MAKE_STR_HELPER(S)
2712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_VAR_STR "exportVarCount: "
2722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_FUNC_STR "exportFuncCount: "
2732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_FOREACH_STR "exportForEachCount: "
27414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala#define EXPORT_REDUCE_STR "exportReduceCount: "
2752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define OBJECT_SLOT_STR "objectSlotCount: "
2762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define PRAGMA_STR "pragmaCount: "
2772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define THREADABLE_STR "isThreadable: "
278aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar#define CHECKSUM_STR "buildChecksum: "
2792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Copy up to a newline or size chars from str -> s, updating str
2812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Returns s when successful and nullptr when '\0' is finally reached.
2822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic char* strgets(char *s, int size, const char **ppstr) {
2832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
2842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
2852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    int i;
2882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (i = 0; i < (size - 1); i++) {
2892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        s[i] = **ppstr;
2902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        (*ppstr)++;
2912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (s[i] == '\0') {
2922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            return s;
2932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        } else if (s[i] == '\n') {
2942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            s[i+1] = '\0';
2952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            return s;
2962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
2972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // size has been exceeded.
3002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    s[i] = '\0';
3012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return s;
3032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
3042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3052abfcc6d129fe3defddef4540aa95cc445c03a7aYang NiScriptExecutable* ScriptExecutable::createFromSharedObject(
3065e48002cc4a11e9ce63852a77488cfb9f6765c2bYang Ni    void* sharedObj, uint32_t expectedChecksum) {
3072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    char line[MAXLINE];
3082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t varCount = 0;
3102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t funcCount = 0;
3112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t forEachCount = 0;
31214ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    size_t reduceCount = 0;
3132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t objectSlotCount = 0;
3142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t pragmaCount = 0;
3152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bool isThreadable = true;
3162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    void** fieldAddress = nullptr;
3182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bool* fieldIsObject = nullptr;
319062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    char** fieldName = nullptr;
3202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    InvokeFunc_t* invokeFunctions = nullptr;
3212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    ForEachFunc_t* forEachFunctions = nullptr;
3222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    uint32_t* forEachSignatures = nullptr;
323ae2ec3febedfc29376b9104413fb4042028f1265David Gross    ReduceDescription* reduceDescriptions = nullptr;
3242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    const char ** pragmaKeys = nullptr;
3252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    const char ** pragmaValues = nullptr;
326cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    uint32_t checksum = 0;
3272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3285aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const char *rsInfo = (const char *) dlsym(sharedObj, kRsInfo);
3298409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    int numEntries = 0;
3305aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const int *rsGlobalEntries = (const int *) dlsym(sharedObj, kRsGlobalEntries);
3315aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const char **rsGlobalNames = (const char **) dlsym(sharedObj, kRsGlobalNames);
3325aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const void **rsGlobalAddresses = (const void **) dlsym(sharedObj, kRsGlobalAddresses);
3335aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const size_t *rsGlobalSizes = (const size_t *) dlsym(sharedObj, kRsGlobalSizes);
3345aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const uint32_t *rsGlobalProperties = (const uint32_t *) dlsym(sharedObj, kRsGlobalProperties);
3352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
3372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
3382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
3402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export var count!: %s", line);
3412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
3422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    fieldAddress = new void*[varCount];
3452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (fieldAddress == nullptr) {
3462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
3472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    fieldIsObject = new bool[varCount];
3502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (fieldIsObject == nullptr) {
3512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
3522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
354062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    fieldName = new char*[varCount];
355062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    if (fieldName == nullptr) {
356062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        goto error;
357062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
358062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
3592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < varCount; ++i) {
3602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
3612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
3622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *c = strrchr(line, '\n');
3642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (c) {
3652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            *c = '\0';
3662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        void* addr = dlsym(sharedObj, line);
3682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (addr == nullptr) {
3692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Failed to find variable address for %s: %s",
3702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  line, dlerror());
3712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // Not a critical error if we don't find a global variable.
3722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        fieldAddress[i] = addr;
3742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        fieldIsObject[i] = false;
375062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        fieldName[i] = new char[strlen(line)+1];
376062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        strcpy(fieldName[i], line);
3772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
3802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
3812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
3832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export func count!: %s", line);
3842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
3852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    invokeFunctions = new InvokeFunc_t[funcCount];
3882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (invokeFunctions == nullptr) {
3892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
3902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < funcCount; ++i) {
3932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
3942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
3952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *c = strrchr(line, '\n');
3972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (c) {
3982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            *c = '\0';
3992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        invokeFunctions[i] = (InvokeFunc_t) dlsym(sharedObj, line);
4022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (invokeFunctions[i] == nullptr) {
4032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Failed to get function address for %s(): %s",
4042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  line, dlerror());
4052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
4132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export forEach count!: %s", line);
4142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    forEachFunctions = new ForEachFunc_t[forEachCount];
4182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (forEachFunctions == nullptr) {
4192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    forEachSignatures = new uint32_t[forEachCount];
4232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (forEachSignatures == nullptr) {
4242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < forEachCount; ++i) {
4282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        unsigned int tmpSig = 0;
4292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char tmpName[MAXLINE];
4302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
434d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang        if (sscanf(line, "%u - %" MAKE_STR(MAXLINESTR) "s",
4352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                   &tmpSig, tmpName) != 2) {
4362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni          ALOGE("Invalid export forEach!: %s", line);
4372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni          goto error;
4382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // Lookup the expanded ForEach kernel.
441d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang        strncat(tmpName, ".expand", MAXLINESTR-strlen(tmpName));
4422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachSignatures[i] = tmpSig;
4432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachFunctions[i] =
4442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            (ForEachFunc_t) dlsym(sharedObj, tmpName);
445062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (i != 0 && forEachFunctions[i] == nullptr &&
446062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            strcmp(tmpName, "root.expand")) {
4472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // Ignore missing root.expand functions.
4482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // root() is always specified at location 0.
44914ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala            ALOGE("Failed to find forEach function address for %s(): %s",
4502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  tmpName, dlerror());
4512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4556c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    // Read general reduce kernels
45646c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
45746c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross        goto error;
45846c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross    }
459ae2ec3febedfc29376b9104413fb4042028f1265David Gross    if (sscanf(line, EXPORT_REDUCE_STR "%zu", &reduceCount) != 1) {
46046c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross        ALOGE("Invalid export reduce new count!: %s", line);
46146c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross        goto error;
46246c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross    }
4636c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
464ae2ec3febedfc29376b9104413fb4042028f1265David Gross    reduceDescriptions = new ReduceDescription[reduceCount];
465ae2ec3febedfc29376b9104413fb4042028f1265David Gross    if (reduceDescriptions == nullptr) {
46646c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross        goto error;
46746c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross    }
46846c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross
469ae2ec3febedfc29376b9104413fb4042028f1265David Gross    for (size_t i = 0; i < reduceCount; ++i) {
4706c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        static const char kNoName[] = ".";
4716c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
4726c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        unsigned int tmpSig = 0;
4736c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        size_t tmpSize = 0;
4746c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameReduce[MAXLINE];
4756c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameInitializer[MAXLINE];
4766c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameAccumulator[MAXLINE];
4776c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameCombiner[MAXLINE];
4786c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameOutConverter[MAXLINE];
4796c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameHalter[MAXLINE];
4806c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
4816c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4826c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
4836c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
484d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang#define DELIMNAME " - %" MAKE_STR(MAXLINESTR) "s"
4856c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (sscanf(line, "%u - %zu" DELIMNAME DELIMNAME DELIMNAME DELIMNAME DELIMNAME DELIMNAME,
4866c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                   &tmpSig, &tmpSize, tmpNameReduce, tmpNameInitializer, tmpNameAccumulator,
4876c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                   tmpNameCombiner, tmpNameOutConverter, tmpNameHalter) != 8) {
4886c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Invalid export reduce new!: %s", line);
4896c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
4906c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
4916c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross#undef DELIMNAME
4926c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
4936c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // For now, we expect
4946c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // - Reduce and Accumulator names
4956c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // - optional Initializer, Combiner, and OutConverter name
4966c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // - no Halter name
4976c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (!strcmp(tmpNameReduce, kNoName) ||
4986c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            !strcmp(tmpNameAccumulator, kNoName)) {
4996c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Expected reduce and accumulator names!: %s", line);
5006c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5016c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5026c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (strcmp(tmpNameHalter, kNoName)) {
5036c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Did not expect halter name!: %s", line);
5046c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5056c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5066c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
50710adb0c2029f112b5738228617d5645f6ecea0c5David Gross        // The current implementation does not use the signature
50810adb0c2029f112b5738228617d5645f6ecea0c5David Gross        // or reduce name.
5096c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
510ae2ec3febedfc29376b9104413fb4042028f1265David Gross        reduceDescriptions[i].accumSize = tmpSize;
5116c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5126c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // Process the (optional) initializer.
5136c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (strcmp(tmpNameInitializer, kNoName)) {
5146c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross          // Lookup the original user-written initializer.
515ae2ec3febedfc29376b9104413fb4042028f1265David Gross          if (!(reduceDescriptions[i].initFunc =
516ae2ec3febedfc29376b9104413fb4042028f1265David Gross                (ReduceInitializerFunc_t) dlsym(sharedObj, tmpNameInitializer))) {
5176c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Failed to find initializer function address for %s(): %s",
5186c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                  tmpNameInitializer, dlerror());
5196c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5206c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross          }
5216c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        } else {
522ae2ec3febedfc29376b9104413fb4042028f1265David Gross          reduceDescriptions[i].initFunc = nullptr;
5236c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5246c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5256c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // Lookup the expanded accumulator.
526d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang        strncat(tmpNameAccumulator, ".expand", MAXLINESTR-strlen(tmpNameAccumulator));
527ae2ec3febedfc29376b9104413fb4042028f1265David Gross        if (!(reduceDescriptions[i].accumFunc =
528ae2ec3febedfc29376b9104413fb4042028f1265David Gross              (ReduceAccumulatorFunc_t) dlsym(sharedObj, tmpNameAccumulator))) {
5296c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Failed to find accumulator function address for %s(): %s",
5306c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                  tmpNameAccumulator, dlerror());
5316c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5326c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5336c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
53410adb0c2029f112b5738228617d5645f6ecea0c5David Gross        // Process the (optional) combiner.
53510adb0c2029f112b5738228617d5645f6ecea0c5David Gross        if (strcmp(tmpNameCombiner, kNoName)) {
53610adb0c2029f112b5738228617d5645f6ecea0c5David Gross          // Lookup the original user-written combiner.
537ae2ec3febedfc29376b9104413fb4042028f1265David Gross          if (!(reduceDescriptions[i].combFunc =
538ae2ec3febedfc29376b9104413fb4042028f1265David Gross                (ReduceCombinerFunc_t) dlsym(sharedObj, tmpNameCombiner))) {
53910adb0c2029f112b5738228617d5645f6ecea0c5David Gross            ALOGE("Failed to find combiner function address for %s(): %s",
54010adb0c2029f112b5738228617d5645f6ecea0c5David Gross                  tmpNameCombiner, dlerror());
54110adb0c2029f112b5738228617d5645f6ecea0c5David Gross            goto error;
54210adb0c2029f112b5738228617d5645f6ecea0c5David Gross          }
54310adb0c2029f112b5738228617d5645f6ecea0c5David Gross        } else {
544ae2ec3febedfc29376b9104413fb4042028f1265David Gross          reduceDescriptions[i].combFunc = nullptr;
54510adb0c2029f112b5738228617d5645f6ecea0c5David Gross        }
54610adb0c2029f112b5738228617d5645f6ecea0c5David Gross
5476c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // Process the (optional) outconverter.
5486c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (strcmp(tmpNameOutConverter, kNoName)) {
5496c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross          // Lookup the original user-written outconverter.
550ae2ec3febedfc29376b9104413fb4042028f1265David Gross          if (!(reduceDescriptions[i].outFunc =
551ae2ec3febedfc29376b9104413fb4042028f1265David Gross                (ReduceOutConverterFunc_t) dlsym(sharedObj, tmpNameOutConverter))) {
5526c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Failed to find outconverter function address for %s(): %s",
5536c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                  tmpNameOutConverter, dlerror());
5546c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5556c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross          }
5566c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        } else {
557ae2ec3febedfc29376b9104413fb4042028f1265David Gross          reduceDescriptions[i].outFunc = nullptr;
5586c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5596c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    }
5606c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
5622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
5632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
5652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid object slot count!: %s", line);
5662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
5672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < objectSlotCount; ++i) {
5702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        uint32_t varNum = 0;
5712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
5722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
5732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
5742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (sscanf(line, "%u", &varNum) != 1) {
5752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Invalid object slot!: %s", line);
5762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
5772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
5782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (varNum < varCount) {
5802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            fieldIsObject[varNum] = true;
5812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
5822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_COMPATIBILITY_LIB
5852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Do not attempt to read pragmas or isThreadable flag in compat lib path.
5862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Neither is applicable for compat lib
5872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
5892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
5902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, PRAGMA_STR "%zu", &pragmaCount) != 1) {
5932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid pragma count!: %s", line);
5942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
5952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    pragmaKeys = new const char*[pragmaCount];
5982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (pragmaKeys == nullptr) {
5992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    pragmaValues = new const char*[pragmaCount];
6032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (pragmaValues == nullptr) {
6042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bzero(pragmaKeys, sizeof(char*) * pragmaCount);
6082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bzero(pragmaValues, sizeof(char*) * pragmaCount);
6092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < pragmaCount; ++i) {
6112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
6122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Unable to read pragma at index %zu!", i);
6132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
6142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
6152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char key[MAXLINE];
6162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char value[MAXLINE] = ""; // initialize in case value is empty
6172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // pragmas can just have a key and no value.  Only check to make sure
6192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // that the key is not empty
620d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang        if (sscanf(line, "%" MAKE_STR(MAXLINESTR) "s - %" MAKE_STR(MAXLINESTR) "s",
6212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                   key, value) == 0 ||
6222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            strlen(key) == 0)
6232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        {
6242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Invalid pragma value!: %s", line);
6252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
6272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
6282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *pKey = new char[strlen(key)+1];
6302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        strcpy(pKey, key);
6312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        pragmaKeys[i] = pKey;
6322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *pValue = new char[strlen(value)+1];
6342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        strcpy(pValue, value);
6352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        pragmaValues[i] = pValue;
6362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        //ALOGE("Pragma %zu: Key: '%s' Value: '%s'", i, pKey, pValue);
6372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
6402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    char tmpFlag[4];
644d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang    if (sscanf(line, THREADABLE_STR "%3s", tmpFlag) != 1) {
6452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid threadable flag!: %s", line);
6462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strcmp(tmpFlag, "yes") == 0) {
6492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        isThreadable = true;
6502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    } else if (strcmp(tmpFlag, "no") == 0) {
6512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        isThreadable = false;
6522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    } else {
6532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid threadable flag!: %s", tmpFlag);
6542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
657aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    if (strgets(line, MAXLINE, &rsInfo) != nullptr) {
658cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        if (sscanf(line, CHECKSUM_STR "%08x", &checksum) != 1) {
659aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            ALOGE("Invalid checksum flag!: %s", line);
660aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            goto error;
661aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        }
662062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    } else {
663062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        ALOGE("Missing checksum in shared obj file");
664aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        goto error;
665aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    }
666aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
667cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    if (expectedChecksum != 0 && checksum != expectedChecksum) {
668cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        ALOGE("Found invalid checksum.  Expected %08x, got %08x\n",
669cb17015fed6b11a5028f31cc804a3847e379945dYang Ni              expectedChecksum, checksum);
670cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        goto error;
671cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    }
672cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
6732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif  // RS_COMPATIBILITY_LIB
6742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6758409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    // Read in information about mutable global variables provided by bcc's
6768409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    // RSGlobalInfoPass
6778409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    if (rsGlobalEntries) {
6788409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        numEntries = *rsGlobalEntries;
6798409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        if (numEntries > 0) {
6808409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines            rsAssert(rsGlobalNames);
6818409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines            rsAssert(rsGlobalAddresses);
6828409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines            rsAssert(rsGlobalSizes);
6835aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines            rsAssert(rsGlobalProperties);
6848409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        }
6858409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    }
6868409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
6872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return new ScriptExecutable(
6885e48002cc4a11e9ce63852a77488cfb9f6765c2bYang Ni        fieldAddress, fieldIsObject, fieldName, varCount,
6892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        invokeFunctions, funcCount,
6902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachFunctions, forEachSignatures, forEachCount,
691ae2ec3febedfc29376b9104413fb4042028f1265David Gross        reduceDescriptions, reduceCount,
6922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        pragmaKeys, pragmaValues, pragmaCount,
6935aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines        rsGlobalNames, rsGlobalAddresses, rsGlobalSizes, rsGlobalProperties,
6945aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines        numEntries, isThreadable, checksum);
6952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nierror:
6972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_COMPATIBILITY_LIB
699aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
7002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t idx = 0; idx < pragmaCount; ++idx) {
7012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        delete [] pragmaKeys[idx];
7022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        delete [] pragmaValues[idx];
7032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
7042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
7052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] pragmaValues;
7062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] pragmaKeys;
7072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif  // RS_COMPATIBILITY_LIB
7082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
7092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] forEachSignatures;
7102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] forEachFunctions;
711062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
7122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] invokeFunctions;
713062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
714062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (size_t i = 0; i < varCount; i++) {
715062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        delete[] fieldName[i];
716062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
717062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    delete[] fieldName;
7182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] fieldIsObject;
7192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] fieldAddress;
7202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
7212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return nullptr;
7222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
7232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
724062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nivoid* ScriptExecutable::getFieldAddress(const char* name) const {
725062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    // TODO: improve this by using a hash map.
726062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (size_t i = 0; i < mExportedVarCount; i++) {
727062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (strcmp(name, mFieldName[i]) == 0) {
728062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return mFieldAddress[i];
729062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
730062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
731062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    return nullptr;
732062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni}
733062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
7348409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hinesbool ScriptExecutable::dumpGlobalInfo() const {
7358409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    ALOGE("Globals: %p %p %p", mGlobalAddresses, mGlobalSizes, mGlobalNames);
7365aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    ALOGE("P   - Pointer");
7375aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    ALOGE(" C  - Constant");
7385aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    ALOGE("  S - Static");
7398409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    for (int i = 0; i < mGlobalEntries; i++) {
7408409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        ALOGE("Global[%d]: %p %zu %s", i, mGlobalAddresses[i], mGlobalSizes[i],
7418409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines              mGlobalNames[i]);
7425aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines        uint32_t properties = mGlobalProperties[i];
7435aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines        ALOGE("%c%c%c Type: %u",
7445aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines              isGlobalPointer(properties)  ? 'P' : ' ',
7455aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines              isGlobalConstant(properties) ? 'C' : ' ',
7465aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines              isGlobalStatic(properties)   ? 'S' : ' ',
7475aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines              getGlobalRsType(properties));
7488409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    }
7498409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    return true;
7508409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines}
7518409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
7522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}  // namespace renderscript
7532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}  // namespace android
754