CacheWriter.cpp revision a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdf
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
93a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Magic word and version
94a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  memcpy(header->magic, OBCC_MAGIC, 4);
95a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  memcpy(header->version, OBCC_VERSION, 4);
96a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
97a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Machine Integer Type
98a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t number = 0x00000001;
99a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
100a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_off_t = sizeof(off_t);
101a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_size_t = sizeof(size_t);
102a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_ptr_t = sizeof(void *);
103a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
104a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Context
105a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->context_cached_addr = mpOwner->getContext();
106a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
107a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // libRS is threadable dirty hack
108a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // TODO: This should be removed in the future
109a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->libRS_threadable = libRS_threadable;
110a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
111a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
112a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
113a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
114a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
115a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareDependencyTable() {
116a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t tableSize = sizeof(OBCC_DependencyTable) +
117a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                     sizeof(OBCC_Dependency) * mDependencies.size();
118a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
119a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
120a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
121a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!tab) {
122a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for dependency table section.\n");
123a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
124a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
125a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
126a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpDependencyTableSection = tab;
127a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->depend_tab_size = tableSize;
128a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
129a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  tab->count = mDependencies.size();
130a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
131a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t i = 0;
132a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (map<string, pair<uint32_t, unsigned char const *> >::iterator
133a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan       I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
134a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_Dependency *dep = &tab->table[i];
135a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
136a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
137a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    dep->res_type = I->second.first;
138a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    memcpy(dep->sha1, I->second.second, 20);
139a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
140a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
141a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
142a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
143a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
144a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
145a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareFuncTable() {
146a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  ssize_t funcCount = 0;
147a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
148a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner->getFunctions(&funcCount, 0, NULL);
149a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
150a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t tableSize = sizeof(OBCC_FuncTable) +
151a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                     sizeof(OBCC_FuncInfo) * funcCount;
152a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
153a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_FuncTable *tab = (OBCC_FuncTable *)malloc(tableSize);
154a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
155a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!tab) {
156a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for function table section.\n");
157a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
158a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
159a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
160a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpFuncTableSection = tab;
161a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->func_table_size = tableSize;
162a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
163a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  tab->count = static_cast<size_t>(funcCount);
164a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
165a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Get the function informations
166a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  vector<char *> funcNameList(funcCount);
167a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner->getFunctions(0, funcCount, &*funcNameList.begin());
168a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
169a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (int i = 0; i < funcCount; ++i) {
170a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    char *funcName = funcNameList[i];
171a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size_t funcNameLen = strlen(funcName);
172a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
173a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    void *funcAddr = NULL;
174a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    ssize_t funcBinarySize = 0;
175a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    mpOwner->getFunctionBinary(funcName, &funcAddr, &funcBinarySize);
176a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
177a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_FuncInfo *funcInfo = &tab->table[i];
178a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    funcInfo->name_strp_index = addString(funcName, funcNameLen);
179a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    funcInfo->cached_addr = funcAddr;
180a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    funcInfo->size = static_cast<size_t>(funcBinarySize);
181a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
182a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
183a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
184a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
185a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
186a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
187a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::preparePragmaList() {
188a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  ssize_t stringCount;
189a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
190a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner->getPragmas(&stringCount, 0, NULL);
191a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
192a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t pragmaCount = static_cast<size_t>(stringCount) / 2;
193a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
194a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_PragmaList) +
195a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                    sizeof(OBCC_Pragma) * pragmaCount;
196a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
197a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
198a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
199a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
200a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for pragma list\n");
201a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
202a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
203a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
204a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpPragmaListSection = list;
205a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->pragma_list_size = listSize;
206a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
207a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = pragmaCount;
208a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
209a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  vector<char *> strings(stringCount);
210a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner->getPragmas(&stringCount, stringCount, &*strings.begin());
211a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
212a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < pragmaCount; ++i) {
213a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    char *key = strings[2 * i];
214a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size_t keyLen = strlen(key);
215a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
216a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    char *value = strings[2 * i + 1];
217a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size_t valueLen = strlen(value);
218a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
219a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_Pragma *pragma = &list->list[i];
220a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    pragma->key_strp_index = addString(key, keyLen);
221a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    pragma->value_strp_index = addString(value, valueLen);
222a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
223a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
224a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
225a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
226a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
227a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
228a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareRelocationTable() {
229a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // TODO(logan): Implement relocation table cache write.
230a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return false;
231a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
232a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
233a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
234a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareStringPool() {
235a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Calculate string pool size
236a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t size = sizeof(OBCC_StringPool) +
237a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                sizeof(OBCC_String) * mStringPool.size();
238a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
239a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  off_t strOffset = size;
240a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
241a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < mStringPool.size(); ++i) {
242a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size += mStringPool[i].second + 1;
243a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
244a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
245a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Create string pool
246a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
247a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
248a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!pool) {
249a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate string pool.\n");
250a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
251a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
252a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
253a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpStringPoolSection = pool;
254a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->str_pool_size = size;
255a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
256a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  pool->count = mStringPool.size();
257a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan
258a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
259a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
260a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < mStringPool.size(); ++i) {
261a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_String *str = &pool->list[i];
262a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
263a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    str->length = mStringPool[i].second;
264a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    str->offset = strOffset;
265a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    memcpy(strPtr, mStringPool[i].first, str->length);
266a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
267a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    strPtr += str->length;
268a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    *strPtr++ = '\0';
269a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
270a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan    strOffset += str->length + 1;
271a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
272a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
273a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
274a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
275a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
276a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
277a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareExportVarList() {
278a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  ssize_t varCount;
279a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
280a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner->getExportVars(&varCount, 0, NULL);
281a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
282a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_ExportVarList) + sizeof(void *) * varCount;
283a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
284a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_ExportVarList *list = (OBCC_ExportVarList *)malloc(listSize);
285a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
286a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
287a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for export variable list\n");
288a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
289a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
290a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
291a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpExportVarListSection = list;
292a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->export_var_list_size = listSize;
293a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
294a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = static_cast<size_t>(varCount);
295a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
296a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner->getExportVars(&varCount, varCount, list->cached_addr_list);
297a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
298a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
299a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
300a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
301a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareExportFuncList() {
302a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  ssize_t funcCount;
303a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
304a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner->getExportFuncs(&funcCount, 0, NULL);
305a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
306a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_ExportFuncList) + sizeof(void *) * funcCount;
307a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
308a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_ExportFuncList *list = (OBCC_ExportFuncList *)malloc(listSize);
309a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
310a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
311a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for export function list\n");
312a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
313a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
314a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
315a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpExportFuncListSection = list;
316a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->export_func_list_size = listSize;
317a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
318a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = static_cast<size_t>(funcCount);
319a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
320a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner->getExportFuncs(&funcCount, funcCount, list->cached_addr_list);
321a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
322a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
323a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
324a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
325a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::calcSectionOffset() {
326a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t offset = sizeof(OBCC_Header);
327a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
328a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define OFFSET_INCREASE(NAME)                                               \
329a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  do {                                                                      \
330a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    /* Align to a word */                                                   \
331a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size_t rem = offset % sizeof(int);                                      \
332a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    if (rem > 0) {                                                          \
333a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      offset += sizeof(int) - rem;                                          \
334a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
335a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                                                                            \
336a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    /* Save the offset and increase it */                                   \
337a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    mpHeaderSection->NAME##_offset = offset;                                \
338a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    offset += mpHeaderSection->NAME##_size;                                 \
339a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  } while (0)
340a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
341a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(str_pool);
342a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(depend_tab);
343a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  //OFFSET_INCREASE(reloc_tab);
344a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(export_var_list);
345a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(export_func_list);
346a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(pragma_list);
347a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(func_table);
348a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
349a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef OFFSET_INCREASE
350a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
351a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Context
352a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  long pagesize = sysconf(_SC_PAGESIZE);
353a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t context_offset_rem = offset % pagesize;
354a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (context_offset_rem) {
355a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    offset += pagesize - context_offset_rem;
356a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
357a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
358a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->context_offset = offset;
359a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
360a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
361a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
362a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
363a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::calcContextChecksum() {
364a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t sum = 0;
365a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t *ptr = reinterpret_cast<uint32_t *>(mpOwner->getContext());
366a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
367a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
368a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    sum ^= *ptr++;
369a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
370a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
371a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->context_parity_checksum = sum;
372a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
373a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
374a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
375a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
376a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::writeAll() {
377a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION)                          \
378a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  do {                                                                      \
379a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    if (mFile->seek(OFFSET, SEEK_SET) == -1) {                              \
380a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      LOGE("Unable to seek to " #NAME " section for writing.\n");           \
381a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      return false;                                                         \
382a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
383a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                                                                            \
384a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    if (mFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) !=          \
385a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan        static_cast<ssize_t>(SIZE)) {                                       \
386a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      LOGE("Unable to write " #NAME " section to cache file.\n");           \
387a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      return false;                                                         \
388a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
389a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  } while (0)
390a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
391a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define WRITE_SECTION_SIMPLE(NAME, SECTION)                                 \
392a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION(NAME,                                                       \
393a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                mpHeaderSection->NAME##_offset,                             \
394a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                mpHeaderSection->NAME##_size,                               \
395a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                SECTION)
396a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
397a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION(header, 0, sizeof(OBCC_Header), mpHeaderSection);
398a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
399a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
400a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
401a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  //WRITE_SECTION_SIMPLE(reloc_tab, mpRelocationTableSection);
402a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(export_var_list, mpExportVarListSection);
403a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(export_func_list, mpExportFuncListSection);
404a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
405a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(func_table, mpFuncTableSection);
406a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
407a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION(context, mpHeaderSection->context_offset, BCC_CONTEXT_SIZE,
408a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                mpOwner->getContext());
409a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
410a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef WRITE_SECTION_SIMPLE
411a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef WRITE_SECTION
412a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
413a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
414a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
415a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
416a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
417a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan} // namespace bcc
418