1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_RENDERSCRIPT_EXECUTABLE_H
18 #define ANDROID_RENDERSCRIPT_EXECUTABLE_H
19 
20 #include <stdlib.h>
21 
22 #include "rsCpuScript.h"
23 
24 namespace android {
25 namespace renderscript {
26 
27 class Context;
28 
29 class SharedLibraryUtils {
30 public:
31 #ifndef RS_COMPATIBILITY_LIB
32     static bool createSharedLibrary(const char* driverName,
33                                     const char* cacheDir,
34                                     const char* resName);
35 #endif
36 
37     // Load the shared library referred to by cacheDir and resName. If we have
38     // already loaded this library, we instead create a new copy (in the
39     // cache dir) and then load that. We then immediately destroy the copy.
40     // This is required behavior to implement script instancing for the support
41     // library, since shared objects are loaded and de-duped by name only.
42 
43     // For 64bit RS Support Lib, the shared lib path cannot be constructed from
44     // cacheDir, so nativeLibDir is needed to load shared libs.
45     static void* loadSharedLibrary(const char *cacheDir, const char *resName,
46                                    const char *nativeLibDir = nullptr,
47                                    bool *alreadyLoaded = nullptr);
48 
49     // Create a len length string containing random characters from [A-Za-z0-9].
50     static String8 getRandomString(size_t len);
51 
52 private:
53     // Attempt to load the shared library from origName, but then fall back to
54     // creating a copy of the shared library if necessary (to ensure instancing).
55     // This function returns the dlopen()-ed handle if successful.
56     static void *loadSOHelper(const char *origName, const char *cacheDir,
57                               const char *resName, bool* alreadyLoaded = nullptr);
58 
59     static const char* LD_EXE_PATH;
60     static const char* RS_CACHE_DIR;
61 };
62 
63 class ScriptExecutable {
64 public:
ScriptExecutable(Context * RSContext,void ** fieldAddress,bool * fieldIsObject,const char * const * fieldName,size_t varCount,InvokeFunc_t * invokeFunctions,size_t funcCount,ForEachFunc_t * forEachFunctions,uint32_t * forEachSignatures,size_t forEachCount,const char ** pragmaKeys,const char ** pragmaValues,size_t pragmaCount,const char ** globalNames,const void ** globalAddresses,const size_t * globalSizes,const uint32_t * globalProperties,size_t globalEntries,bool isThreadable,uint32_t buildChecksum)65     ScriptExecutable(Context* RSContext,
66                      void** fieldAddress, bool* fieldIsObject,
67                      const char* const * fieldName, size_t varCount,
68                      InvokeFunc_t* invokeFunctions, size_t funcCount,
69                      ForEachFunc_t* forEachFunctions, uint32_t* forEachSignatures,
70                      size_t forEachCount,
71                      const char** pragmaKeys, const char** pragmaValues,
72                      size_t pragmaCount,
73                      const char **globalNames, const void **globalAddresses,
74                      const size_t *globalSizes,
75                      const uint32_t *globalProperties, size_t globalEntries,
76                      bool isThreadable, uint32_t buildChecksum) :
77         mFieldAddress(fieldAddress), mFieldIsObject(fieldIsObject),
78         mFieldName(fieldName), mExportedVarCount(varCount),
79         mInvokeFunctions(invokeFunctions), mFuncCount(funcCount),
80         mForEachFunctions(forEachFunctions), mForEachSignatures(forEachSignatures),
81         mForEachCount(forEachCount),
82         mPragmaKeys(pragmaKeys), mPragmaValues(pragmaValues),
83         mPragmaCount(pragmaCount), mGlobalNames(globalNames),
84         mGlobalAddresses(globalAddresses), mGlobalSizes(globalSizes),
85         mGlobalProperties(globalProperties), mGlobalEntries(globalEntries),
86         mIsThreadable(isThreadable), mBuildChecksum(buildChecksum),
87         mRS(RSContext) {
88     }
89 
~ScriptExecutable()90     ~ScriptExecutable() {
91         for (size_t i = 0; i < mExportedVarCount; ++i) {
92             if (mFieldIsObject[i]) {
93                 if (mFieldAddress[i] != nullptr) {
94                     rs_object_base *obj_addr =
95                             reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
96                     rsrClearObject(mRS, obj_addr);
97                 }
98             }
99         }
100 
101         for (size_t i = 0; i < mPragmaCount; ++i) {
102             delete [] mPragmaKeys[i];
103             delete [] mPragmaValues[i];
104         }
105         delete[] mPragmaValues;
106         delete[] mPragmaKeys;
107 
108         delete[] mForEachSignatures;
109         delete[] mForEachFunctions;
110 
111         delete[] mInvokeFunctions;
112 
113         for (size_t i = 0; i < mExportedVarCount; i++) {
114             delete[] mFieldName[i];
115         }
116         delete[] mFieldName;
117         delete[] mFieldIsObject;
118         delete[] mFieldAddress;
119     }
120 
121     // Create an ScriptExecutable object from a shared object.
122     // If expectedChecksum is not zero, it will be compared to the checksum
123     // embedded in the shared object. A mismatch will cause a failure.
124     // If succeeded, returns the new object. Otherwise, returns nullptr.
125     static ScriptExecutable*
126             createFromSharedObject(Context* RSContext, void* sharedObj,
127                                    uint32_t expectedChecksum = 0);
128 
getExportedVariableCount()129     size_t getExportedVariableCount() const { return mExportedVarCount; }
getExportedFunctionCount()130     size_t getExportedFunctionCount() const { return mFuncCount; }
getExportedForEachCount()131     size_t getExportedForEachCount() const { return mForEachCount; }
getPragmaCount()132     size_t getPragmaCount() const { return mPragmaCount; }
133 
getFieldAddress(int slot)134     void* getFieldAddress(int slot) const { return mFieldAddress[slot]; }
135     void* getFieldAddress(const char* name) const;
getFieldIsObject(int slot)136     bool getFieldIsObject(int slot) const { return mFieldIsObject[slot]; }
getFieldName(int slot)137     const char* getFieldName(int slot) const { return mFieldName[slot]; }
138 
getInvokeFunction(int slot)139     InvokeFunc_t getInvokeFunction(int slot) const { return mInvokeFunctions[slot]; }
140 
getForEachFunction(int slot)141     ForEachFunc_t getForEachFunction(int slot) const { return mForEachFunctions[slot]; }
getForEachSignature(int slot)142     uint32_t getForEachSignature(int slot) const { return mForEachSignatures[slot]; }
143 
getPragmaKeys()144     const char ** getPragmaKeys() const { return mPragmaKeys; }
getPragmaValues()145     const char ** getPragmaValues() const { return mPragmaValues; }
146 
getGlobalName(int i)147     const char* getGlobalName(int i) const {
148         if (i < mGlobalEntries) {
149             return mGlobalNames[i];
150         } else {
151             return nullptr;
152         }
153     }
getGlobalAddress(int i)154     const void* getGlobalAddress(int i) const {
155         if (i < mGlobalEntries) {
156             return mGlobalAddresses[i];
157         } else {
158             return nullptr;
159         }
160     }
getGlobalSize(int i)161     size_t getGlobalSize(int i) const {
162         if (i < mGlobalEntries) {
163             return mGlobalSizes[i];
164         } else {
165             return 0;
166         }
167     }
getGlobalProperties(int i)168     uint32_t getGlobalProperties(int i) const {
169         if (i < mGlobalEntries) {
170             return mGlobalProperties[i];
171         } else {
172             return 0;
173         }
174     }
getGlobalEntries()175     int getGlobalEntries() const { return mGlobalEntries; }
176 
getThreadable()177     bool getThreadable() const { return mIsThreadable; }
178 
getBuildChecksum()179     uint32_t getBuildChecksum() const { return mBuildChecksum; }
180 
181     bool dumpGlobalInfo() const;
182 
183 private:
184     void** mFieldAddress;
185     bool* mFieldIsObject;
186     const char* const * mFieldName;
187     size_t mExportedVarCount;
188 
189     InvokeFunc_t* mInvokeFunctions;
190     size_t mFuncCount;
191 
192     ForEachFunc_t* mForEachFunctions;
193     uint32_t* mForEachSignatures;
194     size_t mForEachCount;
195 
196     const char ** mPragmaKeys;
197     const char ** mPragmaValues;
198     size_t mPragmaCount;
199 
200     const char ** mGlobalNames;
201     const void ** mGlobalAddresses;
202     const size_t * mGlobalSizes;
203     const uint32_t * mGlobalProperties;
204     int mGlobalEntries;
205 
206     bool mIsThreadable;
207     uint32_t mBuildChecksum;
208 
209     Context* mRS;
210 };
211 
212 }  // namespace renderscript
213 }  // namespace android
214 
215 #endif  // ANDROID_RENDERSCRIPT_EXECUTABLE_H
216