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