blob: 1421baffcf24cf11580b334417cbe4a26dd8b420 [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' };
Sebastien Hertz4e99b3d2014-06-24 14:35:40 +020026const uint8_t OatHeader::kOatVersion[] = { '0', '3', '7', '\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,
42 const InstructionSetFeatures& instruction_set_features,
43 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,
Dave Allison70202782013-10-22 17:52:19 -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));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070070
Brian Carlstrome24fa612011-09-29 00:53:55 -070071 adler32_checksum_ = adler32(0L, Z_NULL, 0);
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070072
Brian Carlstromf852fb22012-10-19 11:01:58 -070073 CHECK_NE(instruction_set, kNone);
Elliott Hughesa72ec822012-03-05 17:12:22 -080074 instruction_set_ = instruction_set;
75 UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070076
Dave Allison70202782013-10-22 17:52:19 -070077 instruction_set_features_ = instruction_set_features;
78 UpdateChecksum(&instruction_set_features_, sizeof(instruction_set_features_));
79
Brian Carlstrome24fa612011-09-29 00:53:55 -070080 dex_file_count_ = dex_files->size();
81 UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070082
Brian Carlstrom28db0122012-10-18 16:20:41 -070083 image_file_location_oat_checksum_ = image_file_location_oat_checksum;
84 UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
85
Brian Carlstrom700c8d32012-11-05 10:42:02 -080086 CHECK(IsAligned<kPageSize>(image_file_location_oat_data_begin));
87 image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
88 UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070089
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070090 // Flatten the map. Will also update variable_size_data_size_.
91 Flatten(variable_data);
92
93 // Update checksum for variable data size.
94 UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_));
95
96 // Update for data, if existing.
97 if (key_value_store_size_ > 0U) {
98 UpdateChecksum(&key_value_store_, key_value_store_size_);
99 }
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700100
Brian Carlstrome24fa612011-09-29 00:53:55 -0700101 executable_offset_ = 0;
Ian Rogers468532e2013-08-05 10:56:33 -0700102 interpreter_to_interpreter_bridge_offset_ = 0;
103 interpreter_to_compiled_code_bridge_offset_ = 0;
104 jni_dlsym_lookup_offset_ = 0;
Jeff Hao88474b42013-10-23 16:24:40 -0700105 portable_imt_conflict_trampoline_offset_ = 0;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700106 portable_resolution_trampoline_offset_ = 0;
Ian Rogers468532e2013-08-05 10:56:33 -0700107 portable_to_interpreter_bridge_offset_ = 0;
Andreas Gampe2da88232014-02-27 12:26:20 -0800108 quick_generic_jni_trampoline_offset_ = 0;
Jeff Hao88474b42013-10-23 16:24:40 -0700109 quick_imt_conflict_trampoline_offset_ = 0;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700110 quick_resolution_trampoline_offset_ = 0;
Ian Rogers468532e2013-08-05 10:56:33 -0700111 quick_to_interpreter_bridge_offset_ = 0;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700112}
113
114bool OatHeader::IsValid() const {
Brian Carlstromf852fb22012-10-19 11:01:58 -0700115 if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700116 return false;
117 }
Brian Carlstromf852fb22012-10-19 11:01:58 -0700118 if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700119 return false;
120 }
121 return true;
122}
123
124const char* OatHeader::GetMagic() const {
125 CHECK(IsValid());
126 return reinterpret_cast<const char*>(magic_);
127}
128
Brian Carlstrome24fa612011-09-29 00:53:55 -0700129uint32_t OatHeader::GetChecksum() const {
130 CHECK(IsValid());
131 return adler32_checksum_;
132}
133
134void OatHeader::UpdateChecksum(const void* data, size_t length) {
135 DCHECK(IsValid());
136 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
137 adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
138}
139
Elliott Hughesa72ec822012-03-05 17:12:22 -0800140InstructionSet OatHeader::GetInstructionSet() const {
141 CHECK(IsValid());
142 return instruction_set_;
143}
144
Dave Allison70202782013-10-22 17:52:19 -0700145const InstructionSetFeatures& OatHeader::GetInstructionSetFeatures() const {
146 CHECK(IsValid());
147 return instruction_set_features_;
148}
149
Brian Carlstrome24fa612011-09-29 00:53:55 -0700150uint32_t OatHeader::GetExecutableOffset() const {
151 DCHECK(IsValid());
Elliott Hughes06b37d92011-10-16 11:51:29 -0700152 DCHECK_ALIGNED(executable_offset_, kPageSize);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700153 CHECK_GT(executable_offset_, sizeof(OatHeader));
154 return executable_offset_;
155}
156
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700157void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
158 DCHECK_ALIGNED(executable_offset, kPageSize);
159 CHECK_GT(executable_offset, sizeof(OatHeader));
160 DCHECK(IsValid());
161 DCHECK_EQ(executable_offset_, 0U);
162
163 executable_offset_ = executable_offset;
164 UpdateChecksum(&executable_offset_, sizeof(executable_offset));
165}
166
Ian Rogers468532e2013-08-05 10:56:33 -0700167const void* OatHeader::GetInterpreterToInterpreterBridge() const {
168 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700169}
170
Ian Rogers468532e2013-08-05 10:56:33 -0700171uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700172 DCHECK(IsValid());
Dave Allisonc6104ae2014-03-12 11:05:39 -0700173 CHECK(interpreter_to_interpreter_bridge_offset_ == 0 ||
174 interpreter_to_interpreter_bridge_offset_ >= executable_offset_);
Ian Rogers468532e2013-08-05 10:56:33 -0700175 return interpreter_to_interpreter_bridge_offset_;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700176}
177
Ian Rogers468532e2013-08-05 10:56:33 -0700178void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700179 CHECK(offset == 0 || offset >= executable_offset_);
180 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700181 DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700182
Ian Rogers468532e2013-08-05 10:56:33 -0700183 interpreter_to_interpreter_bridge_offset_ = offset;
184 UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset));
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700185}
186
Ian Rogers468532e2013-08-05 10:56:33 -0700187const void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
188 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700189}
190
Ian Rogers468532e2013-08-05 10:56:33 -0700191uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700192 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700193 CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
194 return interpreter_to_compiled_code_bridge_offset_;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700195}
196
Ian Rogers468532e2013-08-05 10:56:33 -0700197void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
198 CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700199 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700200 DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700201
Ian Rogers468532e2013-08-05 10:56:33 -0700202 interpreter_to_compiled_code_bridge_offset_ = offset;
203 UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset));
204}
205
206const void* OatHeader::GetJniDlsymLookup() const {
207 return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
208}
209
210uint32_t OatHeader::GetJniDlsymLookupOffset() const {
211 DCHECK(IsValid());
212 CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
213 return jni_dlsym_lookup_offset_;
214}
215
216void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
217 CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
218 DCHECK(IsValid());
219 DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
220
221 jni_dlsym_lookup_offset_ = offset;
222 UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset));
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700223}
224
Jeff Hao88474b42013-10-23 16:24:40 -0700225const void* OatHeader::GetPortableImtConflictTrampoline() const {
226 return reinterpret_cast<const uint8_t*>(this) + GetPortableImtConflictTrampolineOffset();
227}
228
229uint32_t OatHeader::GetPortableImtConflictTrampolineOffset() const {
230 DCHECK(IsValid());
231 CHECK_GE(portable_imt_conflict_trampoline_offset_, jni_dlsym_lookup_offset_);
232 return portable_imt_conflict_trampoline_offset_;
233}
234
235void OatHeader::SetPortableImtConflictTrampolineOffset(uint32_t offset) {
236 CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
237 DCHECK(IsValid());
238 DCHECK_EQ(portable_imt_conflict_trampoline_offset_, 0U) << offset;
239
240 portable_imt_conflict_trampoline_offset_ = offset;
241 UpdateChecksum(&portable_imt_conflict_trampoline_offset_, sizeof(offset));
242}
243
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700244const void* OatHeader::GetPortableResolutionTrampoline() const {
245 return reinterpret_cast<const uint8_t*>(this) + GetPortableResolutionTrampolineOffset();
246}
247
248uint32_t OatHeader::GetPortableResolutionTrampolineOffset() const {
249 DCHECK(IsValid());
Jeff Hao88474b42013-10-23 16:24:40 -0700250 CHECK_GE(portable_resolution_trampoline_offset_, portable_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700251 return portable_resolution_trampoline_offset_;
252}
253
254void OatHeader::SetPortableResolutionTrampolineOffset(uint32_t offset) {
Jeff Hao88474b42013-10-23 16:24:40 -0700255 CHECK(offset == 0 || offset >= portable_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700256 DCHECK(IsValid());
257 DCHECK_EQ(portable_resolution_trampoline_offset_, 0U) << offset;
258
259 portable_resolution_trampoline_offset_ = offset;
260 UpdateChecksum(&portable_resolution_trampoline_offset_, sizeof(offset));
261}
262
Ian Rogers468532e2013-08-05 10:56:33 -0700263const void* OatHeader::GetPortableToInterpreterBridge() const {
264 return reinterpret_cast<const uint8_t*>(this) + GetPortableToInterpreterBridgeOffset();
265}
266
267uint32_t OatHeader::GetPortableToInterpreterBridgeOffset() const {
268 DCHECK(IsValid());
269 CHECK_GE(portable_to_interpreter_bridge_offset_, portable_resolution_trampoline_offset_);
270 return portable_to_interpreter_bridge_offset_;
271}
272
273void OatHeader::SetPortableToInterpreterBridgeOffset(uint32_t offset) {
274 CHECK(offset == 0 || offset >= portable_resolution_trampoline_offset_);
275 DCHECK(IsValid());
276 DCHECK_EQ(portable_to_interpreter_bridge_offset_, 0U) << offset;
277
278 portable_to_interpreter_bridge_offset_ = offset;
279 UpdateChecksum(&portable_to_interpreter_bridge_offset_, sizeof(offset));
280}
281
Andreas Gampe2da88232014-02-27 12:26:20 -0800282const void* OatHeader::GetQuickGenericJniTrampoline() const {
283 return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset();
284}
285
286uint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
287 DCHECK(IsValid());
288 CHECK_GE(quick_generic_jni_trampoline_offset_, portable_to_interpreter_bridge_offset_);
289 return quick_generic_jni_trampoline_offset_;
290}
291
292void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
293 CHECK(offset == 0 || offset >= portable_to_interpreter_bridge_offset_);
294 DCHECK(IsValid());
295 DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
296
297 quick_generic_jni_trampoline_offset_ = offset;
298 UpdateChecksum(&quick_generic_jni_trampoline_offset_, sizeof(offset));
299}
300
Jeff Hao88474b42013-10-23 16:24:40 -0700301const void* OatHeader::GetQuickImtConflictTrampoline() const {
302 return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset();
303}
304
305uint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
306 DCHECK(IsValid());
Andreas Gampe2da88232014-02-27 12:26:20 -0800307 CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
Jeff Hao88474b42013-10-23 16:24:40 -0700308 return quick_imt_conflict_trampoline_offset_;
309}
310
311void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
Andreas Gampe2da88232014-02-27 12:26:20 -0800312 CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
Jeff Hao88474b42013-10-23 16:24:40 -0700313 DCHECK(IsValid());
314 DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
315
316 quick_imt_conflict_trampoline_offset_ = offset;
317 UpdateChecksum(&quick_imt_conflict_trampoline_offset_, sizeof(offset));
318}
319
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700320const void* OatHeader::GetQuickResolutionTrampoline() const {
321 return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
322}
323
324uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
325 DCHECK(IsValid());
Jeff Hao88474b42013-10-23 16:24:40 -0700326 CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700327 return quick_resolution_trampoline_offset_;
328}
329
330void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
Jeff Hao88474b42013-10-23 16:24:40 -0700331 CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700332 DCHECK(IsValid());
333 DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
334
335 quick_resolution_trampoline_offset_ = offset;
336 UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset));
337}
338
Ian Rogers468532e2013-08-05 10:56:33 -0700339const void* OatHeader::GetQuickToInterpreterBridge() const {
340 return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
341}
342
343uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
344 DCHECK(IsValid());
345 CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
346 return quick_to_interpreter_bridge_offset_;
347}
348
349void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
350 CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
351 DCHECK(IsValid());
352 DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
353
354 quick_to_interpreter_bridge_offset_ = offset;
355 UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset));
356}
357
Brian Carlstrom28db0122012-10-18 16:20:41 -0700358uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700359 CHECK(IsValid());
Brian Carlstrom28db0122012-10-18 16:20:41 -0700360 return image_file_location_oat_checksum_;
361}
362
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800363uint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
Brian Carlstrom28db0122012-10-18 16:20:41 -0700364 CHECK(IsValid());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800365 return image_file_location_oat_data_begin_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700366}
367
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700368uint32_t OatHeader::GetKeyValueStoreSize() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700369 CHECK(IsValid());
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700370 return key_value_store_size_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700371}
372
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700373const uint8_t* OatHeader::GetKeyValueStore() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700374 CHECK(IsValid());
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700375 return key_value_store_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700376}
377
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700378// Advance start until it is either end or \0.
379static const char* ParseString(const char* start, const char* end) {
380 while (start < end && *start != 0) {
381 start++;
382 }
383 return start;
384}
385
386const char* OatHeader::GetStoreValueByKey(const char* key) const {
387 const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
388 const char* end = ptr + key_value_store_size_;
389
390 while (ptr < end) {
391 // Scan for a closing zero.
392 const char* str_end = ParseString(ptr, end);
393 if (str_end < end) {
394 if (strcmp(key, ptr) == 0) {
395 // Same as key. Check if value is OK.
396 if (ParseString(str_end + 1, end) < end) {
397 return str_end + 1;
398 }
399 } else {
400 // Different from key. Advance over the value.
401 ptr = ParseString(str_end + 1, end) + 1;
402 }
403 } else {
404 break;
405 }
406 }
407 // Not found.
408 return nullptr;
409}
410
411bool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
412 const char** value) const {
413 const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
414 const char* end = ptr + key_value_store_size_;
415 ssize_t counter = static_cast<ssize_t>(index);
416
417 while (ptr < end && counter >= 0) {
418 // Scan for a closing zero.
419 const char* str_end = ParseString(ptr, end);
420 if (str_end < end) {
421 const char* maybe_key = ptr;
422 ptr = ParseString(str_end + 1, end) + 1;
423 if (ptr <= end) {
424 if (counter == 0) {
425 *key = maybe_key;
426 *value = str_end + 1;
427 return true;
428 } else {
429 counter--;
430 }
431 } else {
432 return false;
433 }
434 } else {
435 break;
436 }
437 }
438 // Not found.
439 return false;
440}
441
442size_t OatHeader::GetHeaderSize() const {
443 return sizeof(OatHeader) + key_value_store_size_;
444}
445
446void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
447 char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
448 if (key_value_store != nullptr) {
449 SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
450 SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
451 for ( ; it != end; ++it) {
452 strcpy(data_ptr, it->first.c_str());
453 data_ptr += it->first.length() + 1;
454 strcpy(data_ptr, it->second.c_str());
455 data_ptr += it->second.length() + 1;
456 }
457 }
458 key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700459}
460
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700461OatMethodOffsets::OatMethodOffsets()
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700462 : code_offset_(0),
Jeff Hao74180ca2013-03-27 15:29:11 -0700463 gc_map_offset_(0)
Logan Chienccb7bf12012-03-28 12:52:32 +0800464{}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700465
466OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
Jeff Hao74180ca2013-03-27 15:29:11 -0700467 uint32_t gc_map_offset
Logan Chienccb7bf12012-03-28 12:52:32 +0800468 )
Elliott Hughes362f9bc2011-10-17 18:56:41 -0700469 : code_offset_(code_offset),
Jeff Hao74180ca2013-03-27 15:29:11 -0700470 gc_map_offset_(gc_map_offset)
Logan Chienccb7bf12012-03-28 12:52:32 +0800471{}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700472
473OatMethodOffsets::~OatMethodOffsets() {}
474
Vladimir Marko7624d252014-05-02 14:40:15 +0100475OatQuickMethodHeader::OatQuickMethodHeader()
Vladimir Marko8a630572014-04-09 18:45:35 +0100476 : mapping_table_offset_(0),
477 vmap_table_offset_(0),
Vladimir Marko7624d252014-05-02 14:40:15 +0100478 frame_info_(0, 0, 0),
Vladimir Marko8a630572014-04-09 18:45:35 +0100479 code_size_(0)
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100480{}
481
Vladimir Marko7624d252014-05-02 14:40:15 +0100482OatQuickMethodHeader::OatQuickMethodHeader(
483 uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t frame_size_in_bytes,
484 uint32_t core_spill_mask, uint32_t fp_spill_mask, uint32_t code_size)
Vladimir Marko8a630572014-04-09 18:45:35 +0100485 : mapping_table_offset_(mapping_table_offset),
486 vmap_table_offset_(vmap_table_offset),
Vladimir Marko7624d252014-05-02 14:40:15 +0100487 frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask),
Vladimir Marko8a630572014-04-09 18:45:35 +0100488 code_size_(code_size)
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100489{}
490
Vladimir Marko7624d252014-05-02 14:40:15 +0100491OatQuickMethodHeader::~OatQuickMethodHeader() {}
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100492
Brian Carlstrome24fa612011-09-29 00:53:55 -0700493} // namespace art