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 */
164a289ed61242964b921434de7d375f46480472a1Brian Carlstrom
174a289ed61242964b921434de7d375f46480472a1Brian Carlstrom#include "image.h"
184a289ed61242964b921434de7d375f46480472a1Brian Carlstrom
1980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/bit_utils.h"
202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array.h"
212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
224f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h"
232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
244a289ed61242964b921434de7d375f46480472a1Brian Carlstromnamespace art {
254a289ed61242964b921434de7d375f46480472a1Brian Carlstrom
2613735955f39b3b304c37d2b2840663c131262c18Ian Rogersconst uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
27df2d4f22d5e89692c90b443da82fe2930518418bArtem Udovichenkoconst uint8_t ImageHeader::kImageVersion[] = { '0', '3', '0', '\0' };
284a289ed61242964b921434de7d375f46480472a1Brian Carlstrom
292dd0e2cea360bc9206eb88ecc40d259e796c239dIan RogersImageHeader::ImageHeader(uint32_t image_begin,
3031e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier                         uint32_t image_size,
31e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                         ImageSection* sections,
322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                         uint32_t image_roots,
332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                         uint32_t oat_checksum,
342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                         uint32_t oat_file_begin,
352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                         uint32_t oat_data_begin,
362dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers                         uint32_t oat_data_end,
3746774767fcf7780d1455e755729198648d08742eIgor Murashkin                         uint32_t oat_file_end,
38fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                         uint32_t boot_image_begin,
39fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                         uint32_t boot_image_size,
40fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                         uint32_t boot_oat_begin,
41fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                         uint32_t boot_oat_size,
42e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier                         uint32_t pointer_size,
43ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier                         bool compile_pic,
44fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                         bool is_pic,
45ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier                         StorageMode storage_mode,
46ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier                         size_t data_size)
472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  : image_begin_(image_begin),
4831e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    image_size_(image_size),
492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    oat_checksum_(oat_checksum),
502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    oat_file_begin_(oat_file_begin),
512dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    oat_data_begin_(oat_data_begin),
522dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    oat_data_end_(oat_data_end),
532dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    oat_file_end_(oat_file_end),
54fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    boot_image_begin_(boot_image_begin),
55fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    boot_image_size_(boot_image_size),
56fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    boot_oat_begin_(boot_oat_begin),
57fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    boot_oat_size_(boot_oat_size),
5853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    patch_delta_(0),
5946774767fcf7780d1455e755729198648d08742eIgor Murashkin    image_roots_(image_roots),
60e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    pointer_size_(pointer_size),
61ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier    compile_pic_(compile_pic),
62fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    is_pic_(is_pic),
63ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier    storage_mode_(storage_mode),
64ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier    data_size_(data_size) {
652dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  CHECK_EQ(image_begin, RoundUp(image_begin, kPageSize));
662dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  CHECK_EQ(oat_file_begin, RoundUp(oat_file_begin, kPageSize));
672dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  CHECK_EQ(oat_data_begin, RoundUp(oat_data_begin, kPageSize));
682dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  CHECK_LT(image_roots, oat_file_begin);
692dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  CHECK_LE(oat_file_begin, oat_data_begin);
702dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  CHECK_LT(oat_data_begin, oat_data_end);
712dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  CHECK_LE(oat_data_end, oat_file_end);
72e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  CHECK(ValidPointerSize(pointer_size_)) << pointer_size_;
732dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  memcpy(magic_, kImageMagic, sizeof(kImageMagic));
742dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  memcpy(version_, kImageVersion, sizeof(kImageVersion));
75e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  std::copy_n(sections, kSectionCount, sections_);
762dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers}
772dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
7853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Lightvoid ImageHeader::RelocateImage(off_t delta) {
7953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  CHECK_ALIGNED(delta, kPageSize) << " patch delta must be page aligned";
8053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  oat_file_begin_ += delta;
8153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  oat_data_begin_ += delta;
8253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  oat_data_end_ += delta;
8353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  oat_file_end_ += delta;
841bc977cf2f8199311a97f2ba9431a184540e3e9cNicolas Geoffray  patch_delta_ += delta;
85fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  RelocateImageObjects(delta);
86fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  RelocateImageMethods(delta);
87fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier}
88fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier
89fbc31087932a65e036a153afab3049dc5298656aMathieu Chartiervoid ImageHeader::RelocateImageObjects(off_t delta) {
90fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  image_begin_ += delta;
91fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  image_roots_ += delta;
92fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier}
93fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier
94fbc31087932a65e036a153afab3049dc5298656aMathieu Chartiervoid ImageHeader::RelocateImageMethods(off_t delta) {
95e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  for (size_t i = 0; i < kImageMethodsCount; ++i) {
96e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier    image_methods_[i] += delta;
97e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  }
9853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light}
9953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light
10068708f536d11f8824d881b640f3902093075c0a6Brian Carlstrombool ImageHeader::IsValid() const {
10168708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom  if (memcmp(magic_, kImageMagic, sizeof(kImageMagic)) != 0) {
10268708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom    return false;
10368708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom  }
10468708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom  if (memcmp(version_, kImageVersion, sizeof(kImageVersion)) != 0) {
10568708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom    return false;
10668708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom  }
10753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  // Unsigned so wraparound is well defined.
10853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  if (image_begin_ >= image_begin_ + image_size_) {
10953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    return false;
11053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
11153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  if (oat_file_begin_ > oat_file_end_) {
11253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    return false;
11353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
11453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  if (oat_data_begin_ > oat_data_end_) {
11553cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    return false;
11653cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
11753cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  if (oat_file_begin_ >= oat_data_begin_) {
11853cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    return false;
11953cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
12053cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  if (!IsAligned<kPageSize>(patch_delta_)) {
12153cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light    return false;
12253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light  }
12368708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom  return true;
12468708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom}
12568708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom
12668708f536d11f8824d881b640f3902093075c0a6Brian Carlstromconst char* ImageHeader::GetMagic() const {
12768708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom  CHECK(IsValid());
12868708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom  return reinterpret_cast<const char*>(magic_);
12968708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom}
13068708f536d11f8824d881b640f3902093075c0a6Brian Carlstrom
131e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu ChartierArtMethod* ImageHeader::GetImageMethod(ImageMethod index) const {
132e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  CHECK_LT(static_cast<size_t>(index), kImageMethodsCount);
133e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  return reinterpret_cast<ArtMethod*>(image_methods_[index]);
134e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier}
135e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier
136e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartiervoid ImageHeader::SetImageMethod(ImageMethod index, ArtMethod* method) {
137e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  CHECK_LT(static_cast<size_t>(index), kImageMethodsCount);
138e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  image_methods_[index] = reinterpret_cast<uint64_t>(method);
139e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier}
140e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier
141e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierconst ImageSection& ImageHeader::GetImageSection(ImageSections index) const {
142e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  CHECK_LT(static_cast<size_t>(index), kSectionCount);
143e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  return sections_[index];
144e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier}
145e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier
146e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartierstd::ostream& operator<<(std::ostream& os, const ImageSection& section) {
147e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  return os << "size=" << section.Size() << " range=" << section.Offset() << "-" << section.End();
148e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier}
149e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier
150cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartiervoid ImageHeader::VisitPackedArtFields(ArtFieldVisitor* visitor, uint8_t* base) const {
151cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier  const ImageSection& fields = GetFieldsSection();
152cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier  for (size_t pos = 0; pos < fields.Size(); ) {
153cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier    auto* array = reinterpret_cast<LengthPrefixedArray<ArtField>*>(base + fields.Offset() + pos);
15435831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko    for (size_t i = 0; i < array->size(); ++i) {
15554d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier      visitor->Visit(&array->At(i, sizeof(ArtField)));
15654d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier    }
15735831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko    pos += array->ComputeSize(array->size());
15854d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier  }
15954d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier}
16054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier
161cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartiervoid ImageHeader::VisitPackedArtMethods(ArtMethodVisitor* visitor,
162cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier                                        uint8_t* base,
163cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier                                        size_t pointer_size) const {
16414632857428b7e37761e6e811c19021715a400f8Vladimir Marko  const size_t method_alignment = ArtMethod::Alignment(pointer_size);
16514632857428b7e37761e6e811c19021715a400f8Vladimir Marko  const size_t method_size = ArtMethod::Size(pointer_size);
166cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier  const ImageSection& methods = GetMethodsSection();
167cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier  for (size_t pos = 0; pos < methods.Size(); ) {
168cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier    auto* array = reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(base + methods.Offset() + pos);
16935831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko    for (size_t i = 0; i < array->size(); ++i) {
170cf36d493124d8048efa0bd6f67d817ce3cd6b725Vladimir Marko      visitor->Visit(&array->At(i, method_size, method_alignment));
17154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier    }
17235831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko    pos += array->ComputeSize(array->size(), method_size, method_alignment);
17354d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier  }
174cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier  const ImageSection& runtime_methods = GetRuntimeMethodsSection();
175cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier  for (size_t pos = 0; pos < runtime_methods.Size(); ) {
176cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier    auto* method = reinterpret_cast<ArtMethod*>(base + runtime_methods.Offset() + pos);
177cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier    visitor->Visit(method);
178cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier    pos += method_size;
179cdca476bf3394ce9d97a369e84e701b427009318Mathieu Chartier  }
18054d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier}
18154d220eb9cc51215d75b9e0fe921b94bebbb3fd6Mathieu Chartier
1824a289ed61242964b921434de7d375f46480472a1Brian Carlstrom}  // namespace art
183