CacheReader.cpp revision 42598054d2d278bddde812f160517162e95342c1
1f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan/*
2f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * Copyright 2010, The Android Open Source Project
3f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan *
4f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * Licensed under the Apache License, Version 2.0 (the "License");
5f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * you may not use this file except in compliance with the License.
6f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * You may obtain a copy of the License at
7f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan *
8f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan *     http://www.apache.org/licenses/LICENSE-2.0
9f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan *
10f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * Unless required by applicable law or agreed to in writing, software
11f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * distributed under the License is distributed on an "AS IS" BASIS,
12f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * See the License for the specific language governing permissions and
14f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan * limitations under the License.
15f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan */
16f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
17f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#define LOG_TAG "bcc"
18f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <cutils/log.h>
19f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
20f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include "CacheReader.h"
21f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
22f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include "ContextManager.h"
23f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include "FileHandle.h"
24f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include "ScriptCached.h"
25f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
26f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <bcc/bcc_cache.h>
27f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
28f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <llvm/ADT/OwningPtr.h>
29f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
30f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <errno.h>
31f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <sys/stat.h>
32f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <sys/types.h>
33f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
34f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <utility>
35f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <vector>
36f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
37f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <new>
38f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
39856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#include <stdlib.h>
40f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#include <string.h>
41f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
42f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganusing namespace std;
43f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
44f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
45f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogannamespace bcc {
46f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
47856ceb2774bd2c601970c2bc26fb87b2e9b00258LoganCacheReader::~CacheReader() {
48856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mpHeader) { free(mpHeader); }
49856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mpCachedDependTable) { free(mpCachedDependTable); }
50856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mpPragmaList) { free(mpPragmaList); }
51856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mpFuncTable) { free(mpFuncTable); }
52856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan}
53856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
54e7eb773baa51408a0f8f871d779888d0d381b5d7LoganScriptCached *CacheReader::readCacheFile(FileHandle *file, Script *S) {
55f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // Check file handle
56f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (!file || file->getFD() < 0) {
57f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return NULL;
58f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
59f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
60a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  mFile = file;
61a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan
62f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // Allocate ScriptCached object
63e7eb773baa51408a0f8f871d779888d0d381b5d7Logan  mpResult.reset(new (nothrow) ScriptCached(S));
64f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
65856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (!mpResult) {
66f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to allocate ScriptCached object.\n");
67f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return NULL;
68f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
69f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
70f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  bool result = checkFileSize()
71f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readHeader()
72f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && checkHeader()
73f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && checkMachineIntType()
74f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && checkSectionOffsetAndSize()
75f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readStringPool()
76f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && checkStringPool()
77f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readDependencyTable()
78f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && checkDependency()
79f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readExportVarList()
80f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readExportFuncList()
81f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readPragmaList()
82f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readFuncTable()
83071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines             && readObjectSlotList()
84f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readContext()
85f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && checkContext()
86f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             //&& readRelocationTable()
87f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             //&& relocate()
88f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             ;
89f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
90856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  return result ? mpResult.take() : NULL;
91f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
92f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
93f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
94f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkFileSize() {
95f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  struct stat stfile;
96f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (fstat(mFile->getFD(), &stfile) < 0) {
97f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to stat cache file.\n");
98f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
99f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
100f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
101f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  mFileSize = stfile.st_size;
102f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
103f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (mFileSize < (off_t)sizeof(OBCC_Header) ||
104f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      mFileSize < (off_t)BCC_CONTEXT_SIZE) {
105f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Cache file is too small to be correct.\n");
106f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
107f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
108f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
109f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
110f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
111f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
112f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
113f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readHeader() {
114f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (mFile->seek(0, SEEK_SET) != 0) {
115f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
116f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
117f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
118f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
119856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  mpHeader = (OBCC_Header *)malloc(sizeof(OBCC_Header));
120856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (!mpHeader) {
121f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to allocate for cache header.\n");
122f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
123f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
124f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
125856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mFile->read(reinterpret_cast<char *>(mpHeader), sizeof(OBCC_Header)) !=
126f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      (ssize_t)sizeof(OBCC_Header)) {
127f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to read cache header.\n");
128f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
129f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
130f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
131a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  // Dirty hack for libRS.
132a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  // TODO(all): This should be removed in the future.
133a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  if (mpHeader->libRS_threadable) {
134a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan    mpResult->mLibRSThreadable = true;
135a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  }
136a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan
137f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
138f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
139f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
140f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
141f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkHeader() {
142856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (memcmp(mpHeader->magic, OBCC_MAGIC, 4) != 0) {
143f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Bad magic word\n");
144f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
145f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
146f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
147856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (memcmp(mpHeader->version, OBCC_VERSION, 4) != 0) {
148e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan    mpHeader->version[4 - 1] = '\0'; // ensure c-style string terminated
149a65266520846ecca8cc95587776c050c646ad624Shih-wei Liao    LOGI("Cache file format version mismatch: now %s cached %s\n",
150e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan         OBCC_VERSION, mpHeader->version);
151e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan    return false;
152e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan  }
153e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan
154e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan  if (memcmp(mpHeader->libbcc_build_time, libbcc_build_time, 24) != 0) {
155e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan    mpHeader->libbcc_build_time[24 - 1] = '\0'; // ensure terminated
15639ebe2c22f8557752065465345bb3006d06e4497Shih-wei Liao    LOGW("Build time mismatch: lib %s cached %s\n", libbcc_build_time,
157e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan         mpHeader->libbcc_build_time);
158f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
159f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
160f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
161f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
162f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
163f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
164f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
165f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkMachineIntType() {
166f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  uint32_t number = 0x00000001;
167f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
168f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  bool isLittleEndian = (*reinterpret_cast<char *>(&number) == 1);
169856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if ((isLittleEndian && mpHeader->endianness != 'e') ||
170856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      (!isLittleEndian && mpHeader->endianness != 'E')) {
171f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Machine endianness mismatch.\n");
172f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
173f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
174f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
175856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if ((unsigned int)mpHeader->sizeof_off_t != sizeof(off_t) ||
176856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      (unsigned int)mpHeader->sizeof_size_t != sizeof(size_t) ||
177856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      (unsigned int)mpHeader->sizeof_ptr_t != sizeof(void *)) {
178f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Machine integer size mismatch.\n");
179f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
180f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
181f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
182f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
183f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
184f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
185f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
186f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkSectionOffsetAndSize() {
187f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#define CHECK_SECTION_OFFSET(NAME)                                          \
188f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  do {                                                                      \
189856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    off_t offset = mpHeader-> NAME##_offset;                                \
190856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    off_t size = (off_t)mpHeader-> NAME##_size;                             \
191f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                                                            \
192f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    if (mFileSize < offset || mFileSize < offset + size) {                  \
193f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      LOGE(#NAME " section overflow.\n");                                   \
194f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      return false;                                                         \
195f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    }                                                                       \
196f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                                                            \
197f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    if (offset % sizeof(int) != 0) {                                        \
198f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      LOGE(#NAME " offset must aligned to %d.\n", sizeof(int));             \
199f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      return false;                                                         \
200f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    }                                                                       \
201f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                                                            \
202f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    if (size < static_cast<off_t>(sizeof(size_t))) {                        \
203f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      LOGE(#NAME " size is too small to be correct.\n");                    \
204f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      return false;                                                         \
205f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    }                                                                       \
206f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  } while (0)
207f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
208f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(str_pool);
209f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(depend_tab);
210a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  //CHECK_SECTION_OFFSET(reloc_tab);
211f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(export_var_list);
212f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(export_func_list);
213f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(pragma_list);
214f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
215f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#undef CHECK_SECTION_OFFSET
216f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
217856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mFileSize < mpHeader->context_offset ||
218856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      mFileSize < mpHeader->context_offset + BCC_CONTEXT_SIZE) {
219f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("context section overflow.\n");
220f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
221f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
222f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
223f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  long pagesize = sysconf(_SC_PAGESIZE);
224856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mpHeader->context_offset % pagesize != 0) {
225f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("context offset must aligned to pagesize.\n");
226f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
227f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
228f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
229f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // TODO(logan): Move this to some where else.
230856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if ((uintptr_t)mpHeader->context_cached_addr % pagesize != 0) {
231f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("cached address is not aligned to pagesize.\n");
232f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
233f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
234f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
235f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
236f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
237f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
238f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
239856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#define CACHE_READER_READ_SECTION(TYPE, AUTO_MANAGED_HOLDER, NAME)          \
240856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  TYPE *NAME##_raw = (TYPE *)malloc(mpHeader->NAME##_size);                 \
241856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                                                            \
242856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (!NAME##_raw) {                                                        \
243856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    LOGE("Unable to allocate for " #NAME "\n");                             \
244856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    return false;                                                           \
245856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  }                                                                         \
246856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                                                            \
247856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  /* We have to ensure that some one will deallocate NAME##_raw */          \
248856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  AUTO_MANAGED_HOLDER = NAME##_raw;                                         \
249856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                                                            \
250856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mFile->seek(mpHeader->NAME##_offset, SEEK_SET) == -1) {               \
251856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    LOGE("Unable to seek to " #NAME " section\n");                          \
252856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    return false;                                                           \
253856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  }                                                                         \
254856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                                                            \
255856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mFile->read(reinterpret_cast<char *>(NAME##_raw),                     \
256856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                  mpHeader->NAME##_size) != (ssize_t)mpHeader->NAME##_size) \
257856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  {                                                                         \
258856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    LOGE("Unable to read " #NAME ".\n");                                    \
259856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    return false;                                                           \
260f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
261f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
262f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
263856ceb2774bd2c601970c2bc26fb87b2e9b00258Loganbool CacheReader::readStringPool() {
264856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_StringPool,
265856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                            mpResult->mpStringPoolRaw, str_pool);
266f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
267856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  char *str_base = reinterpret_cast<char *>(str_pool_raw);
268f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
269856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> &pool = mpResult->mStringPool;
270856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  for (size_t i = 0; i < str_pool_raw->count; ++i) {
271856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    char *str = str_base + str_pool_raw->list[i].offset;
272f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    pool.push_back(str);
273f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
274f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
275f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
276f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
277f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
278f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
279f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkStringPool() {
280856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  OBCC_StringPool *poolR = mpResult->mpStringPoolRaw;
281856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> &pool = mpResult->mStringPool;
282f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
283f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // Ensure that every c-style string is ended with '\0'
284f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  for (size_t i = 0; i < poolR->count; ++i) {
285f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    if (pool[i][poolR->list[i].length] != '\0') {
286f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      LOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
287f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      return false;
288f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    }
289f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
290f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
291f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
292f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
293f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
294f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
295f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readDependencyTable() {
296856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_DependencyTable, mpCachedDependTable,
297856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                            depend_tab);
298f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
299f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
300f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
301f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
302f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkDependency() {
303856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mDependencies.size() != mpCachedDependTable->count) {
304856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    LOGE("Dependencies count mismatch. (%lu vs %lu)\n",
305856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan         (unsigned long)mDependencies.size(),
306856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan         (unsigned long)mpCachedDependTable->count);
307f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
308f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
309f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
310856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> &strPool = mpResult->mStringPool;
31175cc8a5c58b3260e530eae9f2edd502b71d25373Logan  map<string, pair<uint32_t, unsigned char const *> >::iterator dep;
312f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
313856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  dep = mDependencies.begin();
314856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  for (size_t i = 0; i < mpCachedDependTable->count; ++i, ++dep) {
315856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    string const &depName = dep->first;
316856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    uint32_t depType = dep->second.first;
31775cc8a5c58b3260e530eae9f2edd502b71d25373Logan    unsigned char const *depSHA1 = dep->second.second;
318f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
319856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    OBCC_Dependency *depCached =&mpCachedDependTable->table[i];
320856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    char const *depCachedName = strPool[depCached->res_name_strp_index];
321856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    uint32_t depCachedType = depCached->res_type;
32275cc8a5c58b3260e530eae9f2edd502b71d25373Logan    unsigned char const *depCachedSHA1 = depCached->sha1;
323f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
324856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    if (depName != depCachedName) {
325856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("Cache dependency name mismatch:\n");
326856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("  given:  %s\n", depName.c_str());
327856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("  cached: %s\n", depCachedName);
328f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
329856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      return false;
330856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    }
331f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
332856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    if (memcmp(depSHA1, depCachedSHA1, 20) != 0) {
333856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
334f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
335856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#define PRINT_SHA1(PREFIX, X, POSTFIX) \
336856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
337856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                  "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" POSTFIX, \
338856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan           X[0], X[1], X[2], X[3], X[4], X[5], X[6], X[7], X[8], X[9], \
339856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan           X[10],X[11],X[12],X[13],X[14],X[15],X[16],X[17],X[18],X[19]);
340f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
341856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      PRINT_SHA1("  given:  ", depSHA1, "\n");
342856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      PRINT_SHA1("  cached: ", depCachedSHA1, "\n");
343f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
344856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#undef PRINT_SHA1
345f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
346856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      return false;
347856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    }
348856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
349856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    if (depType != depCachedType) {
350856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("Cache dependency %s resource type mismatch.\n", depCachedName);
351856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      return false;
352856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    }
353f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
354f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
355f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
356f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
357f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
358856ceb2774bd2c601970c2bc26fb87b2e9b00258Loganbool CacheReader::readExportVarList() {
359856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_ExportVarList,
360856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                            mpResult->mpExportVars, export_var_list);
361856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  return true;
362856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan}
363f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
364f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
365856ceb2774bd2c601970c2bc26fb87b2e9b00258Loganbool CacheReader::readExportFuncList() {
366856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_ExportFuncList,
367856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                            mpResult->mpExportFuncs, export_func_list);
368856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  return true;
369856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan}
370f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
371f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
372856ceb2774bd2c601970c2bc26fb87b2e9b00258Loganbool CacheReader::readPragmaList() {
373856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_PragmaList, mpPragmaList, pragma_list);
374f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
375856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> const &strPool = mpResult->mStringPool;
376856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  ScriptCached::PragmaList &pragmas = mpResult->mPragmas;
377f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
378856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  for (size_t i = 0; i < pragma_list_raw->count; ++i) {
379856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    OBCC_Pragma *pragma = &pragma_list_raw->list[i];
380f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    pragmas.push_back(make_pair(strPool[pragma->key_strp_index],
381f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                strPool[pragma->value_strp_index]));
382f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
383f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
384f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
385f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
386f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
387f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
388071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hinesbool CacheReader::readObjectSlotList() {
389071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  CACHE_READER_READ_SECTION(OBCC_ObjectSlotList,
390071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines                            mpResult->mpObjectSlotList, object_slot_list);
391071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  return true;
392071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines}
393071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
394071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
395f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readFuncTable() {
396856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_FuncTable, mpFuncTable, func_table);
397856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
398856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> &strPool = mpResult->mStringPool;
399856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  ScriptCached::FuncTable &table = mpResult->mFunctions;
400856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  for (size_t i = 0; i < func_table_raw->count; ++i) {
401856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    OBCC_FuncInfo *func = &func_table_raw->table[i];
402856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    table.insert(make_pair(strPool[func->name_strp_index],
403856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                           make_pair(func->cached_addr, func->size)));
404856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  }
405856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
406856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  return true;
407f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
408f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
409856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#undef CACHE_READER_READ_SECTION
410856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
411f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
412f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readContext() {
413856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  mpResult->mContext = allocateContext(mpHeader->context_cached_addr,
414f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                      mFile->getFD(),
415856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                      mpHeader->context_offset);
416f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
417856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (!mpResult->mContext) {
418f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    // Unable to allocate at cached address.  Give up.
41942598054d2d278bddde812f160517162e95342c1Logan    mIsContextSlotNotAvail = true;
420f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
421f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
422f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    // TODO(logan): If relocation is fixed, we should try to allocate the
423f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    // code in different location, and relocate the context.
424f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
425f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
426f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
427f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
428f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
429f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
430f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkContext() {
431856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  uint32_t sum = mpHeader->context_parity_checksum;
432856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  uint32_t *ptr = reinterpret_cast<uint32_t *>(mpResult->mContext);
433f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
434f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
435f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    sum ^= *ptr++;
436f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
437f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
438f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (sum != 0) {
439f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Checksum check failed\n");
440f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
441f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
442f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
443f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  LOGI("Passed checksum even parity verification.\n");
444f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
445f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
446f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
447f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
448f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readRelocationTable() {
449f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // TODO(logan): Not finished.
450f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
451f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
452f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
453f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
454f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::relocate() {
455f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // TODO(logan): Not finished.
456f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
457f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
458f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
459f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
460f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan} // namespace bcc
461