blob: b0971ba6b6460fe80900d37a6928e21d33c167e2 [file] [log] [blame]
Logana27a83f2011-01-07 10:25:48 +08001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "bcc"
18#include <cutils/log.h>
19
20#include "CacheWriter.h"
21
22#include "ContextManager.h"
23#include "FileHandle.h"
24#include "Script.h"
25
26#include <map>
27#include <string>
28#include <vector>
29#include <utility>
30
31#include <stdint.h>
32#include <stdlib.h>
33#include <string.h>
34
35using namespace std;
36
37namespace bcc {
38
Logan9d938942011-01-07 10:44:43 +080039CacheWriter::~CacheWriter() {
40#define CHECK_AND_FREE(VAR) if (VAR) { free(VAR); }
41
42 CHECK_AND_FREE(mpHeaderSection);
43 CHECK_AND_FREE(mpStringPoolSection);
44 CHECK_AND_FREE(mpDependencyTableSection);
45 //CHECK_AND_FREE(mpRelocationTableSection);
46 CHECK_AND_FREE(mpExportVarListSection);
47 CHECK_AND_FREE(mpExportFuncListSection);
48 CHECK_AND_FREE(mpPragmaListSection);
49 CHECK_AND_FREE(mpFuncTableSection);
Stephen Hines071288a2011-01-27 14:38:26 -080050 CHECK_AND_FREE(mpObjectSlotSection);
Logan9d938942011-01-07 10:44:43 +080051
52#undef CHECK_AND_FREE
53}
54
Logana27a83f2011-01-07 10:25:48 +080055bool CacheWriter::writeCacheFile(FileHandle *file, Script *S,
56 uint32_t libRS_threadable) {
57 if (!file || file->getFD() < 0) {
58 return false;
59 }
60
61 mFile = file;
62 mpOwner = S;
63
64 bool result = prepareHeader(libRS_threadable)
65 && prepareDependencyTable()
66 && prepareFuncTable()
67 && preparePragmaList()
68 //&& prepareRelocationTable()
69 && prepareStringPool()
70 && prepareExportVarList()
71 && prepareExportFuncList()
Stephen Hines071288a2011-01-27 14:38:26 -080072 && prepareObjectSlotList()
Logana27a83f2011-01-07 10:25:48 +080073 && calcSectionOffset()
74 && calcContextChecksum()
75 && writeAll()
76 ;
77
78 return result;
79}
80
81
82bool CacheWriter::prepareHeader(uint32_t libRS_threadable) {
83 OBCC_Header *header = (OBCC_Header *)malloc(sizeof(OBCC_Header));
84
85 if (!header) {
86 LOGE("Unable to allocate for header.\n");
87 return false;
88 }
89
90 mpHeaderSection = header;
91
92 // Initialize
93 memset(header, '\0', sizeof(OBCC_Header));
94
Shih-wei Liaof7cfc022011-01-07 06:39:53 -080095 // Magic word and version
Logana27a83f2011-01-07 10:25:48 +080096 memcpy(header->magic, OBCC_MAGIC, 4);
97 memcpy(header->version, OBCC_VERSION, 4);
Logane1323992011-01-12 04:47:13 +080098 memcpy(header->libbcc_build_time, libbcc_build_time, 24);
Logana27a83f2011-01-07 10:25:48 +080099
100 // Machine Integer Type
101 uint32_t number = 0x00000001;
102 header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
103 header->sizeof_off_t = sizeof(off_t);
104 header->sizeof_size_t = sizeof(size_t);
105 header->sizeof_ptr_t = sizeof(void *);
106
107 // Context
108 header->context_cached_addr = mpOwner->getContext();
109
110 // libRS is threadable dirty hack
111 // TODO: This should be removed in the future
112 header->libRS_threadable = libRS_threadable;
113
114 return true;
115}
116
117
118bool CacheWriter::prepareDependencyTable() {
119 size_t tableSize = sizeof(OBCC_DependencyTable) +
120 sizeof(OBCC_Dependency) * mDependencies.size();
121
122 OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
Shih-wei Liaof7cfc022011-01-07 06:39:53 -0800123
Logana27a83f2011-01-07 10:25:48 +0800124 if (!tab) {
125 LOGE("Unable to allocate for dependency table section.\n");
126 return false;
127 }
128
129 mpDependencyTableSection = tab;
130 mpHeaderSection->depend_tab_size = tableSize;
131
132 tab->count = mDependencies.size();
133
134 size_t i = 0;
135 for (map<string, pair<uint32_t, unsigned char const *> >::iterator
136 I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
137 OBCC_Dependency *dep = &tab->table[i];
138
139 dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
140 dep->res_type = I->second.first;
141 memcpy(dep->sha1, I->second.second, 20);
142 }
143
144 return true;
145}
146
147
148bool CacheWriter::prepareFuncTable() {
Loganbe79ada2011-01-13 01:33:45 +0800149 size_t funcCount = mpOwner->getFuncCount();
Logana27a83f2011-01-07 10:25:48 +0800150
151 size_t tableSize = sizeof(OBCC_FuncTable) +
152 sizeof(OBCC_FuncInfo) * funcCount;
153
154 OBCC_FuncTable *tab = (OBCC_FuncTable *)malloc(tableSize);
155
156 if (!tab) {
157 LOGE("Unable to allocate for function table section.\n");
158 return false;
159 }
160
161 mpFuncTableSection = tab;
Shih-wei Liaof7cfc022011-01-07 06:39:53 -0800162 mpHeaderSection->func_table_size = tableSize;
Logana27a83f2011-01-07 10:25:48 +0800163
164 tab->count = static_cast<size_t>(funcCount);
165
Shih-wei Liaof7cfc022011-01-07 06:39:53 -0800166 // Get the function informations
Loganf340bf72011-01-14 17:51:40 +0800167 vector<FuncInfo> funcInfoList(funcCount);
168 mpOwner->getFuncInfoList(funcCount, &*funcInfoList.begin());
Logana27a83f2011-01-07 10:25:48 +0800169
Loganbe79ada2011-01-13 01:33:45 +0800170 for (size_t i = 0; i < funcCount; ++i) {
Loganf340bf72011-01-14 17:51:40 +0800171 FuncInfo *info = &funcInfoList[i];
172 OBCC_FuncInfo *outputInfo = &tab->table[i];
Logana27a83f2011-01-07 10:25:48 +0800173
Loganf340bf72011-01-14 17:51:40 +0800174 outputInfo->name_strp_index = addString(info->name, strlen(info->name));
175 outputInfo->cached_addr = info->addr;
176 outputInfo->size = info->size;
Logana27a83f2011-01-07 10:25:48 +0800177 }
178
179 return true;
180}
181
182
183bool CacheWriter::preparePragmaList() {
Loganbe79ada2011-01-13 01:33:45 +0800184 size_t pragmaCount = mpOwner->getPragmaCount();
Logana27a83f2011-01-07 10:25:48 +0800185
186 size_t listSize = sizeof(OBCC_PragmaList) +
187 sizeof(OBCC_Pragma) * pragmaCount;
188
189 OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
190
191 if (!list) {
192 LOGE("Unable to allocate for pragma list\n");
193 return false;
194 }
195
196 mpPragmaListSection = list;
197 mpHeaderSection->pragma_list_size = listSize;
198
199 list->count = pragmaCount;
200
Loganbe79ada2011-01-13 01:33:45 +0800201 vector<char const *> keyList(pragmaCount);
202 vector<char const *> valueList(pragmaCount);
203 mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
Logana27a83f2011-01-07 10:25:48 +0800204
205 for (size_t i = 0; i < pragmaCount; ++i) {
Loganbe79ada2011-01-13 01:33:45 +0800206 char const *key = keyList[i];
207 char const *value = valueList[i];
Logana27a83f2011-01-07 10:25:48 +0800208
Loganbe79ada2011-01-13 01:33:45 +0800209 size_t keyLen = strlen(key);
Logana27a83f2011-01-07 10:25:48 +0800210 size_t valueLen = strlen(value);
211
212 OBCC_Pragma *pragma = &list->list[i];
213 pragma->key_strp_index = addString(key, keyLen);
214 pragma->value_strp_index = addString(value, valueLen);
215 }
216
217 return true;
218}
219
220
221bool CacheWriter::prepareRelocationTable() {
222 // TODO(logan): Implement relocation table cache write.
223 return false;
224}
225
226
227bool CacheWriter::prepareStringPool() {
228 // Calculate string pool size
229 size_t size = sizeof(OBCC_StringPool) +
230 sizeof(OBCC_String) * mStringPool.size();
231
232 off_t strOffset = size;
233
234 for (size_t i = 0; i < mStringPool.size(); ++i) {
235 size += mStringPool[i].second + 1;
236 }
237
238 // Create string pool
239 OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
240
241 if (!pool) {
242 LOGE("Unable to allocate string pool.\n");
243 return false;
244 }
245
246 mpStringPoolSection = pool;
247 mpHeaderSection->str_pool_size = size;
248
Logana2e15af2011-01-07 11:46:08 +0800249 pool->count = mStringPool.size();
250
Logana27a83f2011-01-07 10:25:48 +0800251 char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
252
253 for (size_t i = 0; i < mStringPool.size(); ++i) {
254 OBCC_String *str = &pool->list[i];
255
256 str->length = mStringPool[i].second;
257 str->offset = strOffset;
258 memcpy(strPtr, mStringPool[i].first, str->length);
259
260 strPtr += str->length;
261 *strPtr++ = '\0';
262
Logana2e15af2011-01-07 11:46:08 +0800263 strOffset += str->length + 1;
Logana27a83f2011-01-07 10:25:48 +0800264 }
265
266 return true;
267}
268
269
270bool CacheWriter::prepareExportVarList() {
Loganbe79ada2011-01-13 01:33:45 +0800271 size_t varCount = mpOwner->getExportVarCount();
Logana27a83f2011-01-07 10:25:48 +0800272 size_t listSize = sizeof(OBCC_ExportVarList) + sizeof(void *) * varCount;
273
274 OBCC_ExportVarList *list = (OBCC_ExportVarList *)malloc(listSize);
275
276 if (!list) {
277 LOGE("Unable to allocate for export variable list\n");
278 return false;
279 }
280
281 mpExportVarListSection = list;
282 mpHeaderSection->export_var_list_size = listSize;
283
284 list->count = static_cast<size_t>(varCount);
285
Loganbe79ada2011-01-13 01:33:45 +0800286 mpOwner->getExportVarList(varCount, list->cached_addr_list);
Logana27a83f2011-01-07 10:25:48 +0800287 return true;
288}
289
290
291bool CacheWriter::prepareExportFuncList() {
Loganbe79ada2011-01-13 01:33:45 +0800292 size_t funcCount = mpOwner->getExportFuncCount();
Logana27a83f2011-01-07 10:25:48 +0800293 size_t listSize = sizeof(OBCC_ExportFuncList) + sizeof(void *) * funcCount;
294
295 OBCC_ExportFuncList *list = (OBCC_ExportFuncList *)malloc(listSize);
296
297 if (!list) {
298 LOGE("Unable to allocate for export function list\n");
299 return false;
300 }
301
302 mpExportFuncListSection = list;
303 mpHeaderSection->export_func_list_size = listSize;
304
305 list->count = static_cast<size_t>(funcCount);
306
Loganbe79ada2011-01-13 01:33:45 +0800307 mpOwner->getExportFuncList(funcCount, list->cached_addr_list);
Logana27a83f2011-01-07 10:25:48 +0800308 return true;
309}
310
311
Stephen Hines071288a2011-01-27 14:38:26 -0800312bool CacheWriter::prepareObjectSlotList() {
313 size_t objectSlotCount = mpOwner->getObjectSlotCount();
314
315 size_t listSize = sizeof(OBCC_ObjectSlotList) +
316 sizeof(uint32_t) * objectSlotCount;
317
318 OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
319
320 if (!list) {
321 LOGE("Unable to allocate for object slot list\n");
322 return false;
323 }
324
325 mpObjectSlotSection = list;
326 mpHeaderSection->object_slot_list_size = listSize;
327
328 list->count = objectSlotCount;
329
330 mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
331 return true;
332}
333
334
Logana27a83f2011-01-07 10:25:48 +0800335bool CacheWriter::calcSectionOffset() {
336 size_t offset = sizeof(OBCC_Header);
337
338#define OFFSET_INCREASE(NAME) \
339 do { \
340 /* Align to a word */ \
341 size_t rem = offset % sizeof(int); \
342 if (rem > 0) { \
343 offset += sizeof(int) - rem; \
344 } \
345 \
346 /* Save the offset and increase it */ \
347 mpHeaderSection->NAME##_offset = offset; \
348 offset += mpHeaderSection->NAME##_size; \
349 } while (0)
350
351 OFFSET_INCREASE(str_pool);
352 OFFSET_INCREASE(depend_tab);
353 //OFFSET_INCREASE(reloc_tab);
354 OFFSET_INCREASE(export_var_list);
355 OFFSET_INCREASE(export_func_list);
356 OFFSET_INCREASE(pragma_list);
357 OFFSET_INCREASE(func_table);
Stephen Hines071288a2011-01-27 14:38:26 -0800358 OFFSET_INCREASE(object_slot_list);
Logana27a83f2011-01-07 10:25:48 +0800359
360#undef OFFSET_INCREASE
361
362 // Context
363 long pagesize = sysconf(_SC_PAGESIZE);
364 size_t context_offset_rem = offset % pagesize;
365 if (context_offset_rem) {
366 offset += pagesize - context_offset_rem;
367 }
368
369 mpHeaderSection->context_offset = offset;
370 return true;
371}
372
373
374bool CacheWriter::calcContextChecksum() {
375 uint32_t sum = 0;
376 uint32_t *ptr = reinterpret_cast<uint32_t *>(mpOwner->getContext());
377
Logan1dc63142011-02-25 17:14:51 +0800378 for (size_t i = 0; i < ContextManager::ContextSize / sizeof(uint32_t); ++i) {
Logana27a83f2011-01-07 10:25:48 +0800379 sum ^= *ptr++;
380 }
381
382 mpHeaderSection->context_parity_checksum = sum;
383 return true;
384}
385
386
387bool CacheWriter::writeAll() {
388#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION) \
389 do { \
390 if (mFile->seek(OFFSET, SEEK_SET) == -1) { \
391 LOGE("Unable to seek to " #NAME " section for writing.\n"); \
392 return false; \
393 } \
394 \
395 if (mFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) != \
396 static_cast<ssize_t>(SIZE)) { \
397 LOGE("Unable to write " #NAME " section to cache file.\n"); \
398 return false; \
399 } \
400 } while (0)
401
402#define WRITE_SECTION_SIMPLE(NAME, SECTION) \
403 WRITE_SECTION(NAME, \
404 mpHeaderSection->NAME##_offset, \
405 mpHeaderSection->NAME##_size, \
406 SECTION)
407
408 WRITE_SECTION(header, 0, sizeof(OBCC_Header), mpHeaderSection);
409
410 WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
411 WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
412 //WRITE_SECTION_SIMPLE(reloc_tab, mpRelocationTableSection);
413 WRITE_SECTION_SIMPLE(export_var_list, mpExportVarListSection);
414 WRITE_SECTION_SIMPLE(export_func_list, mpExportFuncListSection);
415 WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
416 WRITE_SECTION_SIMPLE(func_table, mpFuncTableSection);
Stephen Hines071288a2011-01-27 14:38:26 -0800417 WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
Logana27a83f2011-01-07 10:25:48 +0800418
Logan1dc63142011-02-25 17:14:51 +0800419 WRITE_SECTION(context, mpHeaderSection->context_offset,
420 ContextManager::ContextSize,
Logana27a83f2011-01-07 10:25:48 +0800421 mpOwner->getContext());
422
423#undef WRITE_SECTION_SIMPLE
424#undef WRITE_SECTION
425
426 return true;
427}
428
429
Logana27a83f2011-01-07 10:25:48 +0800430} // namespace bcc