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#include "CacheWriter.h"
18a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
19a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include "ContextManager.h"
204dcd6798f3db374a056ea6acc6b425f544c5207cLogan#include "DebugHelper.h"
21a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include "FileHandle.h"
22a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include "Script.h"
23a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
24a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <map>
25a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <string>
26a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <vector>
27a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <utility>
28a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
29a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <stdint.h>
30a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <stdlib.h>
31a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#include <string.h>
32a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
33a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganusing namespace std;
34a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
35a27a83f2b01b1710238d077dc9dfd7655f4513cdLogannamespace bcc {
36a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
379d93894295ac70d85c5792da4c1398391fb67915LoganCacheWriter::~CacheWriter() {
389d93894295ac70d85c5792da4c1398391fb67915Logan#define CHECK_AND_FREE(VAR) if (VAR) { free(VAR); }
399d93894295ac70d85c5792da4c1398391fb67915Logan
409d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpHeaderSection);
419d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpStringPoolSection);
429d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpDependencyTableSection);
439d93894295ac70d85c5792da4c1398391fb67915Logan  //CHECK_AND_FREE(mpRelocationTableSection);
449d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpExportVarListSection);
459d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpExportFuncListSection);
469d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpPragmaListSection);
479d93894295ac70d85c5792da4c1398391fb67915Logan  CHECK_AND_FREE(mpFuncTableSection);
48071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  CHECK_AND_FREE(mpObjectSlotSection);
499d93894295ac70d85c5792da4c1398391fb67915Logan
509d93894295ac70d85c5792da4c1398391fb67915Logan#undef CHECK_AND_FREE
519d93894295ac70d85c5792da4c1398391fb67915Logan}
529d93894295ac70d85c5792da4c1398391fb67915Logan
5303a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chienbool CacheWriter::writeCacheFile(FileHandle *objFile,
5403a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien                                 FileHandle *infoFile,
5503a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien                                 Script *S,
56a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                                 uint32_t libRS_threadable) {
5703a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien  if (!objFile || objFile->getFD() < 0 ||
5803a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien      !infoFile || infoFile->getFD() < 0) {
59a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
60a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
61a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
6203a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien  mObjFile = objFile;
6303a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien  mInfoFile = infoFile;
64a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpOwner = S;
65a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
66a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  bool result = prepareHeader(libRS_threadable)
67a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareDependencyTable()
68a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareFuncTable()
69a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && preparePragmaList()
70a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             //&& prepareRelocationTable()
71a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareStringPool()
72a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareExportVarList()
73a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && prepareExportFuncList()
74071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines             && prepareObjectSlotList()
75a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && calcSectionOffset()
76a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && calcContextChecksum()
77a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             && writeAll()
78a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan             ;
79a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
80a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return result;
81a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
82a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
83a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
84a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareHeader(uint32_t libRS_threadable) {
85a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_Header *header = (OBCC_Header *)malloc(sizeof(OBCC_Header));
86a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
87a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!header) {
88a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for header.\n");
89a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
90a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
91a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
92a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection = header;
93a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
94a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Initialize
95a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  memset(header, '\0', sizeof(OBCC_Header));
96a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
97f7cfc026ec9e3a307d1252c46be9a089d74d3ef3Shih-wei Liao  // Magic word and version
98a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  memcpy(header->magic, OBCC_MAGIC, 4);
99a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  memcpy(header->version, OBCC_VERSION, 4);
100a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
101a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Machine Integer Type
102a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t number = 0x00000001;
103a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
104a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_off_t = sizeof(off_t);
105a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_size_t = sizeof(size_t);
106a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->sizeof_ptr_t = sizeof(void *);
107a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
108a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Context
109a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->context_cached_addr = mpOwner->getContext();
110a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
111a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // libRS is threadable dirty hack
112a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // TODO: This should be removed in the future
113a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  header->libRS_threadable = libRS_threadable;
114a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
115a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
116a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
117a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
118a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
119a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareDependencyTable() {
120a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t tableSize = sizeof(OBCC_DependencyTable) +
121a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                     sizeof(OBCC_Dependency) * mDependencies.size();
122a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
123a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
124f7cfc026ec9e3a307d1252c46be9a089d74d3ef3Shih-wei Liao
125a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!tab) {
126a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for dependency table section.\n");
127a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
128a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
129a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
130a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpDependencyTableSection = tab;
131a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->depend_tab_size = tableSize;
132a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
133a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  tab->count = mDependencies.size();
134a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
135a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t i = 0;
136a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (map<string, pair<uint32_t, unsigned char const *> >::iterator
137a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan       I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
138a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_Dependency *dep = &tab->table[i];
139a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
140a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
141a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    dep->res_type = I->second.first;
142a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    memcpy(dep->sha1, I->second.second, 20);
143a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
144a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
145a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
146a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
147a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
148a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
149a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareFuncTable() {
150be79ada39b5e77b638940d2e157a45904ee09275Logan  size_t funcCount = mpOwner->getFuncCount();
151a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
152a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t tableSize = sizeof(OBCC_FuncTable) +
153a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                     sizeof(OBCC_FuncInfo) * funcCount;
154a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
155a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_FuncTable *tab = (OBCC_FuncTable *)malloc(tableSize);
156a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
157a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!tab) {
158a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for function table section.\n");
159a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
160a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
161a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
162a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpFuncTableSection = tab;
163f7cfc026ec9e3a307d1252c46be9a089d74d3ef3Shih-wei Liao  mpHeaderSection->func_table_size = tableSize;
164a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
165a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  tab->count = static_cast<size_t>(funcCount);
166a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
167f7cfc026ec9e3a307d1252c46be9a089d74d3ef3Shih-wei Liao  // Get the function informations
168f340bf71ff377979d279132dcf5a801d76747d1fLogan  vector<FuncInfo> funcInfoList(funcCount);
169f340bf71ff377979d279132dcf5a801d76747d1fLogan  mpOwner->getFuncInfoList(funcCount, &*funcInfoList.begin());
170a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
171be79ada39b5e77b638940d2e157a45904ee09275Logan  for (size_t i = 0; i < funcCount; ++i) {
172f340bf71ff377979d279132dcf5a801d76747d1fLogan    FuncInfo *info = &funcInfoList[i];
173f340bf71ff377979d279132dcf5a801d76747d1fLogan    OBCC_FuncInfo *outputInfo = &tab->table[i];
174a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
175f340bf71ff377979d279132dcf5a801d76747d1fLogan    outputInfo->name_strp_index = addString(info->name, strlen(info->name));
176f340bf71ff377979d279132dcf5a801d76747d1fLogan    outputInfo->cached_addr = info->addr;
177f340bf71ff377979d279132dcf5a801d76747d1fLogan    outputInfo->size = info->size;
178a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
179a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
180a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
181a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
182a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
183a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
184a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::preparePragmaList() {
185be79ada39b5e77b638940d2e157a45904ee09275Logan  size_t pragmaCount = mpOwner->getPragmaCount();
186a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
187a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_PragmaList) +
188a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                    sizeof(OBCC_Pragma) * pragmaCount;
189a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
190a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
191a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
192a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
193a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for pragma list\n");
194a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
195a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
196a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
197a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpPragmaListSection = list;
198a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->pragma_list_size = listSize;
199a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
200a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = pragmaCount;
201a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
202be79ada39b5e77b638940d2e157a45904ee09275Logan  vector<char const *> keyList(pragmaCount);
203be79ada39b5e77b638940d2e157a45904ee09275Logan  vector<char const *> valueList(pragmaCount);
204be79ada39b5e77b638940d2e157a45904ee09275Logan  mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
205a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
206a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < pragmaCount; ++i) {
207be79ada39b5e77b638940d2e157a45904ee09275Logan    char const *key = keyList[i];
208be79ada39b5e77b638940d2e157a45904ee09275Logan    char const *value = valueList[i];
209a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
210be79ada39b5e77b638940d2e157a45904ee09275Logan    size_t keyLen = strlen(key);
211a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size_t valueLen = strlen(value);
212a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
213a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_Pragma *pragma = &list->list[i];
214a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    pragma->key_strp_index = addString(key, keyLen);
215a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    pragma->value_strp_index = addString(value, valueLen);
216a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
217a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
218a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
219a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
220a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
221a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
222a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareRelocationTable() {
223a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // TODO(logan): Implement relocation table cache write.
224a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return false;
225a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
226a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
227a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
228a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareStringPool() {
229a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Calculate string pool size
230a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t size = sizeof(OBCC_StringPool) +
231a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                sizeof(OBCC_String) * mStringPool.size();
232a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
233a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  off_t strOffset = size;
234a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
235a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < mStringPool.size(); ++i) {
236a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size += mStringPool[i].second + 1;
237a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
238a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
239a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  // Create string pool
240a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
241a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
242a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!pool) {
243a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate string pool.\n");
244a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
245a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
246a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
247a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpStringPoolSection = pool;
248a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->str_pool_size = size;
249a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
250a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan  pool->count = mStringPool.size();
251a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan
252a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
253a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
254a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  for (size_t i = 0; i < mStringPool.size(); ++i) {
255a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    OBCC_String *str = &pool->list[i];
256a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
257a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    str->length = mStringPool[i].second;
258a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    str->offset = strOffset;
259a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    memcpy(strPtr, mStringPool[i].first, str->length);
260a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
261a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    strPtr += str->length;
262a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    *strPtr++ = '\0';
263a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
264a2e15af1239e9d5bf6c6c9c5ecb9651217d0efdfLogan    strOffset += str->length + 1;
265a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
266a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
267a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
268a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
269a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
270a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
271a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareExportVarList() {
272be79ada39b5e77b638940d2e157a45904ee09275Logan  size_t varCount = mpOwner->getExportVarCount();
273a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_ExportVarList) + sizeof(void *) * varCount;
274a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
275a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_ExportVarList *list = (OBCC_ExportVarList *)malloc(listSize);
276a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
277a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
278a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for export variable list\n");
279a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
280a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
281a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
282a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpExportVarListSection = list;
283a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->export_var_list_size = listSize;
284a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
285a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = static_cast<size_t>(varCount);
286a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
287be79ada39b5e77b638940d2e157a45904ee09275Logan  mpOwner->getExportVarList(varCount, list->cached_addr_list);
288a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
289a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
290a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
291a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
292a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::prepareExportFuncList() {
293be79ada39b5e77b638940d2e157a45904ee09275Logan  size_t funcCount = mpOwner->getExportFuncCount();
294a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t listSize = sizeof(OBCC_ExportFuncList) + sizeof(void *) * funcCount;
295a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
296a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OBCC_ExportFuncList *list = (OBCC_ExportFuncList *)malloc(listSize);
297a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
298a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  if (!list) {
299a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    LOGE("Unable to allocate for export function list\n");
300a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    return false;
301a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
302a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
303a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpExportFuncListSection = list;
304a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->export_func_list_size = listSize;
305a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
306a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  list->count = static_cast<size_t>(funcCount);
307a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
308be79ada39b5e77b638940d2e157a45904ee09275Logan  mpOwner->getExportFuncList(funcCount, list->cached_addr_list);
309a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
310a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
311a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
312a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
313071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hinesbool CacheWriter::prepareObjectSlotList() {
314071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  size_t objectSlotCount = mpOwner->getObjectSlotCount();
315071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
316071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  size_t listSize = sizeof(OBCC_ObjectSlotList) +
317071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines                    sizeof(uint32_t) * objectSlotCount;
318071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
319071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
320071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
321071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  if (!list) {
322071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines    LOGE("Unable to allocate for object slot list\n");
323071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines    return false;
324071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  }
325071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
326071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  mpObjectSlotSection = list;
327071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  mpHeaderSection->object_slot_list_size = listSize;
328071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
329071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  list->count = objectSlotCount;
330071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
331071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
332071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  return true;
333071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines}
334071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
335071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines
336a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::calcSectionOffset() {
337a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  size_t offset = sizeof(OBCC_Header);
338a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
339a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define OFFSET_INCREASE(NAME)                                               \
340a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  do {                                                                      \
341a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    /* Align to a word */                                                   \
342a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    size_t rem = offset % sizeof(int);                                      \
343a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    if (rem > 0) {                                                          \
344a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      offset += sizeof(int) - rem;                                          \
345a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
346a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                                                                            \
347a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    /* Save the offset and increase it */                                   \
348a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    mpHeaderSection->NAME##_offset = offset;                                \
349a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    offset += mpHeaderSection->NAME##_size;                                 \
350a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  } while (0)
351a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
352a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(str_pool);
353a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(depend_tab);
354a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  //OFFSET_INCREASE(reloc_tab);
355a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(export_var_list);
356a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(export_func_list);
357a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(pragma_list);
358a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  OFFSET_INCREASE(func_table);
359071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  OFFSET_INCREASE(object_slot_list);
360a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
361a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef OFFSET_INCREASE
362a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
363a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
364a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
365a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
366a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::calcContextChecksum() {
367a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t sum = 0;
368a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  uint32_t *ptr = reinterpret_cast<uint32_t *>(mpOwner->getContext());
369a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
3701dc6314a03b320f9ba5431834c2deeba13f5f065Logan  for (size_t i = 0; i < ContextManager::ContextSize / sizeof(uint32_t); ++i) {
371a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    sum ^= *ptr++;
372a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  }
373a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
374a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  mpHeaderSection->context_parity_checksum = sum;
375a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
376a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
377a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
378a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
379a27a83f2b01b1710238d077dc9dfd7655f4513cdLoganbool CacheWriter::writeAll() {
380a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION)                          \
381a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  do {                                                                      \
38203a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien    if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) {                          \
383a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      LOGE("Unable to seek to " #NAME " section for writing.\n");           \
384a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      return false;                                                         \
385a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
386a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                                                                            \
38703a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien    if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) !=      \
388a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan        static_cast<ssize_t>(SIZE)) {                                       \
389a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      LOGE("Unable to write " #NAME " section to cache file.\n");           \
390a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan      return false;                                                         \
391a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan    }                                                                       \
392a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  } while (0)
393a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
394a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#define WRITE_SECTION_SIMPLE(NAME, SECTION)                                 \
395a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION(NAME,                                                       \
396a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                mpHeaderSection->NAME##_offset,                             \
397a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                mpHeaderSection->NAME##_size,                               \
398a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan                SECTION)
399a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
400a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION(header, 0, sizeof(OBCC_Header), mpHeaderSection);
401a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
402a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
403a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
404a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  //WRITE_SECTION_SIMPLE(reloc_tab, mpRelocationTableSection);
405a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(export_var_list, mpExportVarListSection);
406a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(export_func_list, mpExportFuncListSection);
407a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
408a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  WRITE_SECTION_SIMPLE(func_table, mpFuncTableSection);
409071288a0a3bbc3c4a6e161ea7474a5c06bd15ae0Stephen Hines  WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
410a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
411a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef WRITE_SECTION_SIMPLE
412a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan#undef WRITE_SECTION
413a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
41403a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien
41503a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien  // Write Context to Executable File
41603a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien  char const *context = (char const *)mpOwner->getContext();
41703a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien  size_t context_size = ContextManager::ContextSize;
41803a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien  if (mObjFile->write(context, context_size) != (ssize_t)context_size) {
41903a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien    LOGE("Unable to write context image to executable file\n");
42003a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien    return false;
42103a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien  }
42203a2e30e9ee0e3a880eb60f5047302d216db9582Logan Chien
423a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan  return true;
424a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan}
425a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
426a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan
427a27a83f2b01b1710238d077dc9dfd7655f4513cdLogan} // namespace bcc
428