blob: ef98e798dc47192306b2ee1d402f0a3e9084f321 [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);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070044 CHECK_AND_FREE(mpPragmaListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070045 CHECK_AND_FREE(mpObjectSlotSection);
Joseph Wenf36637f2011-07-06 18:27:12 -070046 CHECK_AND_FREE(mpExportVarNameListSection);
47 CHECK_AND_FREE(mpExportFuncNameListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070048
49#undef CHECK_AND_FREE
50}
51
52bool MCCacheWriter::writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
53 Script *S, uint32_t libRS_threadable) {
54 if (!objFile || objFile->getFD() < 0 || !infoFile || infoFile->getFD() < 0) {
55 return false;
56 }
57
58 mObjFile = objFile;
59 mInfoFile = infoFile;
60 mpOwner = S;
61
62 bool result = prepareHeader(libRS_threadable)
63 && prepareDependencyTable()
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -070064 && preparePragmaList()
Joseph Wenf36637f2011-07-06 18:27:12 -070065 && prepareExportVarNameList()
66 && prepareExportFuncNameList()
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) {
81 LOGE("Unable to allocate for header.\n");
82 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
101 header->root_base_addr = mpOwner->lookup("root");
102
103 LOGD("Lookup root() address [%p]", header->root_base_addr);
104
105 // libRS is threadable dirty hack
106 // TODO: This should be removed in the future
107 header->libRS_threadable = libRS_threadable;
108
109 return true;
110}
111
112
113bool MCCacheWriter::prepareDependencyTable() {
114 size_t tableSize = sizeof(OBCC_DependencyTable) +
115 sizeof(OBCC_Dependency) * mDependencies.size();
116
117 OBCC_DependencyTable *tab = (OBCC_DependencyTable *)malloc(tableSize);
118
119 if (!tab) {
120 LOGE("Unable to allocate for dependency table section.\n");
121 return false;
122 }
123
124 mpDependencyTableSection = tab;
125 mpHeaderSection->depend_tab_size = tableSize;
126
127 tab->count = mDependencies.size();
128
129 size_t i = 0;
130 for (map<string, pair<uint32_t, unsigned char const *> >::iterator
131 I = mDependencies.begin(), E = mDependencies.end(); I != E; ++I, ++i) {
132 OBCC_Dependency *dep = &tab->table[i];
133
134 dep->res_name_strp_index = addString(I->first.c_str(), I->first.size());
135 dep->res_type = I->second.first;
136 memcpy(dep->sha1, I->second.second, 20);
137 }
138
139 return true;
140}
141
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700142bool MCCacheWriter::preparePragmaList() {
143 size_t pragmaCount = mpOwner->getPragmaCount();
144
145 size_t listSize = sizeof(OBCC_PragmaList) +
146 sizeof(OBCC_Pragma) * pragmaCount;
147
148 OBCC_PragmaList *list = (OBCC_PragmaList *)malloc(listSize);
149
150 if (!list) {
151 LOGE("Unable to allocate for pragma list\n");
152 return false;
153 }
154
155 mpPragmaListSection = list;
156 mpHeaderSection->pragma_list_size = listSize;
157
158 list->count = pragmaCount;
159
160 vector<char const *> keyList(pragmaCount);
161 vector<char const *> valueList(pragmaCount);
162 mpOwner->getPragmaList(pragmaCount, &*keyList.begin(), &*valueList.begin());
163
164 for (size_t i = 0; i < pragmaCount; ++i) {
165 char const *key = keyList[i];
166 char const *value = valueList[i];
167
168 size_t keyLen = strlen(key);
169 size_t valueLen = strlen(value);
170
171 OBCC_Pragma *pragma = &list->list[i];
172 pragma->key_strp_index = addString(key, keyLen);
173 pragma->value_strp_index = addString(value, valueLen);
174 }
175
176 return true;
177}
178
179bool MCCacheWriter::prepareStringPool() {
180 // Calculate string pool size
181 size_t size = sizeof(OBCC_StringPool) +
182 sizeof(OBCC_String) * mStringPool.size();
183
184 off_t strOffset = size;
185
186 for (size_t i = 0; i < mStringPool.size(); ++i) {
187 size += mStringPool[i].second + 1;
188 }
189
190 // Create string pool
191 OBCC_StringPool *pool = (OBCC_StringPool *)malloc(size);
192
193 if (!pool) {
194 LOGE("Unable to allocate string pool.\n");
195 return false;
196 }
197
198 mpStringPoolSection = pool;
199 mpHeaderSection->str_pool_size = size;
200
201 pool->count = mStringPool.size();
202
203 char *strPtr = reinterpret_cast<char *>(pool) + strOffset;
204
205 for (size_t i = 0; i < mStringPool.size(); ++i) {
206 OBCC_String *str = &pool->list[i];
207
208 str->length = mStringPool[i].second;
209 str->offset = strOffset;
210 memcpy(strPtr, mStringPool[i].first, str->length);
211
212 strPtr += str->length;
213 *strPtr++ = '\0';
214
215 strOffset += str->length + 1;
216 }
217
218 return true;
219}
220
221
Joseph Wenf36637f2011-07-06 18:27:12 -0700222bool MCCacheWriter::prepareExportVarNameList() {
223 size_t varCount = mpOwner->getExportVarCount();
224 size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * varCount;
225
226 OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
227
228 if (!list) {
229 LOGE("Unable to allocate for export variable name list\n");
230 return false;
231 }
232
233 mpExportVarNameListSection = list;
234 mpHeaderSection->export_var_name_list_size = listSize;
235
236 list->count = static_cast<size_t>(varCount);
237
238 mpOwner->getExportVarNameList(varNameList);
239 for (size_t i = 0; i < varCount; ++i) {
240 list->strp_indexs[i] = addString(varNameList[i].c_str(), varNameList[i].length());
241 }
242 return true;
243}
244
245
Joseph Wenf36637f2011-07-06 18:27:12 -0700246bool MCCacheWriter::prepareExportFuncNameList() {
247 size_t funcCount = mpOwner->getExportFuncCount();
248 size_t listSize = sizeof(OBCC_String_Ptr) + sizeof(size_t) * funcCount;
249
250 OBCC_String_Ptr *list = (OBCC_String_Ptr*)malloc(listSize);
251
252 if (!list) {
253 LOGE("Unable to allocate for export function name list\n");
254 return false;
255 }
256
257 mpExportFuncNameListSection = list;
258 mpHeaderSection->export_func_name_list_size = listSize;
259
260 list->count = static_cast<size_t>(funcCount);
261
262 mpOwner->getExportFuncNameList(funcNameList);
263 for (size_t i = 0; i < funcCount; ++i) {
264 list->strp_indexs[i] = addString(funcNameList[i].c_str(), funcNameList[i].length());
265 }
266 return true;
267}
268
269
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700270bool MCCacheWriter::prepareObjectSlotList() {
271 size_t objectSlotCount = mpOwner->getObjectSlotCount();
272
273 size_t listSize = sizeof(OBCC_ObjectSlotList) +
274 sizeof(uint32_t) * objectSlotCount;
275
276 OBCC_ObjectSlotList *list = (OBCC_ObjectSlotList *)malloc(listSize);
277
278 if (!list) {
279 LOGE("Unable to allocate for object slot list\n");
280 return false;
281 }
282
283 mpObjectSlotSection = list;
284 mpHeaderSection->object_slot_list_size = listSize;
285
286 list->count = objectSlotCount;
287
288 mpOwner->getObjectSlotList(objectSlotCount, list->object_slot_list);
289 return true;
290}
291
292
293bool MCCacheWriter::calcSectionOffset() {
294 size_t offset = sizeof(MCO_Header);
295
296#define OFFSET_INCREASE(NAME) \
297 do { \
298 /* Align to a word */ \
299 size_t rem = offset % sizeof(int); \
300 if (rem > 0) { \
301 offset += sizeof(int) - rem; \
302 } \
303 \
304 /* Save the offset and increase it */ \
305 mpHeaderSection->NAME##_offset = offset; \
306 offset += mpHeaderSection->NAME##_size; \
307 } while (0)
308
309 OFFSET_INCREASE(str_pool);
310 OFFSET_INCREASE(depend_tab);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700311 OFFSET_INCREASE(pragma_list);
312 OFFSET_INCREASE(func_table);
313 OFFSET_INCREASE(object_slot_list);
Joseph Wenf36637f2011-07-06 18:27:12 -0700314 OFFSET_INCREASE(export_var_name_list);
315 OFFSET_INCREASE(export_func_name_list);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700316
317#undef OFFSET_INCREASE
318
319 return true;
320}
321
322
323bool MCCacheWriter::writeAll() {
324#define WRITE_SECTION(NAME, OFFSET, SIZE, SECTION) \
325 do { \
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700326 if (mInfoFile->seek(OFFSET, SEEK_SET) == -1) { \
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700327 LOGE("Unable to seek to " #NAME " section for writing.\n"); \
328 return false; \
329 } \
330 \
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700331 if (mInfoFile->write(reinterpret_cast<char *>(SECTION), (SIZE)) != \
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700332 static_cast<ssize_t>(SIZE)) { \
333 LOGE("Unable to write " #NAME " section to cache file.\n"); \
334 return false; \
335 } \
336 } while (0)
337
338#define WRITE_SECTION_SIMPLE(NAME, SECTION) \
339 WRITE_SECTION(NAME, \
340 mpHeaderSection->NAME##_offset, \
341 mpHeaderSection->NAME##_size, \
342 SECTION)
343
344 WRITE_SECTION(header, 0, sizeof(MCO_Header), mpHeaderSection);
345
346 WRITE_SECTION_SIMPLE(str_pool, mpStringPoolSection);
347 WRITE_SECTION_SIMPLE(depend_tab, mpDependencyTableSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700348 WRITE_SECTION_SIMPLE(pragma_list, mpPragmaListSection);
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700349 WRITE_SECTION_SIMPLE(object_slot_list, mpObjectSlotSection);
350
Joseph Wenf36637f2011-07-06 18:27:12 -0700351 WRITE_SECTION_SIMPLE(export_var_name_list, mpExportVarNameListSection);
352 WRITE_SECTION_SIMPLE(export_func_name_list, mpExportFuncNameListSection);
353
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700354#undef WRITE_SECTION_SIMPLE
355#undef WRITE_SECTION
Shih-wei Liao6d0804b2011-06-19 11:30:00 -0700356
357 if (static_cast<size_t>(mObjFile->write(mpOwner->getELF(),
358 mpOwner->getELFSize()))
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700359 != mpOwner->getELFSize()) {
360 LOGE("Unable to write ELF to cache file.\n");
361 return false;
362 }
363
364 return true;
365}
366
Shih-wei Liao5e3e0ce2011-06-17 13:59:46 -0700367} // namespace bcc
368#endif