blob: 4b536178d83cf28b9dbf1c7820c659c68d110382 [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
Logana27a83f2011-01-07 10:25:48 +080017#include "CacheWriter.h"
18
19#include "ContextManager.h"
Logan4dcd6792011-02-28 05:12:00 +080020#include "DebugHelper.h"
Logana27a83f2011-01-07 10:25:48 +080021#include "FileHandle.h"
22#include "Script.h"
23
24#include <map>
25#include <string>
26#include <vector>
27#include <utility>
28
29#include <stdint.h>
30#include <stdlib.h>
31#include <string.h>
32
33using namespace std;
34
35namespace bcc {
36
Logan9d938942011-01-07 10:44:43 +080037CacheWriter::~CacheWriter() {
38#define CHECK_AND_FREE(VAR) if (VAR) { free(VAR); }
39
40 CHECK_AND_FREE(mpHeaderSection);
41 CHECK_AND_FREE(mpStringPoolSection);
42 CHECK_AND_FREE(mpDependencyTableSection);
43 //CHECK_AND_FREE(mpRelocationTableSection);
44 CHECK_AND_FREE(mpExportVarListSection);
45 CHECK_AND_FREE(mpExportFuncListSection);
46 CHECK_AND_FREE(mpPragmaListSection);
47 CHECK_AND_FREE(mpFuncTableSection);
Stephen Hines071288a2011-01-27 14:38:26 -080048 CHECK_AND_FREE(mpObjectSlotSection);
Logan9d938942011-01-07 10:44:43 +080049
50#undef CHECK_AND_FREE
51}
52
Logan Chien03a2e302011-07-13 21:46:32 +080053bool CacheWriter::writeCacheFile(FileHandle *objFile,
54 FileHandle *infoFile,
55 Script *S,
Logana27a83f2011-01-07 10:25:48 +080056 uint32_t libRS_threadable) {
Logan Chien03a2e302011-07-13 21:46:32 +080057 if (!objFile || objFile->getFD() < 0 ||
58 !infoFile || infoFile->getFD() < 0) {
Logana27a83f2011-01-07 10:25:48 +080059 return false;
60 }
61
Logan Chien03a2e302011-07-13 21:46:32 +080062 mObjFile = objFile;
63 mInfoFile = infoFile;
Logana27a83f2011-01-07 10:25:48 +080064 mpOwner = S;
65
66 bool result = prepareHeader(libRS_threadable)
67 && prepareDependencyTable()
68 && prepareFuncTable()
69 && preparePragmaList()
70 //&& prepareRelocationTable()
71 && prepareStringPool()
72 && prepareExportVarList()
73 && prepareExportFuncList()
Stephen Hines071288a2011-01-27 14:38:26 -080074 && prepareObjectSlotList()
Logana27a83f2011-01-07 10:25:48 +080075 && calcSectionOffset()
76 && calcContextChecksum()
77 && writeAll()
78 ;
79
80 return result;
81}
82
83
84bool CacheWriter::prepareHeader(uint32_t libRS_threadable) {
85 OBCC_Header *header = (OBCC_Header *)malloc(sizeof(OBCC_Header));
86
87 if (!header) {
88 LOGE("Unable to allocate for header.\n");
89 return false;
90 }
91
92 mpHeaderSection = header;
93
94 // Initialize
95 memset(header, '\0', sizeof(OBCC_Header));
96
Shih-wei Liaof7cfc022011-01-07 06:39:53 -080097 // Magic word and version
Logana27a83f2011-01-07 10:25:48 +080098 memcpy(header->magic, OBCC_MAGIC, 4);
99 memcpy(header->version, OBCC_VERSION, 4);
100
101 // Machine Integer Type
102 uint32_t number = 0x00000001;
103 header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
104 header->sizeof_off_t = sizeof(off_t);
105 header->sizeof_size_t = sizeof(size_t);
106 header->sizeof_ptr_t = sizeof(void *);
107
108 // Context
109 header->context_cached_addr = mpOwner->getContext();
110
111 // libRS is threadable dirty hack
112 // TODO: This should be removed in the future
113 header->libRS_threadable = libRS_threadable;
114
115 return true;
116}
117
118
119bool CacheWriter::prepareDependencyTable() {
120 size_t tableSize = sizeof(OBCC_DependencyTable) +
121 sizeof(OBCC_Dependency) * mDependencies.size();
122
123 OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
Shih-wei Liaof7cfc022011-01-07 06:39:53 -0800124
Logana27a83f2011-01-07 10:25:48 +0800125 if (!tab) {
126 LOGE("Unable to allocate for dependency table section.\n");
127 return false;
128 }
129
130 mpDependencyTableSection = tab;
131 mpHeaderSection->depend_tab_size = tableSize;
132
133 tab->count = mDependencies.size();
134
135 size_t i = 0;
136 for (map<string, pair<uint32_t, unsigned char const *> >::iterator
137 I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
138 OBCC_Dependency *dep = &tab->table[i];
139
140 dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
141 dep->res_type = I->second.first;
142 memcpy(dep->sha1, I->second.second, 20);
143 }
144
145 return true;
146}
147
148
149bool CacheWriter::prepareFuncTable() {
Loganbe79ada2011-01-13 01:33:45 +0800150 size_t funcCount = mpOwner->getFuncCount();
Logana27a83f2011-01-07 10:25:48 +0800151
152 size_t tableSize = sizeof(OBCC_FuncTable) +
153 sizeof(OBCC_FuncInfo) * funcCount;
154
155 OBCC_FuncTable *tab = (OBCC_FuncTable *)malloc(tableSize);
156
157 if (!tab) {
158 LOGE("Unable to allocate for function table section.\n");
159 return false;
160 }
161
162 mpFuncTableSection = tab;
Shih-wei Liaof7cfc022011-01-07 06:39:53 -0800163 mpHeaderSection->func_table_size = tableSize;
Logana27a83f2011-01-07 10:25:48 +0800164
165 tab->count = static_cast<size_t>(funcCount);
166
Shih-wei Liaof7cfc022011-01-07 06:39:53 -0800167 // Get the function informations
Loganf340bf72011-01-14 17:51:40 +0800168 vector<FuncInfo> funcInfoList(funcCount);
169 mpOwner->getFuncInfoList(funcCount, &*funcInfoList.begin());
Logana27a83f2011-01-07 10:25:48 +0800170
Loganbe79ada2011-01-13 01:33:45 +0800171 for (size_t i = 0; i < funcCount; ++i) {
Loganf340bf72011-01-14 17:51:40 +0800172 FuncInfo *info = &funcInfoList[i];
173 OBCC_FuncInfo *outputInfo = &tab->table[i];
Logana27a83f2011-01-07 10:25:48 +0800174
Loganf340bf72011-01-14 17:51:40 +0800175 outputInfo->name_strp_index = addString(info->name, strlen(info->name));
176 outputInfo->cached_addr = info->addr;
177 outputInfo->size = info->size;
Logana27a83f2011-01-07 10:25:48 +0800178 }
179
180 return true;
181}
182
183
184bool CacheWriter::preparePragmaList() {
Loganbe79ada2011-01-13 01:33:45 +0800185 size_t pragmaCount = mpOwner->getPragmaCount();
Logana27a83f2011-01-07 10:25:48 +0800186
187 size_t listSize = sizeof(OBCC_PragmaList) +
188 sizeof(OBCC_Pragma) * pragmaCount;
189
190 OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
191
192 if (!list) {
193 LOGE("Unable to allocate for pragma list\n");
194 return false;
195 }
196
197 mpPragmaListSection = list;
198 mpHeaderSection->pragma_list_size = listSize;
199
200 list->count = pragmaCount;
201
Loganbe79ada2011-01-13 01:33:45 +0800202 vector<char const *> keyList(pragmaCount);
203 vector<char const *> valueList(pragmaCount);
204 mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
Logana27a83f2011-01-07 10:25:48 +0800205
206 for (size_t i = 0; i < pragmaCount; ++i) {
Loganbe79ada2011-01-13 01:33:45 +0800207 char const *key = keyList[i];
208 char const *value = valueList[i];
Logana27a83f2011-01-07 10:25:48 +0800209
Loganbe79ada2011-01-13 01:33:45 +0800210 size_t keyLen = strlen(key);
Logana27a83f2011-01-07 10:25:48 +0800211 size_t valueLen = strlen(value);
212
213 OBCC_Pragma *pragma = &list->list[i];
214 pragma->key_strp_index = addString(key, keyLen);
215 pragma->value_strp_index = addString(value, valueLen);
216 }
217
218 return true;
219}
220
221
222bool CacheWriter::prepareRelocationTable() {
223 // TODO(logan): Implement relocation table cache write.
224 return false;
225}
226
227
228bool CacheWriter::prepareStringPool() {
229 // Calculate string pool size
230 size_t size = sizeof(OBCC_StringPool) +
231 sizeof(OBCC_String) * mStringPool.size();
232
233 off_t strOffset = size;
234
235 for (size_t i = 0; i < mStringPool.size(); ++i) {
236 size += mStringPool[i].second + 1;
237 }
238
239 // Create string pool
240 OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
241
242 if (!pool) {
243 LOGE("Unable to allocate string pool.\n");
244 return false;
245 }
246
247 mpStringPoolSection = pool;
248 mpHeaderSection->str_pool_size = size;
249
Logana2e15af2011-01-07 11:46:08 +0800250 pool->count = mStringPool.size();
251
Logana27a83f2011-01-07 10:25:48 +0800252 char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
253
254 for (size_t i = 0; i < mStringPool.size(); ++i) {
255 OBCC_String *str = &pool->list[i];
256
257 str->length = mStringPool[i].second;
258 str->offset = strOffset;
259 memcpy(strPtr, mStringPool[i].first, str->length);
260
261 strPtr += str->length;
262 *strPtr++ = '\0';
263
Logana2e15af2011-01-07 11:46:08 +0800264 strOffset += str->length + 1;
Logana27a83f2011-01-07 10:25:48 +0800265 }
266
267 return true;
268}
269
270
271bool CacheWriter::prepareExportVarList() {
Loganbe79ada2011-01-13 01:33:45 +0800272 size_t varCount = mpOwner->getExportVarCount();
Logana27a83f2011-01-07 10:25:48 +0800273 size_t listSize = sizeof(OBCC_ExportVarList) + sizeof(void *) * varCount;
274
275 OBCC_ExportVarList *list = (OBCC_ExportVarList *)malloc(listSize);
276
277 if (!list) {
278 LOGE("Unable to allocate for export variable list\n");
279 return false;
280 }
281
282 mpExportVarListSection = list;
283 mpHeaderSection->export_var_list_size = listSize;
284
285 list->count = static_cast<size_t>(varCount);
286
Loganbe79ada2011-01-13 01:33:45 +0800287 mpOwner->getExportVarList(varCount, list->cached_addr_list);
Logana27a83f2011-01-07 10:25:48 +0800288 return true;
289}
290
291
292bool CacheWriter::prepareExportFuncList() {
Loganbe79ada2011-01-13 01:33:45 +0800293 size_t funcCount = mpOwner->getExportFuncCount();
Logana27a83f2011-01-07 10:25:48 +0800294 size_t listSize = sizeof(OBCC_ExportFuncList) + sizeof(void *) * funcCount;
295
296 OBCC_ExportFuncList *list = (OBCC_ExportFuncList *)malloc(listSize);
297
298 if (!list) {
299 LOGE("Unable to allocate for export function list\n");
300 return false;
301 }
302
303 mpExportFuncListSection = list;
304 mpHeaderSection->export_func_list_size = listSize;
305
306 list->count = static_cast<size_t>(funcCount);
307
Loganbe79ada2011-01-13 01:33:45 +0800308 mpOwner->getExportFuncList(funcCount, list->cached_addr_list);
Logana27a83f2011-01-07 10:25:48 +0800309 return true;
310}
311
312
Stephen Hines071288a2011-01-27 14:38:26 -0800313bool CacheWriter::prepareObjectSlotList() {
314 size_t objectSlotCount = mpOwner->getObjectSlotCount();
315
316 size_t listSize = sizeof(OBCC_ObjectSlotList) +
317 sizeof(uint32_t) * objectSlotCount;
318
319 OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
320
321 if (!list) {
322 LOGE("Unable to allocate for object slot list\n");
323 return false;
324 }
325
326 mpObjectSlotSection = list;
327 mpHeaderSection->object_slot_list_size = listSize;
328
329 list->count = objectSlotCount;
330
331 mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
332 return true;
333}
334
335
Logana27a83f2011-01-07 10:25:48 +0800336bool CacheWriter::calcSectionOffset() {
337 size_t offset = sizeof(OBCC_Header);
338
339#define OFFSET_INCREASE(NAME) \
340 do { \
341 /* Align to a word */ \
342 size_t rem = offset % sizeof(int); \
343 if (rem > 0) { \
344 offset += sizeof(int) - rem; \
345 } \
346 \
347 /* Save the offset and increase it */ \
348 mpHeaderSection->NAME##_offset = offset; \
349 offset += mpHeaderSection->NAME##_size; \
350 } while (0)
351
352 OFFSET_INCREASE(str_pool);
353 OFFSET_INCREASE(depend_tab);
354 //OFFSET_INCREASE(reloc_tab);
355 OFFSET_INCREASE(export_var_list);
356 OFFSET_INCREASE(export_func_list);
357 OFFSET_INCREASE(pragma_list);
358 OFFSET_INCREASE(func_table);
Stephen Hines071288a2011-01-27 14:38:26 -0800359 OFFSET_INCREASE(object_slot_list);
Logana27a83f2011-01-07 10:25:48 +0800360
361#undef OFFSET_INCREASE
Logana27a83f2011-01-07 10:25:48 +0800362 return true;
363}
364
365
366bool CacheWriter::calcContextChecksum() {
367 uint32_t sum = 0;
368 uint32_t *ptr = reinterpret_cast<uint32_t *>(mpOwner->getContext());
369
Logan1dc63142011-02-25 17:14:51 +0800370 for (size_t i = 0; i < ContextManager::ContextSize / sizeof(uint32_t); ++i) {
Logana27a83f2011-01-07 10:25:48 +0800371 sum ^= *ptr++;
372 }
373
374 mpHeaderSection->context_parity_checksum = sum;
375 return true;
376}
377
378
379bool CacheWriter::writeAll() {
380#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION) \
381 do { \
Logan Chien03a2e302011-07-13 21:46:32 +0800382 if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) { \
Logana27a83f2011-01-07 10:25:48 +0800383 LOGE("Unable to seek to " #NAME " section for writing.\n"); \
384 return false; \
385 } \
386 \
Logan Chien03a2e302011-07-13 21:46:32 +0800387 if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) != \
Logana27a83f2011-01-07 10:25:48 +0800388 static_cast<ssize_t>(SIZE)) { \
389 LOGE("Unable to write " #NAME " section to cache file.\n"); \
390 return false; \
391 } \
392 } while (0)
393
394#define WRITE_SECTION_SIMPLE(NAME, SECTION) \
395 WRITE_SECTION(NAME, \
396 mpHeaderSection->NAME##_offset, \
397 mpHeaderSection->NAME##_size, \
398 SECTION)
399
400 WRITE_SECTION(header, 0, sizeof(OBCC_Header), mpHeaderSection);
401
402 WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
403 WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
404 //WRITE_SECTION_SIMPLE(reloc_tab, mpRelocationTableSection);
405 WRITE_SECTION_SIMPLE(export_var_list, mpExportVarListSection);
406 WRITE_SECTION_SIMPLE(export_func_list, mpExportFuncListSection);
407 WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
408 WRITE_SECTION_SIMPLE(func_table, mpFuncTableSection);
Stephen Hines071288a2011-01-27 14:38:26 -0800409 WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
Logana27a83f2011-01-07 10:25:48 +0800410
Logana27a83f2011-01-07 10:25:48 +0800411#undef WRITE_SECTION_SIMPLE
412#undef WRITE_SECTION
413
Logan Chien03a2e302011-07-13 21:46:32 +0800414
415 // Write Context to Executable File
416 char const *context = (char const *)mpOwner->getContext();
417 size_t context_size = ContextManager::ContextSize;
418 if (mObjFile->write(context, context_size) != (ssize_t)context_size) {
419 LOGE("Unable to write context image to executable file\n");
420 return false;
421 }
422
Logana27a83f2011-01-07 10:25:48 +0800423 return true;
424}
425
426
Logana27a83f2011-01-07 10:25:48 +0800427} // namespace bcc