blob: d39b55cfcbd2892b56830d865d5096b16d1843a0 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Brian Carlstrome24fa612011-09-29 00:53:55 -070016
17#include "oat.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080018#include "utils.h"
Brian Carlstrome24fa612011-09-29 00:53:55 -070019
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070020#include <string.h>
Brian Carlstrome24fa612011-09-29 00:53:55 -070021#include <zlib.h>
22
23namespace art {
24
25const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
Nicolas Geoffray1ba0f592014-10-27 15:14:55 +000026const uint8_t OatHeader::kOatVersion[] = { '0', '4', '4', '\0' };
Brian Carlstrome24fa612011-09-29 00:53:55 -070027
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070028static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
29 size_t estimate = 0U;
30 if (variable_data != nullptr) {
31 SafeMap<std::string, std::string>::const_iterator it = variable_data->begin();
32 SafeMap<std::string, std::string>::const_iterator end = variable_data->end();
33 for ( ; it != end; ++it) {
34 estimate += it->first.length() + 1;
35 estimate += it->second.length() + 1;
36 }
37 }
38 return sizeof(OatHeader) + estimate;
39}
40
41OatHeader* OatHeader::Create(InstructionSet instruction_set,
Ian Rogers6f3dbba2014-10-14 17:41:57 -070042 const InstructionSetFeatures* instruction_set_features,
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070043 const std::vector<const DexFile*>* dex_files,
44 uint32_t image_file_location_oat_checksum,
45 uint32_t image_file_location_oat_data_begin,
46 const SafeMap<std::string, std::string>* variable_data) {
47 // Estimate size of optional data.
48 size_t needed_size = ComputeOatHeaderSize(variable_data);
49
50 // Reserve enough memory.
51 void* memory = operator new (needed_size);
52
53 // Create the OatHeader in-place.
54 return new (memory) OatHeader(instruction_set,
55 instruction_set_features,
56 dex_files,
57 image_file_location_oat_checksum,
58 image_file_location_oat_data_begin,
59 variable_data);
Elliott Hughesa72ec822012-03-05 17:12:22 -080060}
61
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070062OatHeader::OatHeader(InstructionSet instruction_set,
Ian Rogers6f3dbba2014-10-14 17:41:57 -070063 const InstructionSetFeatures* instruction_set_features,
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070064 const std::vector<const DexFile*>* dex_files,
Brian Carlstrom28db0122012-10-18 16:20:41 -070065 uint32_t image_file_location_oat_checksum,
Brian Carlstrom700c8d32012-11-05 10:42:02 -080066 uint32_t image_file_location_oat_data_begin,
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070067 const SafeMap<std::string, std::string>* variable_data) {
Brian Carlstrome24fa612011-09-29 00:53:55 -070068 memcpy(magic_, kOatMagic, sizeof(kOatMagic));
69 memcpy(version_, kOatVersion, sizeof(kOatVersion));
Alex Lighta59dd802014-07-02 16:28:08 -070070 executable_offset_ = 0;
71 image_patch_delta_ = 0;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070072
Brian Carlstrome24fa612011-09-29 00:53:55 -070073 adler32_checksum_ = adler32(0L, Z_NULL, 0);
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070074
Brian Carlstromf852fb22012-10-19 11:01:58 -070075 CHECK_NE(instruction_set, kNone);
Elliott Hughesa72ec822012-03-05 17:12:22 -080076 instruction_set_ = instruction_set;
77 UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070078
Ian Rogers6f3dbba2014-10-14 17:41:57 -070079 instruction_set_features_bitmap_ = instruction_set_features->AsBitmap();
80 UpdateChecksum(&instruction_set_features_bitmap_, sizeof(instruction_set_features_bitmap_));
Dave Allison70202782013-10-22 17:52:19 -070081
Brian Carlstrome24fa612011-09-29 00:53:55 -070082 dex_file_count_ = dex_files->size();
83 UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070084
Brian Carlstrom28db0122012-10-18 16:20:41 -070085 image_file_location_oat_checksum_ = image_file_location_oat_checksum;
86 UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
87
Brian Carlstrom700c8d32012-11-05 10:42:02 -080088 CHECK(IsAligned<kPageSize>(image_file_location_oat_data_begin));
89 image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
90 UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070091
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070092 // Flatten the map. Will also update variable_size_data_size_.
93 Flatten(variable_data);
94
95 // Update checksum for variable data size.
96 UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_));
97
98 // Update for data, if existing.
99 if (key_value_store_size_ > 0U) {
100 UpdateChecksum(&key_value_store_, key_value_store_size_);
101 }
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700102
Ian Rogers468532e2013-08-05 10:56:33 -0700103 interpreter_to_interpreter_bridge_offset_ = 0;
104 interpreter_to_compiled_code_bridge_offset_ = 0;
105 jni_dlsym_lookup_offset_ = 0;
Jeff Hao88474b42013-10-23 16:24:40 -0700106 portable_imt_conflict_trampoline_offset_ = 0;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700107 portable_resolution_trampoline_offset_ = 0;
Ian Rogers468532e2013-08-05 10:56:33 -0700108 portable_to_interpreter_bridge_offset_ = 0;
Andreas Gampe2da88232014-02-27 12:26:20 -0800109 quick_generic_jni_trampoline_offset_ = 0;
Jeff Hao88474b42013-10-23 16:24:40 -0700110 quick_imt_conflict_trampoline_offset_ = 0;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700111 quick_resolution_trampoline_offset_ = 0;
Ian Rogers468532e2013-08-05 10:56:33 -0700112 quick_to_interpreter_bridge_offset_ = 0;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700113}
114
115bool OatHeader::IsValid() const {
Brian Carlstromf852fb22012-10-19 11:01:58 -0700116 if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700117 return false;
118 }
Brian Carlstromf852fb22012-10-19 11:01:58 -0700119 if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700120 return false;
121 }
Alex Lighta59dd802014-07-02 16:28:08 -0700122 if (!IsAligned<kPageSize>(executable_offset_)) {
123 return false;
124 }
125 if (!IsAligned<kPageSize>(image_patch_delta_)) {
126 return false;
127 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700128 return true;
129}
130
131const char* OatHeader::GetMagic() const {
132 CHECK(IsValid());
133 return reinterpret_cast<const char*>(magic_);
134}
135
Brian Carlstrome24fa612011-09-29 00:53:55 -0700136uint32_t OatHeader::GetChecksum() const {
137 CHECK(IsValid());
138 return adler32_checksum_;
139}
140
141void OatHeader::UpdateChecksum(const void* data, size_t length) {
142 DCHECK(IsValid());
143 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
144 adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
145}
146
Elliott Hughesa72ec822012-03-05 17:12:22 -0800147InstructionSet OatHeader::GetInstructionSet() const {
148 CHECK(IsValid());
149 return instruction_set_;
150}
151
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700152uint32_t OatHeader::GetInstructionSetFeaturesBitmap() const {
Dave Allison70202782013-10-22 17:52:19 -0700153 CHECK(IsValid());
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700154 return instruction_set_features_bitmap_;
Dave Allison70202782013-10-22 17:52:19 -0700155}
156
Brian Carlstrome24fa612011-09-29 00:53:55 -0700157uint32_t OatHeader::GetExecutableOffset() const {
158 DCHECK(IsValid());
Elliott Hughes06b37d92011-10-16 11:51:29 -0700159 DCHECK_ALIGNED(executable_offset_, kPageSize);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700160 CHECK_GT(executable_offset_, sizeof(OatHeader));
161 return executable_offset_;
162}
163
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700164void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
165 DCHECK_ALIGNED(executable_offset, kPageSize);
166 CHECK_GT(executable_offset, sizeof(OatHeader));
167 DCHECK(IsValid());
168 DCHECK_EQ(executable_offset_, 0U);
169
170 executable_offset_ = executable_offset;
171 UpdateChecksum(&executable_offset_, sizeof(executable_offset));
172}
173
Ian Rogers468532e2013-08-05 10:56:33 -0700174const void* OatHeader::GetInterpreterToInterpreterBridge() const {
175 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700176}
177
Ian Rogers468532e2013-08-05 10:56:33 -0700178uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700179 DCHECK(IsValid());
Dave Allisonc6104ae2014-03-12 11:05:39 -0700180 CHECK(interpreter_to_interpreter_bridge_offset_ == 0 ||
181 interpreter_to_interpreter_bridge_offset_ >= executable_offset_);
Ian Rogers468532e2013-08-05 10:56:33 -0700182 return interpreter_to_interpreter_bridge_offset_;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700183}
184
Ian Rogers468532e2013-08-05 10:56:33 -0700185void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700186 CHECK(offset == 0 || offset >= executable_offset_);
187 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700188 DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700189
Ian Rogers468532e2013-08-05 10:56:33 -0700190 interpreter_to_interpreter_bridge_offset_ = offset;
191 UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset));
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700192}
193
Ian Rogers468532e2013-08-05 10:56:33 -0700194const void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
195 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700196}
197
Ian Rogers468532e2013-08-05 10:56:33 -0700198uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700199 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700200 CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
201 return interpreter_to_compiled_code_bridge_offset_;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700202}
203
Ian Rogers468532e2013-08-05 10:56:33 -0700204void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
205 CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700206 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700207 DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700208
Ian Rogers468532e2013-08-05 10:56:33 -0700209 interpreter_to_compiled_code_bridge_offset_ = offset;
210 UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset));
211}
212
213const void* OatHeader::GetJniDlsymLookup() const {
214 return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
215}
216
217uint32_t OatHeader::GetJniDlsymLookupOffset() const {
218 DCHECK(IsValid());
219 CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
220 return jni_dlsym_lookup_offset_;
221}
222
223void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
224 CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
225 DCHECK(IsValid());
226 DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
227
228 jni_dlsym_lookup_offset_ = offset;
229 UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset));
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700230}
231
Jeff Hao88474b42013-10-23 16:24:40 -0700232const void* OatHeader::GetPortableImtConflictTrampoline() const {
233 return reinterpret_cast<const uint8_t*>(this) + GetPortableImtConflictTrampolineOffset();
234}
235
236uint32_t OatHeader::GetPortableImtConflictTrampolineOffset() const {
237 DCHECK(IsValid());
238 CHECK_GE(portable_imt_conflict_trampoline_offset_, jni_dlsym_lookup_offset_);
239 return portable_imt_conflict_trampoline_offset_;
240}
241
242void OatHeader::SetPortableImtConflictTrampolineOffset(uint32_t offset) {
243 CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
244 DCHECK(IsValid());
245 DCHECK_EQ(portable_imt_conflict_trampoline_offset_, 0U) << offset;
246
247 portable_imt_conflict_trampoline_offset_ = offset;
248 UpdateChecksum(&portable_imt_conflict_trampoline_offset_, sizeof(offset));
249}
250
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700251const void* OatHeader::GetPortableResolutionTrampoline() const {
252 return reinterpret_cast<const uint8_t*>(this) + GetPortableResolutionTrampolineOffset();
253}
254
255uint32_t OatHeader::GetPortableResolutionTrampolineOffset() const {
256 DCHECK(IsValid());
Jeff Hao88474b42013-10-23 16:24:40 -0700257 CHECK_GE(portable_resolution_trampoline_offset_, portable_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700258 return portable_resolution_trampoline_offset_;
259}
260
261void OatHeader::SetPortableResolutionTrampolineOffset(uint32_t offset) {
Jeff Hao88474b42013-10-23 16:24:40 -0700262 CHECK(offset == 0 || offset >= portable_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700263 DCHECK(IsValid());
264 DCHECK_EQ(portable_resolution_trampoline_offset_, 0U) << offset;
265
266 portable_resolution_trampoline_offset_ = offset;
267 UpdateChecksum(&portable_resolution_trampoline_offset_, sizeof(offset));
268}
269
Ian Rogers468532e2013-08-05 10:56:33 -0700270const void* OatHeader::GetPortableToInterpreterBridge() const {
271 return reinterpret_cast<const uint8_t*>(this) + GetPortableToInterpreterBridgeOffset();
272}
273
274uint32_t OatHeader::GetPortableToInterpreterBridgeOffset() const {
275 DCHECK(IsValid());
276 CHECK_GE(portable_to_interpreter_bridge_offset_, portable_resolution_trampoline_offset_);
277 return portable_to_interpreter_bridge_offset_;
278}
279
280void OatHeader::SetPortableToInterpreterBridgeOffset(uint32_t offset) {
281 CHECK(offset == 0 || offset >= portable_resolution_trampoline_offset_);
282 DCHECK(IsValid());
283 DCHECK_EQ(portable_to_interpreter_bridge_offset_, 0U) << offset;
284
285 portable_to_interpreter_bridge_offset_ = offset;
286 UpdateChecksum(&portable_to_interpreter_bridge_offset_, sizeof(offset));
287}
288
Andreas Gampe2da88232014-02-27 12:26:20 -0800289const void* OatHeader::GetQuickGenericJniTrampoline() const {
290 return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset();
291}
292
293uint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
294 DCHECK(IsValid());
295 CHECK_GE(quick_generic_jni_trampoline_offset_, portable_to_interpreter_bridge_offset_);
296 return quick_generic_jni_trampoline_offset_;
297}
298
299void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
300 CHECK(offset == 0 || offset >= portable_to_interpreter_bridge_offset_);
301 DCHECK(IsValid());
302 DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
303
304 quick_generic_jni_trampoline_offset_ = offset;
305 UpdateChecksum(&quick_generic_jni_trampoline_offset_, sizeof(offset));
306}
307
Jeff Hao88474b42013-10-23 16:24:40 -0700308const void* OatHeader::GetQuickImtConflictTrampoline() const {
309 return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset();
310}
311
312uint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
313 DCHECK(IsValid());
Andreas Gampe2da88232014-02-27 12:26:20 -0800314 CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
Jeff Hao88474b42013-10-23 16:24:40 -0700315 return quick_imt_conflict_trampoline_offset_;
316}
317
318void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
Andreas Gampe2da88232014-02-27 12:26:20 -0800319 CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
Jeff Hao88474b42013-10-23 16:24:40 -0700320 DCHECK(IsValid());
321 DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
322
323 quick_imt_conflict_trampoline_offset_ = offset;
324 UpdateChecksum(&quick_imt_conflict_trampoline_offset_, sizeof(offset));
325}
326
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700327const void* OatHeader::GetQuickResolutionTrampoline() const {
328 return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
329}
330
331uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
332 DCHECK(IsValid());
Jeff Hao88474b42013-10-23 16:24:40 -0700333 CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700334 return quick_resolution_trampoline_offset_;
335}
336
337void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
Jeff Hao88474b42013-10-23 16:24:40 -0700338 CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700339 DCHECK(IsValid());
340 DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
341
342 quick_resolution_trampoline_offset_ = offset;
343 UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset));
344}
345
Ian Rogers468532e2013-08-05 10:56:33 -0700346const void* OatHeader::GetQuickToInterpreterBridge() const {
347 return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
348}
349
350uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
351 DCHECK(IsValid());
352 CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
353 return quick_to_interpreter_bridge_offset_;
354}
355
356void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
357 CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
358 DCHECK(IsValid());
359 DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
360
361 quick_to_interpreter_bridge_offset_ = offset;
362 UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset));
363}
364
Alex Lighta59dd802014-07-02 16:28:08 -0700365int32_t OatHeader::GetImagePatchDelta() const {
366 CHECK(IsValid());
367 return image_patch_delta_;
368}
369
370void OatHeader::RelocateOat(off_t delta) {
371 CHECK(IsValid());
372 CHECK_ALIGNED(delta, kPageSize);
373 image_patch_delta_ += delta;
374 if (image_file_location_oat_data_begin_ != 0) {
375 image_file_location_oat_data_begin_ += delta;
376 }
377}
378
379void OatHeader::SetImagePatchDelta(int32_t off) {
380 CHECK(IsValid());
381 CHECK_ALIGNED(off, kPageSize);
382 image_patch_delta_ = off;
383}
384
Brian Carlstrom28db0122012-10-18 16:20:41 -0700385uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700386 CHECK(IsValid());
Brian Carlstrom28db0122012-10-18 16:20:41 -0700387 return image_file_location_oat_checksum_;
388}
389
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800390uint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
Brian Carlstrom28db0122012-10-18 16:20:41 -0700391 CHECK(IsValid());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800392 return image_file_location_oat_data_begin_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700393}
394
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700395uint32_t OatHeader::GetKeyValueStoreSize() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700396 CHECK(IsValid());
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700397 return key_value_store_size_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700398}
399
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700400const uint8_t* OatHeader::GetKeyValueStore() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700401 CHECK(IsValid());
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700402 return key_value_store_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700403}
404
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700405// Advance start until it is either end or \0.
406static const char* ParseString(const char* start, const char* end) {
407 while (start < end && *start != 0) {
408 start++;
409 }
410 return start;
411}
412
413const char* OatHeader::GetStoreValueByKey(const char* key) const {
414 const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
415 const char* end = ptr + key_value_store_size_;
416
417 while (ptr < end) {
418 // Scan for a closing zero.
419 const char* str_end = ParseString(ptr, end);
420 if (str_end < end) {
421 if (strcmp(key, ptr) == 0) {
422 // Same as key. Check if value is OK.
423 if (ParseString(str_end + 1, end) < end) {
424 return str_end + 1;
425 }
426 } else {
427 // Different from key. Advance over the value.
428 ptr = ParseString(str_end + 1, end) + 1;
429 }
430 } else {
431 break;
432 }
433 }
434 // Not found.
435 return nullptr;
436}
437
438bool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
439 const char** value) const {
440 const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
441 const char* end = ptr + key_value_store_size_;
442 ssize_t counter = static_cast<ssize_t>(index);
443
444 while (ptr < end && counter >= 0) {
445 // Scan for a closing zero.
446 const char* str_end = ParseString(ptr, end);
447 if (str_end < end) {
448 const char* maybe_key = ptr;
449 ptr = ParseString(str_end + 1, end) + 1;
450 if (ptr <= end) {
451 if (counter == 0) {
452 *key = maybe_key;
453 *value = str_end + 1;
454 return true;
455 } else {
456 counter--;
457 }
458 } else {
459 return false;
460 }
461 } else {
462 break;
463 }
464 }
465 // Not found.
466 return false;
467}
468
469size_t OatHeader::GetHeaderSize() const {
470 return sizeof(OatHeader) + key_value_store_size_;
471}
472
Igor Murashkin46774762014-10-22 11:37:02 -0700473bool OatHeader::IsPic() const {
474 const char* pic_string = GetStoreValueByKey(OatHeader::kPicKey);
475 static const char kTrue[] = "true";
476 return (pic_string != nullptr && strncmp(pic_string, kTrue, sizeof(kTrue)) == 0);
477}
478
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700479void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
480 char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
481 if (key_value_store != nullptr) {
482 SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
483 SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
484 for ( ; it != end; ++it) {
485 strcpy(data_ptr, it->first.c_str());
486 data_ptr += it->first.length() + 1;
487 strcpy(data_ptr, it->second.c_str());
488 data_ptr += it->second.length() + 1;
489 }
490 }
491 key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700492}
493
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700494OatMethodOffsets::OatMethodOffsets()
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700495 : code_offset_(0),
Jeff Hao74180ca2013-03-27 15:29:11 -0700496 gc_map_offset_(0)
Logan Chienccb7bf12012-03-28 12:52:32 +0800497{}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700498
499OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
Jeff Hao74180ca2013-03-27 15:29:11 -0700500 uint32_t gc_map_offset
Logan Chienccb7bf12012-03-28 12:52:32 +0800501 )
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700502 : code_offset_(code_offset),
Jeff Hao74180ca2013-03-27 15:29:11 -0700503 gc_map_offset_(gc_map_offset)
Logan Chienccb7bf12012-03-28 12:52:32 +0800504{}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700505
506OatMethodOffsets::~OatMethodOffsets() {}
507
Vladimir Marko7624d252014-05-02 14:40:15 +0100508OatQuickMethodHeader::OatQuickMethodHeader()
Vladimir Marko8a630572014-04-09 18:45:35 +0100509 : mapping_table_offset_(0),
510 vmap_table_offset_(0),
Vladimir Marko7624d252014-05-02 14:40:15 +0100511 frame_info_(0, 0, 0),
Vladimir Marko8a630572014-04-09 18:45:35 +0100512 code_size_(0)
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100513{}
514
Vladimir Marko7624d252014-05-02 14:40:15 +0100515OatQuickMethodHeader::OatQuickMethodHeader(
516 uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t frame_size_in_bytes,
517 uint32_t core_spill_mask, uint32_t fp_spill_mask, uint32_t code_size)
Vladimir Marko8a630572014-04-09 18:45:35 +0100518 : mapping_table_offset_(mapping_table_offset),
519 vmap_table_offset_(vmap_table_offset),
Vladimir Marko7624d252014-05-02 14:40:15 +0100520 frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask),
Vladimir Marko8a630572014-04-09 18:45:35 +0100521 code_size_(code_size)
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100522{}
523
Vladimir Marko7624d252014-05-02 14:40:15 +0100524OatQuickMethodHeader::~OatQuickMethodHeader() {}
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100525
Brian Carlstrome24fa612011-09-29 00:53:55 -0700526} // namespace art