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 "oat.h"
     18 #include "utils.h"
     19 
     20 #include <zlib.h>
     21 
     22 namespace art {
     23 
     24 const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
     25 const uint8_t OatHeader::kOatVersion[] = { '0', '0', '7', '\0' };
     26 
     27 OatHeader::OatHeader() {
     28   memset(this, 0, sizeof(*this));
     29 }
     30 
     31 OatHeader::OatHeader(InstructionSet instruction_set,
     32                      const std::vector<const DexFile*>* dex_files,
     33                      uint32_t image_file_location_oat_checksum,
     34                      uint32_t image_file_location_oat_data_begin,
     35                      const std::string& image_file_location) {
     36   memcpy(magic_, kOatMagic, sizeof(kOatMagic));
     37   memcpy(version_, kOatVersion, sizeof(kOatVersion));
     38 
     39   adler32_checksum_ = adler32(0L, Z_NULL, 0);
     40 
     41   CHECK_NE(instruction_set, kNone);
     42   instruction_set_ = instruction_set;
     43   UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
     44 
     45   dex_file_count_ = dex_files->size();
     46   UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
     47 
     48   image_file_location_oat_checksum_ = image_file_location_oat_checksum;
     49   UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
     50 
     51   CHECK(IsAligned<kPageSize>(image_file_location_oat_data_begin));
     52   image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
     53   UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
     54 
     55   image_file_location_size_ = image_file_location.size();
     56   UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_));
     57   UpdateChecksum(image_file_location.data(), image_file_location_size_);
     58 
     59   executable_offset_ = 0;
     60   interpreter_to_interpreter_bridge_offset_ = 0;
     61   interpreter_to_compiled_code_bridge_offset_ = 0;
     62   jni_dlsym_lookup_offset_ = 0;
     63   portable_resolution_trampoline_offset_ = 0;
     64   portable_to_interpreter_bridge_offset_ = 0;
     65   quick_resolution_trampoline_offset_ = 0;
     66   quick_to_interpreter_bridge_offset_ = 0;
     67 }
     68 
     69 bool OatHeader::IsValid() const {
     70   if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
     71     return false;
     72   }
     73   if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
     74     return false;
     75   }
     76   return true;
     77 }
     78 
     79 const char* OatHeader::GetMagic() const {
     80   CHECK(IsValid());
     81   return reinterpret_cast<const char*>(magic_);
     82 }
     83 
     84 uint32_t OatHeader::GetChecksum() const {
     85   CHECK(IsValid());
     86   return adler32_checksum_;
     87 }
     88 
     89 void OatHeader::UpdateChecksum(const void* data, size_t length) {
     90   DCHECK(IsValid());
     91   const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
     92   adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
     93 }
     94 
     95 InstructionSet OatHeader::GetInstructionSet() const {
     96   CHECK(IsValid());
     97   return instruction_set_;
     98 }
     99 
    100 uint32_t OatHeader::GetExecutableOffset() const {
    101   DCHECK(IsValid());
    102   DCHECK_ALIGNED(executable_offset_, kPageSize);
    103   CHECK_GT(executable_offset_, sizeof(OatHeader));
    104   return executable_offset_;
    105 }
    106 
    107 void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
    108   DCHECK_ALIGNED(executable_offset, kPageSize);
    109   CHECK_GT(executable_offset, sizeof(OatHeader));
    110   DCHECK(IsValid());
    111   DCHECK_EQ(executable_offset_, 0U);
    112 
    113   executable_offset_ = executable_offset;
    114   UpdateChecksum(&executable_offset_, sizeof(executable_offset));
    115 }
    116 
    117 const void* OatHeader::GetInterpreterToInterpreterBridge() const {
    118   return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
    119 }
    120 
    121 uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
    122   DCHECK(IsValid());
    123   CHECK_GE(interpreter_to_interpreter_bridge_offset_, executable_offset_);
    124   return interpreter_to_interpreter_bridge_offset_;
    125 }
    126 
    127 void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
    128   CHECK(offset == 0 || offset >= executable_offset_);
    129   DCHECK(IsValid());
    130   DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
    131 
    132   interpreter_to_interpreter_bridge_offset_ = offset;
    133   UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset));
    134 }
    135 
    136 const void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
    137   return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
    138 }
    139 
    140 uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
    141   DCHECK(IsValid());
    142   CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
    143   return interpreter_to_compiled_code_bridge_offset_;
    144 }
    145 
    146 void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
    147   CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
    148   DCHECK(IsValid());
    149   DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
    150 
    151   interpreter_to_compiled_code_bridge_offset_ = offset;
    152   UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset));
    153 }
    154 
    155 const void* OatHeader::GetJniDlsymLookup() const {
    156   return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
    157 }
    158 
    159 uint32_t OatHeader::GetJniDlsymLookupOffset() const {
    160   DCHECK(IsValid());
    161   CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
    162   return jni_dlsym_lookup_offset_;
    163 }
    164 
    165 void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
    166   CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
    167   DCHECK(IsValid());
    168   DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
    169 
    170   jni_dlsym_lookup_offset_ = offset;
    171   UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset));
    172 }
    173 
    174 const void* OatHeader::GetPortableResolutionTrampoline() const {
    175   return reinterpret_cast<const uint8_t*>(this) + GetPortableResolutionTrampolineOffset();
    176 }
    177 
    178 uint32_t OatHeader::GetPortableResolutionTrampolineOffset() const {
    179   DCHECK(IsValid());
    180   CHECK_GE(portable_resolution_trampoline_offset_, jni_dlsym_lookup_offset_);
    181   return portable_resolution_trampoline_offset_;
    182 }
    183 
    184 void OatHeader::SetPortableResolutionTrampolineOffset(uint32_t offset) {
    185   CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
    186   DCHECK(IsValid());
    187   DCHECK_EQ(portable_resolution_trampoline_offset_, 0U) << offset;
    188 
    189   portable_resolution_trampoline_offset_ = offset;
    190   UpdateChecksum(&portable_resolution_trampoline_offset_, sizeof(offset));
    191 }
    192 
    193 const void* OatHeader::GetPortableToInterpreterBridge() const {
    194   return reinterpret_cast<const uint8_t*>(this) + GetPortableToInterpreterBridgeOffset();
    195 }
    196 
    197 uint32_t OatHeader::GetPortableToInterpreterBridgeOffset() const {
    198   DCHECK(IsValid());
    199   CHECK_GE(portable_to_interpreter_bridge_offset_, portable_resolution_trampoline_offset_);
    200   return portable_to_interpreter_bridge_offset_;
    201 }
    202 
    203 void OatHeader::SetPortableToInterpreterBridgeOffset(uint32_t offset) {
    204   CHECK(offset == 0 || offset >= portable_resolution_trampoline_offset_);
    205   DCHECK(IsValid());
    206   DCHECK_EQ(portable_to_interpreter_bridge_offset_, 0U) << offset;
    207 
    208   portable_to_interpreter_bridge_offset_ = offset;
    209   UpdateChecksum(&portable_to_interpreter_bridge_offset_, sizeof(offset));
    210 }
    211 
    212 const void* OatHeader::GetQuickResolutionTrampoline() const {
    213   return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
    214 }
    215 
    216 uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
    217   DCHECK(IsValid());
    218   CHECK_GE(quick_resolution_trampoline_offset_, portable_to_interpreter_bridge_offset_);
    219   return quick_resolution_trampoline_offset_;
    220 }
    221 
    222 void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
    223   CHECK(offset == 0 || offset >= portable_to_interpreter_bridge_offset_);
    224   DCHECK(IsValid());
    225   DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
    226 
    227   quick_resolution_trampoline_offset_ = offset;
    228   UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset));
    229 }
    230 
    231 const void* OatHeader::GetQuickToInterpreterBridge() const {
    232   return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
    233 }
    234 
    235 uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
    236   DCHECK(IsValid());
    237   CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
    238   return quick_to_interpreter_bridge_offset_;
    239 }
    240 
    241 void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
    242   CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
    243   DCHECK(IsValid());
    244   DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
    245 
    246   quick_to_interpreter_bridge_offset_ = offset;
    247   UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset));
    248 }
    249 
    250 uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
    251   CHECK(IsValid());
    252   return image_file_location_oat_checksum_;
    253 }
    254 
    255 uint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
    256   CHECK(IsValid());
    257   return image_file_location_oat_data_begin_;
    258 }
    259 
    260 uint32_t OatHeader::GetImageFileLocationSize() const {
    261   CHECK(IsValid());
    262   return image_file_location_size_;
    263 }
    264 
    265 const uint8_t* OatHeader::GetImageFileLocationData() const {
    266   CHECK(IsValid());
    267   return image_file_location_data_;
    268 }
    269 
    270 std::string OatHeader::GetImageFileLocation() const {
    271   CHECK(IsValid());
    272   return std::string(reinterpret_cast<const char*>(GetImageFileLocationData()),
    273                      GetImageFileLocationSize());
    274 }
    275 
    276 OatMethodOffsets::OatMethodOffsets()
    277   : code_offset_(0),
    278     frame_size_in_bytes_(0),
    279     core_spill_mask_(0),
    280     fp_spill_mask_(0),
    281     mapping_table_offset_(0),
    282     vmap_table_offset_(0),
    283     gc_map_offset_(0)
    284 {}
    285 
    286 OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
    287                                    uint32_t frame_size_in_bytes,
    288                                    uint32_t core_spill_mask,
    289                                    uint32_t fp_spill_mask,
    290                                    uint32_t mapping_table_offset,
    291                                    uint32_t vmap_table_offset,
    292                                    uint32_t gc_map_offset
    293                                    )
    294   : code_offset_(code_offset),
    295     frame_size_in_bytes_(frame_size_in_bytes),
    296     core_spill_mask_(core_spill_mask),
    297     fp_spill_mask_(fp_spill_mask),
    298     mapping_table_offset_(mapping_table_offset),
    299     vmap_table_offset_(vmap_table_offset),
    300     gc_map_offset_(gc_map_offset)
    301 {}
    302 
    303 OatMethodOffsets::~OatMethodOffsets() {}
    304 
    305 }  // namespace art
    306