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
82a61168a777ee434ce2c28945aa74f6a6bcf2820Miao Wang#include <sys/stat.h>
92a61168a777ee434ce2c28945aa74f6a6bcf2820Miao Wang
102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifdef RS_COMPATIBILITY_LIB
112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <stdio.h>
122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#else
1303fab68da223638671c6e21864283e25bb1fec41Jean-Luc Brouillet#include "bcc/Config.h"
142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif
152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
16316ffa59464f42ac94fd5f992f608c7767001e6dJiyong Park#include <unistd.h>
172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <dlfcn.h>
182536d3fdafb08cef53b9f099e966dbbe82943a85Mathias Agopian#include <sys/stat.h>
192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ninamespace android {
212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ninamespace renderscript {
222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ninamespace {
242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Check if a path exists and attempt to create it if it doesn't.
262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic bool ensureCacheDirExists(const char *path) {
272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (access(path, R_OK | W_OK | X_OK) == 0) {
282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // Done if we can rwx the directory
292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return true;
302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (mkdir(path, 0700) == 0) {
322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return true;
332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return false;
352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Copy the file named \p srcFile to \p dstFile.
382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Return 0 on success and -1 if anything wasn't copied.
392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic int copyFile(const char *dstFile, const char *srcFile) {
402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::ifstream srcStream(srcFile);
412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!srcStream) {
422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not verify or read source file: %s", srcFile);
432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return -1;
442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::ofstream dstStream(dstFile);
462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!dstStream) {
472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not verify or write destination file: %s", dstFile);
482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return -1;
492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    dstStream << srcStream.rdbuf();
512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!dstStream) {
522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not write destination file: %s", dstFile);
532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return -1;
542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    srcStream.close();
572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    dstStream.close();
582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return 0;
602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic std::string findSharedObjectName(const char *cacheDir,
63a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni                                        const char *resName,
64a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni                                        const bool reuse = true) {
652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string scriptSOName(cacheDir);
662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#if defined(RS_COMPATIBILITY_LIB) && !defined(__LP64__)
672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t cutPos = scriptSOName.rfind("cache");
682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (cutPos != std::string::npos) {
692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        scriptSOName.erase(cutPos);
702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    } else {
712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir);
722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    scriptSOName.append("/lib/librs.");
742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#else
752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    scriptSOName.append("/librs.");
762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif // RS_COMPATIBILITY_LIB
772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    scriptSOName.append(resName);
78a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    if (!reuse) {
79a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // If the generated shared library is not reused, e.g., with a debug
80a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // context or forced by a system property, multiple threads may read
81a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // and write the shared library at the same time. To avoid the race
82a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // on the generated shared library, delete it before finishing script
83a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // initialization. To avoid deleting a file generated by a regular
84a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // context, use a special suffix here.
85a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // Because the script initialization is guarded by a lock from the Java
86a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // API, it is safe to name this file with a consistent name and suffix
87a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // and delete it after loading. The same lock has also prevented write-
88a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // write races on the .so during script initialization even if reuse is
89a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        // true.
90a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        scriptSOName.append("#delete_after_load");
91a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    }
922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    scriptSOName.append(".so");
932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return scriptSOName;
952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
97da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park#ifndef RS_COMPATIBILITY_LIB
98da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Parkstatic bool isRunningInVndkNamespace() {
99da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    static bool result = []() {
100da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park        Dl_info info;
101da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park        if (dladdr(reinterpret_cast<const void*>(&isRunningInVndkNamespace), &info) != 0) {
102da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park            std::string filename = std::string(info.dli_fname);
103da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park            return filename.find("/vndk-sp") != std::string::npos;
104da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park        } else {
105da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park            ALOGW("Can't determine whether this lib is running in vndk namespace or not. Assuming it is in vndk namespace.");
106da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park        }
107da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park        return true;
108da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    }();
109da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    return result;
110da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park}
111da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park#endif
112da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park
1132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}  // anonymous namespace
1142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Niconst char* SharedLibraryUtils::LD_EXE_PATH = "/system/bin/ld.mc";
1162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Niconst char* SharedLibraryUtils::RS_CACHE_DIR = "com.android.renderscript.cache";
1172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_COMPATIBILITY_LIB
1192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1204c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hinesbool SharedLibraryUtils::createSharedLibrary(const char *driverName,
1214c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines                                             const char *cacheDir,
122a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni                                             const char *resName,
123a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni                                             const bool reuse,
124a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni                                             std::string *fullPath) {
125a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    std::string sharedLibName = findSharedObjectName(cacheDir, resName, reuse);
126a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    if (fullPath) {
127a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        *fullPath = sharedLibName;
128a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    }
1292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string objFileName = cacheDir;
1302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    objFileName.append("/");
1312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    objFileName.append(resName);
1322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    objFileName.append(".o");
1334c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    // Should be something like "libRSDriver.so".
1344c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    std::string linkDriverName = driverName;
1354c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    // Remove ".so" and replace "lib" with "-l".
1364c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    // This will leave us with "-lRSDriver" instead.
1374c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    linkDriverName.erase(linkDriverName.length() - 3);
1384c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines    linkDriverName.replace(0, 3, "-l");
1392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
140e0f1e2ef6df041d4d88a4d4135c46ddcb0c50029Justin Yun    static const std::string vndkLibCompilerRt =
141e0f1e2ef6df041d4d88a4d4135c46ddcb0c50029Justin Yun        getVndkSysLibPath() + "/libcompiler_rt.so";
142da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    const char *compiler_rt = isRunningInVndkNamespace() ?
143e0f1e2ef6df041d4d88a4d4135c46ddcb0c50029Justin Yun        vndkLibCompilerRt.c_str() : SYSLIBPATH "/libcompiler_rt.so";
144c2be413317efcc44e3b282fd38fca3334c11777ePirama Arumuga Nainar    const char *mTriple = "-mtriple=" DEFAULT_TARGET_TRIPLE_STRING;
145c2be413317efcc44e3b282fd38fca3334c11777ePirama Arumuga Nainar    const char *libPath = "--library-path=" SYSLIBPATH;
146da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    // vndk path is only added when RS framework is running in vndk namespace.
147da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    // If we unconditionally add the vndk path to the library path, then RS
148da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    // driver in the vndk-sp directory will always be used even for CPU fallback
149da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    // case, where RS framework is loaded from the default namespace.
150e0f1e2ef6df041d4d88a4d4135c46ddcb0c50029Justin Yun    static const std::string vndkLibPathString =
151e0f1e2ef6df041d4d88a4d4135c46ddcb0c50029Justin Yun        "--library-path=" + getVndkSysLibPath();
152da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    const char *vndkLibPath = isRunningInVndkNamespace() ?
153e0f1e2ef6df041d4d88a4d4135c46ddcb0c50029Justin Yun        vndkLibPathString.c_str() : "";
154682672e36b05349bc4d9dee74e9fab73ce804183Pirama Arumuga Nainar    const char *vendorLibPath = "--library-path=" SYSLIBPATH_VENDOR;
155c2be413317efcc44e3b282fd38fca3334c11777ePirama Arumuga Nainar
156da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park    // The search path order should be vendor -> vndk -> system
1572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::vector<const char *> args = {
1582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        LD_EXE_PATH,
1592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        "-shared",
1602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        "-nostdlib",
161da43d5866f6224e17e756fdfea405ca4b00a38fcJiyong Park        compiler_rt, mTriple, vendorLibPath, vndkLibPath, libPath,
1624c368af7e705f0bcb77fa99495b2e33ef20d2699Stephen Hines        linkDriverName.c_str(), "-lm", "-lc",
1632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        objFileName.c_str(),
1642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        "-o", sharedLibName.c_str(),
1652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        nullptr
1662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    };
1672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1682fa8a238dd69afebdeb757adcb1d674043d78e32Pirama Arumuga Nainar    return rsuExecuteCommand(LD_EXE_PATH, args.size()-1, args.data());
1692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
1712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif  // RS_COMPATIBILITY_LIB
1732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Niconst char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc";
1752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
176a845c35880f8434619ac299e8af47aa6a5049e8dYang Nivoid* SharedLibraryUtils::loadAndDeleteSharedLibrary(const char *fullPath) {
177a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    void *loaded = dlopen(fullPath, RTLD_NOW | RTLD_LOCAL);
178a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    if (loaded == nullptr) {
179a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        ALOGE("Unable to open shared library (%s): %s", fullPath, dlerror());
180a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        return nullptr;
181a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    }
182a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni
183a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    int r = unlink(fullPath);
184a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    if (r != 0) {
185a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        ALOGE("Could not unlink copy %s", fullPath);
186a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni        return nullptr;
187a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    }
188a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni    return loaded;
189a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni}
190a845c35880f8434619ac299e8af47aa6a5049e8dYang Ni
1912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nivoid* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir,
1922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                                            const char *resName,
1931efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni                                            const char *nativeLibDir,
1941efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni                                            bool* alreadyLoaded) {
1952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    void *loaded = nullptr;
1962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
1972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#if defined(RS_COMPATIBILITY_LIB) && defined(__LP64__)
1982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string scriptSOName = findSharedObjectName(nativeLibDir, resName);
1992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#else
2002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string scriptSOName = findSharedObjectName(cacheDir, resName);
2012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif
2022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // We should check if we can load the library from the standard app
2042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // location for shared libraries first.
2051efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName, alreadyLoaded);
2062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (loaded == nullptr) {
2082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Unable to open shared library (%s): %s",
2092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni              scriptSOName.c_str(), dlerror());
2102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifdef RS_COMPATIBILITY_LIB
2122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // One final attempt to find the library in "/system/lib".
2132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // We do this to allow bundled applications to use the compatibility
2142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // library fallback path. Those applications don't have a private
2152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // library path, so they need to install to the system directly.
2162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // Note that this is really just a testing path.
2172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        std::string scriptSONameSystem("/system/lib/librs.");
2182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        scriptSONameSystem.append(resName);
2192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        scriptSONameSystem.append(".so");
2202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir,
2212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                              resName);
2222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (loaded == nullptr) {
2232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Unable to open system shared library (%s): %s",
2242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  scriptSONameSystem.c_str(), dlerror());
2252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
2262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif
2272abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2282abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return loaded;
2302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
2312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
23282e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wangstd::string SharedLibraryUtils::getRandomString(size_t len) {
2331efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    char buf[len + 1];
2341efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    for (size_t i = 0; i < len; i++) {
2351efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        uint32_t r = arc4random() & 0xffff;
2361efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        r %= 62;
2371efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        if (r < 26) {
2381efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            // lowercase
2391efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            buf[i] = 'a' + r;
2401efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        } else if (r < 52) {
2411efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            // uppercase
2421efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            buf[i] = 'A' + (r - 26);
2431efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        } else {
2441efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            // Use a number
2451efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            buf[i] = '0' + (r - 52);
2461efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        }
2471efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    }
2481efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    buf[len] = '\0';
24982e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang    return std::string(buf);
2501efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni}
2511efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni
2522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nivoid* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir,
2531efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni                                       const char *resName, bool *alreadyLoaded) {
2542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Keep track of which .so libraries have been loaded. Once a library is
2552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // in the set (per-process granularity), we must instead make a copy of
2562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // the original shared object (randomly named .so file) and load that one
2572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // instead. If we don't do this, we end up aliasing global data between
2582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // the various Script instances (which are supposed to be completely
2592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // independent).
2602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    static std::set<std::string> LoadedLibraries;
2612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    void *loaded = nullptr;
2632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Skip everything if we don't even have the original library available.
2652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (access(origName, F_OK) != 0) {
2662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
2672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Common path is that we have not loaded this Script/library before.
2702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (LoadedLibraries.find(origName) == LoadedLibraries.end()) {
2711efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        if (alreadyLoaded != nullptr) {
2721efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni            *alreadyLoaded = false;
2731efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        }
2742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL);
2752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (loaded) {
2762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            LoadedLibraries.insert(origName);
2772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
2782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return loaded;
2792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2811efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    if (alreadyLoaded != nullptr) {
2821efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni        *alreadyLoaded = true;
2831efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni    }
2841efae29f4bbe6c165caf6dfc4b89cf8a5f8c469bYang Ni
2852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    std::string newName(cacheDir);
2862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Append RS_CACHE_DIR only if it is not found in cacheDir
2882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // In driver mode, RS_CACHE_DIR is already appended to cacheDir.
2892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (newName.find(RS_CACHE_DIR) == std::string::npos) {
2902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        newName.append("/");
2912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        newName.append(RS_CACHE_DIR);
2922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        newName.append("/");
2932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
2952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!ensureCacheDirExists(newName.c_str())) {
2962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not verify or create cache dir: %s", cacheDir);
2972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
2982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
2992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Construct an appropriately randomized filename for the copy.
3012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    newName.append("librs.");
3022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    newName.append(resName);
3032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    newName.append("#");
30482e135c4bbe18855d8ed02632bb074f8da0b96e0Miao Wang    newName.append(getRandomString(6).c_str());  // 62^6 potential filename variants.
3052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    newName.append(".so");
3062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    int r = copyFile(newName.c_str(), origName);
3082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (r != 0) {
3092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not create copy %s -> %s", origName, newName.c_str());
3102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
3112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL);
3132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    r = unlink(newName.c_str());
3142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (r != 0) {
3152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Could not unlink copy %s", newName.c_str());
3162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (loaded) {
3182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        LoadedLibraries.insert(newName.c_str());
3192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return loaded;
3222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
3232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
324d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang// MAXLINESTR must be compatible with operator '#' in C macro.
325d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang#define MAXLINESTR 499
326d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang// MAXLINE must be (MAXLINESTR + 1), representing the size of a C string
327d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang// containing MAXLINESTR non-null chars plus a null.
328d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang#define MAXLINE (MAXLINESTR + 1)
3292abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define MAKE_STR_HELPER(S) #S
3302abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define MAKE_STR(S) MAKE_STR_HELPER(S)
3312abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_VAR_STR "exportVarCount: "
3322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_FUNC_STR "exportFuncCount: "
3332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define EXPORT_FOREACH_STR "exportForEachCount: "
33414ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala#define EXPORT_REDUCE_STR "exportReduceCount: "
3352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define OBJECT_SLOT_STR "objectSlotCount: "
3362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define PRAGMA_STR "pragmaCount: "
3372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#define THREADABLE_STR "isThreadable: "
338aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar#define CHECKSUM_STR "buildChecksum: "
3393bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond#define VERSIONINFO_STR "versionInfo: "
3402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Copy up to a newline or size chars from str -> s, updating str
3422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni// Returns s when successful and nullptr when '\0' is finally reached.
3432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nistatic char* strgets(char *s, int size, const char **ppstr) {
3442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) {
3452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
3462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    int i;
3492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (i = 0; i < (size - 1); i++) {
3502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        s[i] = **ppstr;
3512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        (*ppstr)++;
3522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (s[i] == '\0') {
3532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            return s;
3542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        } else if (s[i] == '\n') {
3552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            s[i+1] = '\0';
3562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            return s;
3572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
3582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
3592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // size has been exceeded.
3612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    s[i] = '\0';
3622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return s;
3642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
3652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
366ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler// Creates a duplicate of a string. The new string is as small as possible,
367ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler// only including characters up to and including the first null-terminator;
368ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler// otherwise, the new string will be the same size as the input string.
369ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler// The code that calls duplicateString is responsible for the new string's
370ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler// lifetime, and is responsible for freeing it when it is no longer needed.
371ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butlerstatic char* duplicateString(const char *str, size_t length) {
372ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler    const size_t newLen = strnlen(str, length-1) + 1;
373ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler    char *newStr = new char[newLen];
374ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler    strlcpy(newStr, str, newLen);
375ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler    return newStr;
376ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler}
377ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler
3782abfcc6d129fe3defddef4540aa95cc445c03a7aYang NiScriptExecutable* ScriptExecutable::createFromSharedObject(
3795e48002cc4a11e9ce63852a77488cfb9f6765c2bYang Ni    void* sharedObj, uint32_t expectedChecksum) {
3802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    char line[MAXLINE];
3812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t varCount = 0;
3832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t funcCount = 0;
3842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t forEachCount = 0;
38514ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala    size_t reduceCount = 0;
3862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t objectSlotCount = 0;
3872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    size_t pragmaCount = 0;
3882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bool isThreadable = true;
3892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
3902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    void** fieldAddress = nullptr;
3912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bool* fieldIsObject = nullptr;
392062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    char** fieldName = nullptr;
3932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    InvokeFunc_t* invokeFunctions = nullptr;
3942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    ForEachFunc_t* forEachFunctions = nullptr;
3952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    uint32_t* forEachSignatures = nullptr;
396ae2ec3febedfc29376b9104413fb4042028f1265David Gross    ReduceDescription* reduceDescriptions = nullptr;
3972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    const char ** pragmaKeys = nullptr;
3982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    const char ** pragmaValues = nullptr;
399cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    uint32_t checksum = 0;
4002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4015aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const char *rsInfo = (const char *) dlsym(sharedObj, kRsInfo);
4028409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    int numEntries = 0;
4035aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const int *rsGlobalEntries = (const int *) dlsym(sharedObj, kRsGlobalEntries);
4045aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const char **rsGlobalNames = (const char **) dlsym(sharedObj, kRsGlobalNames);
4055aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const void **rsGlobalAddresses = (const void **) dlsym(sharedObj, kRsGlobalAddresses);
4065aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const size_t *rsGlobalSizes = (const size_t *) dlsym(sharedObj, kRsGlobalSizes);
4075aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    const uint32_t *rsGlobalProperties = (const uint32_t *) dlsym(sharedObj, kRsGlobalProperties);
4082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
4112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
4132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export var count!: %s", line);
4142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
4152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    fieldAddress = new void*[varCount];
4182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (fieldAddress == nullptr) {
4192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        return nullptr;
4202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    fieldIsObject = new bool[varCount];
4232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (fieldIsObject == nullptr) {
4242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
427062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    fieldName = new char*[varCount];
428062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    if (fieldName == nullptr) {
429062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        goto error;
430062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
431062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
4322abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < varCount; ++i) {
4332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *c = strrchr(line, '\n');
4372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (c) {
4382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            *c = '\0';
4392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        void* addr = dlsym(sharedObj, line);
4412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (addr == nullptr) {
4422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Failed to find variable address for %s: %s",
4432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  line, dlerror());
4442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // Not a critical error if we don't find a global variable.
4452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        fieldAddress[i] = addr;
4472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        fieldIsObject[i] = false;
448ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler        fieldName[i] = duplicateString(line, sizeof(line));
4492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
4552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export func count!: %s", line);
4562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    invokeFunctions = new InvokeFunc_t[funcCount];
4602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (invokeFunctions == nullptr) {
4612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < funcCount; ++i) {
4652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char *c = strrchr(line, '\n');
4692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (c) {
4702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            *c = '\0';
4712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        invokeFunctions[i] = (InvokeFunc_t) dlsym(sharedObj, line);
4742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (invokeFunctions[i] == nullptr) {
4752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Failed to get function address for %s(): %s",
4762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  line, dlerror());
4772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
4782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
4792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
4822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
4852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid export forEach count!: %s", line);
4862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    forEachFunctions = new ForEachFunc_t[forEachCount];
4902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (forEachFunctions == nullptr) {
4912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    forEachSignatures = new uint32_t[forEachCount];
4952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (forEachSignatures == nullptr) {
4962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
4972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
4982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
4992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < forEachCount; ++i) {
5002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        unsigned int tmpSig = 0;
5012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char tmpName[MAXLINE];
5022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
5042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
5052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
506d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang        if (sscanf(line, "%u - %" MAKE_STR(MAXLINESTR) "s",
5072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                   &tmpSig, tmpName) != 2) {
5082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni          ALOGE("Invalid export forEach!: %s", line);
5092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni          goto error;
5102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
5112abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // Lookup the expanded ForEach kernel.
513d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang        strncat(tmpName, ".expand", MAXLINESTR-strlen(tmpName));
5142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachSignatures[i] = tmpSig;
5152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachFunctions[i] =
5162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            (ForEachFunc_t) dlsym(sharedObj, tmpName);
517062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (i != 0 && forEachFunctions[i] == nullptr &&
518062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            strcmp(tmpName, "root.expand")) {
5192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // Ignore missing root.expand functions.
5202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            // root() is always specified at location 0.
52114ce007a633b10e3b9a3fae29d8f53a7e8c9b59fMatt Wala            ALOGE("Failed to find forEach function address for %s(): %s",
5222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                  tmpName, dlerror());
5232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
5242abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
5252abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
5262abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
5276c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    // Read general reduce kernels
52846c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
52946c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross        goto error;
53046c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross    }
531ae2ec3febedfc29376b9104413fb4042028f1265David Gross    if (sscanf(line, EXPORT_REDUCE_STR "%zu", &reduceCount) != 1) {
53246c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross        ALOGE("Invalid export reduce new count!: %s", line);
53346c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross        goto error;
53446c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross    }
5356c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
536ae2ec3febedfc29376b9104413fb4042028f1265David Gross    reduceDescriptions = new ReduceDescription[reduceCount];
537ae2ec3febedfc29376b9104413fb4042028f1265David Gross    if (reduceDescriptions == nullptr) {
53846c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross        goto error;
53946c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross    }
54046c93e405b0ad7e8fca12d0b1f9eac3997798e45David Gross
541ae2ec3febedfc29376b9104413fb4042028f1265David Gross    for (size_t i = 0; i < reduceCount; ++i) {
5426c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        static const char kNoName[] = ".";
5436c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5446c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        unsigned int tmpSig = 0;
5456c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        size_t tmpSize = 0;
5466c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameReduce[MAXLINE];
5476c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameInitializer[MAXLINE];
5486c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameAccumulator[MAXLINE];
5496c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameCombiner[MAXLINE];
5506c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameOutConverter[MAXLINE];
5516c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        char tmpNameHalter[MAXLINE];
5526c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5536c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
5546c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5556c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
556d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang#define DELIMNAME " - %" MAKE_STR(MAXLINESTR) "s"
5576c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (sscanf(line, "%u - %zu" DELIMNAME DELIMNAME DELIMNAME DELIMNAME DELIMNAME DELIMNAME,
5586c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                   &tmpSig, &tmpSize, tmpNameReduce, tmpNameInitializer, tmpNameAccumulator,
5596c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                   tmpNameCombiner, tmpNameOutConverter, tmpNameHalter) != 8) {
5606c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Invalid export reduce new!: %s", line);
5616c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5626c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5636c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross#undef DELIMNAME
5646c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5656c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // For now, we expect
5666c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // - Reduce and Accumulator names
5676c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // - optional Initializer, Combiner, and OutConverter name
5686c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // - no Halter name
5696c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (!strcmp(tmpNameReduce, kNoName) ||
5706c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            !strcmp(tmpNameAccumulator, kNoName)) {
5716c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Expected reduce and accumulator names!: %s", line);
5726c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5736c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5746c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (strcmp(tmpNameHalter, kNoName)) {
5756c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Did not expect halter name!: %s", line);
5766c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5776c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5786c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
57910adb0c2029f112b5738228617d5645f6ecea0c5David Gross        // The current implementation does not use the signature
58010adb0c2029f112b5738228617d5645f6ecea0c5David Gross        // or reduce name.
5816c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
582ae2ec3febedfc29376b9104413fb4042028f1265David Gross        reduceDescriptions[i].accumSize = tmpSize;
5836c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5846c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // Process the (optional) initializer.
5856c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (strcmp(tmpNameInitializer, kNoName)) {
5866c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross          // Lookup the original user-written initializer.
587ae2ec3febedfc29376b9104413fb4042028f1265David Gross          if (!(reduceDescriptions[i].initFunc =
588ae2ec3febedfc29376b9104413fb4042028f1265David Gross                (ReduceInitializerFunc_t) dlsym(sharedObj, tmpNameInitializer))) {
5896c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Failed to find initializer function address for %s(): %s",
5906c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                  tmpNameInitializer, dlerror());
5916c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
5926c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross          }
5936c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        } else {
594ae2ec3febedfc29376b9104413fb4042028f1265David Gross          reduceDescriptions[i].initFunc = nullptr;
5956c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
5966c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
5976c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // Lookup the expanded accumulator.
598d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang        strncat(tmpNameAccumulator, ".expand", MAXLINESTR-strlen(tmpNameAccumulator));
599ae2ec3febedfc29376b9104413fb4042028f1265David Gross        if (!(reduceDescriptions[i].accumFunc =
600ae2ec3febedfc29376b9104413fb4042028f1265David Gross              (ReduceAccumulatorFunc_t) dlsym(sharedObj, tmpNameAccumulator))) {
6016c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Failed to find accumulator function address for %s(): %s",
6026c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                  tmpNameAccumulator, dlerror());
6036c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
6046c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
6056c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
60610adb0c2029f112b5738228617d5645f6ecea0c5David Gross        // Process the (optional) combiner.
60710adb0c2029f112b5738228617d5645f6ecea0c5David Gross        if (strcmp(tmpNameCombiner, kNoName)) {
60810adb0c2029f112b5738228617d5645f6ecea0c5David Gross          // Lookup the original user-written combiner.
609ae2ec3febedfc29376b9104413fb4042028f1265David Gross          if (!(reduceDescriptions[i].combFunc =
610ae2ec3febedfc29376b9104413fb4042028f1265David Gross                (ReduceCombinerFunc_t) dlsym(sharedObj, tmpNameCombiner))) {
61110adb0c2029f112b5738228617d5645f6ecea0c5David Gross            ALOGE("Failed to find combiner function address for %s(): %s",
61210adb0c2029f112b5738228617d5645f6ecea0c5David Gross                  tmpNameCombiner, dlerror());
61310adb0c2029f112b5738228617d5645f6ecea0c5David Gross            goto error;
61410adb0c2029f112b5738228617d5645f6ecea0c5David Gross          }
61510adb0c2029f112b5738228617d5645f6ecea0c5David Gross        } else {
616ae2ec3febedfc29376b9104413fb4042028f1265David Gross          reduceDescriptions[i].combFunc = nullptr;
61710adb0c2029f112b5738228617d5645f6ecea0c5David Gross        }
61810adb0c2029f112b5738228617d5645f6ecea0c5David Gross
6196c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        // Process the (optional) outconverter.
6206c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        if (strcmp(tmpNameOutConverter, kNoName)) {
6216c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross          // Lookup the original user-written outconverter.
622ae2ec3febedfc29376b9104413fb4042028f1265David Gross          if (!(reduceDescriptions[i].outFunc =
623ae2ec3febedfc29376b9104413fb4042028f1265David Gross                (ReduceOutConverterFunc_t) dlsym(sharedObj, tmpNameOutConverter))) {
6246c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            ALOGE("Failed to find outconverter function address for %s(): %s",
6256c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross                  tmpNameOutConverter, dlerror());
6266c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross            goto error;
6276c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross          }
6286c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        } else {
629ae2ec3febedfc29376b9104413fb4042028f1265David Gross          reduceDescriptions[i].outFunc = nullptr;
6306c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross        }
6316c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross    }
6326c1876bbef1b2c89975dce91230a168bd2d2ce4cDavid Gross
6332abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
6342abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6352abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6362abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
6372abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid object slot count!: %s", line);
6382abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6392abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6402abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6412abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < objectSlotCount; ++i) {
6422abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        uint32_t varNum = 0;
6432abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
6442abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
6452abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
6462abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (sscanf(line, "%u", &varNum) != 1) {
6472abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Invalid object slot!: %s", line);
6482abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
6492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
6502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6512abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (varNum < varCount) {
6522abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            fieldIsObject[varNum] = true;
6532abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
6542abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6552abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6562abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_COMPATIBILITY_LIB
6572abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Do not attempt to read pragmas or isThreadable flag in compat lib path.
6582abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    // Neither is applicable for compat lib
6592abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6602abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
6612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6632abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6642abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (sscanf(line, PRAGMA_STR "%zu", &pragmaCount) != 1) {
6652abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid pragma count!: %s", line);
6662abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6672abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6682abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6692abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    pragmaKeys = new const char*[pragmaCount];
6702abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (pragmaKeys == nullptr) {
6712abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6722abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6732abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6742abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    pragmaValues = new const char*[pragmaCount];
6752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (pragmaValues == nullptr) {
6762abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
6772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
6782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6792abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bzero(pragmaKeys, sizeof(char*) * pragmaCount);
6802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    bzero(pragmaValues, sizeof(char*) * pragmaCount);
6812abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6822abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    for (size_t i = 0; i < pragmaCount; ++i) {
6832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
6842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Unable to read pragma at index %zu!", i);
6852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
6862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
6872abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char key[MAXLINE];
6882abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        char value[MAXLINE] = ""; // initialize in case value is empty
6892abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // pragmas can just have a key and no value.  Only check to make sure
6912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        // that the key is not empty
692d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang        if (sscanf(line, "%" MAKE_STR(MAXLINESTR) "s - %" MAKE_STR(MAXLINESTR) "s",
6932abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                   key, value) == 0 ||
6942abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            strlen(key) == 0)
6952abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        {
6962abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            ALOGE("Invalid pragma value!: %s", line);
6972abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
6982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            goto error;
6992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        }
7002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
701ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler        pragmaKeys[i] = duplicateString(key, sizeof(key));
702ca451c3280b6265a9b79273b4bf89e121a050cabMichael Butler        pragmaValues[i] = duplicateString(value, sizeof(value));
7032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        //ALOGE("Pragma %zu: Key: '%s' Value: '%s'", i, pKey, pValue);
7042abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
7052abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
7062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
7072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
7082abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
7092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
7102abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    char tmpFlag[4];
711d48481048a68725e79bbe8ba8ea75e710c646fe1Miao Wang    if (sscanf(line, THREADABLE_STR "%3s", tmpFlag) != 1) {
7122abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid threadable flag!: %s", line);
7132abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
7142abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
7152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    if (strcmp(tmpFlag, "yes") == 0) {
7162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        isThreadable = true;
7172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    } else if (strcmp(tmpFlag, "no") == 0) {
7182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        isThreadable = false;
7192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    } else {
7202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        ALOGE("Invalid threadable flag!: %s", tmpFlag);
7212abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        goto error;
7222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
7232abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
724aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    if (strgets(line, MAXLINE, &rsInfo) != nullptr) {
725cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        if (sscanf(line, CHECKSUM_STR "%08x", &checksum) != 1) {
726aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            ALOGE("Invalid checksum flag!: %s", line);
727aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar            goto error;
728aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        }
729062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    } else {
730062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        ALOGE("Missing checksum in shared obj file");
731aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar        goto error;
732aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar    }
733aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
734cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    if (expectedChecksum != 0 && checksum != expectedChecksum) {
735cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        ALOGE("Found invalid checksum.  Expected %08x, got %08x\n",
736cb17015fed6b11a5028f31cc804a3847e379945dYang Ni              expectedChecksum, checksum);
737cb17015fed6b11a5028f31cc804a3847e379945dYang Ni        goto error;
738cb17015fed6b11a5028f31cc804a3847e379945dYang Ni    }
739cb17015fed6b11a5028f31cc804a3847e379945dYang Ni
7403bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond    {
7413bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond      // Parse the version info string, but ignore its contents as it's only
7423bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond      // used by the debugger
7433bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond      size_t nLines = 0;
7443bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond      if (strgets(line, MAXLINE, &rsInfo) != nullptr) {
7453bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond        if (sscanf(line, VERSIONINFO_STR "%zu", &nLines) != 1) {
7463bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond          ALOGE("invalid versionInfo count");
7473bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond          goto error;
7483bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond        } else {
7493bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond          // skip the versionInfo packet as libRs doesn't use it
7505f4af759693231777add7683eb06c2cb8af5022cIvan Lozano          while (nLines) {
7515f4af759693231777add7683eb06c2cb8af5022cIvan Lozano            --nLines;
7523bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond            if (strgets(line, MAXLINE, &rsInfo) == nullptr)
7533bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond              goto error;
7543bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond          }
7553bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond        }
7563bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond      } else {
7573bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond        ALOGE(".rs.info is missing versionInfo section");
7583bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond      }
7593bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond    }
7603bc02c5bbcc1f1cd838455bf1a32c57c18addda8Luke Drummond
7612abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif  // RS_COMPATIBILITY_LIB
7622abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
7638409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    // Read in information about mutable global variables provided by bcc's
7648409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    // RSGlobalInfoPass
7658409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    if (rsGlobalEntries) {
7668409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        numEntries = *rsGlobalEntries;
7678409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        if (numEntries > 0) {
7688409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines            rsAssert(rsGlobalNames);
7698409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines            rsAssert(rsGlobalAddresses);
7708409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines            rsAssert(rsGlobalSizes);
7715aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines            rsAssert(rsGlobalProperties);
7728409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        }
7738409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    }
7748409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
7752abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return new ScriptExecutable(
7765e48002cc4a11e9ce63852a77488cfb9f6765c2bYang Ni        fieldAddress, fieldIsObject, fieldName, varCount,
7772abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        invokeFunctions, funcCount,
7782abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        forEachFunctions, forEachSignatures, forEachCount,
779ae2ec3febedfc29376b9104413fb4042028f1265David Gross        reduceDescriptions, reduceCount,
7802abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni        pragmaKeys, pragmaValues, pragmaCount,
7815aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines        rsGlobalNames, rsGlobalAddresses, rsGlobalSizes, rsGlobalProperties,
7825aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines        numEntries, isThreadable, checksum);
7832abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
7842abfcc6d129fe3defddef4540aa95cc445c03a7aYang Nierror:
7852abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
7862abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#ifndef RS_COMPATIBILITY_LIB
787aa6757ffc1b23d771566439c3179fdbc1e5ba569Pirama Arumuga Nainar
788a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang    if (pragmaKeys) {
789a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang        for (size_t idx = 0; idx < pragmaCount; ++idx) {
790a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang            delete [] pragmaKeys[idx];
791a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang        }
792a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang    }
793a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang
794a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang    if (pragmaValues) {
795a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang        for (size_t idx = 0; idx < pragmaCount; ++idx) {
796a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang            delete [] pragmaValues[idx];
797a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang        }
7982abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    }
7992abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
8002abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] pragmaValues;
8012abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] pragmaKeys;
8022abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#endif  // RS_COMPATIBILITY_LIB
8032abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
804a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang    delete[] reduceDescriptions;
805a824b7c0138e49136fabe166ab4431aa9c220b9fTing-Yuan Huang
8062abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] forEachSignatures;
8072abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] forEachFunctions;
808062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
8092abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] invokeFunctions;
810062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
811062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (size_t i = 0; i < varCount; i++) {
812062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        delete[] fieldName[i];
813062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
814062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    delete[] fieldName;
8152abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] fieldIsObject;
8162abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    delete[] fieldAddress;
8172abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
8182abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni    return nullptr;
8192abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}
8202abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni
821062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nivoid* ScriptExecutable::getFieldAddress(const char* name) const {
822062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    // TODO: improve this by using a hash map.
823062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (size_t i = 0; i < mExportedVarCount; i++) {
824062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (strcmp(name, mFieldName[i]) == 0) {
825062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return mFieldAddress[i];
826062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
827062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
828062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    return nullptr;
829062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni}
830062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
8318409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hinesbool ScriptExecutable::dumpGlobalInfo() const {
8328409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    ALOGE("Globals: %p %p %p", mGlobalAddresses, mGlobalSizes, mGlobalNames);
8335aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    ALOGE("P   - Pointer");
8345aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    ALOGE(" C  - Constant");
8355aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines    ALOGE("  S - Static");
8368409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    for (int i = 0; i < mGlobalEntries; i++) {
8378409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines        ALOGE("Global[%d]: %p %zu %s", i, mGlobalAddresses[i], mGlobalSizes[i],
8388409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines              mGlobalNames[i]);
8395aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines        uint32_t properties = mGlobalProperties[i];
8405aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines        ALOGE("%c%c%c Type: %u",
8415aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines              isGlobalPointer(properties)  ? 'P' : ' ',
8425aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines              isGlobalConstant(properties) ? 'C' : ' ',
8435aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines              isGlobalStatic(properties)   ? 'S' : ' ',
8445aa018cc36e589b07674957714d27ae3d1fa1c4eStephen Hines              getGlobalRsType(properties));
8458409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    }
8468409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines    return true;
8478409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines}
8488409d6414dd4a42aa59779fcfe9fce18648cb135Stephen Hines
8492abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}  // namespace renderscript
8502abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni}  // namespace android
851