oat.cc revision 80afd02024d20e60b197d3adfbb43cc303cf29e0
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
17e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat.h"
18e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
1922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe#include <string.h>
20e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include <zlib.h>
21e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
22d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set_features.h"
2380afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/bit_utils.h"
242bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe#include "base/stringprintf.h"
25d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
26e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art {
27e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
282bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampeconstexpr uint8_t OatHeader::kOatMagic[4];
292bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampeconstexpr uint8_t OatHeader::kOatVersion[4];
300de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzconstexpr const char OatHeader::kTrueValue[];
310de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzconstexpr const char OatHeader::kFalseValue[];
32e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
3322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampestatic size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
3422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  size_t estimate = 0U;
3522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  if (variable_data != nullptr) {
3622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator it = variable_data->begin();
3722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator end = variable_data->end();
3822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    for ( ; it != end; ++it) {
3922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      estimate += it->first.length() + 1;
4022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      estimate += it->second.length() + 1;
4122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
4222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
4322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return sizeof(OatHeader) + estimate;
4422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
4522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
4622f8e5c82d12951be38cd893426e13bee33fd69dAndreas GampeOatHeader* OatHeader::Create(InstructionSet instruction_set,
476f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                             const InstructionSetFeatures* instruction_set_features,
4822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                             const std::vector<const DexFile*>* dex_files,
4922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                             uint32_t image_file_location_oat_checksum,
5022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                             uint32_t image_file_location_oat_data_begin,
5122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                             const SafeMap<std::string, std::string>* variable_data) {
5222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Estimate size of optional data.
5322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  size_t needed_size = ComputeOatHeaderSize(variable_data);
5422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
5522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Reserve enough memory.
5622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  void* memory = operator new (needed_size);
5722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
5822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Create the OatHeader in-place.
5922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return new (memory) OatHeader(instruction_set,
6022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                instruction_set_features,
6122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                dex_files,
6222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                image_file_location_oat_checksum,
6322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                image_file_location_oat_data_begin,
6422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                variable_data);
65a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes}
66a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
6781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian CarlstromOatHeader::OatHeader(InstructionSet instruction_set,
686f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                     const InstructionSetFeatures* instruction_set_features,
6981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom                     const std::vector<const DexFile*>* dex_files,
7028db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom                     uint32_t image_file_location_oat_checksum,
71700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom                     uint32_t image_file_location_oat_data_begin,
7222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                     const SafeMap<std::string, std::string>* variable_data) {
732bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  // Don't want asserts in header as they would be checked in each file that includes it. But the
742bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  // fields are private, so we check inside a method.
752bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  static_assert(sizeof(magic_) == sizeof(kOatMagic),
762bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                "Oat magic and magic_ have different lengths.");
772bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  static_assert(sizeof(version_) == sizeof(kOatVersion),
782bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                "Oat version and version_ have different lengths.");
792bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe
80e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  memcpy(magic_, kOatMagic, sizeof(kOatMagic));
81e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  memcpy(version_, kOatVersion, sizeof(kOatVersion));
82a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  executable_offset_ = 0;
83a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  image_patch_delta_ = 0;
8481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
85e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  adler32_checksum_ = adler32(0L, Z_NULL, 0);
8681f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
87f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom  CHECK_NE(instruction_set, kNone);
88a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes  instruction_set_ = instruction_set;
89a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes  UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
9081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
916f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  instruction_set_features_bitmap_ = instruction_set_features->AsBitmap();
926f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  UpdateChecksum(&instruction_set_features_bitmap_, sizeof(instruction_set_features_bitmap_));
937020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison
94e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  dex_file_count_ = dex_files->size();
95e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
9681f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
9728db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom  image_file_location_oat_checksum_ = image_file_location_oat_checksum;
9828db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom  UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
9928db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom
100700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  CHECK(IsAligned<kPageSize>(image_file_location_oat_data_begin));
101700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
102700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
10381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
10422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Flatten the map. Will also update variable_size_data_size_.
10522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  Flatten(variable_data);
10622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
10722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Update checksum for variable data size.
10822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_));
10922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
11022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Update for data, if existing.
11122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  if (key_value_store_size_ > 0U) {
11222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    UpdateChecksum(&key_value_store_, key_value_store_size_);
11322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
11481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
115468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  interpreter_to_interpreter_bridge_offset_ = 0;
116468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  interpreter_to_compiled_code_bridge_offset_ = 0;
117468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  jni_dlsym_lookup_offset_ = 0;
1182da882315a61072664f7ce3c212307342e907207Andreas Gampe  quick_generic_jni_trampoline_offset_ = 0;
11988474b416eb257078e590bf9bc7957cee604a186Jeff Hao  quick_imt_conflict_trampoline_offset_ = 0;
1200aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  quick_resolution_trampoline_offset_ = 0;
121468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  quick_to_interpreter_bridge_offset_ = 0;
122e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
123e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
124e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatHeader::IsValid() const {
125f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
126e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
127e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
128f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom  if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
129e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
130e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
131a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (!IsAligned<kPageSize>(executable_offset_)) {
132a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    return false;
133a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
134a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (!IsAligned<kPageSize>(image_patch_delta_)) {
135a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    return false;
136a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
137e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return true;
138e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
139e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
1402bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampestd::string OatHeader::GetValidationErrorMessage() const {
1412bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
1422bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length");
1432bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return StringPrintf("Invalid oat magic, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
1442bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
1452bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        magic_[0], magic_[1], magic_[2], magic_[3]);
1462bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1472bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
1482bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length");
1492bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
1502bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
1512bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        version_[0], version_[1], version_[2], version_[3]);
1522bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1532bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (!IsAligned<kPageSize>(executable_offset_)) {
1542bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return "Executable offset not page-aligned.";
1552bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1562bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (!IsAligned<kPageSize>(image_patch_delta_)) {
1572bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return "Image patch delta not page-aligned.";
1582bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1592bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  return "";
1602bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe}
1612bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe
162e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromconst char* OatHeader::GetMagic() const {
163e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(IsValid());
164e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return reinterpret_cast<const char*>(magic_);
165e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
166e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
167e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromuint32_t OatHeader::GetChecksum() const {
168e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(IsValid());
169e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return adler32_checksum_;
170e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
171e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
172e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid OatHeader::UpdateChecksum(const void* data, size_t length) {
173e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  DCHECK(IsValid());
174e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
175e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
176e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
177e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
178a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott HughesInstructionSet OatHeader::GetInstructionSet() const {
179a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes  CHECK(IsValid());
180a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes  return instruction_set_;
181a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes}
182a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
1836f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogersuint32_t OatHeader::GetInstructionSetFeaturesBitmap() const {
1847020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison  CHECK(IsValid());
1856f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  return instruction_set_features_bitmap_;
1867020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison}
1877020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison
188e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromuint32_t OatHeader::GetExecutableOffset() const {
189e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  DCHECK(IsValid());
19006b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes  DCHECK_ALIGNED(executable_offset_, kPageSize);
191e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK_GT(executable_offset_, sizeof(OatHeader));
192e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return executable_offset_;
193e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
194e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
1950aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haovoid OatHeader::SetExecutableOffset(uint32_t executable_offset) {
1960aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_ALIGNED(executable_offset, kPageSize);
1970aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  CHECK_GT(executable_offset, sizeof(OatHeader));
1980aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
1990aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_EQ(executable_offset_, 0U);
2000aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
2010aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  executable_offset_ = executable_offset;
2020aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  UpdateChecksum(&executable_offset_, sizeof(executable_offset));
2030aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2040aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
205468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetInterpreterToInterpreterBridge() const {
206468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
2070aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2080aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
209468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
2100aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
211c6104ae36351591157fa09c482796256f82daddcDave Allison  CHECK(interpreter_to_interpreter_bridge_offset_ == 0 ||
212c6104ae36351591157fa09c482796256f82daddcDave Allison        interpreter_to_interpreter_bridge_offset_ >= executable_offset_);
213468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return interpreter_to_interpreter_bridge_offset_;
2140aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2150aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
216468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
2170aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  CHECK(offset == 0 || offset >= executable_offset_);
2180aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
219468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
2200aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
221468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  interpreter_to_interpreter_bridge_offset_ = offset;
222468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset));
2230aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2240aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
225468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
226468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
2270aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2280aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
229468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
2300aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
231468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
232468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return interpreter_to_compiled_code_bridge_offset_;
2330aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2340aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
235468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
236468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
2370aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
238468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
2390aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
240468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  interpreter_to_compiled_code_bridge_offset_ = offset;
241468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset));
242468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
243468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
244468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetJniDlsymLookup() const {
245468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
246468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
247468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
248468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetJniDlsymLookupOffset() const {
249468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
250468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
251468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return jni_dlsym_lookup_offset_;
252468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
253468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
254468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
255468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
256468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
257468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
258468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
259468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  jni_dlsym_lookup_offset_ = offset;
260468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset));
2610aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2620aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
2632da882315a61072664f7ce3c212307342e907207Andreas Gampeconst void* OatHeader::GetQuickGenericJniTrampoline() const {
2642da882315a61072664f7ce3c212307342e907207Andreas Gampe  return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset();
2652da882315a61072664f7ce3c212307342e907207Andreas Gampe}
2662da882315a61072664f7ce3c212307342e907207Andreas Gampe
2672da882315a61072664f7ce3c212307342e907207Andreas Gampeuint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
2682da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK(IsValid());
269956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  CHECK_GE(quick_generic_jni_trampoline_offset_, jni_dlsym_lookup_offset_);
2702da882315a61072664f7ce3c212307342e907207Andreas Gampe  return quick_generic_jni_trampoline_offset_;
2712da882315a61072664f7ce3c212307342e907207Andreas Gampe}
2722da882315a61072664f7ce3c212307342e907207Andreas Gampe
2732da882315a61072664f7ce3c212307342e907207Andreas Gampevoid OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
274956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
2752da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK(IsValid());
2762da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
2772da882315a61072664f7ce3c212307342e907207Andreas Gampe
2782da882315a61072664f7ce3c212307342e907207Andreas Gampe  quick_generic_jni_trampoline_offset_ = offset;
2792da882315a61072664f7ce3c212307342e907207Andreas Gampe  UpdateChecksum(&quick_generic_jni_trampoline_offset_, sizeof(offset));
2802da882315a61072664f7ce3c212307342e907207Andreas Gampe}
2812da882315a61072664f7ce3c212307342e907207Andreas Gampe
28288474b416eb257078e590bf9bc7957cee604a186Jeff Haoconst void* OatHeader::GetQuickImtConflictTrampoline() const {
28388474b416eb257078e590bf9bc7957cee604a186Jeff Hao  return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset();
28488474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
28588474b416eb257078e590bf9bc7957cee604a186Jeff Hao
28688474b416eb257078e590bf9bc7957cee604a186Jeff Haouint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
28788474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK(IsValid());
2882da882315a61072664f7ce3c212307342e907207Andreas Gampe  CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
28988474b416eb257078e590bf9bc7957cee604a186Jeff Hao  return quick_imt_conflict_trampoline_offset_;
29088474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
29188474b416eb257078e590bf9bc7957cee604a186Jeff Hao
29288474b416eb257078e590bf9bc7957cee604a186Jeff Haovoid OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
2932da882315a61072664f7ce3c212307342e907207Andreas Gampe  CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
29488474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK(IsValid());
29588474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
29688474b416eb257078e590bf9bc7957cee604a186Jeff Hao
29788474b416eb257078e590bf9bc7957cee604a186Jeff Hao  quick_imt_conflict_trampoline_offset_ = offset;
29888474b416eb257078e590bf9bc7957cee604a186Jeff Hao  UpdateChecksum(&quick_imt_conflict_trampoline_offset_, sizeof(offset));
29988474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
30088474b416eb257078e590bf9bc7957cee604a186Jeff Hao
3010aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haoconst void* OatHeader::GetQuickResolutionTrampoline() const {
3020aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
3030aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3040aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3050aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haouint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
3060aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
30788474b416eb257078e590bf9bc7957cee604a186Jeff Hao  CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
3080aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  return quick_resolution_trampoline_offset_;
3090aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3100aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3110aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haovoid OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
31288474b416eb257078e590bf9bc7957cee604a186Jeff Hao  CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
3130aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
3140aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
3150aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3160aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  quick_resolution_trampoline_offset_ = offset;
3170aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset));
3180aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3190aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
320468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetQuickToInterpreterBridge() const {
321468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
322468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
323468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
324468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
325468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
326468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
327468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return quick_to_interpreter_bridge_offset_;
328468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
329468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
330468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
331468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
332468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
333468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
334468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
335468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  quick_to_interpreter_bridge_offset_ = offset;
336468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset));
337468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
338468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
339a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightint32_t OatHeader::GetImagePatchDelta() const {
340a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
341a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  return image_patch_delta_;
342a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
343a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
344a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightvoid OatHeader::RelocateOat(off_t delta) {
345a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
346a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK_ALIGNED(delta, kPageSize);
347a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  image_patch_delta_ += delta;
348a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (image_file_location_oat_data_begin_ != 0) {
349a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    image_file_location_oat_data_begin_ += delta;
350a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
351a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
352a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
353a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightvoid OatHeader::SetImagePatchDelta(int32_t off) {
354a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
355a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK_ALIGNED(off, kPageSize);
356a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  image_patch_delta_ = off;
357a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
358a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
35928db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstromuint32_t OatHeader::GetImageFileLocationOatChecksum() const {
36028db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom  CHECK(IsValid());
36128db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom  return image_file_location_oat_checksum_;
36228db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom}
36328db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom
364700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromuint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
36581f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
366700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return image_file_location_oat_data_begin_;
36781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
36881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
36922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeuint32_t OatHeader::GetKeyValueStoreSize() const {
37081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
37122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return key_value_store_size_;
37281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
37381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
37422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeconst uint8_t* OatHeader::GetKeyValueStore() const {
37581f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
37622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return key_value_store_;
377c87d27b25994da8670d82a8f7bad6327b693bfffAndreas Gampe}
378c87d27b25994da8670d82a8f7bad6327b693bfffAndreas Gampe
37922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe// Advance start until it is either end or \0.
38022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampestatic const char* ParseString(const char* start, const char* end) {
38122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (start < end && *start != 0) {
38222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    start++;
38322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
38422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return start;
38522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
38622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
38722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeconst char* OatHeader::GetStoreValueByKey(const char* key) const {
38822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
38922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* end = ptr + key_value_store_size_;
39022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
39122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (ptr < end) {
39222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // Scan for a closing zero.
39322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    const char* str_end = ParseString(ptr, end);
39422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    if (str_end < end) {
39522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      if (strcmp(key, ptr) == 0) {
39622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        // Same as key. Check if value is OK.
39722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        if (ParseString(str_end + 1, end) < end) {
39822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          return str_end + 1;
39922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        }
40022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      } else {
40122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        // Different from key. Advance over the value.
40222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        ptr = ParseString(str_end + 1, end) + 1;
40322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      }
40422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    } else {
40522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      break;
40622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
40722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
40822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Not found.
40922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return nullptr;
41022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
41122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
41222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampebool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
41322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                            const char** value) const {
41422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
41522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* end = ptr + key_value_store_size_;
41622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  ssize_t counter = static_cast<ssize_t>(index);
41722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
41822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (ptr < end && counter >= 0) {
41922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // Scan for a closing zero.
42022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    const char* str_end = ParseString(ptr, end);
42122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    if (str_end < end) {
42222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      const char* maybe_key = ptr;
42322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      ptr = ParseString(str_end + 1, end) + 1;
42422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      if (ptr <= end) {
42522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        if (counter == 0) {
42622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          *key = maybe_key;
42722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          *value = str_end + 1;
42822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          return true;
42922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        } else {
43022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          counter--;
43122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        }
43222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      } else {
43322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        return false;
43422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      }
43522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    } else {
43622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      break;
43722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
43822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
43922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Not found.
44022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return false;
44122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
44222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
44322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampesize_t OatHeader::GetHeaderSize() const {
44422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return sizeof(OatHeader) + key_value_store_size_;
44522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
44622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
44746774767fcf7780d1455e755729198648d08742eIgor Murashkinbool OatHeader::IsPic() const {
4480de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  return IsKeyEnabled(OatHeader::kPicKey);
4490de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz}
4500de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz
4510de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzbool OatHeader::IsDebuggable() const {
4520de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  return IsKeyEnabled(OatHeader::kDebuggableKey);
4530de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz}
4540de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz
4550de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzbool OatHeader::IsKeyEnabled(const char* key) const {
4560de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  const char* key_value = GetStoreValueByKey(key);
4570de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  return (key_value != nullptr && strncmp(key_value, kTrueValue, sizeof(kTrueValue)) == 0);
45846774767fcf7780d1455e755729198648d08742eIgor Murashkin}
45946774767fcf7780d1455e755729198648d08742eIgor Murashkin
46022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampevoid OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
46122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
46222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  if (key_value_store != nullptr) {
46322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
46422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
46522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    for ( ; it != end; ++it) {
46622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      strcpy(data_ptr, it->first.c_str());
46722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      data_ptr += it->first.length() + 1;
46822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      strcpy(data_ptr, it->second.c_str());
46922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      data_ptr += it->second.length() + 1;
47022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
47122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
47222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
47381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
47481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
475957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu ChartierOatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) {
476957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier}
4773320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
4783320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromOatMethodOffsets::~OatMethodOffsets() {}
4793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
4807624d25dad2d1ba25969ae704fccf68649103ae5Vladimir MarkoOatQuickMethodHeader::OatQuickMethodHeader(
481957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t gc_map_offset,
482957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    uint32_t frame_size_in_bytes, uint32_t core_spill_mask, uint32_t fp_spill_mask,
483957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    uint32_t code_size)
484957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier    : mapping_table_offset_(mapping_table_offset), vmap_table_offset_(vmap_table_offset),
485957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier      gc_map_offset_(gc_map_offset),
486957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier      frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask), code_size_(code_size) {
487957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier}
48896c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko
4897624d25dad2d1ba25969ae704fccf68649103ae5Vladimir MarkoOatQuickMethodHeader::~OatQuickMethodHeader() {}
49096c6ab93336b972a38bd2448bcccf19188b8389bVladimir Marko
491e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}  // namespace art
492