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
2246ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h"
2346ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
24d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set_features.h"
2580afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/bit_utils.h"
26f45d61c0866461c9476f17644b27dc0664d507c5Andreas Gampe#include "base/strlcpy.h"
27d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers
28e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art {
29e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
3046ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf;
3146ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
322bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampeconstexpr uint8_t OatHeader::kOatMagic[4];
332bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampeconstexpr uint8_t OatHeader::kOatVersion[4];
340de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzconstexpr const char OatHeader::kTrueValue[];
350de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzconstexpr const char OatHeader::kFalseValue[];
36e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
3722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampestatic size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
3822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  size_t estimate = 0U;
3922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  if (variable_data != nullptr) {
4022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator it = variable_data->begin();
4122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator end = variable_data->end();
4222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    for ( ; it != end; ++it) {
4322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      estimate += it->first.length() + 1;
4422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      estimate += it->second.length() + 1;
4522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
4622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
4722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return sizeof(OatHeader) + estimate;
4822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
4922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
5022f8e5c82d12951be38cd893426e13bee33fd69dAndreas GampeOatHeader* OatHeader::Create(InstructionSet instruction_set,
516f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                             const InstructionSetFeatures* instruction_set_features,
5249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                             uint32_t dex_file_count,
5322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                             const SafeMap<std::string, std::string>* variable_data) {
5422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Estimate size of optional data.
5522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  size_t needed_size = ComputeOatHeaderSize(variable_data);
5622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
5722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Reserve enough memory.
5822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  void* memory = operator new (needed_size);
5922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
6022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Create the OatHeader in-place.
6122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return new (memory) OatHeader(instruction_set,
6222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                instruction_set_features,
6349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                                dex_file_count,
6422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                variable_data);
65a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes}
66a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
6781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian CarlstromOatHeader::OatHeader(InstructionSet instruction_set,
686f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers                     const InstructionSetFeatures* instruction_set_features,
6949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                     uint32_t dex_file_count,
7049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                     const SafeMap<std::string, std::string>* variable_data)
7149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko    : adler32_checksum_(adler32(0L, Z_NULL, 0)),
7249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      instruction_set_(instruction_set),
7349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      instruction_set_features_bitmap_(instruction_set_features->AsBitmap()),
7449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      dex_file_count_(dex_file_count),
750eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko      oat_dex_files_offset_(0),
7649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      executable_offset_(0),
7749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      interpreter_to_interpreter_bridge_offset_(0),
7849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      interpreter_to_compiled_code_bridge_offset_(0),
7949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      jni_dlsym_lookup_offset_(0),
8049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      quick_generic_jni_trampoline_offset_(0),
8149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      quick_imt_conflict_trampoline_offset_(0),
8249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      quick_resolution_trampoline_offset_(0),
8349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      quick_to_interpreter_bridge_offset_(0),
8449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      image_patch_delta_(0),
8549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      image_file_location_oat_checksum_(0),
8649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko      image_file_location_oat_data_begin_(0) {
872bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  // Don't want asserts in header as they would be checked in each file that includes it. But the
882bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  // fields are private, so we check inside a method.
892bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  static_assert(sizeof(magic_) == sizeof(kOatMagic),
902bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                "Oat magic and magic_ have different lengths.");
912bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  static_assert(sizeof(version_) == sizeof(kOatVersion),
922bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                "Oat version and version_ have different lengths.");
932bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe
94e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  memcpy(magic_, kOatMagic, sizeof(kOatMagic));
95e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  memcpy(version_, kOatVersion, sizeof(kOatVersion));
9681f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
9733bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko  CHECK_NE(instruction_set, InstructionSet::kNone);
9881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
9922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Flatten the map. Will also update variable_size_data_size_.
10022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  Flatten(variable_data);
101e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
102e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
103e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatHeader::IsValid() const {
104f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
105e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
106e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
107f852fb2921128d3b71a76e6b17c78d10fb7085e2Brian Carlstrom  if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
108e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
109e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
110a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (!IsAligned<kPageSize>(executable_offset_)) {
111a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    return false;
112a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
113a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (!IsAligned<kPageSize>(image_patch_delta_)) {
114a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    return false;
115a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
11609d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  if (!IsValidInstructionSet(instruction_set_)) {
11709d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko    return false;
11809d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  }
119e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return true;
120e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
121e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
1222bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampestd::string OatHeader::GetValidationErrorMessage() const {
1232bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
1242bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length");
1252bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return StringPrintf("Invalid oat magic, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
1262bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
1272bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        magic_[0], magic_[1], magic_[2], magic_[3]);
1282bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1292bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
1302bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length");
1312bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
1322bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
1332bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe                        version_[0], version_[1], version_[2], version_[3]);
1342bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1352bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (!IsAligned<kPageSize>(executable_offset_)) {
1362bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return "Executable offset not page-aligned.";
1372bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
1382bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  if (!IsAligned<kPageSize>(image_patch_delta_)) {
1392bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe    return "Image patch delta not page-aligned.";
1402bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  }
14109d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  if (!IsValidInstructionSet(instruction_set_)) {
14209d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko    return StringPrintf("Invalid instruction set, %d.", static_cast<int>(instruction_set_));
14309d0943f5efe92c1f3a6b9dbdf255adb0f960a22Vladimir Marko  }
1442bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe  return "";
1452bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe}
1462bcb3b228bc418bcc7fdc3d58d0a0da422a0b6d5Andreas Gampe
147e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromconst char* OatHeader::GetMagic() const {
148e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(IsValid());
149e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return reinterpret_cast<const char*>(magic_);
150e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
151e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
152e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromuint32_t OatHeader::GetChecksum() const {
153e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK(IsValid());
154e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return adler32_checksum_;
155e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
156e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
15749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Markovoid OatHeader::UpdateChecksumWithHeaderData() {
15849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
15949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&instruction_set_features_bitmap_, sizeof(instruction_set_features_bitmap_));
16049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
16149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
16249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
16349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
16449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  // Update checksum for variable data size.
16549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_));
16649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
16749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  // Update for data, if existing.
16849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  if (key_value_store_size_ > 0U) {
16949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko    UpdateChecksum(&key_value_store_, key_value_store_size_);
17049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  }
17149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
17249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&executable_offset_, sizeof(executable_offset_));
17349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&interpreter_to_interpreter_bridge_offset_,
17449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(interpreter_to_interpreter_bridge_offset_));
17549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_,
17649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(interpreter_to_compiled_code_bridge_offset_));
17749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(jni_dlsym_lookup_offset_));
17849b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&quick_generic_jni_trampoline_offset_,
17949b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(quick_generic_jni_trampoline_offset_));
18049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&quick_imt_conflict_trampoline_offset_,
18149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(quick_imt_conflict_trampoline_offset_));
18249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&quick_resolution_trampoline_offset_,
18349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(quick_resolution_trampoline_offset_));
18449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  UpdateChecksum(&quick_to_interpreter_bridge_offset_,
18549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko                 sizeof(quick_to_interpreter_bridge_offset_));
18649b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko}
18749b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
188e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid OatHeader::UpdateChecksum(const void* data, size_t length) {
189e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  DCHECK(IsValid());
1902c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao  if (data != nullptr) {
1912c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao    const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
1922c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao    adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
1932c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao  } else {
1942c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao    DCHECK_EQ(0U, length);
1952c6b49498e2f084ce217fcd3327103eadc1e0c37Jeff Hao  }
196e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
197e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
198a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott HughesInstructionSet OatHeader::GetInstructionSet() const {
199a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes  CHECK(IsValid());
200a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes  return instruction_set_;
201a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes}
202a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
2036f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogersuint32_t OatHeader::GetInstructionSetFeaturesBitmap() const {
2047020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison  CHECK(IsValid());
2056f3dbbadf4ce66982eb3d400e0a74cb73eb034f3Ian Rogers  return instruction_set_features_bitmap_;
2067020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison}
2077020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison
2080eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Markouint32_t OatHeader::GetOatDexFilesOffset() const {
2090eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko  DCHECK(IsValid());
2100eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko  DCHECK_GT(oat_dex_files_offset_, sizeof(OatHeader));
2110eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko  return oat_dex_files_offset_;
2120eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko}
2130eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko
2140eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Markovoid OatHeader::SetOatDexFilesOffset(uint32_t oat_dex_files_offset) {
2150eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko  DCHECK_GT(oat_dex_files_offset, sizeof(OatHeader));
2160eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko  DCHECK(IsValid());
2170eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko  DCHECK_EQ(oat_dex_files_offset_, 0u);
2180eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko
2190eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko  oat_dex_files_offset_ = oat_dex_files_offset;
2200eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko}
2210eb882bfc5d260e8014c26adfda11602065aa5d8Vladimir Marko
222e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromuint32_t OatHeader::GetExecutableOffset() const {
223e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  DCHECK(IsValid());
22406b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes  DCHECK_ALIGNED(executable_offset_, kPageSize);
225e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  CHECK_GT(executable_offset_, sizeof(OatHeader));
226e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return executable_offset_;
227e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}
228e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
2290aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haovoid OatHeader::SetExecutableOffset(uint32_t executable_offset) {
2300aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_ALIGNED(executable_offset, kPageSize);
2310aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  CHECK_GT(executable_offset, sizeof(OatHeader));
2320aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
2330aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_EQ(executable_offset_, 0U);
2340aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
2350aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  executable_offset_ = executable_offset;
2360aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2370aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
238468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetInterpreterToInterpreterBridge() const {
239468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
2400aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2410aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
242468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
2430aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
244c6104ae36351591157fa09c482796256f82daddcDave Allison  CHECK(interpreter_to_interpreter_bridge_offset_ == 0 ||
245c6104ae36351591157fa09c482796256f82daddcDave Allison        interpreter_to_interpreter_bridge_offset_ >= executable_offset_);
246468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return interpreter_to_interpreter_bridge_offset_;
2470aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2480aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
249468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
2500aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  CHECK(offset == 0 || offset >= executable_offset_);
2510aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
252468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
2530aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
254468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  interpreter_to_interpreter_bridge_offset_ = offset;
2550aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2560aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
257468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
258468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
2590aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2600aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
261468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
2620aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
263468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
264468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return interpreter_to_compiled_code_bridge_offset_;
2650aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2660aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
267468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
268468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
2690aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
270468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
2710aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
272468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  interpreter_to_compiled_code_bridge_offset_ = offset;
273468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
274468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
275468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetJniDlsymLookup() const {
276468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
277468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
278468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
279468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetJniDlsymLookupOffset() const {
280468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
281468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
282468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return jni_dlsym_lookup_offset_;
283468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
284468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
285468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
286468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
287468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
288468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
289468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
290468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  jni_dlsym_lookup_offset_ = offset;
2910aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
2920aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
2932da882315a61072664f7ce3c212307342e907207Andreas Gampeconst void* OatHeader::GetQuickGenericJniTrampoline() const {
2942da882315a61072664f7ce3c212307342e907207Andreas Gampe  return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset();
2952da882315a61072664f7ce3c212307342e907207Andreas Gampe}
2962da882315a61072664f7ce3c212307342e907207Andreas Gampe
2972da882315a61072664f7ce3c212307342e907207Andreas Gampeuint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
2982da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK(IsValid());
299956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  CHECK_GE(quick_generic_jni_trampoline_offset_, jni_dlsym_lookup_offset_);
3002da882315a61072664f7ce3c212307342e907207Andreas Gampe  return quick_generic_jni_trampoline_offset_;
3012da882315a61072664f7ce3c212307342e907207Andreas Gampe}
3022da882315a61072664f7ce3c212307342e907207Andreas Gampe
3032da882315a61072664f7ce3c212307342e907207Andreas Gampevoid OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
304956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
3052da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK(IsValid());
3062da882315a61072664f7ce3c212307342e907207Andreas Gampe  DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
3072da882315a61072664f7ce3c212307342e907207Andreas Gampe
3082da882315a61072664f7ce3c212307342e907207Andreas Gampe  quick_generic_jni_trampoline_offset_ = offset;
3092da882315a61072664f7ce3c212307342e907207Andreas Gampe}
3102da882315a61072664f7ce3c212307342e907207Andreas Gampe
31188474b416eb257078e590bf9bc7957cee604a186Jeff Haoconst void* OatHeader::GetQuickImtConflictTrampoline() const {
31288474b416eb257078e590bf9bc7957cee604a186Jeff Hao  return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset();
31388474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
31488474b416eb257078e590bf9bc7957cee604a186Jeff Hao
31588474b416eb257078e590bf9bc7957cee604a186Jeff Haouint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
31688474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK(IsValid());
3172da882315a61072664f7ce3c212307342e907207Andreas Gampe  CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
31888474b416eb257078e590bf9bc7957cee604a186Jeff Hao  return quick_imt_conflict_trampoline_offset_;
31988474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
32088474b416eb257078e590bf9bc7957cee604a186Jeff Hao
32188474b416eb257078e590bf9bc7957cee604a186Jeff Haovoid OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
3222da882315a61072664f7ce3c212307342e907207Andreas Gampe  CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
32388474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK(IsValid());
32488474b416eb257078e590bf9bc7957cee604a186Jeff Hao  DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
32588474b416eb257078e590bf9bc7957cee604a186Jeff Hao
32688474b416eb257078e590bf9bc7957cee604a186Jeff Hao  quick_imt_conflict_trampoline_offset_ = offset;
32788474b416eb257078e590bf9bc7957cee604a186Jeff Hao}
32888474b416eb257078e590bf9bc7957cee604a186Jeff Hao
3290aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haoconst void* OatHeader::GetQuickResolutionTrampoline() const {
3300aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
3310aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3320aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3330aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haouint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
3340aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
33588474b416eb257078e590bf9bc7957cee604a186Jeff Hao  CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
3360aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  return quick_resolution_trampoline_offset_;
3370aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3380aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3390aba0ba155bef7346bde19e53581200b89ae8a7aJeff Haovoid OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
34088474b416eb257078e590bf9bc7957cee604a186Jeff Hao  CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
3410aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK(IsValid());
3420aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
3430aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
3440aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  quick_resolution_trampoline_offset_ = offset;
3450aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao}
3460aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao
347468532ea115657709bc32ee498e701a4c71762d4Ian Rogersconst void* OatHeader::GetQuickToInterpreterBridge() const {
348468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
349468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
350468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
351468532ea115657709bc32ee498e701a4c71762d4Ian Rogersuint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
352468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
353468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
354468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  return quick_to_interpreter_bridge_offset_;
355468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
356468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
357468532ea115657709bc32ee498e701a4c71762d4Ian Rogersvoid OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
358468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
359468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK(IsValid());
360468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
361468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
362468532ea115657709bc32ee498e701a4c71762d4Ian Rogers  quick_to_interpreter_bridge_offset_ = offset;
363468532ea115657709bc32ee498e701a4c71762d4Ian Rogers}
364468532ea115657709bc32ee498e701a4c71762d4Ian Rogers
365a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightint32_t OatHeader::GetImagePatchDelta() const {
366a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
367a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  return image_patch_delta_;
368a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
369a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
370a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightvoid OatHeader::RelocateOat(off_t delta) {
371a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
372a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK_ALIGNED(delta, kPageSize);
373a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  image_patch_delta_ += delta;
374a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (image_file_location_oat_data_begin_ != 0) {
375a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    image_file_location_oat_data_begin_ += delta;
376a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
377a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
378a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
379a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightvoid OatHeader::SetImagePatchDelta(int32_t off) {
380a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(IsValid());
381a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK_ALIGNED(off, kPageSize);
382a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  image_patch_delta_ = off;
383a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light}
384a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
38528db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstromuint32_t OatHeader::GetImageFileLocationOatChecksum() const {
38628db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom  CHECK(IsValid());
38728db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom  return image_file_location_oat_checksum_;
38828db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom}
38928db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom
39049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Markovoid OatHeader::SetImageFileLocationOatChecksum(uint32_t image_file_location_oat_checksum) {
39149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  CHECK(IsValid());
39249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  image_file_location_oat_checksum_ = image_file_location_oat_checksum;
39349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko}
39449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
395700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromuint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
39681f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
397700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  return image_file_location_oat_data_begin_;
39881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
39981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
40049b0f45d5a9023653ab00c355735910aa51ee0baVladimir Markovoid OatHeader::SetImageFileLocationOatDataBegin(uint32_t image_file_location_oat_data_begin) {
40149b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  CHECK(IsValid());
40249b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  CHECK_ALIGNED(image_file_location_oat_data_begin, kPageSize);
40349b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko  image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
40449b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko}
40549b0f45d5a9023653ab00c355735910aa51ee0baVladimir Marko
40622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeuint32_t OatHeader::GetKeyValueStoreSize() const {
40781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
40822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return key_value_store_size_;
40981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
41081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
41122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeconst uint8_t* OatHeader::GetKeyValueStore() const {
41281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  CHECK(IsValid());
41322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return key_value_store_;
414c87d27b25994da8670d82a8f7bad6327b693bfffAndreas Gampe}
415c87d27b25994da8670d82a8f7bad6327b693bfffAndreas Gampe
41622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe// Advance start until it is either end or \0.
41722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampestatic const char* ParseString(const char* start, const char* end) {
41822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (start < end && *start != 0) {
41922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    start++;
42022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
42122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return start;
42222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
42322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
42422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampeconst char* OatHeader::GetStoreValueByKey(const char* key) const {
42522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
42622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* end = ptr + key_value_store_size_;
42722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
42822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (ptr < end) {
42922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // Scan for a closing zero.
43022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    const char* str_end = ParseString(ptr, end);
43122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    if (str_end < end) {
43222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      if (strcmp(key, ptr) == 0) {
43322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        // Same as key. Check if value is OK.
43422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        if (ParseString(str_end + 1, end) < end) {
43522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          return str_end + 1;
43622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        }
43722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      } else {
43822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        // Different from key. Advance over the value.
43922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        ptr = ParseString(str_end + 1, end) + 1;
44022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      }
44122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    } else {
44222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      break;
44322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
44422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
44522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Not found.
44622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return nullptr;
44722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
44822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
44922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampebool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
45022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe                                            const char** value) const {
45122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
45222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  const char* end = ptr + key_value_store_size_;
45322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  ssize_t counter = static_cast<ssize_t>(index);
45422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
45522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  while (ptr < end && counter >= 0) {
45622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // Scan for a closing zero.
45722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    const char* str_end = ParseString(ptr, end);
45822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    if (str_end < end) {
45922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      const char* maybe_key = ptr;
46022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      ptr = ParseString(str_end + 1, end) + 1;
46122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      if (ptr <= end) {
46222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        if (counter == 0) {
46322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          *key = maybe_key;
46422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          *value = str_end + 1;
46522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          return true;
46622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        } else {
46722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe          counter--;
46822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        }
46922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      } else {
47022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        return false;
47122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      }
47222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    } else {
47322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      break;
47422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
47522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
47622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  // Not found.
47722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return false;
47822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
47922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
48022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampesize_t OatHeader::GetHeaderSize() const {
48122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  return sizeof(OatHeader) + key_value_store_size_;
48222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe}
48322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe
48446774767fcf7780d1455e755729198648d08742eIgor Murashkinbool OatHeader::IsPic() const {
4850de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  return IsKeyEnabled(OatHeader::kPicKey);
4860de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz}
4870de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz
4880de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertzbool OatHeader::IsDebuggable() const {
4890de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  return IsKeyEnabled(OatHeader::kDebuggableKey);
4900de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz}
4910de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz
492f8cd890d86e2a136966d878fea1d0dae6a9c4ad0Andreas Gampebool OatHeader::IsConcurrentCopying() const {
493f8cd890d86e2a136966d878fea1d0dae6a9c4ad0Andreas Gampe  return IsKeyEnabled(OatHeader::kConcurrentCopying);
494f8cd890d86e2a136966d878fea1d0dae6a9c4ad0Andreas Gampe}
495f8cd890d86e2a136966d878fea1d0dae6a9c4ad0Andreas Gampe
4965d950769b607b4f76413212db640a32d796911deDavid Srbeckybool OatHeader::IsNativeDebuggable() const {
4975d950769b607b4f76413212db640a32d796911deDavid Srbecky  return IsKeyEnabled(OatHeader::kNativeDebuggableKey);
4985d950769b607b4f76413212db640a32d796911deDavid Srbecky}
4995d950769b607b4f76413212db640a32d796911deDavid Srbecky
5007bcfcb80a31f57a84d754e00bca8698829365208Andreas GampeCompilerFilter::Filter OatHeader::GetCompilerFilter() const {
5017bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  CompilerFilter::Filter filter;
5027bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  const char* key_value = GetStoreValueByKey(kCompilerFilter);
5037bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  CHECK(key_value != nullptr) << "compiler-filter not found in oat header";
5047bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  CHECK(CompilerFilter::ParseCompilerFilter(key_value, &filter))
5057bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe      << "Invalid compiler-filter in oat header: " << key_value;
5067bcfcb80a31f57a84d754e00bca8698829365208Andreas Gampe  return filter;
507b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle}
508b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle
509b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravlebool OatHeader::KeyHasValue(const char* key, const char* value, size_t value_size) const {
5100de1133ba600f299b3d67938f650720d9f859eb2Sebastien Hertz  const char* key_value = GetStoreValueByKey(key);
511b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle  return (key_value != nullptr && strncmp(key_value, value, value_size) == 0);
512b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle}
513b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle
514b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravlebool OatHeader::IsKeyEnabled(const char* key) const {
515b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle  return KeyHasValue(key, kTrueValue, sizeof(kTrueValue));
51646774767fcf7780d1455e755729198648d08742eIgor Murashkin}
51746774767fcf7780d1455e755729198648d08742eIgor Murashkin
51822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampevoid OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
51922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
52022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  if (key_value_store != nullptr) {
52122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
52222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
52322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    for ( ; it != end; ++it) {
524f45d61c0866461c9476f17644b27dc0664d507c5Andreas Gampe      strlcpy(data_ptr, it->first.c_str(), it->first.length() + 1);
52522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      data_ptr += it->first.length() + 1;
526f45d61c0866461c9476f17644b27dc0664d507c5Andreas Gampe      strlcpy(data_ptr, it->second.c_str(), it->second.length() + 1);
52722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      data_ptr += it->second.length() + 1;
52822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
52922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  }
53022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe  key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
53181f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom}
53281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
533957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu ChartierOatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) {
534957ca1cd025104fccb0b08928f955f9bdb4ab91cMathieu Chartier}
5353320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
5363320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromOatMethodOffsets::~OatMethodOffsets() {}
5373320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
538e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom}  // namespace art
539