1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "image.h" 18 19 #include "base/bit_utils.h" 20 #include "base/length_prefixed_array.h" 21 #include "mirror/object_array.h" 22 #include "mirror/object_array-inl.h" 23 #include "mirror/object-inl.h" 24 #include "utils.h" 25 26 namespace art { 27 28 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; 29 const uint8_t ImageHeader::kImageVersion[] = { '0', '4', '3', '\0' }; // hash-based DexCache fields 30 31 ImageHeader::ImageHeader(uint32_t image_begin, 32 uint32_t image_size, 33 ImageSection* sections, 34 uint32_t image_roots, 35 uint32_t oat_checksum, 36 uint32_t oat_file_begin, 37 uint32_t oat_data_begin, 38 uint32_t oat_data_end, 39 uint32_t oat_file_end, 40 uint32_t boot_image_begin, 41 uint32_t boot_image_size, 42 uint32_t boot_oat_begin, 43 uint32_t boot_oat_size, 44 uint32_t pointer_size, 45 bool compile_pic, 46 bool is_pic, 47 StorageMode storage_mode, 48 size_t data_size) 49 : image_begin_(image_begin), 50 image_size_(image_size), 51 oat_checksum_(oat_checksum), 52 oat_file_begin_(oat_file_begin), 53 oat_data_begin_(oat_data_begin), 54 oat_data_end_(oat_data_end), 55 oat_file_end_(oat_file_end), 56 boot_image_begin_(boot_image_begin), 57 boot_image_size_(boot_image_size), 58 boot_oat_begin_(boot_oat_begin), 59 boot_oat_size_(boot_oat_size), 60 patch_delta_(0), 61 image_roots_(image_roots), 62 pointer_size_(pointer_size), 63 compile_pic_(compile_pic), 64 is_pic_(is_pic), 65 storage_mode_(storage_mode), 66 data_size_(data_size) { 67 CHECK_EQ(image_begin, RoundUp(image_begin, kPageSize)); 68 CHECK_EQ(oat_file_begin, RoundUp(oat_file_begin, kPageSize)); 69 CHECK_EQ(oat_data_begin, RoundUp(oat_data_begin, kPageSize)); 70 CHECK_LT(image_roots, oat_file_begin); 71 CHECK_LE(oat_file_begin, oat_data_begin); 72 CHECK_LT(oat_data_begin, oat_data_end); 73 CHECK_LE(oat_data_end, oat_file_end); 74 CHECK(ValidPointerSize(pointer_size_)) << pointer_size_; 75 memcpy(magic_, kImageMagic, sizeof(kImageMagic)); 76 memcpy(version_, kImageVersion, sizeof(kImageVersion)); 77 std::copy_n(sections, kSectionCount, sections_); 78 } 79 80 void ImageHeader::RelocateImage(off_t delta) { 81 CHECK_ALIGNED(delta, kPageSize) << " patch delta must be page aligned"; 82 oat_file_begin_ += delta; 83 oat_data_begin_ += delta; 84 oat_data_end_ += delta; 85 oat_file_end_ += delta; 86 patch_delta_ += delta; 87 RelocateImageObjects(delta); 88 RelocateImageMethods(delta); 89 } 90 91 void ImageHeader::RelocateImageObjects(off_t delta) { 92 image_begin_ += delta; 93 image_roots_ += delta; 94 } 95 96 void ImageHeader::RelocateImageMethods(off_t delta) { 97 for (size_t i = 0; i < kImageMethodsCount; ++i) { 98 image_methods_[i] += delta; 99 } 100 } 101 102 bool ImageHeader::IsValid() const { 103 if (memcmp(magic_, kImageMagic, sizeof(kImageMagic)) != 0) { 104 return false; 105 } 106 if (memcmp(version_, kImageVersion, sizeof(kImageVersion)) != 0) { 107 return false; 108 } 109 // Unsigned so wraparound is well defined. 110 if (image_begin_ >= image_begin_ + image_size_) { 111 return false; 112 } 113 if (oat_file_begin_ > oat_file_end_) { 114 return false; 115 } 116 if (oat_data_begin_ > oat_data_end_) { 117 return false; 118 } 119 if (oat_file_begin_ >= oat_data_begin_) { 120 return false; 121 } 122 if (!IsAligned<kPageSize>(patch_delta_)) { 123 return false; 124 } 125 return true; 126 } 127 128 const char* ImageHeader::GetMagic() const { 129 CHECK(IsValid()); 130 return reinterpret_cast<const char*>(magic_); 131 } 132 133 ArtMethod* ImageHeader::GetImageMethod(ImageMethod index) const { 134 CHECK_LT(static_cast<size_t>(index), kImageMethodsCount); 135 return reinterpret_cast<ArtMethod*>(image_methods_[index]); 136 } 137 138 void ImageHeader::SetImageMethod(ImageMethod index, ArtMethod* method) { 139 CHECK_LT(static_cast<size_t>(index), kImageMethodsCount); 140 image_methods_[index] = reinterpret_cast<uint64_t>(method); 141 } 142 143 const ImageSection& ImageHeader::GetImageSection(ImageSections index) const { 144 CHECK_LT(static_cast<size_t>(index), kSectionCount); 145 return sections_[index]; 146 } 147 148 std::ostream& operator<<(std::ostream& os, const ImageSection& section) { 149 return os << "size=" << section.Size() << " range=" << section.Offset() << "-" << section.End(); 150 } 151 152 void ImageHeader::VisitPackedArtFields(ArtFieldVisitor* visitor, uint8_t* base) const { 153 const ImageSection& fields = GetFieldsSection(); 154 for (size_t pos = 0; pos < fields.Size(); ) { 155 auto* array = reinterpret_cast<LengthPrefixedArray<ArtField>*>(base + fields.Offset() + pos); 156 for (size_t i = 0; i < array->size(); ++i) { 157 visitor->Visit(&array->At(i, sizeof(ArtField))); 158 } 159 pos += array->ComputeSize(array->size()); 160 } 161 } 162 163 void ImageHeader::VisitPackedArtMethods(ArtMethodVisitor* visitor, 164 uint8_t* base, 165 PointerSize pointer_size) const { 166 const size_t method_alignment = ArtMethod::Alignment(pointer_size); 167 const size_t method_size = ArtMethod::Size(pointer_size); 168 const ImageSection& methods = GetMethodsSection(); 169 for (size_t pos = 0; pos < methods.Size(); ) { 170 auto* array = reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(base + methods.Offset() + pos); 171 for (size_t i = 0; i < array->size(); ++i) { 172 visitor->Visit(&array->At(i, method_size, method_alignment)); 173 } 174 pos += array->ComputeSize(array->size(), method_size, method_alignment); 175 } 176 const ImageSection& runtime_methods = GetRuntimeMethodsSection(); 177 for (size_t pos = 0; pos < runtime_methods.Size(); ) { 178 auto* method = reinterpret_cast<ArtMethod*>(base + runtime_methods.Offset() + pos); 179 visitor->Visit(method); 180 pos += method_size; 181 } 182 } 183 184 PointerSize ImageHeader::GetPointerSize() const { 185 return ConvertToPointerSize(pointer_size_); 186 } 187 188 } // namespace art 189