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,
4849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                             uint32_t dex_file_count,
4922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                             const SafeMap<std::string, std::string>* variable_data) {
5022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Estimate size of optional data.
5122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  size_t needed_size = ComputeOatHeaderSize(variable_data);
5222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
5322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Reserve enough memory.
5422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  void* memory = operator new (needed_size);
5522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
5622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Create the OatHeader in-place.
5722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return new (memory) OatHeader(instruction_set,
5822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                instruction_set_features,
5949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                                dex_file_count,
6022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                variable_data);
61a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes}
62a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
6381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian CarlstromOatHeader::OatHeader(InstructionSet instruction_set,
646f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                     const InstructionSetFeatures* instruction_set_features,
6549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                     uint32_t dex_file_count,
6649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                     const SafeMap<std::string, std::string>* variable_data)
6749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko    : adler32_checksum_(adler32(0L, Z_NULL, 0)),
6849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      instruction_set_(instruction_set),
6949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      instruction_set_features_bitmap_(instruction_set_features->AsBitmap()),
7049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      dex_file_count_(dex_file_count),
7149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      executable_offset_(0),
7249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      interpreter_to_interpreter_bridge_offset_(0),
7349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      interpreter_to_compiled_code_bridge_offset_(0),
7449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      jni_dlsym_lookup_offset_(0),
7549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      quick_generic_jni_trampoline_offset_(0),
7649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      quick_imt_conflict_trampoline_offset_(0),
7749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      quick_resolution_trampoline_offset_(0),
7849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      quick_to_interpreter_bridge_offset_(0),
7949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      image_patch_delta_(0),
8049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      image_file_location_oat_checksum_(0),
8149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      image_file_location_oat_data_begin_(0) {
822bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  // Don't want asserts in header as they would be checked in each file that includes it. But the
832bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  // fields are private, so we check inside a method.
842bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  static_assert(sizeof(magic_) == sizeof(kOatMagic),
852bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                "Oat magic and magic_ have different lengths.");
862bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  static_assert(sizeof(version_) == sizeof(kOatVersion),
872bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                "Oat version and version_ have different lengths.");
882bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe
89e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  memcpy(magic_, kOatMagic, sizeof(kOatMagic));
90e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  memcpy(version_, kOatVersion, sizeof(kOatVersion));
9181f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
92f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom  CHECK_NE(instruction_set, kNone);
9381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
9422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Flatten the map. Will also update variable_size_data_size_.
9522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  Flatten(variable_data);
96e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
97e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
98e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatHeader::IsValid() const {
99f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
100e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
101e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
102f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom  if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
103e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
104e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
105a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (!IsAligned<kPageSize>(executable_offset_)) {
106a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    return false;
107a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
108a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (!IsAligned<kPageSize>(image_patch_delta_)) {
109a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    return false;
110a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
11109d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  if (!IsValidInstructionSet(instruction_set_)) {
11209d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko    return false;
11309d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  }
114e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return true;
115e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
116e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
1172bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampestd::string OatHeader::GetValidationErrorMessage() const {
1182bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
1192bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length");
1202bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return StringPrintf("Invalid oat magic, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
1212bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
1222bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        magic_[0], magic_[1], magic_[2], magic_[3]);
1232bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1242bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
1252bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length");
1262bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
1272bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
1282bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        version_[0], version_[1], version_[2], version_[3]);
1292bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1302bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (!IsAligned<kPageSize>(executable_offset_)) {
1312bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return "Executable offset not page-aligned.";
1322bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1332bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (!IsAligned<kPageSize>(image_patch_delta_)) {
1342bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return "Image patch delta not page-aligned.";
1352bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
13609d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  if (!IsValidInstructionSet(instruction_set_)) {
13709d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko    return StringPrintf("Invalid instruction set, %d.", static_cast<int>(instruction_set_));
13809d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  }
1392bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  return "";
1402bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe}
1412bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe
142e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromconst char* OatHeader::GetMagic() const {
143e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(IsValid());
144e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return reinterpret_cast<const char*>(magic_);
145e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
146e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
147e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromuint32_t OatHeader::GetChecksum() const {
148e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(IsValid());
149e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return adler32_checksum_;
150e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
151e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
15249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Markovoid OatHeader::UpdateChecksumWithHeaderData() {
15349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
15449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&instruction_set_features_bitmap_, sizeof(instruction_set_features_bitmap_));
15549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
15649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
15749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
15849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
15949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  // Update checksum for variable data size.
16049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_));
16149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
16249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  // Update for data, if existing.
16349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  if (key_value_store_size_ > 0U) {
16449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko    UpdateChecksum(&key_value_store_, key_value_store_size_);
16549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  }
16649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
16749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&executable_offset_, sizeof(executable_offset_));
16849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&interpreter_to_interpreter_bridge_offset_,
16949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(interpreter_to_interpreter_bridge_offset_));
17049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_,
17149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(interpreter_to_compiled_code_bridge_offset_));
17249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(jni_dlsym_lookup_offset_));
17349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&quick_generic_jni_trampoline_offset_,
17449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(quick_generic_jni_trampoline_offset_));
17549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&quick_imt_conflict_trampoline_offset_,
17649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(quick_imt_conflict_trampoline_offset_));
17749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&quick_resolution_trampoline_offset_,
17849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(quick_resolution_trampoline_offset_));
17949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&quick_to_interpreter_bridge_offset_,
18049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(quick_to_interpreter_bridge_offset_));
18149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko}
18249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
183e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid OatHeader::UpdateChecksum(const void* data, size_t length) {
184e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  DCHECK(IsValid());
1852c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao  if (data != nullptr) {
1862c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao    const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
1872c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao    adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
1882c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao  } else {
1892c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao    DCHECK_EQ(0U, length);
1902c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao  }
191e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
192e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
193a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott HughesInstructionSet OatHeader::GetInstructionSet() const {
194a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes  CHECK(IsValid());
195a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes  return instruction_set_;
196a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes}
197a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
1986f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogersuint32_t OatHeader::GetInstructionSetFeaturesBitmap() const {
1997020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison  CHECK(IsValid());
2006f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  return instruction_set_features_bitmap_;
2017020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison}
2027020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison
203e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromuint32_t OatHeader::GetExecutableOffset() const {
204e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  DCHECK(IsValid());
20506b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes  DCHECK_ALIGNED(executable_offset_, kPageSize);
206e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK_GT(executable_offset_, sizeof(OatHeader));
207e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return executable_offset_;
208e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
209e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
2100aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haovoid OatHeader::SetExecutableOffset(uint32_t executable_offset) {
2110aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_ALIGNED(executable_offset, kPageSize);
2120aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  CHECK_GT(executable_offset, sizeof(OatHeader));
2130aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
2140aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_EQ(executable_offset_, 0U);
2150aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
2160aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  executable_offset_ = executable_offset;
2170aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2180aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
219468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetInterpreterToInterpreterBridge() const {
220468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
2210aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2220aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
223468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
2240aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
225c6104ae36351591157fa09c482796256f82daddcDave Allison  CHECK(interpreter_to_interpreter_bridge_offset_ == 0 ||
226c6104ae36351591157fa09c482796256f82daddcDave Allison        interpreter_to_interpreter_bridge_offset_ >= executable_offset_);
227468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return interpreter_to_interpreter_bridge_offset_;
2280aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2290aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
230468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
2310aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  CHECK(offset == 0 || offset >= executable_offset_);
2320aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
233468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
2340aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
235468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  interpreter_to_interpreter_bridge_offset_ = offset;
2360aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2370aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
238468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
239468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
2400aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2410aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
242468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
2430aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
244468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
245468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return interpreter_to_compiled_code_bridge_offset_;
2460aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2470aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
248468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
249468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
2500aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
251468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
2520aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
253468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  interpreter_to_compiled_code_bridge_offset_ = offset;
254468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
255468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
256468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetJniDlsymLookup() const {
257468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
258468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
259468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
260468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetJniDlsymLookupOffset() const {
261468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
262468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
263468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return jni_dlsym_lookup_offset_;
264468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
265468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
266468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
267468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
268468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
269468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
270468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
271468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  jni_dlsym_lookup_offset_ = offset;
2720aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2730aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
2742da882315a61072664f7ce3c212307342e907207Andreas Gampeconst void* OatHeader::GetQuickGenericJniTrampoline() const {
2752da882315a61072664f7ce3c212307342e907207Andreas Gampe  return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset();
2762da882315a61072664f7ce3c212307342e907207Andreas Gampe}
2772da882315a61072664f7ce3c212307342e907207Andreas Gampe
2782da882315a61072664f7ce3c212307342e907207Andreas Gampeuint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
2792da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK(IsValid());
280956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  CHECK_GE(quick_generic_jni_trampoline_offset_, jni_dlsym_lookup_offset_);
2812da882315a61072664f7ce3c212307342e907207Andreas Gampe  return quick_generic_jni_trampoline_offset_;
2822da882315a61072664f7ce3c212307342e907207Andreas Gampe}
2832da882315a61072664f7ce3c212307342e907207Andreas Gampe
2842da882315a61072664f7ce3c212307342e907207Andreas Gampevoid OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
285956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
2862da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK(IsValid());
2872da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
2882da882315a61072664f7ce3c212307342e907207Andreas Gampe
2892da882315a61072664f7ce3c212307342e907207Andreas Gampe  quick_generic_jni_trampoline_offset_ = offset;
2902da882315a61072664f7ce3c212307342e907207Andreas Gampe}
2912da882315a61072664f7ce3c212307342e907207Andreas Gampe
29288474b416eb257078e590bf9bc7957cee604a186Jeff Haoconst void* OatHeader::GetQuickImtConflictTrampoline() const {
29388474b416eb257078e590bf9bc7957cee604a186Jeff Hao  return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset();
29488474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
29588474b416eb257078e590bf9bc7957cee604a186Jeff Hao
29688474b416eb257078e590bf9bc7957cee604a186Jeff Haouint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
29788474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK(IsValid());
2982da882315a61072664f7ce3c212307342e907207Andreas Gampe  CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
29988474b416eb257078e590bf9bc7957cee604a186Jeff Hao  return quick_imt_conflict_trampoline_offset_;
30088474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
30188474b416eb257078e590bf9bc7957cee604a186Jeff Hao
30288474b416eb257078e590bf9bc7957cee604a186Jeff Haovoid OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
3032da882315a61072664f7ce3c212307342e907207Andreas Gampe  CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
30488474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK(IsValid());
30588474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
30688474b416eb257078e590bf9bc7957cee604a186Jeff Hao
30788474b416eb257078e590bf9bc7957cee604a186Jeff Hao  quick_imt_conflict_trampoline_offset_ = offset;
30888474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
30988474b416eb257078e590bf9bc7957cee604a186Jeff Hao
3100aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haoconst void* OatHeader::GetQuickResolutionTrampoline() const {
3110aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
3120aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3130aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3140aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haouint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
3150aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
31688474b416eb257078e590bf9bc7957cee604a186Jeff Hao  CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
3170aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  return quick_resolution_trampoline_offset_;
3180aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3190aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3200aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haovoid OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
32188474b416eb257078e590bf9bc7957cee604a186Jeff Hao  CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
3220aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
3230aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
3240aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3250aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  quick_resolution_trampoline_offset_ = offset;
3260aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3270aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
328468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetQuickToInterpreterBridge() const {
329468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
330468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
331468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
332468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
333468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
334468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
335468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return quick_to_interpreter_bridge_offset_;
336468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
337468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
338468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
339468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
340468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
341468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
342468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
343468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  quick_to_interpreter_bridge_offset_ = offset;
344468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
345468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
346a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightint32_t OatHeader::GetImagePatchDelta() const {
347a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
348a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  return image_patch_delta_;
349a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
350a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
351a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightvoid OatHeader::RelocateOat(off_t delta) {
352a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
353a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK_ALIGNED(delta, kPageSize);
354a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  image_patch_delta_ += delta;
355a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (image_file_location_oat_data_begin_ != 0) {
356a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    image_file_location_oat_data_begin_ += delta;
357a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
358a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
359a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
360a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightvoid OatHeader::SetImagePatchDelta(int32_t off) {
361a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
362a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK_ALIGNED(off, kPageSize);
363a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  image_patch_delta_ = off;
364a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
365a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
36628db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstromuint32_t OatHeader::GetImageFileLocationOatChecksum() const {
36728db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom  CHECK(IsValid());
36828db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom  return image_file_location_oat_checksum_;
36928db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom}
37028db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom
37149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Markovoid OatHeader::SetImageFileLocationOatChecksum(uint32_t image_file_location_oat_checksum) {
37249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  CHECK(IsValid());
37349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  image_file_location_oat_checksum_ = image_file_location_oat_checksum;
37449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko}
37549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
376700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromuint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
37781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
378700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return image_file_location_oat_data_begin_;
37981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
38081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
38149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Markovoid OatHeader::SetImageFileLocationOatDataBegin(uint32_t image_file_location_oat_data_begin) {
38249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  CHECK(IsValid());
38349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  CHECK_ALIGNED(image_file_location_oat_data_begin, kPageSize);
38449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
38549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko}
38649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
38722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeuint32_t OatHeader::GetKeyValueStoreSize() const {
38881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
38922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return key_value_store_size_;
39081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
39181f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
39222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeconst uint8_t* OatHeader::GetKeyValueStore() const {
39381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
39422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return key_value_store_;
395c87d27b25994da8670d82a8f7bad6327b693bfffAndreas Gampe}
396c87d27b25994da8670d82a8f7bad6327b693bfffAndreas Gampe
39722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe// Advance start until it is either end or \0.
39822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampestatic const char* ParseString(const char* start, const char* end) {
39922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (start < end && *start != 0) {
40022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    start++;
40122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
40222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return start;
40322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
40422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
40522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeconst char* OatHeader::GetStoreValueByKey(const char* key) const {
40622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
40722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* end = ptr + key_value_store_size_;
40822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
40922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (ptr < end) {
41022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // Scan for a closing zero.
41122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    const char* str_end = ParseString(ptr, end);
41222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    if (str_end < end) {
41322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      if (strcmp(key, ptr) == 0) {
41422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        // Same as key. Check if value is OK.
41522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        if (ParseString(str_end + 1, end) < end) {
41622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          return str_end + 1;
41722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        }
41822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      } else {
41922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        // Different from key. Advance over the value.
42022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        ptr = ParseString(str_end + 1, end) + 1;
42122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      }
42222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    } else {
42322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      break;
42422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
42522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
42622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Not found.
42722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return nullptr;
42822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
42922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
43022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampebool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
43122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                            const char** value) const {
43222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
43322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* end = ptr + key_value_store_size_;
43422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  ssize_t counter = static_cast<ssize_t>(index);
43522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
43622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (ptr < end && counter >= 0) {
43722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // Scan for a closing zero.
43822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    const char* str_end = ParseString(ptr, end);
43922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    if (str_end < end) {
44022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      const char* maybe_key = ptr;
44122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      ptr = ParseString(str_end + 1, end) + 1;
44222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      if (ptr <= end) {
44322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        if (counter == 0) {
44422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          *key = maybe_key;
44522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          *value = str_end + 1;
44622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          return true;
44722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        } else {
44822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          counter--;
44922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        }
45022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      } else {
45122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        return false;
45222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      }
45322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    } else {
45422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      break;
45522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
45622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
45722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Not found.
45822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return false;
45922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
46022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
46122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampesize_t OatHeader::GetHeaderSize() const {
46222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return sizeof(OatHeader) + key_value_store_size_;
46322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
46422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
46546774767fcf7780d1455e755729198648d08742eIgor Murashkinbool OatHeader::IsPic() const {
4660de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  return IsKeyEnabled(OatHeader::kPicKey);
4670de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz}
4680de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz
4691c4eb04b6cb1427f96e9587bd425ee269b8c8479Richard Uhlerbool OatHeader::HasPatchInfo() const {
4701c4eb04b6cb1427f96e9587bd425ee269b8c8479Richard Uhler  return IsKeyEnabled(OatHeader::kHasPatchInfoKey);
4711c4eb04b6cb1427f96e9587bd425ee269b8c8479Richard Uhler}
4721c4eb04b6cb1427f96e9587bd425ee269b8c8479Richard Uhler
4730de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzbool OatHeader::IsDebuggable() const {
4740de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  return IsKeyEnabled(OatHeader::kDebuggableKey);
4750de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz}
4760de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz
4775d950769b607b4f76413212db640a32d796911deDavid Srbeckybool OatHeader::IsNativeDebuggable() const {
4785d950769b607b4f76413212db640a32d796911deDavid Srbecky  return IsKeyEnabled(OatHeader::kNativeDebuggableKey);
4795d950769b607b4f76413212db640a32d796911deDavid Srbecky}
4805d950769b607b4f76413212db640a32d796911deDavid Srbecky
4817bcfcb80a31f57a84d754e00bca8698829365208Andreas GampeCompilerFilter::Filter OatHeader::GetCompilerFilter() const {
4827bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  CompilerFilter::Filter filter;
4837bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  const char* key_value = GetStoreValueByKey(kCompilerFilter);
4847bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  CHECK(key_value != nullptr) << "compiler-filter not found in oat header";
4857bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  CHECK(CompilerFilter::ParseCompilerFilter(key_value, &filter))
4867bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe      << "Invalid compiler-filter in oat header: " << key_value;
4877bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  return filter;
488b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle}
489b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle
490b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravlebool OatHeader::KeyHasValue(const char* key, const char* value, size_t value_size) const {
4910de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  const char* key_value = GetStoreValueByKey(key);
492b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle  return (key_value != nullptr && strncmp(key_value, value, value_size) == 0);
493b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle}
494b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle
495b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravlebool OatHeader::IsKeyEnabled(const char* key) const {
496b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle  return KeyHasValue(key, kTrueValue, sizeof(kTrueValue));
49746774767fcf7780d1455e755729198648d08742eIgor Murashkin}
49846774767fcf7780d1455e755729198648d08742eIgor Murashkin
49922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampevoid OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
50022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
50122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  if (key_value_store != nullptr) {
50222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
50322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
50422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    for ( ; it != end; ++it) {
50522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      strcpy(data_ptr, it->first.c_str());
50622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      data_ptr += it->first.length() + 1;
50722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      strcpy(data_ptr, it->second.c_str());
50822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      data_ptr += it->second.length() + 1;
50922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
51022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
51122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
51281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
51381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
514957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu ChartierOatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) {
515957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier}
5163320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
5173320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromOatMethodOffsets::~OatMethodOffsets() {}
5183320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
519e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}  // namespace art
520