blob: 10f823785e363f9459beb042068d204450839754 [file] [log] [blame]
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -07001/*
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#include "MCCacheWriter.h"
18
19#include "ContextManager.h"
20#include "DebugHelper.h"
21#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
35#if USE_MCJIT
36namespace bcc {
37
38MCCacheWriter::~MCCacheWriter() {
39#define CHECK_AND_FREE(VAR) if (VAR) { free(VAR); }
40
41 CHECK_AND_FREE(mpHeaderSection);
42 CHECK_AND_FREE(mpStringPoolSection);
43 CHECK_AND_FREE(mpDependencyTableSection);
44 CHECK_AND_FREE(mpExportVarListSection);
45 CHECK_AND_FREE(mpExportFuncListSection);
46 CHECK_AND_FREE(mpPragmaListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070047 CHECK_AND_FREE(mpObjectSlotSection);
Joseph Wenf36637f2011-07-06 18:27:12 -070048 CHECK_AND_FREE(mpExportVarNameListSection);
49 CHECK_AND_FREE(mpExportFuncNameListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070050
51#undef CHECK_AND_FREE
52}
53
54bool MCCacheWriter::writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
55 Script *S, uint32_t libRS_threadable) {
56 if (!objFile || objFile->getFD() < 0 || !infoFile || infoFile->getFD() < 0) {
57 return false;
58 }
59
60 mObjFile = objFile;
61 mInfoFile = infoFile;
62 mpOwner = S;
63
64 bool result = prepareHeader(libRS_threadable)
65 && prepareDependencyTable()
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070066 && preparePragmaList()
Joseph Wenf36637f2011-07-06 18:27:12 -070067 && prepareExportVarNameList()
68 && prepareExportFuncNameList()
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070069 && prepareStringPool()
70 && prepareExportVarList()
71 && prepareExportFuncList()
72 && prepareObjectSlotList()
73 && calcSectionOffset()
74 && writeAll()
75 ;
76
77 return result;
78}
79
80
81bool MCCacheWriter::prepareHeader(uint32_t libRS_threadable) {
82 MCO_Header *header = (MCO_Header *)malloc(sizeof(MCO_Header));
83
84 if (!header) {
85 LOGE("Unable to allocate for header.\n");
86 return false;
87 }
88
89 mpHeaderSection = header;
90
91 // Initialize
92 memset(header, '\0', sizeof(MCO_Header));
93
94 // Magic word and version
95 memcpy(header->magic, OBCC_MAGIC, 4);
96 memcpy(header->version, OBCC_VERSION, 4);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070097
98 // Machine Integer Type
99 uint32_t number = 0x00000001;
100 header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
101 header->sizeof_off_t = sizeof(off_t);
102 header->sizeof_size_t = sizeof(size_t);
103 header->sizeof_ptr_t = sizeof(void *);
104
105 header->root_base_addr = mpOwner->lookup("root");
106
107 LOGD("Lookup root() address [%p]", header->root_base_addr);
108
109 // libRS is threadable dirty hack
110 // TODO: This should be removed in the future
111 header->libRS_threadable = libRS_threadable;
112
113 return true;
114}
115
116
117bool MCCacheWriter::prepareDependencyTable() {
118 size_t tableSize = sizeof(OBCC_DependencyTable) +
119 sizeof(OBCC_Dependency) * mDependencies.size();
120
121 OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
122
123 if (!tab) {
124 LOGE("Unable to allocate for dependency table section.\n");
125 return false;
126 }
127
128 mpDependencyTableSection = tab;
129 mpHeaderSection->depend_tab_size = tableSize;
130
131 tab->count = mDependencies.size();
132
133 size_t i = 0;
134 for (map<string, pair<uint32_t, unsigned char const *> >::iterator
135 I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
136 OBCC_Dependency *dep = &tab->table[i];
137
138 dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
139 dep->res_type = I->second.first;
140 memcpy(dep->sha1, I->second.second, 20);
141 }
142
143 return true;
144}
145
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700146bool MCCacheWriter::preparePragmaList() {
147 size_t pragmaCount = mpOwner->getPragmaCount();
148
149 size_t listSize = sizeof(OBCC_PragmaList) +
150 sizeof(OBCC_Pragma) * pragmaCount;
151
152 OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
153
154 if (!list) {
155 LOGE("Unable to allocate for pragma list\n");
156 return false;
157 }
158
159 mpPragmaListSection = list;
160 mpHeaderSection->pragma_list_size = listSize;
161
162 list->count = pragmaCount;
163
164 vector<char const *> keyList(pragmaCount);
165 vector<char const *> valueList(pragmaCount);
166 mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
167
168 for (size_t i = 0; i < pragmaCount; ++i) {
169 char const *key = keyList[i];
170 char const *value = valueList[i];
171
172 size_t keyLen = strlen(key);
173 size_t valueLen = strlen(value);
174
175 OBCC_Pragma *pragma = &list->list[i];
176 pragma->key_strp_index = addString(key, keyLen);
177 pragma->value_strp_index = addString(value, valueLen);
178 }
179
180 return true;
181}
182
183bool MCCacheWriter::prepareStringPool() {
184 // Calculate string pool size
185 size_t size = sizeof(OBCC_StringPool) +
186 sizeof(OBCC_String) * mStringPool.size();
187
188 off_t strOffset = size;
189
190 for (size_t i = 0; i < mStringPool.size(); ++i) {
191 size += mStringPool[i].second + 1;
192 }
193
194 // Create string pool
195 OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
196
197 if (!pool) {
198 LOGE("Unable to allocate string pool.\n");
199 return false;
200 }
201
202 mpStringPoolSection = pool;
203 mpHeaderSection->str_pool_size = size;
204
205 pool->count = mStringPool.size();
206
207 char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
208
209 for (size_t i = 0; i < mStringPool.size(); ++i) {
210 OBCC_String *str = &pool->list[i];
211
212 str->length = mStringPool[i].second;
213 str->offset = strOffset;
214 memcpy(strPtr, mStringPool[i].first, str->length);
215
216 strPtr += str->length;
217 *strPtr++ = '\0';
218
219 strOffset += str->length + 1;
220 }
221
222 return true;
223}
224
225
226bool MCCacheWriter::prepareExportVarList() {
227 size_t varCount = mpOwner->getExportVarCount();
228 size_t listSize = sizeof(OBCC_ExportVarList) + sizeof(void *) * varCount;
229
230 OBCC_ExportVarList *list = (OBCC_ExportVarList *)malloc(listSize);
231
232 if (!list) {
233 LOGE("Unable to allocate for export variable list\n");
234 return false;
235 }
236
237 mpExportVarListSection = list;
238 mpHeaderSection->export_var_list_size = listSize;
239
240 list->count = static_cast<size_t>(varCount);
241
242 mpOwner->getExportVarList(varCount, list->cached_addr_list);
243 return true;
244}
245
246
Joseph Wenf36637f2011-07-06 18:27:12 -0700247bool MCCacheWriter::prepareExportVarNameList() {
248 size_t varCount = mpOwner->getExportVarCount();
249 size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * varCount;
250
251 OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
252
253 if (!list) {
254 LOGE("Unable to allocate for export variable name list\n");
255 return false;
256 }
257
258 mpExportVarNameListSection = list;
259 mpHeaderSection->export_var_name_list_size = listSize;
260
261 list->count = static_cast<size_t>(varCount);
262
263 mpOwner->getExportVarNameList(varNameList);
264 for (size_t i = 0; i < varCount; ++i) {
265 list->strp_indexs[i] = addString(varNameList[i].c_str(), varNameList[i].length());
266 }
267 return true;
268}
269
270
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700271bool MCCacheWriter::prepareExportFuncList() {
272 size_t funcCount = mpOwner->getExportFuncCount();
273 size_t listSize = sizeof(OBCC_ExportFuncList) + sizeof(void *) * funcCount;
274
275 OBCC_ExportFuncList *list = (OBCC_ExportFuncList *)malloc(listSize);
276
277 if (!list) {
278 LOGE("Unable to allocate for export function list\n");
279 return false;
280 }
281
282 mpExportFuncListSection = list;
283 mpHeaderSection->export_func_list_size = listSize;
284
285 list->count = static_cast<size_t>(funcCount);
286
287 mpOwner->getExportFuncList(funcCount, list->cached_addr_list);
288 return true;
289}
290
291
Joseph Wenf36637f2011-07-06 18:27:12 -0700292bool MCCacheWriter::prepareExportFuncNameList() {
293 size_t funcCount = mpOwner->getExportFuncCount();
294 size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * funcCount;
295
296 OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
297
298 if (!list) {
299 LOGE("Unable to allocate for export function name list\n");
300 return false;
301 }
302
303 mpExportFuncNameListSection = list;
304 mpHeaderSection->export_func_name_list_size = listSize;
305
306 list->count = static_cast<size_t>(funcCount);
307
308 mpOwner->getExportFuncNameList(funcNameList);
309 for (size_t i = 0; i < funcCount; ++i) {
310 list->strp_indexs[i] = addString(funcNameList[i].c_str(), funcNameList[i].length());
311 }
312 return true;
313}
314
315
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700316bool MCCacheWriter::prepareObjectSlotList() {
317 size_t objectSlotCount = mpOwner->getObjectSlotCount();
318
319 size_t listSize = sizeof(OBCC_ObjectSlotList) +
320 sizeof(uint32_t) * objectSlotCount;
321
322 OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
323
324 if (!list) {
325 LOGE("Unable to allocate for object slot list\n");
326 return false;
327 }
328
329 mpObjectSlotSection = list;
330 mpHeaderSection->object_slot_list_size = listSize;
331
332 list->count = objectSlotCount;
333
334 mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
335 return true;
336}
337
338
339bool MCCacheWriter::calcSectionOffset() {
340 size_t offset = sizeof(MCO_Header);
341
342#define OFFSET_INCREASE(NAME) \
343 do { \
344 /* Align to a word */ \
345 size_t rem = offset % sizeof(int); \
346 if (rem > 0) { \
347 offset += sizeof(int) - rem; \
348 } \
349 \
350 /* Save the offset and increase it */ \
351 mpHeaderSection->NAME##_offset = offset; \
352 offset += mpHeaderSection->NAME##_size; \
353 } while (0)
354
355 OFFSET_INCREASE(str_pool);
356 OFFSET_INCREASE(depend_tab);
357 OFFSET_INCREASE(export_var_list);
358 OFFSET_INCREASE(export_func_list);
359 OFFSET_INCREASE(pragma_list);
360 OFFSET_INCREASE(func_table);
361 OFFSET_INCREASE(object_slot_list);
Joseph Wenf36637f2011-07-06 18:27:12 -0700362 OFFSET_INCREASE(export_var_name_list);
363 OFFSET_INCREASE(export_func_name_list);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700364
365#undef OFFSET_INCREASE
366
367 return true;
368}
369
370
371bool MCCacheWriter::writeAll() {
372#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION) \
373 do { \
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700374 if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) { \
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700375 LOGE("Unable to seek to " #NAME " section for writing.\n"); \
376 return false; \
377 } \
378 \
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700379 if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) != \
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700380 static_cast<ssize_t>(SIZE)) { \
381 LOGE("Unable to write " #NAME " section to cache file.\n"); \
382 return false; \
383 } \
384 } while (0)
385
386#define WRITE_SECTION_SIMPLE(NAME, SECTION) \
387 WRITE_SECTION(NAME, \
388 mpHeaderSection->NAME##_offset, \
389 mpHeaderSection->NAME##_size, \
390 SECTION)
391
392 WRITE_SECTION(header, 0, sizeof(MCO_Header), mpHeaderSection);
393
394 WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
395 WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
396 WRITE_SECTION_SIMPLE(export_var_list, mpExportVarListSection);
397 WRITE_SECTION_SIMPLE(export_func_list, mpExportFuncListSection);
398 WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700399 WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
400
Joseph Wenf36637f2011-07-06 18:27:12 -0700401 WRITE_SECTION_SIMPLE(export_var_name_list, mpExportVarNameListSection);
402 WRITE_SECTION_SIMPLE(export_func_name_list, mpExportFuncNameListSection);
403
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700404#undef WRITE_SECTION_SIMPLE
405#undef WRITE_SECTION
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700406
407 if (static_cast<size_t>(mObjFile->write(mpOwner->getELF(),
408 mpOwner->getELFSize()))
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700409 != mpOwner->getELFSize()) {
410 LOGE("Unable to write ELF to cache file.\n");
411 return false;
412 }
413
414 return true;
415}
416
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700417} // namespace bcc
418#endif