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 "mirror/object_array.h" 21 #include "mirror/object_array-inl.h" 22 #include "mirror/object-inl.h" 23 24 namespace art { 25 26 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; 27 const uint8_t ImageHeader::kImageVersion[] = { '0', '3', '0', '\0' }; 28 29 ImageHeader::ImageHeader(uint32_t image_begin, 30 uint32_t image_size, 31 ImageSection* sections, 32 uint32_t image_roots, 33 uint32_t oat_checksum, 34 uint32_t oat_file_begin, 35 uint32_t oat_data_begin, 36 uint32_t oat_data_end, 37 uint32_t oat_file_end, 38 uint32_t boot_image_begin, 39 uint32_t boot_image_size, 40 uint32_t boot_oat_begin, 41 uint32_t boot_oat_size, 42 uint32_t pointer_size, 43 bool compile_pic, 44 bool is_pic, 45 StorageMode storage_mode, 46 size_t data_size) 47 : image_begin_(image_begin), 48 image_size_(image_size), 49 oat_checksum_(oat_checksum), 50 oat_file_begin_(oat_file_begin), 51 oat_data_begin_(oat_data_begin), 52 oat_data_end_(oat_data_end), 53 oat_file_end_(oat_file_end), 54 boot_image_begin_(boot_image_begin), 55 boot_image_size_(boot_image_size), 56 boot_oat_begin_(boot_oat_begin), 57 boot_oat_size_(boot_oat_size), 58 patch_delta_(0), 59 image_roots_(image_roots), 60 pointer_size_(pointer_size), 61 compile_pic_(compile_pic), 62 is_pic_(is_pic), 63 storage_mode_(storage_mode), 64 data_size_(data_size) { 65 CHECK_EQ(image_begin, RoundUp(image_begin, kPageSize)); 66 CHECK_EQ(oat_file_begin, RoundUp(oat_file_begin, kPageSize)); 67 CHECK_EQ(oat_data_begin, RoundUp(oat_data_begin, kPageSize)); 68 CHECK_LT(image_roots, oat_file_begin); 69 CHECK_LE(oat_file_begin, oat_data_begin); 70 CHECK_LT(oat_data_begin, oat_data_end); 71 CHECK_LE(oat_data_end, oat_file_end); 72 CHECK(ValidPointerSize(pointer_size_)) << pointer_size_; 73 memcpy(magic_, kImageMagic, sizeof(kImageMagic)); 74 memcpy(version_, kImageVersion, sizeof(kImageVersion)); 75 std::copy_n(sections, kSectionCount, sections_); 76 } 77 78 void ImageHeader::RelocateImage(off_t delta) { 79 CHECK_ALIGNED(delta, kPageSize) << " patch delta must be page aligned"; 80 oat_file_begin_ += delta; 81 oat_data_begin_ += delta; 82 oat_data_end_ += delta; 83 oat_file_end_ += delta; 84 patch_delta_ += delta; 85 RelocateImageObjects(delta); 86 RelocateImageMethods(delta); 87 } 88 89 void ImageHeader::RelocateImageObjects(off_t delta) { 90 image_begin_ += delta; 91 image_roots_ += delta; 92 } 93 94 void ImageHeader::RelocateImageMethods(off_t delta) { 95 for (size_t i = 0; i < kImageMethodsCount; ++i) { 96 image_methods_[i] += delta; 97 } 98 } 99 100 bool ImageHeader::IsValid() const { 101 if (memcmp(magic_, kImageMagic, sizeof(kImageMagic)) != 0) { 102 return false; 103 } 104 if (memcmp(version_, kImageVersion, sizeof(kImageVersion)) != 0) { 105 return false; 106 } 107 // Unsigned so wraparound is well defined. 108 if (image_begin_ >= image_begin_ + image_size_) { 109 return false; 110 } 111 if (oat_file_begin_ > oat_file_end_) { 112 return false; 113 } 114 if (oat_data_begin_ > oat_data_end_) { 115 return false; 116 } 117 if (oat_file_begin_ >= oat_data_begin_) { 118 return false; 119 } 120 if (!IsAligned<kPageSize>(patch_delta_)) { 121 return false; 122 } 123 return true; 124 } 125 126 const char* ImageHeader::GetMagic() const { 127 CHECK(IsValid()); 128 return reinterpret_cast<const char*>(magic_); 129 } 130 131 ArtMethod* ImageHeader::GetImageMethod(ImageMethod index) const { 132 CHECK_LT(static_cast<size_t>(index), kImageMethodsCount); 133 return reinterpret_cast<ArtMethod*>(image_methods_[index]); 134 } 135 136 void ImageHeader::SetImageMethod(ImageMethod index, ArtMethod* method) { 137 CHECK_LT(static_cast<size_t>(index), kImageMethodsCount); 138 image_methods_[index] = reinterpret_cast<uint64_t>(method); 139 } 140 141 const ImageSection& ImageHeader::GetImageSection(ImageSections index) const { 142 CHECK_LT(static_cast<size_t>(index), kSectionCount); 143 return sections_[index]; 144 } 145 146 std::ostream& operator<<(std::ostream& os, const ImageSection& section) { 147 return os << "size=" << section.Size() << " range=" << section.Offset() << "-" << section.End(); 148 } 149 150 void ImageHeader::VisitPackedArtFields(ArtFieldVisitor* visitor, uint8_t* base) const { 151 const ImageSection& fields = GetFieldsSection(); 152 for (size_t pos = 0; pos < fields.Size(); ) { 153 auto* array = reinterpret_cast<LengthPrefixedArray<ArtField>*>(base + fields.Offset() + pos); 154 for (size_t i = 0; i < array->size(); ++i) { 155 visitor->Visit(&array->At(i, sizeof(ArtField))); 156 } 157 pos += array->ComputeSize(array->size()); 158 } 159 } 160 161 void ImageHeader::VisitPackedArtMethods(ArtMethodVisitor* visitor, 162 uint8_t* base, 163 size_t pointer_size) const { 164 const size_t method_alignment = ArtMethod::Alignment(pointer_size); 165 const size_t method_size = ArtMethod::Size(pointer_size); 166 const ImageSection& methods = GetMethodsSection(); 167 for (size_t pos = 0; pos < methods.Size(); ) { 168 auto* array = reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(base + methods.Offset() + pos); 169 for (size_t i = 0; i < array->size(); ++i) { 170 visitor->Visit(&array->At(i, method_size, method_alignment)); 171 } 172 pos += array->ComputeSize(array->size(), method_size, method_alignment); 173 } 174 const ImageSection& runtime_methods = GetRuntimeMethodsSection(); 175 for (size_t pos = 0; pos < runtime_methods.Size(); ) { 176 auto* method = reinterpret_cast<ArtMethod*>(base + runtime_methods.Offset() + pos); 177 visitor->Visit(method); 178 pos += method_size; 179 } 180 } 181 182 } // namespace art 183