CacheWriter.cpp revision f340bf71ff377979d279132dcf5a801d76747d1f
1a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan/*
2a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * Copyright 2010, The Android Open Source Project
3a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan *
4a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * Licensed under the Apache License, Version 2.0 (the "License");
5a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * you may not use this file except in compliance with the License.
6a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * You may obtain a copy of the License at
7a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan *
8a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan *     http://www.apache.org/licenses/LICENSE-2.0
9a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan *
10a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * Unless required by applicable law or agreed to in writing, software
11a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * distributed under the License is distributed on an "AS IS" BASIS,
12a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * See the License for the specific language governing permissions and
14a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan * limitations under the License.
15a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan */
16a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
17a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define LOG_TAG "bcc"
18a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <cutils/log.h>
19a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
20a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include "CacheWriter.h"
21a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
22a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include "ContextManager.h"
23a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include "FileHandle.h"
24a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include "Script.h"
25a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
26a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <map>
27a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <string>
28a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <vector>
29a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <utility>
30a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
31a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <stdint.h>
32a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <stdlib.h>
33a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <string.h>
34a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
35a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganusing namespace std;
36a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
37a27a83f2b01b1710238d077dc9dfd7655f4513cdLogannamespace bcc {
38a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
399d93894295ac70d85c5792da4c1398391fb67915LoganCacheWriter::~CacheWriter() {
409d93894295ac70d85c5792da4c1398391fb67915Logan#define CHECK_AND_FREE(VAR) if (VAR) { free(VAR); }
419d93894295ac70d85c5792da4c1398391fb67915Logan
429d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpHeaderSection);
439d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpStringPoolSection);
449d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpDependencyTableSection);
459d93894295ac70d85c5792da4c1398391fb67915Logan  //CHECK_AND_FREE(mpRelocationTableSection);
469d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpExportVarListSection);
479d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpExportFuncListSection);
489d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpPragmaListSection);
499d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpFuncTableSection);
509d93894295ac70d85c5792da4c1398391fb67915Logan
519d93894295ac70d85c5792da4c1398391fb67915Logan#undef CHECK_AND_FREE
529d93894295ac70d85c5792da4c1398391fb67915Logan}
539d93894295ac70d85c5792da4c1398391fb67915Logan
54a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::writeCacheFile(FileHandle *file, Script *S,
55a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                                 uint32_t libRS_threadable) {
56a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!file || file->getFD() < 0) {
57a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
58a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
59a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
60a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mFile = file;
61a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner = S;
62a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
63a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  bool result = prepareHeader(libRS_threadable)
64a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareDependencyTable()
65a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareFuncTable()
66a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && preparePragmaList()
67a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             //&& prepareRelocationTable()
68a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareStringPool()
69a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareExportVarList()
70a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareExportFuncList()
71a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && calcSectionOffset()
72a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && calcContextChecksum()
73a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && writeAll()
74a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             ;
75a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
76a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return result;
77a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
78a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
79a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
80a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareHeader(uint32_t libRS_threadable) {
81a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_Header *header = (OBCC_Header *)malloc(sizeof(OBCC_Header));
82a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
83a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!header) {
84a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for header.\n");
85a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
86a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
87a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
88a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection = header;
89a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
90a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Initialize
91a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  memset(header, '\0', sizeof(OBCC_Header));
92a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
93f7cfc026ec9e3a307d1252c46be9a089d74d3ef3Shih-wei Liao  // Magic word and version
94a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  memcpy(header->magic, OBCC_MAGIC, 4);
95a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  memcpy(header->version, OBCC_VERSION, 4);
96e132399eb9dc93123d50e9492ac7b01c2c9a4d35Logan  memcpy(header->libbcc_build_time, libbcc_build_time, 24);
97a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
98a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Machine Integer Type
99a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t number = 0x00000001;
100a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
101a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_off_t = sizeof(off_t);
102a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_size_t = sizeof(size_t);
103a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_ptr_t = sizeof(void *);
104a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
105a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Context
106a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->context_cached_addr = mpOwner->getContext();
107a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
108a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // libRS is threadable dirty hack
109a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // TODO: This should be removed in the future
110a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->libRS_threadable = libRS_threadable;
111a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
112a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
113a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
114a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
115a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
116a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareDependencyTable() {
117a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t tableSize = sizeof(OBCC_DependencyTable) +
118a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                     sizeof(OBCC_Dependency) * mDependencies.size();
119a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
120a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
121f7cfc026ec9e3a307d1252c46be9a089d74d3ef3Shih-wei Liao
122a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!tab) {
123a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for dependency table section.\n");
124a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
125a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
126a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
127a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpDependencyTableSection = tab;
128a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->depend_tab_size = tableSize;
129a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
130a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  tab->count = mDependencies.size();
131a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
132a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t i = 0;
133a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (map<string, pair<uint32_t, unsigned char const *> >::iterator
134a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan       I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
135a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_Dependency *dep = &tab->table[i];
136a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
137a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
138a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    dep->res_type = I->second.first;
139a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    memcpy(dep->sha1, I->second.second, 20);
140a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
141a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
142a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
143a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
144a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
145a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
146a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareFuncTable() {
147be79ada39b5e77b638940d2e157a45904ee09275Logan  size_t funcCount = mpOwner->getFuncCount();
148a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
149a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t tableSize = sizeof(OBCC_FuncTable) +
150a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                     sizeof(OBCC_FuncInfo) * funcCount;
151a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
152a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_FuncTable *tab = (OBCC_FuncTable *)malloc(tableSize);
153a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
154a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!tab) {
155a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for function table section.\n");
156a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
157a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
158a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
159a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpFuncTableSection = tab;
160f7cfc026ec9e3a307d1252c46be9a089d74d3ef3Shih-wei Liao  mpHeaderSection->func_table_size = tableSize;
161a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
162a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  tab->count = static_cast<size_t>(funcCount);
163a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
164f7cfc026ec9e3a307d1252c46be9a089d74d3ef3Shih-wei Liao  // Get the function informations
165f340bf71ff377979d279132dcf5a801d76747d1fLogan  vector<FuncInfo> funcInfoList(funcCount);
166f340bf71ff377979d279132dcf5a801d76747d1fLogan  mpOwner->getFuncInfoList(funcCount, &*funcInfoList.begin());
167a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
168be79ada39b5e77b638940d2e157a45904ee09275Logan  for (size_t i = 0; i < funcCount; ++i) {
169f340bf71ff377979d279132dcf5a801d76747d1fLogan    FuncInfo *info = &funcInfoList[i];
170f340bf71ff377979d279132dcf5a801d76747d1fLogan    OBCC_FuncInfo *outputInfo = &tab->table[i];
171a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
172f340bf71ff377979d279132dcf5a801d76747d1fLogan    outputInfo->name_strp_index = addString(info->name, strlen(info->name));
173f340bf71ff377979d279132dcf5a801d76747d1fLogan    outputInfo->cached_addr = info->addr;
174f340bf71ff377979d279132dcf5a801d76747d1fLogan    outputInfo->size = info->size;
175a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
176a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
177a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
178a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
179a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
180a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
181a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::preparePragmaList() {
182be79ada39b5e77b638940d2e157a45904ee09275Logan  size_t pragmaCount = mpOwner->getPragmaCount();
183a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
184a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_PragmaList) +
185a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                    sizeof(OBCC_Pragma) * pragmaCount;
186a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
187a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
188a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
189a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
190a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for pragma list\n");
191a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
192a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
193a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
194a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpPragmaListSection = list;
195a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->pragma_list_size = listSize;
196a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
197a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = pragmaCount;
198a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
199be79ada39b5e77b638940d2e157a45904ee09275Logan  vector<char const *> keyList(pragmaCount);
200be79ada39b5e77b638940d2e157a45904ee09275Logan  vector<char const *> valueList(pragmaCount);
201be79ada39b5e77b638940d2e157a45904ee09275Logan  mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
202a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
203a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < pragmaCount; ++i) {
204be79ada39b5e77b638940d2e157a45904ee09275Logan    char const *key = keyList[i];
205be79ada39b5e77b638940d2e157a45904ee09275Logan    char const *value = valueList[i];
206a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
207be79ada39b5e77b638940d2e157a45904ee09275Logan    size_t keyLen = strlen(key);
208a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size_t valueLen = strlen(value);
209a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
210a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_Pragma *pragma = &list->list[i];
211a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    pragma->key_strp_index = addString(key, keyLen);
212a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    pragma->value_strp_index = addString(value, valueLen);
213a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
214a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
215a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
216a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
217a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
218a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
219a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareRelocationTable() {
220a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // TODO(logan): Implement relocation table cache write.
221a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return false;
222a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
223a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
224a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
225a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareStringPool() {
226a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Calculate string pool size
227a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t size = sizeof(OBCC_StringPool) +
228a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                sizeof(OBCC_String) * mStringPool.size();
229a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
230a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  off_t strOffset = size;
231a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
232a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < mStringPool.size(); ++i) {
233a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size += mStringPool[i].second + 1;
234a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
235a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
236a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Create string pool
237a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
238a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
239a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!pool) {
240a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate string pool.\n");
241a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
242a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
243a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
244a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpStringPoolSection = pool;
245a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->str_pool_size = size;
246a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
247a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  pool->count = mStringPool.size();
248a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan
249a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
250a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
251a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < mStringPool.size(); ++i) {
252a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_String *str = &pool->list[i];
253a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
254a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    str->length = mStringPool[i].second;
255a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    str->offset = strOffset;
256a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    memcpy(strPtr, mStringPool[i].first, str->length);
257a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
258a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    strPtr += str->length;
259a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    *strPtr++ = '\0';
260a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
261a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan    strOffset += str->length + 1;
262a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
263a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
264a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
265a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
266a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
267a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
268a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareExportVarList() {
269be79ada39b5e77b638940d2e157a45904ee09275Logan  size_t varCount = mpOwner->getExportVarCount();
270a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_ExportVarList) + sizeof(void *) * varCount;
271a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
272a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_ExportVarList *list = (OBCC_ExportVarList *)malloc(listSize);
273a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
274a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
275a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for export variable list\n");
276a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
277a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
278a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
279a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpExportVarListSection = list;
280a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->export_var_list_size = listSize;
281a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
282a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = static_cast<size_t>(varCount);
283a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
284be79ada39b5e77b638940d2e157a45904ee09275Logan  mpOwner->getExportVarList(varCount, list->cached_addr_list);
285a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
286a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
287a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
288a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
289a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareExportFuncList() {
290be79ada39b5e77b638940d2e157a45904ee09275Logan  size_t funcCount = mpOwner->getExportFuncCount();
291a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_ExportFuncList) + sizeof(void *) * funcCount;
292a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
293a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_ExportFuncList *list = (OBCC_ExportFuncList *)malloc(listSize);
294a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
295a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
296a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for export function list\n");
297a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
298a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
299a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
300a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpExportFuncListSection = list;
301a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->export_func_list_size = listSize;
302a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
303a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = static_cast<size_t>(funcCount);
304a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
305be79ada39b5e77b638940d2e157a45904ee09275Logan  mpOwner->getExportFuncList(funcCount, list->cached_addr_list);
306a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
307a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
308a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
309a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
310a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::calcSectionOffset() {
311a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t offset = sizeof(OBCC_Header);
312a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
313a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define OFFSET_INCREASE(NAME)                                               \
314a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  do {                                                                      \
315a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    /* Align to a word */                                                   \
316a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size_t rem = offset % sizeof(int);                                      \
317a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    if (rem > 0) {                                                          \
318a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      offset += sizeof(int) - rem;                                          \
319a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
320a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                                                                            \
321a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    /* Save the offset and increase it */                                   \
322a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    mpHeaderSection->NAME##_offset = offset;                                \
323a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    offset += mpHeaderSection->NAME##_size;                                 \
324a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  } while (0)
325a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
326a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(str_pool);
327a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(depend_tab);
328a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  //OFFSET_INCREASE(reloc_tab);
329a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(export_var_list);
330a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(export_func_list);
331a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(pragma_list);
332a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(func_table);
333a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
334a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef OFFSET_INCREASE
335a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
336a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Context
337a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  long pagesize = sysconf(_SC_PAGESIZE);
338a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t context_offset_rem = offset % pagesize;
339a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (context_offset_rem) {
340a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    offset += pagesize - context_offset_rem;
341a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
342a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
343a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->context_offset = offset;
344a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
345a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
346a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
347a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
348a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::calcContextChecksum() {
349a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t sum = 0;
350a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t *ptr = reinterpret_cast<uint32_t *>(mpOwner->getContext());
351a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
352a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
353a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    sum ^= *ptr++;
354a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
355a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
356a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->context_parity_checksum = sum;
357a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
358a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
359a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
360a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
361a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::writeAll() {
362a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION)                          \
363a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  do {                                                                      \
364a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    if (mFile->seek(OFFSET, SEEK_SET) == -1) {                              \
365a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      LOGE("Unable to seek to " #NAME " section for writing.\n");           \
366a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      return false;                                                         \
367a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
368a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                                                                            \
369a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    if (mFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) !=          \
370a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan        static_cast<ssize_t>(SIZE)) {                                       \
371a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      LOGE("Unable to write " #NAME " section to cache file.\n");           \
372a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      return false;                                                         \
373a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
374a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  } while (0)
375a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
376a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define WRITE_SECTION_SIMPLE(NAME, SECTION)                                 \
377a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION(NAME,                                                       \
378a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                mpHeaderSection->NAME##_offset,                             \
379a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                mpHeaderSection->NAME##_size,                               \
380a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                SECTION)
381a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
382a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION(header, 0, sizeof(OBCC_Header), mpHeaderSection);
383a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
384a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
385a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
386a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  //WRITE_SECTION_SIMPLE(reloc_tab, mpRelocationTableSection);
387a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(export_var_list, mpExportVarListSection);
388a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(export_func_list, mpExportFuncListSection);
389a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
390a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(func_table, mpFuncTableSection);
391a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
392a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION(context, mpHeaderSection->context_offset, BCC_CONTEXT_SIZE,
393a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                mpOwner->getContext());
394a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
395a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef WRITE_SECTION_SIMPLE
396a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef WRITE_SECTION
397a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
398a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
399a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
400a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
401a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
402a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan} // namespace bcc
403