Home | History | Annotate | Download | only in runtime
      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