blob: c223e2e0d8fec8455a3290a7facad0ef059dd5d3 [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"
18
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070019#include <string.h>
Brian Carlstrome24fa612011-09-29 00:53:55 -070020#include <zlib.h>
21
Ian Rogersd582fa42014-11-05 23:46:43 -080022#include "arch/instruction_set_features.h"
Andreas Gampe2bcb3b22014-12-12 15:25:14 -080023#include "base/stringprintf.h"
Ian Rogersd582fa42014-11-05 23:46:43 -080024#include "utils.h"
25
Brian Carlstrome24fa612011-09-29 00:53:55 -070026namespace art {
27
Andreas Gampe2bcb3b22014-12-12 15:25:14 -080028constexpr uint8_t OatHeader::kOatMagic[4];
29constexpr uint8_t OatHeader::kOatVersion[4];
Brian Carlstrome24fa612011-09-29 00:53:55 -070030
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070031static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
32 size_t estimate = 0U;
33 if (variable_data != nullptr) {
34 SafeMap<std::string, std::string>::const_iterator it = variable_data->begin();
35 SafeMap<std::string, std::string>::const_iterator end = variable_data->end();
36 for ( ; it != end; ++it) {
37 estimate += it->first.length() + 1;
38 estimate += it->second.length() + 1;
39 }
40 }
41 return sizeof(OatHeader) + estimate;
42}
43
44OatHeader* OatHeader::Create(InstructionSet instruction_set,
Ian Rogers6f3dbba2014-10-14 17:41:57 -070045 const InstructionSetFeatures* instruction_set_features,
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070046 const std::vector<const DexFile*>* dex_files,
47 uint32_t image_file_location_oat_checksum,
48 uint32_t image_file_location_oat_data_begin,
49 const SafeMap<std::string, std::string>* variable_data) {
50 // Estimate size of optional data.
51 size_t needed_size = ComputeOatHeaderSize(variable_data);
52
53 // Reserve enough memory.
54 void* memory = operator new (needed_size);
55
56 // Create the OatHeader in-place.
57 return new (memory) OatHeader(instruction_set,
58 instruction_set_features,
59 dex_files,
60 image_file_location_oat_checksum,
61 image_file_location_oat_data_begin,
62 variable_data);
Elliott Hughesa72ec822012-03-05 17:12:22 -080063}
64
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070065OatHeader::OatHeader(InstructionSet instruction_set,
Ian Rogers6f3dbba2014-10-14 17:41:57 -070066 const InstructionSetFeatures* instruction_set_features,
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070067 const std::vector<const DexFile*>* dex_files,
Brian Carlstrom28db0122012-10-18 16:20:41 -070068 uint32_t image_file_location_oat_checksum,
Brian Carlstrom700c8d32012-11-05 10:42:02 -080069 uint32_t image_file_location_oat_data_begin,
Andreas Gampe22f8e5c2014-07-09 11:38:21 -070070 const SafeMap<std::string, std::string>* variable_data) {
Andreas Gampe2bcb3b22014-12-12 15:25:14 -080071 // Don't want asserts in header as they would be checked in each file that includes it. But the
72 // fields are private, so we check inside a method.
73 static_assert(sizeof(magic_) == sizeof(kOatMagic),
74 "Oat magic and magic_ have different lengths.");
75 static_assert(sizeof(version_) == sizeof(kOatVersion),
76 "Oat version and version_ have different lengths.");
77
Brian Carlstrome24fa612011-09-29 00:53:55 -070078 memcpy(magic_, kOatMagic, sizeof(kOatMagic));
79 memcpy(version_, kOatVersion, sizeof(kOatVersion));
Alex Lighta59dd802014-07-02 16:28:08 -070080 executable_offset_ = 0;
81 image_patch_delta_ = 0;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070082
Brian Carlstrome24fa612011-09-29 00:53:55 -070083 adler32_checksum_ = adler32(0L, Z_NULL, 0);
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070084
Brian Carlstromf852fb22012-10-19 11:01:58 -070085 CHECK_NE(instruction_set, kNone);
Elliott Hughesa72ec822012-03-05 17:12:22 -080086 instruction_set_ = instruction_set;
87 UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070088
Ian Rogers6f3dbba2014-10-14 17:41:57 -070089 instruction_set_features_bitmap_ = instruction_set_features->AsBitmap();
90 UpdateChecksum(&instruction_set_features_bitmap_, sizeof(instruction_set_features_bitmap_));
Dave Allison70202782013-10-22 17:52:19 -070091
Brian Carlstrome24fa612011-09-29 00:53:55 -070092 dex_file_count_ = dex_files->size();
93 UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -070094
Brian Carlstrom28db0122012-10-18 16:20:41 -070095 image_file_location_oat_checksum_ = image_file_location_oat_checksum;
96 UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
97
Brian Carlstrom700c8d32012-11-05 10:42:02 -080098 CHECK(IsAligned<kPageSize>(image_file_location_oat_data_begin));
99 image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
100 UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700101
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700102 // Flatten the map. Will also update variable_size_data_size_.
103 Flatten(variable_data);
104
105 // Update checksum for variable data size.
106 UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_));
107
108 // Update for data, if existing.
109 if (key_value_store_size_ > 0U) {
110 UpdateChecksum(&key_value_store_, key_value_store_size_);
111 }
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700112
Ian Rogers468532e2013-08-05 10:56:33 -0700113 interpreter_to_interpreter_bridge_offset_ = 0;
114 interpreter_to_compiled_code_bridge_offset_ = 0;
115 jni_dlsym_lookup_offset_ = 0;
Andreas Gampe2da88232014-02-27 12:26:20 -0800116 quick_generic_jni_trampoline_offset_ = 0;
Jeff Hao88474b42013-10-23 16:24:40 -0700117 quick_imt_conflict_trampoline_offset_ = 0;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700118 quick_resolution_trampoline_offset_ = 0;
Ian Rogers468532e2013-08-05 10:56:33 -0700119 quick_to_interpreter_bridge_offset_ = 0;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700120}
121
122bool OatHeader::IsValid() const {
Brian Carlstromf852fb22012-10-19 11:01:58 -0700123 if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700124 return false;
125 }
Brian Carlstromf852fb22012-10-19 11:01:58 -0700126 if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700127 return false;
128 }
Alex Lighta59dd802014-07-02 16:28:08 -0700129 if (!IsAligned<kPageSize>(executable_offset_)) {
130 return false;
131 }
132 if (!IsAligned<kPageSize>(image_patch_delta_)) {
133 return false;
134 }
Brian Carlstrome24fa612011-09-29 00:53:55 -0700135 return true;
136}
137
Andreas Gampe2bcb3b22014-12-12 15:25:14 -0800138std::string OatHeader::GetValidationErrorMessage() const {
139 if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
140 static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length");
141 return StringPrintf("Invalid oat magic, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
142 kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
143 magic_[0], magic_[1], magic_[2], magic_[3]);
144 }
145 if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
146 static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length");
147 return StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
148 kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
149 version_[0], version_[1], version_[2], version_[3]);
150 }
151 if (!IsAligned<kPageSize>(executable_offset_)) {
152 return "Executable offset not page-aligned.";
153 }
154 if (!IsAligned<kPageSize>(image_patch_delta_)) {
155 return "Image patch delta not page-aligned.";
156 }
157 return "";
158}
159
Brian Carlstrome24fa612011-09-29 00:53:55 -0700160const char* OatHeader::GetMagic() const {
161 CHECK(IsValid());
162 return reinterpret_cast<const char*>(magic_);
163}
164
Brian Carlstrome24fa612011-09-29 00:53:55 -0700165uint32_t OatHeader::GetChecksum() const {
166 CHECK(IsValid());
167 return adler32_checksum_;
168}
169
170void OatHeader::UpdateChecksum(const void* data, size_t length) {
171 DCHECK(IsValid());
172 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
173 adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
174}
175
Elliott Hughesa72ec822012-03-05 17:12:22 -0800176InstructionSet OatHeader::GetInstructionSet() const {
177 CHECK(IsValid());
178 return instruction_set_;
179}
180
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700181uint32_t OatHeader::GetInstructionSetFeaturesBitmap() const {
Dave Allison70202782013-10-22 17:52:19 -0700182 CHECK(IsValid());
Ian Rogers6f3dbba2014-10-14 17:41:57 -0700183 return instruction_set_features_bitmap_;
Dave Allison70202782013-10-22 17:52:19 -0700184}
185
Brian Carlstrome24fa612011-09-29 00:53:55 -0700186uint32_t OatHeader::GetExecutableOffset() const {
187 DCHECK(IsValid());
Elliott Hughes06b37d92011-10-16 11:51:29 -0700188 DCHECK_ALIGNED(executable_offset_, kPageSize);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700189 CHECK_GT(executable_offset_, sizeof(OatHeader));
190 return executable_offset_;
191}
192
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700193void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
194 DCHECK_ALIGNED(executable_offset, kPageSize);
195 CHECK_GT(executable_offset, sizeof(OatHeader));
196 DCHECK(IsValid());
197 DCHECK_EQ(executable_offset_, 0U);
198
199 executable_offset_ = executable_offset;
200 UpdateChecksum(&executable_offset_, sizeof(executable_offset));
201}
202
Ian Rogers468532e2013-08-05 10:56:33 -0700203const void* OatHeader::GetInterpreterToInterpreterBridge() const {
204 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700205}
206
Ian Rogers468532e2013-08-05 10:56:33 -0700207uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700208 DCHECK(IsValid());
Dave Allisonc6104ae2014-03-12 11:05:39 -0700209 CHECK(interpreter_to_interpreter_bridge_offset_ == 0 ||
210 interpreter_to_interpreter_bridge_offset_ >= executable_offset_);
Ian Rogers468532e2013-08-05 10:56:33 -0700211 return interpreter_to_interpreter_bridge_offset_;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700212}
213
Ian Rogers468532e2013-08-05 10:56:33 -0700214void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700215 CHECK(offset == 0 || offset >= executable_offset_);
216 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700217 DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700218
Ian Rogers468532e2013-08-05 10:56:33 -0700219 interpreter_to_interpreter_bridge_offset_ = offset;
220 UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset));
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700221}
222
Ian Rogers468532e2013-08-05 10:56:33 -0700223const void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
224 return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700225}
226
Ian Rogers468532e2013-08-05 10:56:33 -0700227uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700228 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700229 CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
230 return interpreter_to_compiled_code_bridge_offset_;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700231}
232
Ian Rogers468532e2013-08-05 10:56:33 -0700233void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
234 CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700235 DCHECK(IsValid());
Ian Rogers468532e2013-08-05 10:56:33 -0700236 DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700237
Ian Rogers468532e2013-08-05 10:56:33 -0700238 interpreter_to_compiled_code_bridge_offset_ = offset;
239 UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset));
240}
241
242const void* OatHeader::GetJniDlsymLookup() const {
243 return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
244}
245
246uint32_t OatHeader::GetJniDlsymLookupOffset() const {
247 DCHECK(IsValid());
248 CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
249 return jni_dlsym_lookup_offset_;
250}
251
252void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
253 CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
254 DCHECK(IsValid());
255 DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
256
257 jni_dlsym_lookup_offset_ = offset;
258 UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset));
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700259}
260
Andreas Gampe2da88232014-02-27 12:26:20 -0800261const void* OatHeader::GetQuickGenericJniTrampoline() const {
262 return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset();
263}
264
265uint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
266 DCHECK(IsValid());
Elliott Hughes956af0f2014-12-11 14:34:28 -0800267 CHECK_GE(quick_generic_jni_trampoline_offset_, jni_dlsym_lookup_offset_);
Andreas Gampe2da88232014-02-27 12:26:20 -0800268 return quick_generic_jni_trampoline_offset_;
269}
270
271void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
Elliott Hughes956af0f2014-12-11 14:34:28 -0800272 CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
Andreas Gampe2da88232014-02-27 12:26:20 -0800273 DCHECK(IsValid());
274 DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
275
276 quick_generic_jni_trampoline_offset_ = offset;
277 UpdateChecksum(&quick_generic_jni_trampoline_offset_, sizeof(offset));
278}
279
Jeff Hao88474b42013-10-23 16:24:40 -0700280const void* OatHeader::GetQuickImtConflictTrampoline() const {
281 return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset();
282}
283
284uint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
285 DCHECK(IsValid());
Andreas Gampe2da88232014-02-27 12:26:20 -0800286 CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
Jeff Hao88474b42013-10-23 16:24:40 -0700287 return quick_imt_conflict_trampoline_offset_;
288}
289
290void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
Andreas Gampe2da88232014-02-27 12:26:20 -0800291 CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
Jeff Hao88474b42013-10-23 16:24:40 -0700292 DCHECK(IsValid());
293 DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
294
295 quick_imt_conflict_trampoline_offset_ = offset;
296 UpdateChecksum(&quick_imt_conflict_trampoline_offset_, sizeof(offset));
297}
298
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700299const void* OatHeader::GetQuickResolutionTrampoline() const {
300 return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
301}
302
303uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
304 DCHECK(IsValid());
Jeff Hao88474b42013-10-23 16:24:40 -0700305 CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700306 return quick_resolution_trampoline_offset_;
307}
308
309void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
Jeff Hao88474b42013-10-23 16:24:40 -0700310 CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
Jeff Hao0aba0ba2013-06-03 14:49:28 -0700311 DCHECK(IsValid());
312 DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
313
314 quick_resolution_trampoline_offset_ = offset;
315 UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset));
316}
317
Ian Rogers468532e2013-08-05 10:56:33 -0700318const void* OatHeader::GetQuickToInterpreterBridge() const {
319 return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
320}
321
322uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
323 DCHECK(IsValid());
324 CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
325 return quick_to_interpreter_bridge_offset_;
326}
327
328void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
329 CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
330 DCHECK(IsValid());
331 DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
332
333 quick_to_interpreter_bridge_offset_ = offset;
334 UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset));
335}
336
Alex Lighta59dd802014-07-02 16:28:08 -0700337int32_t OatHeader::GetImagePatchDelta() const {
338 CHECK(IsValid());
339 return image_patch_delta_;
340}
341
342void OatHeader::RelocateOat(off_t delta) {
343 CHECK(IsValid());
344 CHECK_ALIGNED(delta, kPageSize);
345 image_patch_delta_ += delta;
346 if (image_file_location_oat_data_begin_ != 0) {
347 image_file_location_oat_data_begin_ += delta;
348 }
349}
350
351void OatHeader::SetImagePatchDelta(int32_t off) {
352 CHECK(IsValid());
353 CHECK_ALIGNED(off, kPageSize);
354 image_patch_delta_ = off;
355}
356
Brian Carlstrom28db0122012-10-18 16:20:41 -0700357uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700358 CHECK(IsValid());
Brian Carlstrom28db0122012-10-18 16:20:41 -0700359 return image_file_location_oat_checksum_;
360}
361
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800362uint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
Brian Carlstrom28db0122012-10-18 16:20:41 -0700363 CHECK(IsValid());
Brian Carlstrom700c8d32012-11-05 10:42:02 -0800364 return image_file_location_oat_data_begin_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700365}
366
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700367uint32_t OatHeader::GetKeyValueStoreSize() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700368 CHECK(IsValid());
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700369 return key_value_store_size_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700370}
371
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700372const uint8_t* OatHeader::GetKeyValueStore() const {
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700373 CHECK(IsValid());
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700374 return key_value_store_;
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700375}
376
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700377// Advance start until it is either end or \0.
378static const char* ParseString(const char* start, const char* end) {
379 while (start < end && *start != 0) {
380 start++;
381 }
382 return start;
383}
384
385const char* OatHeader::GetStoreValueByKey(const char* key) const {
386 const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
387 const char* end = ptr + key_value_store_size_;
388
389 while (ptr < end) {
390 // Scan for a closing zero.
391 const char* str_end = ParseString(ptr, end);
392 if (str_end < end) {
393 if (strcmp(key, ptr) == 0) {
394 // Same as key. Check if value is OK.
395 if (ParseString(str_end + 1, end) < end) {
396 return str_end + 1;
397 }
398 } else {
399 // Different from key. Advance over the value.
400 ptr = ParseString(str_end + 1, end) + 1;
401 }
402 } else {
403 break;
404 }
405 }
406 // Not found.
407 return nullptr;
408}
409
410bool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
411 const char** value) const {
412 const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
413 const char* end = ptr + key_value_store_size_;
414 ssize_t counter = static_cast<ssize_t>(index);
415
416 while (ptr < end && counter >= 0) {
417 // Scan for a closing zero.
418 const char* str_end = ParseString(ptr, end);
419 if (str_end < end) {
420 const char* maybe_key = ptr;
421 ptr = ParseString(str_end + 1, end) + 1;
422 if (ptr <= end) {
423 if (counter == 0) {
424 *key = maybe_key;
425 *value = str_end + 1;
426 return true;
427 } else {
428 counter--;
429 }
430 } else {
431 return false;
432 }
433 } else {
434 break;
435 }
436 }
437 // Not found.
438 return false;
439}
440
441size_t OatHeader::GetHeaderSize() const {
442 return sizeof(OatHeader) + key_value_store_size_;
443}
444
Igor Murashkin46774762014-10-22 11:37:02 -0700445bool OatHeader::IsPic() const {
446 const char* pic_string = GetStoreValueByKey(OatHeader::kPicKey);
447 static const char kTrue[] = "true";
448 return (pic_string != nullptr && strncmp(pic_string, kTrue, sizeof(kTrue)) == 0);
449}
450
Andreas Gampe22f8e5c2014-07-09 11:38:21 -0700451void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
452 char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
453 if (key_value_store != nullptr) {
454 SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
455 SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
456 for ( ; it != end; ++it) {
457 strcpy(data_ptr, it->first.c_str());
458 data_ptr += it->first.length() + 1;
459 strcpy(data_ptr, it->second.c_str());
460 data_ptr += it->second.length() + 1;
461 }
462 }
463 key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
Brian Carlstrom81f3ca12012-03-17 00:27:35 -0700464}
465
Mathieu Chartier957ca1c2014-11-21 16:51:29 -0800466OatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) {
467}
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700468
469OatMethodOffsets::~OatMethodOffsets() {}
470
Vladimir Marko7624d252014-05-02 14:40:15 +0100471OatQuickMethodHeader::OatQuickMethodHeader(
Mathieu Chartier957ca1c2014-11-21 16:51:29 -0800472 uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t gc_map_offset,
473 uint32_t frame_size_in_bytes, uint32_t core_spill_mask, uint32_t fp_spill_mask,
474 uint32_t code_size)
475 : mapping_table_offset_(mapping_table_offset), vmap_table_offset_(vmap_table_offset),
476 gc_map_offset_(gc_map_offset),
477 frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask), code_size_(code_size) {
478}
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100479
Vladimir Marko7624d252014-05-02 14:40:15 +0100480OatQuickMethodHeader::~OatQuickMethodHeader() {}
Vladimir Marko96c6ab92014-04-08 14:00:50 +0100481
Brian Carlstrome24fa612011-09-29 00:53:55 -0700482} // namespace art