blob: cca724e2d6cd8bf436cacab16b94f8a1459b6a12 [file] [log] [blame]
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -07001/*
Stephen Hinescc366e52012-02-21 17:22:04 -08002 * Copyright 2010-2012, The Android Open Source Project
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -07003 *
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
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070019#include "DebugHelper.h"
20#include "FileHandle.h"
21#include "Script.h"
22
23#include <map>
24#include <string>
25#include <vector>
26#include <utility>
27
28#include <stdint.h>
29#include <stdlib.h>
30#include <string.h>
31
32using namespace std;
33
34#if USE_MCJIT
35namespace bcc {
36
37MCCacheWriter::~MCCacheWriter() {
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);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070043 CHECK_AND_FREE(mpPragmaListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070044 CHECK_AND_FREE(mpObjectSlotSection);
Joseph Wenf36637f2011-07-06 18:27:12 -070045 CHECK_AND_FREE(mpExportVarNameListSection);
46 CHECK_AND_FREE(mpExportFuncNameListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070047
48#undef CHECK_AND_FREE
49}
50
51bool MCCacheWriter::writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
52 Script *S, uint32_t libRS_threadable) {
53 if (!objFile || objFile->getFD() < 0 || !infoFile || infoFile->getFD() < 0) {
54 return false;
55 }
56
57 mObjFile = objFile;
58 mInfoFile = infoFile;
59 mpOwner = S;
60
61 bool result = prepareHeader(libRS_threadable)
62 && prepareDependencyTable()
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070063 && preparePragmaList()
Joseph Wenf36637f2011-07-06 18:27:12 -070064 && prepareExportVarNameList()
65 && prepareExportFuncNameList()
Stephen Hinescc366e52012-02-21 17:22:04 -080066 && prepareExportForEachNameList()
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070067 && prepareStringPool()
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070068 && prepareObjectSlotList()
69 && calcSectionOffset()
70 && writeAll()
71 ;
72
73 return result;
74}
75
76
77bool MCCacheWriter::prepareHeader(uint32_t libRS_threadable) {
78 MCO_Header *header = (MCO_Header *)malloc(sizeof(MCO_Header));
79
80 if (!header) {
Steve Block10c14122012-01-08 10:15:06 +000081 ALOGE("Unable to allocate for header.\n");
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070082 return false;
83 }
84
85 mpHeaderSection = header;
86
87 // Initialize
88 memset(header, '\0', sizeof(MCO_Header));
89
90 // Magic word and version
91 memcpy(header->magic, OBCC_MAGIC, 4);
92 memcpy(header->version, OBCC_VERSION, 4);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070093
94 // Machine Integer Type
95 uint32_t number = 0x00000001;
96 header->endianness = (*reinterpret_cast<char *>(&number) == 1) ? 'e' : 'E';
97 header->sizeof_off_t = sizeof(off_t);
98 header->sizeof_size_t = sizeof(size_t);
99 header->sizeof_ptr_t = sizeof(void *);
100
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700101 // libRS is threadable dirty hack
102 // TODO: This should be removed in the future
103 header->libRS_threadable = libRS_threadable;
104
105 return true;
106}
107
108
109bool MCCacheWriter::prepareDependencyTable() {
110 size_t tableSize = sizeof(OBCC_DependencyTable) +
111 sizeof(OBCC_Dependency) * mDependencies.size();
112
113 OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
114
115 if (!tab) {
Steve Block10c14122012-01-08 10:15:06 +0000116 ALOGE("Unable to allocate for dependency table section.\n");
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700117 return false;
118 }
119
120 mpDependencyTableSection = tab;
121 mpHeaderSection->depend_tab_size = tableSize;
122
123 tab->count = mDependencies.size();
124
125 size_t i = 0;
126 for (map<string, pair<uint32_t, unsigned char const *> >::iterator
127 I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
128 OBCC_Dependency *dep = &tab->table[i];
129
130 dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
131 dep->res_type = I->second.first;
132 memcpy(dep->sha1, I->second.second, 20);
133 }
134
135 return true;
136}
137
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700138bool MCCacheWriter::preparePragmaList() {
139 size_t pragmaCount = mpOwner->getPragmaCount();
140
141 size_t listSize = sizeof(OBCC_PragmaList) +
142 sizeof(OBCC_Pragma) * pragmaCount;
143
144 OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
145
146 if (!list) {
Steve Block10c14122012-01-08 10:15:06 +0000147 ALOGE("Unable to allocate for pragma list\n");
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700148 return false;
149 }
150
151 mpPragmaListSection = list;
152 mpHeaderSection->pragma_list_size = listSize;
153
154 list->count = pragmaCount;
155
156 vector<char const *> keyList(pragmaCount);
157 vector<char const *> valueList(pragmaCount);
158 mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
159
160 for (size_t i = 0; i < pragmaCount; ++i) {
161 char const *key = keyList[i];
162 char const *value = valueList[i];
163
164 size_t keyLen = strlen(key);
165 size_t valueLen = strlen(value);
166
167 OBCC_Pragma *pragma = &list->list[i];
168 pragma->key_strp_index = addString(key, keyLen);
169 pragma->value_strp_index = addString(value, valueLen);
170 }
171
172 return true;
173}
174
175bool MCCacheWriter::prepareStringPool() {
176 // Calculate string pool size
177 size_t size = sizeof(OBCC_StringPool) +
178 sizeof(OBCC_String) * mStringPool.size();
179
180 off_t strOffset = size;
181
182 for (size_t i = 0; i < mStringPool.size(); ++i) {
183 size += mStringPool[i].second + 1;
184 }
185
186 // Create string pool
187 OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
188
189 if (!pool) {
Steve Block10c14122012-01-08 10:15:06 +0000190 ALOGE("Unable to allocate string pool.\n");
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700191 return false;
192 }
193
194 mpStringPoolSection = pool;
195 mpHeaderSection->str_pool_size = size;
196
197 pool->count = mStringPool.size();
198
199 char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
200
201 for (size_t i = 0; i < mStringPool.size(); ++i) {
202 OBCC_String *str = &pool->list[i];
203
204 str->length = mStringPool[i].second;
205 str->offset = strOffset;
206 memcpy(strPtr, mStringPool[i].first, str->length);
207
208 strPtr += str->length;
209 *strPtr++ = '\0';
210
211 strOffset += str->length + 1;
212 }
213
214 return true;
215}
216
217
Joseph Wenf36637f2011-07-06 18:27:12 -0700218bool MCCacheWriter::prepareExportVarNameList() {
219 size_t varCount = mpOwner->getExportVarCount();
220 size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * varCount;
221
222 OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
223
224 if (!list) {
Steve Block10c14122012-01-08 10:15:06 +0000225 ALOGE("Unable to allocate for export variable name list\n");
Joseph Wenf36637f2011-07-06 18:27:12 -0700226 return false;
227 }
228
229 mpExportVarNameListSection = list;
230 mpHeaderSection->export_var_name_list_size = listSize;
231
232 list->count = static_cast<size_t>(varCount);
233
234 mpOwner->getExportVarNameList(varNameList);
235 for (size_t i = 0; i < varCount; ++i) {
236 list->strp_indexs[i] = addString(varNameList[i].c_str(), varNameList[i].length());
237 }
238 return true;
239}
240
241
Joseph Wenf36637f2011-07-06 18:27:12 -0700242bool MCCacheWriter::prepareExportFuncNameList() {
243 size_t funcCount = mpOwner->getExportFuncCount();
244 size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * funcCount;
245
246 OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
247
248 if (!list) {
Steve Block10c14122012-01-08 10:15:06 +0000249 ALOGE("Unable to allocate for export function name list\n");
Joseph Wenf36637f2011-07-06 18:27:12 -0700250 return false;
251 }
252
253 mpExportFuncNameListSection = list;
254 mpHeaderSection->export_func_name_list_size = listSize;
255
256 list->count = static_cast<size_t>(funcCount);
257
258 mpOwner->getExportFuncNameList(funcNameList);
259 for (size_t i = 0; i < funcCount; ++i) {
260 list->strp_indexs[i] = addString(funcNameList[i].c_str(), funcNameList[i].length());
261 }
262 return true;
263}
264
265
Stephen Hinescc366e52012-02-21 17:22:04 -0800266bool MCCacheWriter::prepareExportForEachNameList() {
267 size_t forEachCount = mpOwner->getExportForEachCount();
268 size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * forEachCount;
269
270 OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
271
272 if (!list) {
273 ALOGE("Unable to allocate for export forEach name list\n");
274 return false;
275 }
276
277 mpExportForEachNameListSection = list;
278 mpHeaderSection->export_foreach_name_list_size = listSize;
279
280 list->count = static_cast<size_t>(forEachCount);
281
282 mpOwner->getExportForEachNameList(forEachNameList);
283 for (size_t i = 0; i < forEachCount; ++i) {
284 list->strp_indexs[i] = addString(forEachNameList[i].c_str(), forEachNameList[i].length());
285 }
286 return true;
287}
288
289
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700290bool MCCacheWriter::prepareObjectSlotList() {
291 size_t objectSlotCount = mpOwner->getObjectSlotCount();
292
293 size_t listSize = sizeof(OBCC_ObjectSlotList) +
294 sizeof(uint32_t) * objectSlotCount;
295
296 OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
297
298 if (!list) {
Steve Block10c14122012-01-08 10:15:06 +0000299 ALOGE("Unable to allocate for object slot list\n");
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700300 return false;
301 }
302
303 mpObjectSlotSection = list;
304 mpHeaderSection->object_slot_list_size = listSize;
305
306 list->count = objectSlotCount;
307
308 mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
309 return true;
310}
311
312
313bool MCCacheWriter::calcSectionOffset() {
314 size_t offset = sizeof(MCO_Header);
315
316#define OFFSET_INCREASE(NAME) \
317 do { \
318 /* Align to a word */ \
319 size_t rem = offset % sizeof(int); \
320 if (rem > 0) { \
321 offset += sizeof(int) - rem; \
322 } \
323 \
324 /* Save the offset and increase it */ \
325 mpHeaderSection->NAME##_offset = offset; \
326 offset += mpHeaderSection->NAME##_size; \
327 } while (0)
328
329 OFFSET_INCREASE(str_pool);
330 OFFSET_INCREASE(depend_tab);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700331 OFFSET_INCREASE(pragma_list);
332 OFFSET_INCREASE(func_table);
333 OFFSET_INCREASE(object_slot_list);
Joseph Wenf36637f2011-07-06 18:27:12 -0700334 OFFSET_INCREASE(export_var_name_list);
335 OFFSET_INCREASE(export_func_name_list);
Stephen Hinescc366e52012-02-21 17:22:04 -0800336 OFFSET_INCREASE(export_foreach_name_list);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700337
338#undef OFFSET_INCREASE
339
340 return true;
341}
342
343
344bool MCCacheWriter::writeAll() {
345#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION) \
346 do { \
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700347 if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) { \
Steve Block10c14122012-01-08 10:15:06 +0000348 ALOGE("Unable to seek to " #NAME " section for writing.\n"); \
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700349 return false; \
350 } \
351 \
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700352 if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) != \
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700353 static_cast<ssize_t>(SIZE)) { \
Steve Block10c14122012-01-08 10:15:06 +0000354 ALOGE("Unable to write " #NAME " section to cache file.\n"); \
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700355 return false; \
356 } \
357 } while (0)
358
359#define WRITE_SECTION_SIMPLE(NAME, SECTION) \
360 WRITE_SECTION(NAME, \
361 mpHeaderSection->NAME##_offset, \
362 mpHeaderSection->NAME##_size, \
363 SECTION)
364
365 WRITE_SECTION(header, 0, sizeof(MCO_Header), mpHeaderSection);
366
367 WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
368 WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700369 WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700370 WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
371
Joseph Wenf36637f2011-07-06 18:27:12 -0700372 WRITE_SECTION_SIMPLE(export_var_name_list, mpExportVarNameListSection);
373 WRITE_SECTION_SIMPLE(export_func_name_list, mpExportFuncNameListSection);
Stephen Hinescc366e52012-02-21 17:22:04 -0800374 WRITE_SECTION_SIMPLE(export_foreach_name_list, mpExportForEachNameListSection);
Joseph Wenf36637f2011-07-06 18:27:12 -0700375
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700376#undef WRITE_SECTION_SIMPLE
377#undef WRITE_SECTION
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700378
379 if (static_cast<size_t>(mObjFile->write(mpOwner->getELF(),
380 mpOwner->getELFSize()))
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700381 != mpOwner->getELFSize()) {
Steve Block10c14122012-01-08 10:15:06 +0000382 ALOGE("Unable to write ELF to cache file.\n");
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700383 return false;
384 }
385
386 return true;
387}
388
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700389} // namespace bcc
390#endif