Complete CacheReader.
diff --git a/lib/bcc/CacheReader.cpp b/lib/bcc/CacheReader.cpp
index 949987e..5dc1f85 100644
--- a/lib/bcc/CacheReader.cpp
+++ b/lib/bcc/CacheReader.cpp
@@ -36,6 +36,7 @@
#include <new>
+#include <stdlib.h>
#include <string.h>
using namespace std;
@@ -43,6 +44,13 @@
namespace bcc {
+CacheReader::~CacheReader() {
+ if (mpHeader) { free(mpHeader); }
+ if (mpCachedDependTable) { free(mpCachedDependTable); }
+ if (mpPragmaList) { free(mpPragmaList); }
+ if (mpFuncTable) { free(mpFuncTable); }
+}
+
ScriptCached *CacheReader::readCacheFile(FileHandle *file) {
// Check file handle
if (!file || file->getFD() < 0) {
@@ -50,9 +58,9 @@
}
// Allocate ScriptCached object
- mResult.reset(new (nothrow) ScriptCached(mpOwner));
+ mpResult.reset(new (nothrow) ScriptCached(mpOwner));
- if (!mResult) {
+ if (!mpResult) {
LOGE("Unable to allocate ScriptCached object.\n");
return NULL;
}
@@ -82,12 +90,12 @@
#if 0
// Check the cache file has __isThreadable or not. If it is set,
// then we have to call mpSymbolLookupFn for __clearThreadable.
- if (mHeader->libRSThreadable && mpSymbolLookupFn) {
+ if (mpHeader->libRSThreadable && mpSymbolLookupFn) {
mpSymbolLookupFn(mpSymbolLookupContext, "__clearThreadable");
}
#endif
- return result ? mResult.take() : NULL;
+ return result ? mpResult.take() : NULL;
}
@@ -116,13 +124,13 @@
return false;
}
- mHeader = (OBCC_Header *)malloc(sizeof(OBCC_Header));
- if (!mHeader) {
+ mpHeader = (OBCC_Header *)malloc(sizeof(OBCC_Header));
+ if (!mpHeader) {
LOGE("Unable to allocate for cache header.\n");
return false;
}
- if (mFile->read(reinterpret_cast<char *>(mHeader), sizeof(OBCC_Header)) !=
+ if (mFile->read(reinterpret_cast<char *>(mpHeader), sizeof(OBCC_Header)) !=
(ssize_t)sizeof(OBCC_Header)) {
LOGE("Unable to read cache header.\n");
return false;
@@ -133,14 +141,14 @@
bool CacheReader::checkHeader() {
- if (memcmp(mHeader->magic, OBCC_MAGIC, 4) != 0) {
+ if (memcmp(mpHeader->magic, OBCC_MAGIC, 4) != 0) {
LOGE("Bad magic word\n");
return false;
}
- if (memcmp(mHeader->version, OBCC_VERSION, 4) != 0) {
+ if (memcmp(mpHeader->version, OBCC_VERSION, 4) != 0) {
LOGE("Bad oBCC version 0x%08x\n",
- *reinterpret_cast<uint32_t *>(mHeader->version));
+ *reinterpret_cast<uint32_t *>(mpHeader->version));
return false;
}
@@ -152,15 +160,15 @@
uint32_t number = 0x00000001;
bool isLittleEndian = (*reinterpret_cast<char *>(&number) == 1);
- if ((isLittleEndian && mHeader->endianness != 'e') ||
- (!isLittleEndian && mHeader->endianness != 'E')) {
+ if ((isLittleEndian && mpHeader->endianness != 'e') ||
+ (!isLittleEndian && mpHeader->endianness != 'E')) {
LOGE("Machine endianness mismatch.\n");
return false;
}
- if ((unsigned int)mHeader->sizeof_off_t != sizeof(off_t) ||
- (unsigned int)mHeader->sizeof_size_t != sizeof(size_t) ||
- (unsigned int)mHeader->sizeof_ptr_t != sizeof(void *)) {
+ if ((unsigned int)mpHeader->sizeof_off_t != sizeof(off_t) ||
+ (unsigned int)mpHeader->sizeof_size_t != sizeof(size_t) ||
+ (unsigned int)mpHeader->sizeof_ptr_t != sizeof(void *)) {
LOGE("Machine integer size mismatch.\n");
return false;
}
@@ -172,8 +180,8 @@
bool CacheReader::checkSectionOffsetAndSize() {
#define CHECK_SECTION_OFFSET(NAME) \
do { \
- off_t offset = mHeader-> NAME##_offset; \
- off_t size = (off_t)mHeader-> NAME##_size; \
+ off_t offset = mpHeader-> NAME##_offset; \
+ off_t size = (off_t)mpHeader-> NAME##_size; \
\
if (mFileSize < offset || mFileSize < offset + size) { \
LOGE(#NAME " section overflow.\n"); \
@@ -200,20 +208,20 @@
#undef CHECK_SECTION_OFFSET
- if (mFileSize < mHeader->context_offset ||
- mFileSize < mHeader->context_offset + BCC_CONTEXT_SIZE) {
+ if (mFileSize < mpHeader->context_offset ||
+ mFileSize < mpHeader->context_offset + BCC_CONTEXT_SIZE) {
LOGE("context section overflow.\n");
return false;
}
long pagesize = sysconf(_SC_PAGESIZE);
- if (mHeader->context_offset % pagesize != 0) {
+ if (mpHeader->context_offset % pagesize != 0) {
LOGE("context offset must aligned to pagesize.\n");
return false;
}
// TODO(logan): Move this to some where else.
- if ((uintptr_t)mHeader->context_cached_addr % pagesize != 0) {
+ if ((uintptr_t)mpHeader->context_cached_addr % pagesize != 0) {
LOGE("cached address is not aligned to pagesize.\n");
return false;
}
@@ -222,26 +230,39 @@
}
+#define CACHE_READER_READ_SECTION(TYPE, AUTO_MANAGED_HOLDER, NAME) \
+ TYPE *NAME##_raw = (TYPE *)malloc(mpHeader->NAME##_size); \
+ \
+ if (!NAME##_raw) { \
+ LOGE("Unable to allocate for " #NAME "\n"); \
+ return false; \
+ } \
+ \
+ /* We have to ensure that some one will deallocate NAME##_raw */ \
+ AUTO_MANAGED_HOLDER = NAME##_raw; \
+ \
+ if (mFile->seek(mpHeader->NAME##_offset, SEEK_SET) == -1) { \
+ LOGE("Unable to seek to " #NAME " section\n"); \
+ return false; \
+ } \
+ \
+ if (mFile->read(reinterpret_cast<char *>(NAME##_raw), \
+ mpHeader->NAME##_size) != (ssize_t)mpHeader->NAME##_size) \
+ { \
+ LOGE("Unable to read " #NAME ".\n"); \
+ return false; \
+ }
+
+
bool CacheReader::readStringPool() {
- OBCC_StringPool *poolR = (OBCC_StringPool *)malloc(mHeader->str_pool_size);
+ CACHE_READER_READ_SECTION(OBCC_StringPool,
+ mpResult->mpStringPoolRaw, str_pool);
- if (!poolR) {
- LOGE("Unable to allocate string pool.\n");
- return false;
- }
+ char *str_base = reinterpret_cast<char *>(str_pool_raw);
- mResult->mpStringPoolRaw = poolR; // Managed by mResult from now on.
-
- if (mFile->read(reinterpret_cast<char *>(poolR), mHeader->str_pool_size) !=
- (ssize_t)mHeader->str_pool_size) {
- LOGE("Unable to read string pool.\n");
- return false;
- }
-
- vector<char const *> &pool = mResult->mStringPool;
-
- for (size_t i = 0; i < poolR->count; ++i) {
- char *str = reinterpret_cast<char *>(poolR) + poolR->list[i].offset;
+ vector<char const *> &pool = mpResult->mStringPool;
+ for (size_t i = 0; i < str_pool_raw->count; ++i) {
+ char *str = str_base + str_pool_raw->list[i].offset;
pool.push_back(str);
}
@@ -250,8 +271,8 @@
bool CacheReader::checkStringPool() {
- OBCC_StringPool *poolR = mResult->mpStringPoolRaw;
- vector<char const *> &pool = mResult->mStringPool;
+ OBCC_StringPool *poolR = mpResult->mpStringPoolRaw;
+ vector<char const *> &pool = mpResult->mStringPool;
// Ensure that every c-style string is ended with '\0'
for (size_t i = 0; i < poolR->count; ++i) {
@@ -266,92 +287,90 @@
bool CacheReader::readDependencyTable() {
- // TODO(logan): Not finished.
+ CACHE_READER_READ_SECTION(OBCC_DependencyTable, mpCachedDependTable,
+ depend_tab);
return true;
}
bool CacheReader::checkDependency() {
- // TODO(logan): Not finished.
+ if (mDependencies.size() != mpCachedDependTable->count) {
+ LOGE("Dependencies count mismatch. (%lu vs %lu)\n",
+ (unsigned long)mDependencies.size(),
+ (unsigned long)mpCachedDependTable->count);
+ return false;
+ }
+
+ vector<char const *> &strPool = mpResult->mStringPool;
+ map<string, pair<uint32_t, char const *> >::iterator dep;
+
+ dep = mDependencies.begin();
+ for (size_t i = 0; i < mpCachedDependTable->count; ++i, ++dep) {
+ string const &depName = dep->first;
+ char const *depSHA1 = dep->second.second;
+ uint32_t depType = dep->second.first;
+
+ OBCC_Dependency *depCached =&mpCachedDependTable->table[i];
+ char const *depCachedName = strPool[depCached->res_name_strp_index];
+ char const *depCachedSHA1 = depCached->sha1;
+ uint32_t depCachedType = depCached->res_type;
+
+ if (depName != depCachedName) {
+ LOGE("Cache dependency name mismatch:\n");
+ LOGE(" given: %s\n", depName.c_str());
+ LOGE(" cached: %s\n", depCachedName);
+
+ return false;
+ }
+
+ if (memcmp(depSHA1, depCachedSHA1, 20) != 0) {
+ LOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
+
+#define PRINT_SHA1(PREFIX, X, POSTFIX) \
+ LOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
+ "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" POSTFIX, \
+ X[0], X[1], X[2], X[3], X[4], X[5], X[6], X[7], X[8], X[9], \
+ X[10],X[11],X[12],X[13],X[14],X[15],X[16],X[17],X[18],X[19]);
+
+ PRINT_SHA1(" given: ", depSHA1, "\n");
+ PRINT_SHA1(" cached: ", depCachedSHA1, "\n");
+
+#undef PRINT_SHA1
+
+ return false;
+ }
+
+ if (depType != depCachedType) {
+ LOGE("Cache dependency %s resource type mismatch.\n", depCachedName);
+ return false;
+ }
+ }
+
return true;
}
bool CacheReader::readExportVarList() {
- char *varList = (char *)malloc(mHeader->export_var_list_size);
-
- if (!varList) {
- LOGE("Unable to allocate exported variable list.\n");
- return false;
- }
-
- mResult->mpExportVars = reinterpret_cast<OBCC_ExportVarList *>(varList);
-
- if (mFile->seek(mHeader->export_var_list_offset, SEEK_SET) == -1) {
- LOGE("Unable to seek to exported variable list section.\n");
- return false;
- }
-
- if (mFile->read(varList, mHeader->export_var_list_size) !=
- (ssize_t)mHeader->export_var_list_size) {
- LOGE("Unable to read exported variable list.\n");
- return false;
- }
-
+ CACHE_READER_READ_SECTION(OBCC_ExportVarList,
+ mpResult->mpExportVars, export_var_list);
return true;
}
bool CacheReader::readExportFuncList() {
- char *funcList = (char *)malloc(mHeader->export_func_list_size);
-
- if (!funcList) {
- LOGE("Unable to allocate exported function list.\n");
- return false;
- }
-
- mResult->mpExportFuncs = reinterpret_cast<OBCC_ExportFuncList *>(funcList);
-
- if (mFile->seek(mHeader->export_func_list_offset, SEEK_SET) == -1) {
- LOGE("Unable to seek to exported function list section.\n");
- return false;
- }
-
- if (mFile->read(funcList, mHeader->export_func_list_size) !=
- (ssize_t)mHeader->export_func_list_size) {
- LOGE("Unable to read exported function list.\n");
- return false;
- }
-
+ CACHE_READER_READ_SECTION(OBCC_ExportFuncList,
+ mpResult->mpExportFuncs, export_func_list);
return true;
}
bool CacheReader::readPragmaList() {
- OBCC_PragmaList *pragmaListRaw =
- (OBCC_PragmaList *)malloc(mHeader->pragma_list_size);
+ CACHE_READER_READ_SECTION(OBCC_PragmaList, mpPragmaList, pragma_list);
- if (!pragmaListRaw) {
- LOGE("Unable to allocate pragma list.\n");
- return false;
- }
+ vector<char const *> const &strPool = mpResult->mStringPool;
+ ScriptCached::PragmaList &pragmas = mpResult->mPragmas;
- if (mFile->seek(mHeader->pragma_list_offset, SEEK_SET) == -1) {
- LOGE("Unable to seek to pragma list section.\n");
- return false;
- }
-
- if (mFile->read(reinterpret_cast<char *>(pragmaListRaw),
- mHeader->pragma_list_size) !=
- (ssize_t)mHeader->pragma_list_size) {
- LOGE("Unable to read pragma list.\n");
- return false;
- }
-
- vector<char const *> const &strPool = mResult->mStringPool;
- ScriptCached::PragmaList &pragmas = mResult->mPragmas;
-
- for (size_t i = 0; i < pragmaListRaw->count; ++i) {
- OBCC_Pragma *pragma = &pragmaListRaw->list[i];
+ for (size_t i = 0; i < pragma_list_raw->count; ++i) {
+ OBCC_Pragma *pragma = &pragma_list_raw->list[i];
pragmas.push_back(make_pair(strPool[pragma->key_strp_index],
strPool[pragma->value_strp_index]));
}
@@ -361,16 +380,28 @@
bool CacheReader::readFuncTable() {
- return false;
+ CACHE_READER_READ_SECTION(OBCC_FuncTable, mpFuncTable, func_table);
+
+ vector<char const *> &strPool = mpResult->mStringPool;
+ ScriptCached::FuncTable &table = mpResult->mFunctions;
+ for (size_t i = 0; i < func_table_raw->count; ++i) {
+ OBCC_FuncInfo *func = &func_table_raw->table[i];
+ table.insert(make_pair(strPool[func->name_strp_index],
+ make_pair(func->cached_addr, func->size)));
+ }
+
+ return true;
}
+#undef CACHE_READER_READ_SECTION
+
bool CacheReader::readContext() {
- mResult->mContext = allocateContext(mHeader->context_cached_addr,
+ mpResult->mContext = allocateContext(mpHeader->context_cached_addr,
mFile->getFD(),
- mHeader->context_offset);
+ mpHeader->context_offset);
- if (!mResult->mContext) {
+ if (!mpResult->mContext) {
// Unable to allocate at cached address. Give up.
return false;
@@ -383,8 +414,8 @@
bool CacheReader::checkContext() {
- uint32_t sum = mHeader->context_parity_checksum;
- uint32_t *ptr = reinterpret_cast<uint32_t *>(mResult->mContext);
+ uint32_t sum = mpHeader->context_parity_checksum;
+ uint32_t *ptr = reinterpret_cast<uint32_t *>(mpResult->mContext);
for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
sum ^= *ptr++;