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 
21 #include "rsCpuScript.h"
22 
23 #include <stdlib.h>
24 #include <string>
25 
26 namespace android {
27 namespace renderscript {
28 
29 class Context;
30 
31 class SharedLibraryUtils {
32 public:
33 #ifndef RS_COMPATIBILITY_LIB
34     // Creates a shared library in cacheDir for the bitcode named resName.
35     // If reuse is false and SOPath is not nullptr, saves the filename
36     // used for the shared library in SOPath.
37     static bool createSharedLibrary(const char* driverName,
38                                     const char* cacheDir,
39                                     const char* resName,
40                                     const bool reuse = true,
41                                     std::string *SOPath = nullptr);
42 #endif
43 
44     // Load the shared library referred to by cacheDir and resName. If we have
45     // already loaded this library, we instead create a new copy (in the
46     // cache dir) and then load that. We then immediately destroy the copy.
47     // This is required behavior to implement script instancing for the support
48     // library, since shared objects are loaded and de-duped by name only.
49 
50     // For 64bit RS Support Lib, the shared lib path cannot be constructed from
51     // cacheDir, so nativeLibDir is needed to load shared libs.
52     static void* loadSharedLibrary(const char *cacheDir, const char *resName,
53                                    const char *nativeLibDir = nullptr,
54                                    bool *alreadyLoaded = nullptr);
55 
56     // Load the shared library referred to by fullPath, and delete it right
57     // after loading it. Files loaded by this function are only used once, e.g.,
58     // shared libraries generated for scripts in a debug context. Deleting them
59     // is OK in this case since the shared libraries have already been dlopened.
60     // Deletion is also required because such files are not intended for reuse.
61     static void* loadAndDeleteSharedLibrary(const char *fullPath);
62 
63     // Create a len length string containing random characters from [A-Za-z0-9].
64     static std::string getRandomString(size_t len);
65 
66 private:
67     // Attempt to load the shared library from origName, but then fall back to
68     // creating a copy of the shared library if necessary (to ensure instancing).
69     // This function returns the dlopen()-ed handle if successful.
70     static void *loadSOHelper(const char *origName, const char *cacheDir,
71                               const char *resName, bool* alreadyLoaded = nullptr);
72 
73     static const char* LD_EXE_PATH;
74     static const char* RS_CACHE_DIR;
75 };
76 
77 class ScriptExecutable {
78 public:
ScriptExecutable(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,ReduceDescription * reduceDescriptions,size_t reduceCount,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)79     ScriptExecutable(void** fieldAddress, bool* fieldIsObject,
80                      const char* const * fieldName, size_t varCount,
81                      InvokeFunc_t* invokeFunctions, size_t funcCount,
82                      ForEachFunc_t* forEachFunctions, uint32_t* forEachSignatures,
83                      size_t forEachCount,
84                      ReduceDescription *reduceDescriptions, size_t reduceCount,
85                      const char** pragmaKeys, const char** pragmaValues,
86                      size_t pragmaCount,
87                      const char **globalNames, const void **globalAddresses,
88                      const size_t *globalSizes,
89                      const uint32_t *globalProperties, size_t globalEntries,
90                      bool isThreadable, uint32_t buildChecksum) :
91         mFieldAddress(fieldAddress), mFieldIsObject(fieldIsObject),
92         mFieldName(fieldName), mExportedVarCount(varCount),
93         mInvokeFunctions(invokeFunctions), mFuncCount(funcCount),
94         mForEachFunctions(forEachFunctions), mForEachSignatures(forEachSignatures),
95         mForEachCount(forEachCount),
96         mReduceDescriptions(reduceDescriptions), mReduceCount(reduceCount),
97         mPragmaKeys(pragmaKeys), mPragmaValues(pragmaValues),
98         mPragmaCount(pragmaCount), mGlobalNames(globalNames),
99         mGlobalAddresses(globalAddresses), mGlobalSizes(globalSizes),
100         mGlobalProperties(globalProperties), mGlobalEntries(globalEntries),
101         mIsThreadable(isThreadable), mBuildChecksum(buildChecksum) {
102     }
103 
~ScriptExecutable()104     ~ScriptExecutable() {
105         for (size_t i = 0; i < mExportedVarCount; ++i) {
106             if (mFieldIsObject[i]) {
107                 if (mFieldAddress[i] != nullptr) {
108                     rs_object_base *obj_addr =
109                             reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
110                     rsrClearObject(obj_addr);
111                 }
112             }
113         }
114 
115         for (size_t i = 0; i < mPragmaCount; ++i) {
116             delete [] mPragmaKeys[i];
117             delete [] mPragmaValues[i];
118         }
119         delete[] mPragmaValues;
120         delete[] mPragmaKeys;
121 
122         delete[] mReduceDescriptions;
123 
124         delete[] mForEachSignatures;
125         delete[] mForEachFunctions;
126 
127         delete[] mInvokeFunctions;
128 
129         for (size_t i = 0; i < mExportedVarCount; i++) {
130             delete[] mFieldName[i];
131         }
132         delete[] mFieldName;
133         delete[] mFieldIsObject;
134         delete[] mFieldAddress;
135     }
136 
137     // Create an ScriptExecutable object from a shared object.
138     // If expectedChecksum is not zero, it will be compared to the checksum
139     // embedded in the shared object. A mismatch will cause a failure.
140     // If succeeded, returns the new object. Otherwise, returns nullptr.
141     static ScriptExecutable*
142             createFromSharedObject(void* sharedObj,
143                                    uint32_t expectedChecksum = 0);
144 
getExportedVariableCount()145     size_t getExportedVariableCount() const { return mExportedVarCount; }
getExportedFunctionCount()146     size_t getExportedFunctionCount() const { return mFuncCount; }
getExportedForEachCount()147     size_t getExportedForEachCount() const { return mForEachCount; }
getExportedReduceCount()148     size_t getExportedReduceCount() const { return mReduceCount; }
getPragmaCount()149     size_t getPragmaCount() const { return mPragmaCount; }
150 
getFieldAddress(int slot)151     void* getFieldAddress(int slot) const { return mFieldAddress[slot]; }
152     void* getFieldAddress(const char* name) const;
getFieldIsObject(int slot)153     bool getFieldIsObject(int slot) const { return mFieldIsObject[slot]; }
getFieldName(int slot)154     const char* getFieldName(int slot) const { return mFieldName[slot]; }
155 
getInvokeFunction(int slot)156     InvokeFunc_t getInvokeFunction(int slot) const { return mInvokeFunctions[slot]; }
157 
getForEachFunction(int slot)158     ForEachFunc_t getForEachFunction(int slot) const { return mForEachFunctions[slot]; }
getForEachSignature(int slot)159     uint32_t getForEachSignature(int slot) const { return mForEachSignatures[slot]; }
160 
getReduceDescription(int slot)161     const ReduceDescription* getReduceDescription(int slot) const {
162         return &mReduceDescriptions[slot];
163     }
164 
getPragmaKeys()165     const char ** getPragmaKeys() const { return mPragmaKeys; }
getPragmaValues()166     const char ** getPragmaValues() const { return mPragmaValues; }
167 
getGlobalName(int i)168     const char* getGlobalName(int i) const {
169         if (i < mGlobalEntries) {
170             return mGlobalNames[i];
171         } else {
172             return nullptr;
173         }
174     }
getGlobalAddress(int i)175     const void* getGlobalAddress(int i) const {
176         if (i < mGlobalEntries) {
177             return mGlobalAddresses[i];
178         } else {
179             return nullptr;
180         }
181     }
getGlobalSize(int i)182     size_t getGlobalSize(int i) const {
183         if (i < mGlobalEntries) {
184             return mGlobalSizes[i];
185         } else {
186             return 0;
187         }
188     }
getGlobalProperties(int i)189     uint32_t getGlobalProperties(int i) const {
190         if (i < mGlobalEntries) {
191             return mGlobalProperties[i];
192         } else {
193             return 0;
194         }
195     }
getGlobalEntries()196     int getGlobalEntries() const { return mGlobalEntries; }
197 
getThreadable()198     bool getThreadable() const { return mIsThreadable; }
199 
getBuildChecksum()200     uint32_t getBuildChecksum() const { return mBuildChecksum; }
201 
202     bool dumpGlobalInfo() const;
203 
204 private:
205     void** mFieldAddress;
206     bool* mFieldIsObject;
207     const char* const * mFieldName;
208     size_t mExportedVarCount;
209 
210     InvokeFunc_t* mInvokeFunctions;
211     size_t mFuncCount;
212 
213     ForEachFunc_t* mForEachFunctions;
214     uint32_t* mForEachSignatures;
215     size_t mForEachCount;
216 
217     ReduceDescription* mReduceDescriptions;
218     size_t mReduceCount;
219 
220     const char ** mPragmaKeys;
221     const char ** mPragmaValues;
222     size_t mPragmaCount;
223 
224     const char ** mGlobalNames;
225     const void ** mGlobalAddresses;
226     const size_t * mGlobalSizes;
227     const uint32_t * mGlobalProperties;
228     int mGlobalEntries;
229 
230     bool mIsThreadable;
231     uint32_t mBuildChecksum;
232 };
233 
234 }  // namespace renderscript
235 }  // namespace android
236 
237 #endif  // ANDROID_RENDERSCRIPT_EXECUTABLE_H
238