CacheReader.cpp revision a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdf
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()
83f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && readContext()
84f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             && checkContext()
85f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             //&& readRelocationTable()
86f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             //&& relocate()
87f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan             ;
88f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
89856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  return result ? mpResult.take() : NULL;
90f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
91f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
92f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
93f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkFileSize() {
94f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  struct stat stfile;
95f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (fstat(mFile->getFD(), &stfile) < 0) {
96f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to stat cache file.\n");
97f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
98f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
99f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
100f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  mFileSize = stfile.st_size;
101f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
102f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (mFileSize < (off_t)sizeof(OBCC_Header) ||
103f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      mFileSize < (off_t)BCC_CONTEXT_SIZE) {
104f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Cache file is too small to be correct.\n");
105f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
106f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
107f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
108f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
109f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
110f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
111f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
112f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readHeader() {
113f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (mFile->seek(0, SEEK_SET) != 0) {
114f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to seek to 0. (reason: %s)\n", strerror(errno));
115f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
116f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
117f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
118856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  mpHeader = (OBCC_Header *)malloc(sizeof(OBCC_Header));
119856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (!mpHeader) {
120f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to allocate for cache header.\n");
121f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
122f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
123f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
124856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mFile->read(reinterpret_cast<char *>(mpHeader), sizeof(OBCC_Header)) !=
125f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      (ssize_t)sizeof(OBCC_Header)) {
126f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Unable to read cache header.\n");
127f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
128f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
129f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
130a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  // Dirty hack for libRS.
131a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  // TODO(all): This should be removed in the future.
132a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  if (mpHeader->libRS_threadable) {
133a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan    mpResult->mLibRSThreadable = true;
134a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  }
135a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan
136f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
137f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
138f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
139f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
140f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkHeader() {
141856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (memcmp(mpHeader->magic, OBCC_MAGIC, 4) != 0) {
142f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Bad magic word\n");
143f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
144f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
145f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
146856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (memcmp(mpHeader->version, OBCC_VERSION, 4) != 0) {
147f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Bad oBCC version 0x%08x\n",
148856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan         *reinterpret_cast<uint32_t *>(mpHeader->version));
149f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
150f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
151f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
152f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
153f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
154f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
155f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
156f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkMachineIntType() {
157f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  uint32_t number = 0x00000001;
158f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
159f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  bool isLittleEndian = (*reinterpret_cast<char *>(&number) == 1);
160856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if ((isLittleEndian && mpHeader->endianness != 'e') ||
161856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      (!isLittleEndian && mpHeader->endianness != 'E')) {
162f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Machine endianness mismatch.\n");
163f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
164f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
165f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
166856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if ((unsigned int)mpHeader->sizeof_off_t != sizeof(off_t) ||
167856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      (unsigned int)mpHeader->sizeof_size_t != sizeof(size_t) ||
168856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      (unsigned int)mpHeader->sizeof_ptr_t != sizeof(void *)) {
169f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Machine integer size mismatch.\n");
170f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
171f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
172f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
173f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
174f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
175f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
176f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
177f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkSectionOffsetAndSize() {
178f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#define CHECK_SECTION_OFFSET(NAME)                                          \
179f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  do {                                                                      \
180856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    off_t offset = mpHeader-> NAME##_offset;                                \
181856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    off_t size = (off_t)mpHeader-> NAME##_size;                             \
182f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                                                            \
183f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    if (mFileSize < offset || mFileSize < offset + size) {                  \
184f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      LOGE(#NAME " section overflow.\n");                                   \
185f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      return false;                                                         \
186f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    }                                                                       \
187f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                                                            \
188f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    if (offset % sizeof(int) != 0) {                                        \
189f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      LOGE(#NAME " offset must aligned to %d.\n", sizeof(int));             \
190f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      return false;                                                         \
191f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    }                                                                       \
192f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                                                            \
193f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    if (size < static_cast<off_t>(sizeof(size_t))) {                        \
194f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      LOGE(#NAME " size is too small to be correct.\n");                    \
195f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      return false;                                                         \
196f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    }                                                                       \
197f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  } while (0)
198f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
199f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(str_pool);
200f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(depend_tab);
201a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  //CHECK_SECTION_OFFSET(reloc_tab);
202f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(export_var_list);
203f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(export_func_list);
204f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  CHECK_SECTION_OFFSET(pragma_list);
205f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
206f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan#undef CHECK_SECTION_OFFSET
207f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
208856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mFileSize < mpHeader->context_offset ||
209856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      mFileSize < mpHeader->context_offset + BCC_CONTEXT_SIZE) {
210f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("context section overflow.\n");
211f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
212f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
213f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
214f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  long pagesize = sysconf(_SC_PAGESIZE);
215856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mpHeader->context_offset % pagesize != 0) {
216f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("context offset must aligned to pagesize.\n");
217f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
218f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
219f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
220f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // TODO(logan): Move this to some where else.
221856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if ((uintptr_t)mpHeader->context_cached_addr % pagesize != 0) {
222f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("cached address is not aligned to pagesize.\n");
223f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
224f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
225f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
226f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
227f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
228f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
229f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
230856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#define CACHE_READER_READ_SECTION(TYPE, AUTO_MANAGED_HOLDER, NAME)          \
231856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  TYPE *NAME##_raw = (TYPE *)malloc(mpHeader->NAME##_size);                 \
232856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                                                            \
233856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (!NAME##_raw) {                                                        \
234856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    LOGE("Unable to allocate for " #NAME "\n");                             \
235856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    return false;                                                           \
236856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  }                                                                         \
237856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                                                            \
238856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  /* We have to ensure that some one will deallocate NAME##_raw */          \
239856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  AUTO_MANAGED_HOLDER = NAME##_raw;                                         \
240856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                                                            \
241856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mFile->seek(mpHeader->NAME##_offset, SEEK_SET) == -1) {               \
242856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    LOGE("Unable to seek to " #NAME " section\n");                          \
243856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    return false;                                                           \
244856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  }                                                                         \
245856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                                                            \
246856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mFile->read(reinterpret_cast<char *>(NAME##_raw),                     \
247856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                  mpHeader->NAME##_size) != (ssize_t)mpHeader->NAME##_size) \
248856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  {                                                                         \
249856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    LOGE("Unable to read " #NAME ".\n");                                    \
250856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    return false;                                                           \
251f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
252f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
253f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
254856ceb2774bd2c601970c2bc26fb87b2e9b00258Loganbool CacheReader::readStringPool() {
255856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_StringPool,
256856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                            mpResult->mpStringPoolRaw, str_pool);
257f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
258856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  char *str_base = reinterpret_cast<char *>(str_pool_raw);
259f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
260856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> &pool = mpResult->mStringPool;
261856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  for (size_t i = 0; i < str_pool_raw->count; ++i) {
262856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    char *str = str_base + str_pool_raw->list[i].offset;
263f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    pool.push_back(str);
264f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
265f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
266f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
267f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
268f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
269f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
270f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkStringPool() {
271856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  OBCC_StringPool *poolR = mpResult->mpStringPoolRaw;
272856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> &pool = mpResult->mStringPool;
273f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
274f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // Ensure that every c-style string is ended with '\0'
275f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  for (size_t i = 0; i < poolR->count; ++i) {
276f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    if (pool[i][poolR->list[i].length] != '\0') {
277f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      LOGE("The %lu-th string does not end with '\\0'.\n", (unsigned long)i);
278f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan      return false;
279f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    }
280f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
281f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
282f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
283f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
284f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
285f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
286f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readDependencyTable() {
287856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_DependencyTable, mpCachedDependTable,
288856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                            depend_tab);
289f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
290f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
291f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
292f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
293f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkDependency() {
294856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (mDependencies.size() != mpCachedDependTable->count) {
295856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    LOGE("Dependencies count mismatch. (%lu vs %lu)\n",
296856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan         (unsigned long)mDependencies.size(),
297856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan         (unsigned long)mpCachedDependTable->count);
298f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
299f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
300f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
301856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> &strPool = mpResult->mStringPool;
30275cc8a5c58b3260e530eae9f2edd502b71d25373Logan  map<string, pair<uint32_t, unsigned char const *> >::iterator dep;
303f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
304856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  dep = mDependencies.begin();
305856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  for (size_t i = 0; i < mpCachedDependTable->count; ++i, ++dep) {
306856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    string const &depName = dep->first;
307856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    uint32_t depType = dep->second.first;
30875cc8a5c58b3260e530eae9f2edd502b71d25373Logan    unsigned char const *depSHA1 = dep->second.second;
309f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
310856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    OBCC_Dependency *depCached =&mpCachedDependTable->table[i];
311856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    char const *depCachedName = strPool[depCached->res_name_strp_index];
312856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    uint32_t depCachedType = depCached->res_type;
31375cc8a5c58b3260e530eae9f2edd502b71d25373Logan    unsigned char const *depCachedSHA1 = depCached->sha1;
314f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
315856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    if (depName != depCachedName) {
316856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("Cache dependency name mismatch:\n");
317856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("  given:  %s\n", depName.c_str());
318856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("  cached: %s\n", depCachedName);
319f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
320856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      return false;
321856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    }
322f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
323856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    if (memcmp(depSHA1, depCachedSHA1, 20) != 0) {
324856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("Cache dependency %s sha1 mismatch:\n", depCachedName);
325f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
326856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#define PRINT_SHA1(PREFIX, X, POSTFIX) \
327856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE(PREFIX "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
328856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                  "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" POSTFIX, \
329856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan           X[0], X[1], X[2], X[3], X[4], X[5], X[6], X[7], X[8], X[9], \
330856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan           X[10],X[11],X[12],X[13],X[14],X[15],X[16],X[17],X[18],X[19]);
331f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
332856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      PRINT_SHA1("  given:  ", depSHA1, "\n");
333856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      PRINT_SHA1("  cached: ", depCachedSHA1, "\n");
334f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
335856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#undef PRINT_SHA1
336f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
337856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      return false;
338856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    }
339856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
340856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    if (depType != depCachedType) {
341856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      LOGE("Cache dependency %s resource type mismatch.\n", depCachedName);
342856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan      return false;
343856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    }
344f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
345f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
346f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
347f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
348f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
349856ceb2774bd2c601970c2bc26fb87b2e9b00258Loganbool CacheReader::readExportVarList() {
350856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_ExportVarList,
351856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                            mpResult->mpExportVars, export_var_list);
352856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  return true;
353856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan}
354f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
355f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
356856ceb2774bd2c601970c2bc26fb87b2e9b00258Loganbool CacheReader::readExportFuncList() {
357856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_ExportFuncList,
358856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                            mpResult->mpExportFuncs, export_func_list);
359856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  return true;
360856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan}
361f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
362f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
363856ceb2774bd2c601970c2bc26fb87b2e9b00258Loganbool CacheReader::readPragmaList() {
364856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_PragmaList, mpPragmaList, pragma_list);
365f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
366856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> const &strPool = mpResult->mStringPool;
367856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  ScriptCached::PragmaList &pragmas = mpResult->mPragmas;
368f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
369856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  for (size_t i = 0; i < pragma_list_raw->count; ++i) {
370856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    OBCC_Pragma *pragma = &pragma_list_raw->list[i];
371f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    pragmas.push_back(make_pair(strPool[pragma->key_strp_index],
372f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                strPool[pragma->value_strp_index]));
373f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
374f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
375f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
376f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
377f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
378f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
379f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readFuncTable() {
380856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  CACHE_READER_READ_SECTION(OBCC_FuncTable, mpFuncTable, func_table);
381856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
382856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  vector<char const *> &strPool = mpResult->mStringPool;
383856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  ScriptCached::FuncTable &table = mpResult->mFunctions;
384856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  for (size_t i = 0; i < func_table_raw->count; ++i) {
385856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    OBCC_FuncInfo *func = &func_table_raw->table[i];
386856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan    table.insert(make_pair(strPool[func->name_strp_index],
387856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                           make_pair(func->cached_addr, func->size)));
388856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  }
389856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
390856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  return true;
391f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
392f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
393856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan#undef CACHE_READER_READ_SECTION
394856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan
395f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
396f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readContext() {
397856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  mpResult->mContext = allocateContext(mpHeader->context_cached_addr,
398f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan                                      mFile->getFD(),
399856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan                                      mpHeader->context_offset);
400f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
401856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  if (!mpResult->mContext) {
402f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    // Unable to allocate at cached address.  Give up.
403f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
404f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
405f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    // TODO(logan): If relocation is fixed, we should try to allocate the
406f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    // code in different location, and relocate the context.
407f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
408f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
409f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
410f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
411f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
412f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
413f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::checkContext() {
414856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  uint32_t sum = mpHeader->context_parity_checksum;
415856ceb2774bd2c601970c2bc26fb87b2e9b00258Logan  uint32_t *ptr = reinterpret_cast<uint32_t *>(mpResult->mContext);
416f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
417f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
418f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    sum ^= *ptr++;
419f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
420f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
421f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  if (sum != 0) {
422f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    LOGE("Checksum check failed\n");
423f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan    return false;
424f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  }
425f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
426f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  LOGI("Passed checksum even parity verification.\n");
427f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
428f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
429f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
430f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
431f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::readRelocationTable() {
432f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // TODO(logan): Not finished.
433f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
434f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
435f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
436f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
437f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLoganbool CacheReader::relocate() {
438f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  // TODO(logan): Not finished.
439f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan  return true;
440f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan}
441f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
442f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan
443f7f0ac5d3e12b2e84bd18aa32add4a11bf296dbbLogan} // namespace bcc
444