blob: de730edd6a7bace3f40ffd29fbbef667ac6bf5d9 [file] [log] [blame]
Zonr Changbf6498e2012-04-13 14:35:45 +08001/*
2 * Copyright 2012, 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
Zonr Chang80232dd2012-04-12 15:38:53 +080017#include "bcc/RenderScript/RSExecutable.h"
Zonr Changbf6498e2012-04-13 14:35:45 +080018
Zonr Chang80232dd2012-04-12 15:38:53 +080019#include "bcc/Support/DebugHelper.h"
20#include "bcc/Support/FileBase.h"
21#include "bcc/Support/OutputFile.h"
22#include "bcc/ExecutionEngine/SymbolResolverProxy.h"
Zonr Changbf6498e2012-04-13 14:35:45 +080023
24#include <utils/String8.h>
25
26using namespace bcc;
27
28const char *RSExecutable::SpecialFunctionNames[] = {
29 "root",
30 "init",
31 ".rs.dtor",
32 // Must be NULL-terminated.
33 NULL
34};
35
36RSExecutable *RSExecutable::Create(RSInfo &pInfo,
37 FileBase &pObjFile,
38 SymbolResolverProxy &pResolver) {
39 // Load the object file. Enable the GDB's JIT debugging if the script contains
40 // debug information.
41 ObjectLoader *loader = ObjectLoader::Load(pObjFile,
42 pResolver,
43 pInfo.hasDebugInformation());
44 if (loader == NULL) {
45 return NULL;
46 }
47
48 // Now, all things required to build a RSExecutable object are ready.
49 RSExecutable *result = new (std::nothrow) RSExecutable(pInfo,
50 pObjFile,
51 *loader);
52 if (result == NULL) {
53 ALOGE("Out of memory when create object to hold RS result file for %s!",
54 pObjFile.getName().c_str());
55 return NULL;
56 }
57
58 unsigned idx;
59 // Resolve addresses of RS export vars.
60 idx = 0;
61 const RSInfo::ExportVarNameListTy &export_var_names =
62 pInfo.getExportVarNames();
63 for (RSInfo::ExportVarNameListTy::const_iterator
64 var_iter = export_var_names.begin(),
65 var_end = export_var_names.end(); var_iter != var_end;
66 var_iter++, idx++) {
67 const char *name = *var_iter;
68 void *addr = result->getSymbolAddress(name);
69 if (addr == NULL) {
70 ALOGW("RS export var at entry #%u named %s cannot be found in the result "
71 "object!", idx, name);
72 }
73 result->mExportVarAddrs.push_back(addr);
74 }
75
76 // Resolve addresses of RS export functions.
77 idx = 0;
78 const RSInfo::ExportFuncNameListTy &export_func_names =
79 pInfo.getExportFuncNames();
80 for (RSInfo::ExportFuncNameListTy::const_iterator
81 func_iter = export_func_names.begin(),
82 func_end = export_func_names.end(); func_iter != func_end;
83 func_iter++, idx++) {
84 const char *name = *func_iter;
85 void *addr = result->getSymbolAddress(name);
86 if (addr == NULL) {
87 ALOGW("RS export func at entry #%u named %s cannot be found in the result"
88 " object!", idx, name);
89 }
90 result->mExportFuncAddrs.push_back(addr);
91 }
92
93 // Resolve addresses of expanded RS foreach function.
94 idx = 0;
95 const RSInfo::ExportForeachFuncListTy &export_foreach_funcs =
96 pInfo.getExportForeachFuncs();
97 for (RSInfo::ExportForeachFuncListTy::const_iterator
98 foreach_iter = export_foreach_funcs.begin(),
99 foreach_end = export_foreach_funcs.end();
100 foreach_iter != foreach_end; foreach_iter++, idx++) {
101 const char *func_name = foreach_iter->first;
102 android::String8 expanded_func_name(func_name);
103 expanded_func_name.append(".expand");
104 void *addr = result->getSymbolAddress(expanded_func_name.string());
105 if (addr == NULL) {
106 ALOGW("Expanded RS foreach at entry #%u named %s cannot be found in the "
107 "result object!", idx, expanded_func_name.string());
108 }
109 result->mExportForeachFuncAddrs.push_back(addr);
110 }
111
112 // Copy pragma key/value pairs from RSInfo::getPragmas() into mPragmaKeys and
113 // mPragmaValues, respectively.
114 const RSInfo::PragmaListTy &pragmas = pInfo.getPragmas();
115 for (RSInfo::PragmaListTy::const_iterator pragma_iter = pragmas.begin(),
116 pragma_end = pragmas.end(); pragma_iter != pragma_end;
117 pragma_iter++){
118 result->mPragmaKeys.push_back(pragma_iter->first);
119 result->mPragmaValues.push_back(pragma_iter->second);
120 }
121
122 return result;
123}
124
125bool RSExecutable::syncInfo(bool pForce) {
126 if (!pForce && !mIsInfoDirty) {
127 return true;
128 }
129
130 android::String8 info_path = RSInfo::GetPath(*mObjFile);
131 OutputFile info_file(info_path.string());
132
133 if (info_file.hasError()) {
134 ALOGE("Failed to open the info file %s for write! (%s)", info_path.string(),
135 info_file.getErrorMessage().c_str());
136 return false;
137 }
138
139 // Operation to the RS info file need to acquire the lock on the output file
140 // first.
141 if (!mObjFile->lock(FileBase::kWriteLock)) {
142 ALOGE("Write to RS info file %s required the acquisition of the write lock "
143 "on %s but got failure! (%s)", info_path.string(),
144 mObjFile->getName().c_str(), info_file.getErrorMessage().c_str());
145 return false;
146 }
147
148 // Perform the write.
149 if (!mInfo->write(info_file)) {
150 ALOGE("Failed to sync the RS info file %s!", info_path.string());
151 mObjFile->unlock();
152 return false;
153 }
154
155 mObjFile->unlock();
156 mIsInfoDirty = false;
157 return true;
158}
159
160RSExecutable::~RSExecutable() {
161 syncInfo();
162 delete mInfo;
163 delete mObjFile;
164 delete mLoader;
165}