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 <lz4.h> 20 #include <sstream> 21 22 #include "base/bit_utils.h" 23 #include "base/length_prefixed_array.h" 24 #include "base/utils.h" 25 #include "mirror/object-inl.h" 26 #include "mirror/object_array-inl.h" 27 #include "mirror/object_array.h" 28 29 namespace art { 30 31 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; 32 const uint8_t ImageHeader::kImageVersion[] = { '0', '7', '4', '\0' }; // CRC32UpdateBB intrinsic 33 34 ImageHeader::ImageHeader(uint32_t image_reservation_size, 35 uint32_t component_count, 36 uint32_t image_begin, 37 uint32_t image_size, 38 ImageSection* sections, 39 uint32_t image_roots, 40 uint32_t oat_checksum, 41 uint32_t oat_file_begin, 42 uint32_t oat_data_begin, 43 uint32_t oat_data_end, 44 uint32_t oat_file_end, 45 uint32_t boot_image_begin, 46 uint32_t boot_image_size, 47 uint32_t pointer_size) 48 : image_reservation_size_(image_reservation_size), 49 component_count_(component_count), 50 image_begin_(image_begin), 51 image_size_(image_size), 52 image_checksum_(0u), 53 oat_checksum_(oat_checksum), 54 oat_file_begin_(oat_file_begin), 55 oat_data_begin_(oat_data_begin), 56 oat_data_end_(oat_data_end), 57 oat_file_end_(oat_file_end), 58 boot_image_begin_(boot_image_begin), 59 boot_image_size_(boot_image_size), 60 image_roots_(image_roots), 61 pointer_size_(pointer_size) { 62 CHECK_EQ(image_begin, RoundUp(image_begin, kPageSize)); 63 CHECK_EQ(oat_file_begin, RoundUp(oat_file_begin, kPageSize)); 64 CHECK_EQ(oat_data_begin, RoundUp(oat_data_begin, kPageSize)); 65 CHECK_LT(image_roots, oat_file_begin); 66 CHECK_LE(oat_file_begin, oat_data_begin); 67 CHECK_LT(oat_data_begin, oat_data_end); 68 CHECK_LE(oat_data_end, oat_file_end); 69 CHECK(ValidPointerSize(pointer_size_)) << pointer_size_; 70 memcpy(magic_, kImageMagic, sizeof(kImageMagic)); 71 memcpy(version_, kImageVersion, sizeof(kImageVersion)); 72 std::copy_n(sections, kSectionCount, sections_); 73 } 74 75 void ImageHeader::RelocateImage(int64_t delta) { 76 CHECK_ALIGNED(delta, kPageSize) << " patch delta must be page aligned"; 77 oat_file_begin_ += delta; 78 oat_data_begin_ += delta; 79 oat_data_end_ += delta; 80 oat_file_end_ += delta; 81 RelocateImageObjects(delta); 82 RelocateImageMethods(delta); 83 } 84 85 void ImageHeader::RelocateImageObjects(int64_t delta) { 86 image_begin_ += delta; 87 image_roots_ += delta; 88 } 89 90 void ImageHeader::RelocateImageMethods(int64_t delta) { 91 for (size_t i = 0; i < kImageMethodsCount; ++i) { 92 image_methods_[i] += delta; 93 } 94 } 95 96 bool ImageHeader::IsValid() const { 97 if (memcmp(magic_, kImageMagic, sizeof(kImageMagic)) != 0) { 98 return false; 99 } 100 if (memcmp(version_, kImageVersion, sizeof(kImageVersion)) != 0) { 101 return false; 102 } 103 if (!IsAligned<kPageSize>(image_reservation_size_)) { 104 return false; 105 } 106 // Unsigned so wraparound is well defined. 107 if (image_begin_ >= image_begin_ + image_size_) { 108 return false; 109 } 110 if (oat_file_begin_ > oat_file_end_) { 111 return false; 112 } 113 if (oat_data_begin_ > oat_data_end_) { 114 return false; 115 } 116 if (oat_file_begin_ >= oat_data_begin_) { 117 return false; 118 } 119 return true; 120 } 121 122 const char* ImageHeader::GetMagic() const { 123 CHECK(IsValid()); 124 return reinterpret_cast<const char*>(magic_); 125 } 126 127 ArtMethod* ImageHeader::GetImageMethod(ImageMethod index) const { 128 CHECK_LT(static_cast<size_t>(index), kImageMethodsCount); 129 return reinterpret_cast<ArtMethod*>(image_methods_[index]); 130 } 131 132 std::ostream& operator<<(std::ostream& os, const ImageSection& section) { 133 return os << "size=" << section.Size() << " range=" << section.Offset() << "-" << section.End(); 134 } 135 136 void ImageHeader::VisitObjects(ObjectVisitor* visitor, 137 uint8_t* base, 138 PointerSize pointer_size) const { 139 DCHECK_EQ(pointer_size, GetPointerSize()); 140 const ImageSection& objects = GetObjectsSection(); 141 static const size_t kStartPos = RoundUp(sizeof(ImageHeader), kObjectAlignment); 142 for (size_t pos = kStartPos; pos < objects.Size(); ) { 143 mirror::Object* object = reinterpret_cast<mirror::Object*>(base + objects.Offset() + pos); 144 visitor->Visit(object); 145 pos += RoundUp(object->SizeOf(), kObjectAlignment); 146 } 147 } 148 149 PointerSize ImageHeader::GetPointerSize() const { 150 return ConvertToPointerSize(pointer_size_); 151 } 152 153 bool ImageHeader::Block::Decompress(uint8_t* out_ptr, 154 const uint8_t* in_ptr, 155 std::string* error_msg) const { 156 switch (storage_mode_) { 157 case kStorageModeUncompressed: { 158 CHECK_EQ(image_size_, data_size_); 159 memcpy(out_ptr + image_offset_, in_ptr + data_offset_, data_size_); 160 break; 161 } 162 case kStorageModeLZ4: 163 case kStorageModeLZ4HC: { 164 // LZ4HC and LZ4 have same internal format, both use LZ4_decompress. 165 const size_t decompressed_size = LZ4_decompress_safe( 166 reinterpret_cast<const char*>(in_ptr) + data_offset_, 167 reinterpret_cast<char*>(out_ptr) + image_offset_, 168 data_size_, 169 image_size_); 170 CHECK_EQ(decompressed_size, image_size_); 171 break; 172 } 173 default: { 174 if (error_msg != nullptr) { 175 *error_msg = (std::ostringstream() << "Invalid image format " << storage_mode_).str(); 176 } 177 return false; 178 } 179 } 180 return true; 181 } 182 183 } // namespace art 184