• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 //===----------------------------------------------------------------------===//
18 // This file implements RSInfo::ReadFromFile()
19 //===----------------------------------------------------------------------===//
20 
21 #include "bcc/Renderscript/RSInfo.h"
22 
23 #include <new>
24 
25 #include <utils/FileMap.h>
26 
27 #include "bcc/Support/Log.h"
28 #include "bcc/Support/InputFile.h"
29 
30 using namespace bcc;
31 
32 namespace {
33 
34 template<typename ItemType, typename ItemContainer>
35 inline bool helper_read_list_item(const ItemType &pItem,
36                                   const RSInfo &pInfo,
37                                   ItemContainer &pResult);
38 
39 // Process DependencyTableItem in the file
40 template<> inline bool
helper_read_list_item(const rsinfo::DependencyTableItem & pItem,const RSInfo & pInfo,RSInfo::DependencyTableTy & pResult)41 helper_read_list_item<rsinfo::DependencyTableItem, RSInfo::DependencyTableTy>(
42     const rsinfo::DependencyTableItem &pItem,
43     const RSInfo &pInfo,
44     RSInfo::DependencyTableTy &pResult)
45 {
46   const char *id = pInfo.getStringFromPool(pItem.id);
47   const uint8_t *sha1 =
48       reinterpret_cast<const uint8_t *>(pInfo.getStringFromPool(pItem.sha1));
49 
50   if (id == NULL) {
51     ALOGE("Invalid string index %d for source id in RS dependenct table.",
52           pItem.id);
53     return false;
54   }
55 
56   if (sha1 == NULL) {
57     ALOGE("Invalid string index %d for SHA-1 checksum in RS dependenct table.",
58           pItem.id);
59     return false;
60   }
61 
62   pResult.push(std::make_pair(id, sha1));
63   return true;
64 }
65 
66 // Process PragmaItem in the file
67 template<> inline bool
helper_read_list_item(const rsinfo::PragmaItem & pItem,const RSInfo & pInfo,RSInfo::PragmaListTy & pResult)68 helper_read_list_item<rsinfo::PragmaItem, RSInfo::PragmaListTy>(
69     const rsinfo::PragmaItem &pItem,
70     const RSInfo &pInfo,
71     RSInfo::PragmaListTy &pResult)
72 {
73   const char *key = pInfo.getStringFromPool(pItem.key);
74   const char *value =pInfo.getStringFromPool(pItem.value);
75 
76   if (key == NULL) {
77     ALOGE("Invalid string index %d for key in RS pragma list.", pItem.key);
78     return false;
79   }
80 
81   if (value == NULL) {
82     ALOGE("Invalid string index %d for value in RS pragma list.", pItem.value);
83     return false;
84   }
85 
86   pResult.push(std::make_pair(key, value));
87   return true;
88 }
89 
90 // Procee ObjectSlotItem in the file
91 template<> inline bool
helper_read_list_item(const rsinfo::ObjectSlotItem & pItem,const RSInfo & pInfo,RSInfo::ObjectSlotListTy & pResult)92 helper_read_list_item<rsinfo::ObjectSlotItem, RSInfo::ObjectSlotListTy>(
93     const rsinfo::ObjectSlotItem &pItem,
94     const RSInfo &pInfo,
95     RSInfo::ObjectSlotListTy &pResult)
96 {
97   pResult.push(pItem.slot);
98   return true;
99 }
100 
101 // Procee ExportVarNameItem in the file
102 template<> inline bool
helper_read_list_item(const rsinfo::ExportVarNameItem & pItem,const RSInfo & pInfo,RSInfo::ExportVarNameListTy & pResult)103 helper_read_list_item<rsinfo::ExportVarNameItem, RSInfo::ExportVarNameListTy>(
104     const rsinfo::ExportVarNameItem &pItem,
105     const RSInfo &pInfo,
106     RSInfo::ExportVarNameListTy &pResult)
107 {
108   const char *name = pInfo.getStringFromPool(pItem.name);
109 
110   if (name == NULL) {
111     ALOGE("Invalid string index %d for name in RS export vars.", pItem.name);
112     return false;
113   }
114 
115   pResult.push(name);
116   return true;
117 }
118 
119 // Procee ExportFuncNameItem in the file
120 template<> inline bool
helper_read_list_item(const rsinfo::ExportFuncNameItem & pItem,const RSInfo & pInfo,RSInfo::ExportFuncNameListTy & pResult)121 helper_read_list_item<rsinfo::ExportFuncNameItem, RSInfo::ExportFuncNameListTy>(
122     const rsinfo::ExportFuncNameItem &pItem,
123     const RSInfo &pInfo,
124     RSInfo::ExportFuncNameListTy &pResult)
125 {
126   const char *name = pInfo.getStringFromPool(pItem.name);
127 
128   if (name == NULL) {
129     ALOGE("Invalid string index %d for name in RS export funcs.", pItem.name);
130     return false;
131   }
132 
133   pResult.push(name);
134   return true;
135 }
136 
137 // Procee ExportForeachFuncItem in the file
138 template<> inline bool
helper_read_list_item(const rsinfo::ExportForeachFuncItem & pItem,const RSInfo & pInfo,RSInfo::ExportForeachFuncListTy & pResult)139 helper_read_list_item<rsinfo::ExportForeachFuncItem, RSInfo::ExportForeachFuncListTy>(
140     const rsinfo::ExportForeachFuncItem &pItem,
141     const RSInfo &pInfo,
142     RSInfo::ExportForeachFuncListTy &pResult)
143 {
144   const char *name = pInfo.getStringFromPool(pItem.name);
145 
146   if (name == NULL) {
147     ALOGE("Invalid string index %d for name in RS export foreachs.", pItem.name);
148     return false;
149   }
150 
151   pResult.push(std::make_pair(name, pItem.signature));
152   return true;
153 }
154 
155 template<typename ItemType, typename ItemContainer>
helper_read_list(const uint8_t * pData,const RSInfo & pInfo,const rsinfo::ListHeader & pHeader,ItemContainer & pResult)156 inline bool helper_read_list(const uint8_t *pData,
157                              const RSInfo &pInfo,
158                              const rsinfo::ListHeader &pHeader,
159                              ItemContainer &pResult) {
160   const ItemType *item;
161 
162   // Out-of-range exception has been checked.
163   for (uint32_t i = 0; i < pHeader.count; i++) {
164     item = reinterpret_cast<const ItemType *>(pData +
165                                               pHeader.offset +
166                                               i * pHeader.itemSize);
167     if (!helper_read_list_item<ItemType, ItemContainer>(*item, pInfo, pResult)) {
168       return false;
169     }
170   }
171   return true;
172 }
173 
174 } // end anonymous namespace
175 
ReadFromFile(InputFile & pInput,const DependencyTableTy & pDeps)176 RSInfo *RSInfo::ReadFromFile(InputFile &pInput, const DependencyTableTy &pDeps) {
177   android::FileMap *map = NULL;
178   RSInfo *result = NULL;
179   const uint8_t *data;
180   const rsinfo::Header *header;
181   size_t filesize;
182   const char *input_filename = pInput.getName().c_str();
183   const off_t cur_input_offset = pInput.tell();
184 
185   if (pInput.hasError()) {
186     ALOGE("Invalid RS info file %s! (%s)", input_filename,
187                                            pInput.getErrorMessage().c_str());
188     goto bail;
189   }
190 
191   filesize = pInput.getSize();
192   if (pInput.hasError()) {
193     ALOGE("Failed to get the size of RS info file %s! (%s)",
194           input_filename, pInput.getErrorMessage().c_str());
195     goto bail;
196   }
197 
198   // Create memory map for the file.
199   map = pInput.createMap(/* pOffset */cur_input_offset,
200                          /* pLength */filesize - cur_input_offset);
201   if (map == NULL) {
202     ALOGE("Failed to map RS info file %s to the memory! (%s)",
203           input_filename, pInput.getErrorMessage().c_str());
204     goto bail;
205   }
206 
207   data = reinterpret_cast<const uint8_t *>(map->getDataPtr());
208 
209   // Header starts at the beginning of the file.
210   header = reinterpret_cast<const rsinfo::Header *>(data);
211 
212   // Check the magic.
213   if (::memcmp(header->magic, RSINFO_MAGIC, sizeof(header->magic)) != 0) {
214     ALOGV("Wrong magic found in the RS info file %s. Treat it as a dirty "
215           "cache.", input_filename);
216     goto bail;
217   }
218 
219   // Check the version.
220   if (::memcmp(header->version,
221                RSINFO_VERSION,
222                sizeof((header->version)) != 0)) {
223     ALOGV("Mismatch the version of RS info file %s: (current) %s v.s. (file) "
224           "%s. Treat it as as a dirty cache.", input_filename, RSINFO_VERSION,
225           header->version);
226     goto bail;
227   }
228 
229   // Check the size.
230   if ((header->headerSize != sizeof(rsinfo::Header)) ||
231       (header->dependencyTable.itemSize != sizeof(rsinfo::DependencyTableItem)) ||
232       (header->pragmaList.itemSize != sizeof(rsinfo::PragmaItem)) ||
233       (header->objectSlotList.itemSize != sizeof(rsinfo::ObjectSlotItem)) ||
234       (header->exportVarNameList.itemSize != sizeof(rsinfo::ExportVarNameItem)) ||
235       (header->exportFuncNameList.itemSize != sizeof(rsinfo::ExportFuncNameItem)) ||
236       (header->exportForeachFuncList.itemSize != sizeof(rsinfo::ExportForeachFuncItem))) {
237     ALOGW("Corrupted RS info file %s! (unexpected size found)", input_filename);
238     goto bail;
239   }
240 
241   // Check the range.
242 #define LIST_DATA_RANGE(_list_header) \
243   ((_list_header).offset + (_list_header).count * (_list_header).itemSize)
244   if (((header->headerSize + header->strPoolSize) > filesize) ||
245       (LIST_DATA_RANGE(header->dependencyTable) > filesize) ||
246       (LIST_DATA_RANGE(header->pragmaList) > filesize) ||
247       (LIST_DATA_RANGE(header->objectSlotList) > filesize) ||
248       (LIST_DATA_RANGE(header->exportVarNameList) > filesize) ||
249       (LIST_DATA_RANGE(header->exportFuncNameList) > filesize) ||
250       (LIST_DATA_RANGE(header->exportForeachFuncList) > filesize)) {
251     ALOGW("Corrupted RS info file %s! (data out of the range)", input_filename);
252     goto bail;
253   }
254 #undef LIST_DATA_RANGE
255 
256   // File seems ok, create result RSInfo object.
257   result = new (std::nothrow) RSInfo(header->strPoolSize);
258   if (result == NULL) {
259     ALOGE("Out of memory when create RSInfo object for %s!", input_filename);
260     goto bail;
261   }
262 
263   // Make advice on our access pattern.
264   map->advise(android::FileMap::SEQUENTIAL);
265 
266   // Copy the header.
267   ::memcpy(&result->mHeader, header, sizeof(rsinfo::Header));
268 
269   if (header->strPoolSize > 0) {
270     // Copy the string pool. The string pool is immediately after the header at
271     // the offset header->headerSize.
272     if (result->mStringPool == NULL) {
273       ALOGE("Out of memory when allocate string pool for RS info file %s!",
274             input_filename);
275       goto bail;
276     }
277     ::memcpy(result->mStringPool, data + result->mHeader.headerSize,
278              result->mHeader.strPoolSize);
279   }
280 
281   // Populate all the data to the result object.
282   if (!helper_read_list<rsinfo::DependencyTableItem, DependencyTableTy>
283         (data, *result, header->dependencyTable, result->mDependencyTable)) {
284     goto bail;
285   }
286 
287   // Check dependency to see whether the cache is dirty or not.
288   if (!CheckDependency(*result, pInput.getName().c_str(), pDeps)) {
289     goto bail;
290   }
291 
292   if (!helper_read_list<rsinfo::PragmaItem, PragmaListTy>
293         (data, *result, header->pragmaList, result->mPragmas)) {
294     goto bail;
295   }
296 
297   if (!helper_read_list<rsinfo::ObjectSlotItem, ObjectSlotListTy>
298         (data, *result, header->objectSlotList, result->mObjectSlots)) {
299     goto bail;
300   }
301 
302   if (!helper_read_list<rsinfo::ExportVarNameItem, ExportVarNameListTy>
303         (data, *result, header->exportVarNameList, result->mExportVarNames)) {
304     goto bail;
305   }
306 
307   if (!helper_read_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy>
308         (data, *result, header->exportFuncNameList, result->mExportFuncNames)) {
309     goto bail;
310   }
311 
312   if (!helper_read_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy>
313         (data, *result, header->exportForeachFuncList, result->mExportForeachFuncs)) {
314     goto bail;
315   }
316 
317   // Clean up.
318   map->release();
319 
320   return result;
321 
322 bail:
323   if (map != NULL) {
324     map->release();
325   }
326 
327   delete result;
328 
329   return NULL;
330 } // RSInfo::ReadFromFile
331