diff options
| author | Yang Ni <yangni@google.com> | 2015-02-17 16:05:19 -0800 |
|---|---|---|
| committer | Yang Ni <yangni@google.com> | 2015-02-20 08:51:43 -0800 |
| commit | 2abfcc6d129fe3defddef4540aa95cc445c03a7a (patch) | |
| tree | a479a0b28ca28dd1d62f516bb7940254556cfd20 /cpu_ref/rsCpuScript.cpp | |
| parent | e15ea72be26441644c21d536f18525702a24d28a (diff) | |
| download | android_frameworks_rs-2abfcc6d129fe3defddef4540aa95cc445c03a7a.tar.gz android_frameworks_rs-2abfcc6d129fe3defddef4540aa95cc445c03a7a.tar.bz2 android_frameworks_rs-2abfcc6d129fe3defddef4540aa95cc445c03a7a.zip | |
Moved class ScriptExecutable to its own module
b/19283946
This move also included the related class SharedObjectUtils.
Change-Id: Iefd587b659c4ad99340c330955b41cd92df45563
Diffstat (limited to 'cpu_ref/rsCpuScript.cpp')
| -rw-r--r-- | cpu_ref/rsCpuScript.cpp | 566 |
1 files changed, 4 insertions, 562 deletions
diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp index 1c7fdac8..af8b6407 100644 --- a/cpu_ref/rsCpuScript.cpp +++ b/cpu_ref/rsCpuScript.cpp @@ -16,6 +16,7 @@ #include "rsCpuCore.h" #include "rsCpuScript.h" +#include "rsCpuExecutable.h" #ifdef RS_COMPATIBILITY_LIB #include <stdio.h> @@ -41,7 +42,6 @@ #include <dlfcn.h> #include <stdlib.h> #include <string.h> -#include <fstream> #include <iostream> #ifdef __LP64__ @@ -51,90 +51,6 @@ #endif namespace { - -// Create a len length string containing random characters from [A-Za-z0-9]. -static std::string getRandomString(size_t len) { - char buf[len + 1]; - for (size_t i = 0; i < len; i++) { - uint32_t r = arc4random() & 0xffff; - r %= 62; - if (r < 26) { - // lowercase - buf[i] = 'a' + r; - } else if (r < 52) { - // uppercase - buf[i] = 'A' + (r - 26); - } else { - // Use a number - buf[i] = '0' + (r - 52); - } - } - buf[len] = '\0'; - return std::string(buf); -} - -// Check if a path exists and attempt to create it if it doesn't. -static bool ensureCacheDirExists(const char *path) { - if (access(path, R_OK | W_OK | X_OK) == 0) { - // Done if we can rwx the directory - return true; - } - if (mkdir(path, 0700) == 0) { - return true; - } - return false; -} - -// Copy the file named \p srcFile to \p dstFile. -// Return 0 on success and -1 if anything wasn't copied. -static int copyFile(const char *dstFile, const char *srcFile) { - std::ifstream srcStream(srcFile); - if (!srcStream) { - ALOGE("Could not verify or read source file: %s", srcFile); - return -1; - } - std::ofstream dstStream(dstFile); - if (!dstStream) { - ALOGE("Could not verify or write destination file: %s", dstFile); - return -1; - } - dstStream << srcStream.rdbuf(); - if (!dstStream) { - ALOGE("Could not write destination file: %s", dstFile); - return -1; - } - - srcStream.close(); - dstStream.close(); - - return 0; -} - -static std::string findSharedObjectName(const char *cacheDir, - const char *resName) { -#ifndef RS_SERVER - std::string scriptSOName(cacheDir); -#if defined(RS_COMPATIBILITY_LIB) && !defined(__LP64__) - size_t cutPos = scriptSOName.rfind("cache"); - if (cutPos != std::string::npos) { - scriptSOName.erase(cutPos); - } else { - ALOGE("Found peculiar cacheDir (missing \"cache\"): %s", cacheDir); - } - scriptSOName.append("/lib/librs."); -#else - scriptSOName.append("/librs."); -#endif // RS_COMPATIBILITY_LIB - -#else - std::string scriptSOName("lib"); -#endif // RS_SERVER - scriptSOName.append(resName); - scriptSOName.append(".so"); - - return scriptSOName; -} - #ifndef RS_COMPATIBILITY_LIB static bool is_force_recompile() { @@ -256,228 +172,12 @@ static bool compileBitcode(const std::string &bcFileName, } } -std::string getCommandLine(int argc, const char* const* argv) { - std::string s; - for (int i = 0; i < argc; i++) { - if (i > 0) { - s += ' '; - } - s += argv[i]; - } - return s; -} - #endif // !defined(RS_COMPATIBILITY_LIB) } // namespace namespace android { namespace renderscript { -const char* SharedLibraryUtils::LD_EXE_PATH = "/system/bin/ld.mc"; -const char* SharedLibraryUtils::RS_CACHE_DIR = "com.android.renderscript.cache"; - -#ifndef RS_COMPATIBILITY_LIB - -bool SharedLibraryUtils::createSharedLibrary(const char *cacheDir, const char *resName) { - std::string sharedLibName = findSharedObjectName(cacheDir, resName); - std::string objFileName = cacheDir; - objFileName.append("/"); - objFileName.append(resName); - objFileName.append(".o"); - - const char *compiler_rt = SYSLIBPATH"/libcompiler_rt.so"; - std::vector<const char *> args = { - LD_EXE_PATH, - "-shared", - "-nostdlib", - compiler_rt, - "-mtriple", DEFAULT_TARGET_TRIPLE_STRING, - "-L", SYSLIBPATH, - "-lRSDriver", "-lm", "-lc", - objFileName.c_str(), - "-o", sharedLibName.c_str(), - nullptr - }; - - std::string cmdLineStr = getCommandLine(args.size()-1, args.data()); - - pid_t pid = fork(); - - switch (pid) { - case -1: { // Error occurred (we attempt no recovery) - ALOGE("Couldn't fork for linker (%s) execution", LD_EXE_PATH); - return false; - } - case 0: { // Child process - ALOGV("Invoking ld.mc with args '%s'", cmdLineStr.c_str()); - execv(LD_EXE_PATH, (char* const*) args.data()); - - ALOGE("execv() failed: %s", strerror(errno)); - abort(); - return false; - } - default: { // Parent process (actual driver) - // Wait on child process to finish compiling the source. - int status = 0; - pid_t w = waitpid(pid, &status, 0); - if (w == -1) { - ALOGE("Could not wait for linker (%s)", LD_EXE_PATH); - return false; - } - - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { - return true; - } - - ALOGE("Linker (%s) terminated unexpectedly", LD_EXE_PATH); - return false; - } - } -} - -#endif // RS_COMPATIBILITY_LIB - - -void* SharedLibraryUtils::loadSharedLibrary(const char *cacheDir, const char *resName, const char *nativeLibDir) { - void *loaded = nullptr; - -#if defined(RS_COMPATIBILITY_LIB) && defined(__LP64__) - std::string scriptSOName = findSharedObjectName(nativeLibDir, resName); -#else - std::string scriptSOName = findSharedObjectName(cacheDir, resName); -#endif - - // We should check if we can load the library from the standard app - // location for shared libraries first. - loaded = loadSOHelper(scriptSOName.c_str(), cacheDir, resName); - - if (loaded == nullptr) { - ALOGE("Unable to open shared library (%s): %s", - scriptSOName.c_str(), dlerror()); - -#ifdef RS_COMPATIBILITY_LIB - // One final attempt to find the library in "/system/lib". - // We do this to allow bundled applications to use the compatibility - // library fallback path. Those applications don't have a private - // library path, so they need to install to the system directly. - // Note that this is really just a testing path. - std::string scriptSONameSystem("/system/lib/librs."); - scriptSONameSystem.append(resName); - scriptSONameSystem.append(".so"); - loaded = loadSOHelper(scriptSONameSystem.c_str(), cacheDir, - resName); - if (loaded == nullptr) { - ALOGE("Unable to open system shared library (%s): %s", - scriptSONameSystem.c_str(), dlerror()); - } -#endif - } - - return loaded; -} - -void* SharedLibraryUtils::loadSOHelper(const char *origName, const char *cacheDir, - const char *resName) { - // Keep track of which .so libraries have been loaded. Once a library is - // in the set (per-process granularity), we must instead make a copy of - // the original shared object (randomly named .so file) and load that one - // instead. If we don't do this, we end up aliasing global data between - // the various Script instances (which are supposed to be completely - // independent). - static std::set<std::string> LoadedLibraries; - - void *loaded = nullptr; - - // Skip everything if we don't even have the original library available. - if (access(origName, F_OK) != 0) { - return nullptr; - } - - // Common path is that we have not loaded this Script/library before. - if (LoadedLibraries.find(origName) == LoadedLibraries.end()) { - loaded = dlopen(origName, RTLD_NOW | RTLD_LOCAL); - if (loaded) { - LoadedLibraries.insert(origName); - } - return loaded; - } - - std::string newName(cacheDir); - - // Append RS_CACHE_DIR only if it is not found in cacheDir - // In driver mode, RS_CACHE_DIR is already appended to cacheDir. - if (newName.find(RS_CACHE_DIR) == std::string::npos) { - newName.append("/"); - newName.append(RS_CACHE_DIR); - newName.append("/"); - } - - if (!ensureCacheDirExists(newName.c_str())) { - ALOGE("Could not verify or create cache dir: %s", cacheDir); - return nullptr; - } - - // Construct an appropriately randomized filename for the copy. - newName.append("librs."); - newName.append(resName); - newName.append("#"); - newName.append(getRandomString(6)); // 62^6 potential filename variants. - newName.append(".so"); - - int r = copyFile(newName.c_str(), origName); - if (r != 0) { - ALOGE("Could not create copy %s -> %s", origName, newName.c_str()); - return nullptr; - } - loaded = dlopen(newName.c_str(), RTLD_NOW | RTLD_LOCAL); - r = unlink(newName.c_str()); - if (r != 0) { - ALOGE("Could not unlink copy %s", newName.c_str()); - } - if (loaded) { - LoadedLibraries.insert(newName.c_str()); - } - - return loaded; -} - -const char* RsdCpuScriptImpl::BCC_EXE_PATH = "/system/bin/bcc"; - -#define MAXLINE 500 -#define MAKE_STR_HELPER(S) #S -#define MAKE_STR(S) MAKE_STR_HELPER(S) -#define EXPORT_VAR_STR "exportVarCount: " -#define EXPORT_FUNC_STR "exportFuncCount: " -#define EXPORT_FOREACH_STR "exportForEachCount: " -#define OBJECT_SLOT_STR "objectSlotCount: " -#define PRAGMA_STR "pragmaCount: " -#define THREADABLE_STR "isThreadable: " - -// Copy up to a newline or size chars from str -> s, updating str -// Returns s when successful and nullptr when '\0' is finally reached. -static char* strgets(char *s, int size, const char **ppstr) { - if (!ppstr || !*ppstr || **ppstr == '\0' || size < 1) { - return nullptr; - } - - int i; - for (i = 0; i < (size - 1); i++) { - s[i] = **ppstr; - (*ppstr)++; - if (s[i] == '\0') { - return s; - } else if (s[i] == '\n') { - s[i+1] = '\0'; - return s; - } - } - - // size has been exceeded. - s[i] = '\0'; - - return s; -} - RsdCpuScriptImpl::RsdCpuScriptImpl(RsdCpuReferenceImpl *ctx, const Script *s) { mCtx = ctx; mScript = s; @@ -537,265 +237,6 @@ bool RsdCpuScriptImpl::storeRSInfoFromSO() { return true; } -ScriptExecutable* ScriptExecutable::createFromSharedObject( - Context* RSContext, void* sharedObj) { - char line[MAXLINE]; - - size_t varCount = 0; - size_t funcCount = 0; - size_t forEachCount = 0; - size_t objectSlotCount = 0; - size_t pragmaCount = 0; - bool isThreadable = true; - - void** fieldAddress = nullptr; - bool* fieldIsObject = nullptr; - InvokeFunc_t* invokeFunctions = nullptr; - ForEachFunc_t* forEachFunctions = nullptr; - uint32_t* forEachSignatures = nullptr; - const char ** pragmaKeys = nullptr; - const char ** pragmaValues = nullptr; - - const char *rsInfo = (const char *) dlsym(sharedObj, ".rs.info"); - - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - return nullptr; - } - if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) { - ALOGE("Invalid export var count!: %s", line); - return nullptr; - } - - fieldAddress = new void*[varCount]; - if (fieldAddress == nullptr) { - return nullptr; - } - - fieldIsObject = new bool[varCount]; - if (fieldIsObject == nullptr) { - goto error; - } - - for (size_t i = 0; i < varCount; ++i) { - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - char *c = strrchr(line, '\n'); - if (c) { - *c = '\0'; - } - void* addr = dlsym(sharedObj, line); - if (addr == nullptr) { - ALOGE("Failed to find variable address for %s: %s", - line, dlerror()); - // Not a critical error if we don't find a global variable. - } - fieldAddress[i] = addr; - fieldIsObject[i] = false; - } - - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) { - ALOGE("Invalid export func count!: %s", line); - goto error; - } - - invokeFunctions = new InvokeFunc_t[funcCount]; - if (invokeFunctions == nullptr) { - goto error; - } - - for (size_t i = 0; i < funcCount; ++i) { - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - char *c = strrchr(line, '\n'); - if (c) { - *c = '\0'; - } - - invokeFunctions[i] = (InvokeFunc_t) dlsym(sharedObj, line); - if (invokeFunctions[i] == nullptr) { - ALOGE("Failed to get function address for %s(): %s", - line, dlerror()); - goto error; - } - } - - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) { - ALOGE("Invalid export forEach count!: %s", line); - goto error; - } - - forEachFunctions = new ForEachFunc_t[forEachCount]; - if (forEachFunctions == nullptr) { - goto error; - } - - forEachSignatures = new uint32_t[forEachCount]; - if (forEachSignatures == nullptr) { - goto error; - } - - for (size_t i = 0; i < forEachCount; ++i) { - unsigned int tmpSig = 0; - char tmpName[MAXLINE]; - - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s", - &tmpSig, tmpName) != 2) { - ALOGE("Invalid export forEach!: %s", line); - goto error; - } - - // Lookup the expanded ForEach kernel. - strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName)); - forEachSignatures[i] = tmpSig; - forEachFunctions[i] = - (ForEachFunc_t) dlsym(sharedObj, tmpName); - if (i != 0 && forEachFunctions[i] == nullptr) { - // Ignore missing root.expand functions. - // root() is always specified at location 0. - ALOGE("Failed to find forEach function address for %s: %s", - tmpName, dlerror()); - goto error; - } - } - - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) { - ALOGE("Invalid object slot count!: %s", line); - goto error; - } - - for (size_t i = 0; i < objectSlotCount; ++i) { - uint32_t varNum = 0; - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - if (sscanf(line, "%u", &varNum) != 1) { - ALOGE("Invalid object slot!: %s", line); - goto error; - } - - if (varNum < varCount) { - fieldIsObject[varNum] = true; - } - } - -#ifndef RS_COMPATIBILITY_LIB - // Do not attempt to read pragmas or isThreadable flag in compat lib path. - // Neither is applicable for compat lib - - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - - if (sscanf(line, PRAGMA_STR "%zu", &pragmaCount) != 1) { - ALOGE("Invalid pragma count!: %s", line); - goto error; - } - - pragmaKeys = new const char*[pragmaCount]; - if (pragmaKeys == nullptr) { - goto error; - } - - pragmaValues = new const char*[pragmaCount]; - if (pragmaValues == nullptr) { - goto error; - } - - bzero(pragmaKeys, sizeof(char*) * pragmaCount); - bzero(pragmaValues, sizeof(char*) * pragmaCount); - - for (size_t i = 0; i < pragmaCount; ++i) { - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - ALOGE("Unable to read pragma at index %zu!", i); - goto error; - } - - char key[MAXLINE]; - char value[MAXLINE] = ""; // initialize in case value is empty - - // pragmas can just have a key and no value. Only check to make sure - // that the key is not empty - if (sscanf(line, "%" MAKE_STR(MAXLINE) "s - %" MAKE_STR(MAXLINE) "s", - key, value) == 0 || - strlen(key) == 0) - { - ALOGE("Invalid pragma value!: %s", line); - - goto error; - } - - char *pKey = new char[strlen(key)+1]; - strcpy(pKey, key); - pragmaKeys[i] = pKey; - - char *pValue = new char[strlen(value)+1]; - strcpy(pValue, value); - pragmaValues[i] = pValue; - //ALOGE("Pragma %zu: Key: '%s' Value: '%s'", i, pKey, pValue); - } - - if (strgets(line, MAXLINE, &rsInfo) == nullptr) { - goto error; - } - - char tmpFlag[4]; - if (sscanf(line, THREADABLE_STR "%4s", tmpFlag) != 1) { - ALOGE("Invalid threadable flag!: %s", line); - goto error; - } - if (strcmp(tmpFlag, "yes") == 0) { - isThreadable = true; - } else if (strcmp(tmpFlag, "no") == 0) { - isThreadable = false; - } else { - ALOGE("Invalid threadable flag!: %s", tmpFlag); - goto error; - } - -#endif // RS_COMPATIBILITY_LIB - - return new ScriptExecutable( - RSContext, fieldAddress, fieldIsObject, varCount, - invokeFunctions, funcCount, - forEachFunctions, forEachSignatures, forEachCount, - pragmaKeys, pragmaValues, pragmaCount, - isThreadable); - -error: - -#ifndef RS_COMPATIBILITY_LIB - for (size_t idx = 0; idx < pragmaCount; ++idx) { - delete [] pragmaKeys[idx]; - delete [] pragmaValues[idx]; - } - - delete[] pragmaValues; - delete[] pragmaKeys; -#endif // RS_COMPATIBILITY_LIB - - delete[] forEachSignatures; - delete[] forEachFunctions; - delete[] invokeFunctions; - delete[] fieldIsObject; - delete[] fieldAddress; - - return nullptr; -} - bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, uint8_t const *bitcode, size_t bitcodeSize, uint32_t flags, char const *bccPluginName) { @@ -846,8 +287,9 @@ bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir, setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib, useRSDebugContext, bccPluginName); // The last argument of compileArguments ia a nullptr, so remove 1 from the size. - std::string compileCommandLine = - getCommandLine(compileArguments.size() - 1, compileArguments.data()); + std::unique_ptr<const char> joined( + rsuJoinStrings(compileArguments.size() - 1, compileArguments.data())); + std::string compileCommandLine (joined.get()); if (!is_force_recompile() && !useRSDebugContext) { mScriptSO = SharedLibraryUtils::loadSharedLibrary(cacheDir, resName); |
