RSInfoReader.cpp revision 1e2adce6df4414d827149ec563c9c89f21ea7426
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 "RSInfo.h" 22 23#include <new> 24 25#include <utils/FileMap.h> 26 27#include "DebugHelper.h" 28#include "InputFile.h" 29 30using namespace bcc; 31 32namespace { 33 34template<typename ItemType, typename ItemContainer> 35inline bool helper_read_list_item(const ItemType &pItem, 36 const RSInfo &pInfo, 37 ItemContainer &pResult); 38 39// Process DependencyTableItem in the file 40template<> inline bool 41helper_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 67template<> inline bool 68helper_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 91template<> inline bool 92helper_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 102template<> inline bool 103helper_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 120template<> inline bool 121helper_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 138template<> inline bool 139helper_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 155template<typename ItemType, typename ItemContainer> 156inline 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 176RSInfo *RSInfo::ReadFromFile(InputFile &pInput, 177 const RSScript::SourceDependencyListTy &pDeps) { 178 android::FileMap *map = NULL; 179 RSInfo *result = NULL; 180 const uint8_t *data; 181 const rsinfo::Header *header; 182 size_t filesize; 183 const char *input_filename = pInput.getName().c_str(); 184 const off_t cur_input_offset = pInput.tell(); 185 186 if (pInput.hasError()) { 187 ALOGE("Invalid RS info file %s! (%s)", input_filename, 188 pInput.getErrorMessage().c_str()); 189 goto bail; 190 } 191 192 filesize = pInput.getSize(); 193 if (pInput.hasError()) { 194 ALOGE("Failed to get the size of RS info file %s! (%s)", 195 input_filename, pInput.getErrorMessage().c_str()); 196 goto bail; 197 } 198 199 // Create memory map for the file. 200 map = pInput.createMap(/* pOffset */cur_input_offset, 201 /* pLength */filesize - cur_input_offset); 202 if (map == NULL) { 203 ALOGE("Failed to map RS info file %s to the memory! (%s)", 204 input_filename, pInput.getErrorMessage().c_str()); 205 goto bail; 206 } 207 208 data = reinterpret_cast<const uint8_t *>(map->getDataPtr()); 209 210 // Header starts at the beginning of the file. 211 header = reinterpret_cast<const rsinfo::Header *>(data); 212 213 // Check the magic. 214 if (::memcmp(header->magic, RSINFO_MAGIC, sizeof(header->magic)) != 0) { 215 ALOGV("Wrong magic found in the RS info file %s. Treat it as a dirty " 216 "cache.", input_filename); 217 goto bail; 218 } 219 220 // Check the version. 221 if (::memcmp(header->version, 222 RSINFO_VERSION, 223 sizeof((header->version)) != 0)) { 224 ALOGV("Mismatch the version of RS info file %s: (current) %s v.s. (file) " 225 "%s. Treat it as as a dirty cache.", input_filename, RSINFO_VERSION, 226 header->version); 227 goto bail; 228 } 229 230 // Check the size. 231 if ((header->headerSize != sizeof(rsinfo::Header)) || 232 (header->dependencyTable.itemSize != sizeof(rsinfo::DependencyTableItem)) || 233 (header->pragmaList.itemSize != sizeof(rsinfo::PragmaItem)) || 234 (header->objectSlotList.itemSize != sizeof(rsinfo::ObjectSlotItem)) || 235 (header->exportVarNameList.itemSize != sizeof(rsinfo::ExportVarNameItem)) || 236 (header->exportFuncNameList.itemSize != sizeof(rsinfo::ExportFuncNameItem)) || 237 (header->exportForeachFuncList.itemSize != sizeof(rsinfo::ExportForeachFuncItem))) { 238 ALOGW("Corrupted RS info file %s! (unexpected size found)", input_filename); 239 goto bail; 240 } 241 242 // Check the range. 243#define LIST_DATA_RANGE(_list_header) \ 244 ((_list_header).offset + (_list_header).count * (_list_header).itemSize) 245 if (((header->headerSize + header->strPoolSize) > filesize) || 246 (LIST_DATA_RANGE(header->dependencyTable) > filesize) || 247 (LIST_DATA_RANGE(header->pragmaList) > filesize) || 248 (LIST_DATA_RANGE(header->objectSlotList) > filesize) || 249 (LIST_DATA_RANGE(header->exportVarNameList) > filesize) || 250 (LIST_DATA_RANGE(header->exportFuncNameList) > filesize) || 251 (LIST_DATA_RANGE(header->exportForeachFuncList) > filesize)) { 252 ALOGW("Corrupted RS info file %s! (data out of the range)", input_filename); 253 goto bail; 254 } 255#undef LIST_DATA_RANGE 256 257 // File seems ok, create result RSInfo object. 258 result = new (std::nothrow) RSInfo(header->strPoolSize); 259 if (result == NULL) { 260 ALOGE("Out of memory when create RSInfo object for %s!", input_filename); 261 goto bail; 262 } 263 264 // Make advice on our access pattern. 265 map->advise(android::FileMap::SEQUENTIAL); 266 267 // Copy the header. 268 ::memcpy(&result->mHeader, header, sizeof(rsinfo::Header)); 269 270 if (header->strPoolSize > 0) { 271 // Copy the string pool. The string pool is immediately after the header at 272 // the offset header->headerSize. 273 if (result->mStringPool == NULL) { 274 ALOGE("Out of memory when allocate string pool for RS info file %s!", 275 input_filename); 276 goto bail; 277 } 278 ::memcpy(result->mStringPool, data + result->mHeader.headerSize, 279 result->mHeader.strPoolSize); 280 } 281 282 // Populate all the data to the result object. 283 if (!helper_read_list<rsinfo::DependencyTableItem, DependencyTableTy> 284 (data, *result, header->dependencyTable, result->mDependencyTable)) { 285 goto bail; 286 } 287 288 // Check dependency to see whether the cache is dirty or not. 289 if (!CheckDependency(*result, pInput.getName().c_str(), pDeps)) { 290 goto bail; 291 } 292 293 if (!helper_read_list<rsinfo::PragmaItem, PragmaListTy> 294 (data, *result, header->pragmaList, result->mPragmas)) { 295 goto bail; 296 } 297 298 if (!helper_read_list<rsinfo::ObjectSlotItem, ObjectSlotListTy> 299 (data, *result, header->objectSlotList, result->mObjectSlots)) { 300 goto bail; 301 } 302 303 if (!helper_read_list<rsinfo::ExportVarNameItem, ExportVarNameListTy> 304 (data, *result, header->exportVarNameList, result->mExportVarNames)) { 305 goto bail; 306 } 307 308 if (!helper_read_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy> 309 (data, *result, header->exportFuncNameList, result->mExportFuncNames)) { 310 goto bail; 311 } 312 313 if (!helper_read_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy> 314 (data, *result, header->exportForeachFuncList, result->mExportForeachFuncs)) { 315 goto bail; 316 } 317 318 // Clean up. 319 map->release(); 320 321 return result; 322 323bail: 324 if (map != NULL) { 325 map->release(); 326 } 327 328 delete result; 329 330 return NULL; 331} // RSInfo::ReadFromFile 332