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