• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ImageHeader(uint32_t image_reservation_size,uint32_t component_count,uint32_t image_begin,uint32_t image_size,ImageSection * sections,uint32_t image_roots,uint32_t oat_checksum,uint32_t oat_file_begin,uint32_t oat_data_begin,uint32_t oat_data_end,uint32_t oat_file_end,uint32_t boot_image_begin,uint32_t boot_image_size,uint32_t pointer_size)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 
RelocateImage(int64_t delta)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 
RelocateImageObjects(int64_t delta)85 void ImageHeader::RelocateImageObjects(int64_t delta) {
86   image_begin_ += delta;
87   image_roots_ += delta;
88 }
89 
RelocateImageMethods(int64_t delta)90 void ImageHeader::RelocateImageMethods(int64_t delta) {
91   for (size_t i = 0; i < kImageMethodsCount; ++i) {
92     image_methods_[i] += delta;
93   }
94 }
95 
IsValid() const96 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 
GetMagic() const122 const char* ImageHeader::GetMagic() const {
123   CHECK(IsValid());
124   return reinterpret_cast<const char*>(magic_);
125 }
126 
GetImageMethod(ImageMethod index) const127 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 
operator <<(std::ostream & os,const ImageSection & section)132 std::ostream& operator<<(std::ostream& os, const ImageSection& section) {
133   return os << "size=" << section.Size() << " range=" << section.Offset() << "-" << section.End();
134 }
135 
VisitObjects(ObjectVisitor * visitor,uint8_t * base,PointerSize pointer_size) const136 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 
GetPointerSize() const149 PointerSize ImageHeader::GetPointerSize() const {
150   return ConvertToPointerSize(pointer_size_);
151 }
152 
Decompress(uint8_t * out_ptr,const uint8_t * in_ptr,std::string * error_msg) const153 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