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 <string.h>
     21 #include <zlib.h>
     22 
     23 namespace art {
     24 
     25 const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
     26 const uint8_t OatHeader::kOatVersion[] = { '0', '4', '5', '\0' };
     27 
     28 static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
     29   size_t estimate = 0U;
     30   if (variable_data != nullptr) {
     31     SafeMap<std::string, std::string>::const_iterator it = variable_data->begin();
     32     SafeMap<std::string, std::string>::const_iterator end = variable_data->end();
     33     for ( ; it != end; ++it) {
     34       estimate += it->first.length() + 1;
     35       estimate += it->second.length() + 1;
     36     }
     37   }
     38   return sizeof(OatHeader) + estimate;
     39 }
     40 
     41 OatHeader* OatHeader::Create(InstructionSet instruction_set,
     42                              const InstructionSetFeatures& instruction_set_features,
     43                              const std::vector<const DexFile*>* dex_files,
     44                              uint32_t image_file_location_oat_checksum,
     45                              uint32_t image_file_location_oat_data_begin,
     46                              const SafeMap<std::string, std::string>* variable_data) {
     47   // Estimate size of optional data.
     48   size_t needed_size = ComputeOatHeaderSize(variable_data);
     49 
     50   // Reserve enough memory.
     51   void* memory = operator new (needed_size);
     52 
     53   // Create the OatHeader in-place.
     54   return new (memory) OatHeader(instruction_set,
     55                                 instruction_set_features,
     56                                 dex_files,
     57                                 image_file_location_oat_checksum,
     58                                 image_file_location_oat_data_begin,
     59                                 variable_data);
     60 }
     61 
     62 OatHeader::OatHeader(InstructionSet instruction_set,
     63                      const InstructionSetFeatures& instruction_set_features,
     64                      const std::vector<const DexFile*>* dex_files,
     65                      uint32_t image_file_location_oat_checksum,
     66                      uint32_t image_file_location_oat_data_begin,
     67                      const SafeMap<std::string, std::string>* variable_data) {
     68   memcpy(magic_, kOatMagic, sizeof(kOatMagic));
     69   memcpy(version_, kOatVersion, sizeof(kOatVersion));
     70   executable_offset_ = 0;
     71   image_patch_delta_ = 0;
     72 
     73   adler32_checksum_ = adler32(0L, Z_NULL, 0);
     74 
     75   CHECK_NE(instruction_set, kNone);
     76   instruction_set_ = instruction_set;
     77   UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
     78 
     79   instruction_set_features_ = instruction_set_features;
     80   UpdateChecksum(&instruction_set_features_, sizeof(instruction_set_features_));
     81 
     82   dex_file_count_ = dex_files->size();
     83   UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
     84 
     85   image_file_location_oat_checksum_ = image_file_location_oat_checksum;
     86   UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
     87 
     88   CHECK(IsAligned<kPageSize>(image_file_location_oat_data_begin));
     89   image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
     90   UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
     91 
     92   // Flatten the map. Will also update variable_size_data_size_.
     93   Flatten(variable_data);
     94 
     95   // Update checksum for variable data size.
     96   UpdateChecksum(&key_value_store_size_, sizeof(key_value_store_size_));
     97 
     98   // Update for data, if existing.
     99   if (key_value_store_size_ > 0U) {
    100     UpdateChecksum(&key_value_store_, key_value_store_size_);
    101   }
    102 
    103   interpreter_to_interpreter_bridge_offset_ = 0;
    104   interpreter_to_compiled_code_bridge_offset_ = 0;
    105   jni_dlsym_lookup_offset_ = 0;
    106   portable_imt_conflict_trampoline_offset_ = 0;
    107   portable_resolution_trampoline_offset_ = 0;
    108   portable_to_interpreter_bridge_offset_ = 0;
    109   quick_generic_jni_trampoline_offset_ = 0;
    110   quick_imt_conflict_trampoline_offset_ = 0;
    111   quick_resolution_trampoline_offset_ = 0;
    112   quick_to_interpreter_bridge_offset_ = 0;
    113 }
    114 
    115 bool OatHeader::IsValid() const {
    116   if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
    117     return false;
    118   }
    119   if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
    120     return false;
    121   }
    122   if (!IsAligned<kPageSize>(executable_offset_)) {
    123     return false;
    124   }
    125   if (!IsAligned<kPageSize>(image_patch_delta_)) {
    126     return false;
    127   }
    128   return true;
    129 }
    130 
    131 const char* OatHeader::GetMagic() const {
    132   CHECK(IsValid());
    133   return reinterpret_cast<const char*>(magic_);
    134 }
    135 
    136 uint32_t OatHeader::GetChecksum() const {
    137   CHECK(IsValid());
    138   return adler32_checksum_;
    139 }
    140 
    141 void OatHeader::UpdateChecksum(const void* data, size_t length) {
    142   DCHECK(IsValid());
    143   const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
    144   adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
    145 }
    146 
    147 InstructionSet OatHeader::GetInstructionSet() const {
    148   CHECK(IsValid());
    149   return instruction_set_;
    150 }
    151 
    152 const InstructionSetFeatures& OatHeader::GetInstructionSetFeatures() const {
    153   CHECK(IsValid());
    154   return instruction_set_features_;
    155 }
    156 
    157 uint32_t OatHeader::GetExecutableOffset() const {
    158   DCHECK(IsValid());
    159   DCHECK_ALIGNED(executable_offset_, kPageSize);
    160   CHECK_GT(executable_offset_, sizeof(OatHeader));
    161   return executable_offset_;
    162 }
    163 
    164 void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
    165   DCHECK_ALIGNED(executable_offset, kPageSize);
    166   CHECK_GT(executable_offset, sizeof(OatHeader));
    167   DCHECK(IsValid());
    168   DCHECK_EQ(executable_offset_, 0U);
    169 
    170   executable_offset_ = executable_offset;
    171   UpdateChecksum(&executable_offset_, sizeof(executable_offset));
    172 }
    173 
    174 const void* OatHeader::GetInterpreterToInterpreterBridge() const {
    175   return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
    176 }
    177 
    178 uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
    179   DCHECK(IsValid());
    180   CHECK(interpreter_to_interpreter_bridge_offset_ == 0 ||
    181         interpreter_to_interpreter_bridge_offset_ >= executable_offset_);
    182   return interpreter_to_interpreter_bridge_offset_;
    183 }
    184 
    185 void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
    186   CHECK(offset == 0 || offset >= executable_offset_);
    187   DCHECK(IsValid());
    188   DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
    189 
    190   interpreter_to_interpreter_bridge_offset_ = offset;
    191   UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset));
    192 }
    193 
    194 const void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
    195   return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
    196 }
    197 
    198 uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
    199   DCHECK(IsValid());
    200   CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
    201   return interpreter_to_compiled_code_bridge_offset_;
    202 }
    203 
    204 void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
    205   CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
    206   DCHECK(IsValid());
    207   DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
    208 
    209   interpreter_to_compiled_code_bridge_offset_ = offset;
    210   UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset));
    211 }
    212 
    213 const void* OatHeader::GetJniDlsymLookup() const {
    214   return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
    215 }
    216 
    217 uint32_t OatHeader::GetJniDlsymLookupOffset() const {
    218   DCHECK(IsValid());
    219   CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
    220   return jni_dlsym_lookup_offset_;
    221 }
    222 
    223 void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
    224   CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
    225   DCHECK(IsValid());
    226   DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
    227 
    228   jni_dlsym_lookup_offset_ = offset;
    229   UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset));
    230 }
    231 
    232 const void* OatHeader::GetPortableImtConflictTrampoline() const {
    233   return reinterpret_cast<const uint8_t*>(this) + GetPortableImtConflictTrampolineOffset();
    234 }
    235 
    236 uint32_t OatHeader::GetPortableImtConflictTrampolineOffset() const {
    237   DCHECK(IsValid());
    238   CHECK_GE(portable_imt_conflict_trampoline_offset_, jni_dlsym_lookup_offset_);
    239   return portable_imt_conflict_trampoline_offset_;
    240 }
    241 
    242 void OatHeader::SetPortableImtConflictTrampolineOffset(uint32_t offset) {
    243   CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
    244   DCHECK(IsValid());
    245   DCHECK_EQ(portable_imt_conflict_trampoline_offset_, 0U) << offset;
    246 
    247   portable_imt_conflict_trampoline_offset_ = offset;
    248   UpdateChecksum(&portable_imt_conflict_trampoline_offset_, sizeof(offset));
    249 }
    250 
    251 const void* OatHeader::GetPortableResolutionTrampoline() const {
    252   return reinterpret_cast<const uint8_t*>(this) + GetPortableResolutionTrampolineOffset();
    253 }
    254 
    255 uint32_t OatHeader::GetPortableResolutionTrampolineOffset() const {
    256   DCHECK(IsValid());
    257   CHECK_GE(portable_resolution_trampoline_offset_, portable_imt_conflict_trampoline_offset_);
    258   return portable_resolution_trampoline_offset_;
    259 }
    260 
    261 void OatHeader::SetPortableResolutionTrampolineOffset(uint32_t offset) {
    262   CHECK(offset == 0 || offset >= portable_imt_conflict_trampoline_offset_);
    263   DCHECK(IsValid());
    264   DCHECK_EQ(portable_resolution_trampoline_offset_, 0U) << offset;
    265 
    266   portable_resolution_trampoline_offset_ = offset;
    267   UpdateChecksum(&portable_resolution_trampoline_offset_, sizeof(offset));
    268 }
    269 
    270 const void* OatHeader::GetPortableToInterpreterBridge() const {
    271   return reinterpret_cast<const uint8_t*>(this) + GetPortableToInterpreterBridgeOffset();
    272 }
    273 
    274 uint32_t OatHeader::GetPortableToInterpreterBridgeOffset() const {
    275   DCHECK(IsValid());
    276   CHECK_GE(portable_to_interpreter_bridge_offset_, portable_resolution_trampoline_offset_);
    277   return portable_to_interpreter_bridge_offset_;
    278 }
    279 
    280 void OatHeader::SetPortableToInterpreterBridgeOffset(uint32_t offset) {
    281   CHECK(offset == 0 || offset >= portable_resolution_trampoline_offset_);
    282   DCHECK(IsValid());
    283   DCHECK_EQ(portable_to_interpreter_bridge_offset_, 0U) << offset;
    284 
    285   portable_to_interpreter_bridge_offset_ = offset;
    286   UpdateChecksum(&portable_to_interpreter_bridge_offset_, sizeof(offset));
    287 }
    288 
    289 const void* OatHeader::GetQuickGenericJniTrampoline() const {
    290   return reinterpret_cast<const uint8_t*>(this) + GetQuickGenericJniTrampolineOffset();
    291 }
    292 
    293 uint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
    294   DCHECK(IsValid());
    295   CHECK_GE(quick_generic_jni_trampoline_offset_, portable_to_interpreter_bridge_offset_);
    296   return quick_generic_jni_trampoline_offset_;
    297 }
    298 
    299 void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
    300   CHECK(offset == 0 || offset >= portable_to_interpreter_bridge_offset_);
    301   DCHECK(IsValid());
    302   DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
    303 
    304   quick_generic_jni_trampoline_offset_ = offset;
    305   UpdateChecksum(&quick_generic_jni_trampoline_offset_, sizeof(offset));
    306 }
    307 
    308 const void* OatHeader::GetQuickImtConflictTrampoline() const {
    309   return reinterpret_cast<const uint8_t*>(this) + GetQuickImtConflictTrampolineOffset();
    310 }
    311 
    312 uint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
    313   DCHECK(IsValid());
    314   CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
    315   return quick_imt_conflict_trampoline_offset_;
    316 }
    317 
    318 void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
    319   CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
    320   DCHECK(IsValid());
    321   DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
    322 
    323   quick_imt_conflict_trampoline_offset_ = offset;
    324   UpdateChecksum(&quick_imt_conflict_trampoline_offset_, sizeof(offset));
    325 }
    326 
    327 const void* OatHeader::GetQuickResolutionTrampoline() const {
    328   return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
    329 }
    330 
    331 uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
    332   DCHECK(IsValid());
    333   CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
    334   return quick_resolution_trampoline_offset_;
    335 }
    336 
    337 void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
    338   CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
    339   DCHECK(IsValid());
    340   DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
    341 
    342   quick_resolution_trampoline_offset_ = offset;
    343   UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset));
    344 }
    345 
    346 const void* OatHeader::GetQuickToInterpreterBridge() const {
    347   return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
    348 }
    349 
    350 uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
    351   DCHECK(IsValid());
    352   CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
    353   return quick_to_interpreter_bridge_offset_;
    354 }
    355 
    356 void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
    357   CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
    358   DCHECK(IsValid());
    359   DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
    360 
    361   quick_to_interpreter_bridge_offset_ = offset;
    362   UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset));
    363 }
    364 
    365 int32_t OatHeader::GetImagePatchDelta() const {
    366   CHECK(IsValid());
    367   return image_patch_delta_;
    368 }
    369 
    370 void OatHeader::RelocateOat(off_t delta) {
    371   CHECK(IsValid());
    372   CHECK_ALIGNED(delta, kPageSize);
    373   image_patch_delta_ += delta;
    374   if (image_file_location_oat_data_begin_ != 0) {
    375     image_file_location_oat_data_begin_ += delta;
    376   }
    377 }
    378 
    379 void OatHeader::SetImagePatchDelta(int32_t off) {
    380   CHECK(IsValid());
    381   CHECK_ALIGNED(off, kPageSize);
    382   image_patch_delta_ = off;
    383 }
    384 
    385 uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
    386   CHECK(IsValid());
    387   return image_file_location_oat_checksum_;
    388 }
    389 
    390 uint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
    391   CHECK(IsValid());
    392   return image_file_location_oat_data_begin_;
    393 }
    394 
    395 uint32_t OatHeader::GetKeyValueStoreSize() const {
    396   CHECK(IsValid());
    397   return key_value_store_size_;
    398 }
    399 
    400 const uint8_t* OatHeader::GetKeyValueStore() const {
    401   CHECK(IsValid());
    402   return key_value_store_;
    403 }
    404 
    405 // Advance start until it is either end or \0.
    406 static const char* ParseString(const char* start, const char* end) {
    407   while (start < end && *start != 0) {
    408     start++;
    409   }
    410   return start;
    411 }
    412 
    413 const char* OatHeader::GetStoreValueByKey(const char* key) const {
    414   const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
    415   const char* end = ptr + key_value_store_size_;
    416 
    417   while (ptr < end) {
    418     // Scan for a closing zero.
    419     const char* str_end = ParseString(ptr, end);
    420     if (str_end < end) {
    421       if (strcmp(key, ptr) == 0) {
    422         // Same as key. Check if value is OK.
    423         if (ParseString(str_end + 1, end) < end) {
    424           return str_end + 1;
    425         }
    426       } else {
    427         // Different from key. Advance over the value.
    428         ptr = ParseString(str_end + 1, end) + 1;
    429       }
    430     } else {
    431       break;
    432     }
    433   }
    434   // Not found.
    435   return nullptr;
    436 }
    437 
    438 bool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
    439                                             const char** value) const {
    440   const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
    441   const char* end = ptr + key_value_store_size_;
    442   ssize_t counter = static_cast<ssize_t>(index);
    443 
    444   while (ptr < end && counter >= 0) {
    445     // Scan for a closing zero.
    446     const char* str_end = ParseString(ptr, end);
    447     if (str_end < end) {
    448       const char* maybe_key = ptr;
    449       ptr = ParseString(str_end + 1, end) + 1;
    450       if (ptr <= end) {
    451         if (counter == 0) {
    452           *key = maybe_key;
    453           *value = str_end + 1;
    454           return true;
    455         } else {
    456           counter--;
    457         }
    458       } else {
    459         return false;
    460       }
    461     } else {
    462       break;
    463     }
    464   }
    465   // Not found.
    466   return false;
    467 }
    468 
    469 size_t OatHeader::GetHeaderSize() const {
    470   return sizeof(OatHeader) + key_value_store_size_;
    471 }
    472 
    473 bool OatHeader::IsPic() const {
    474   const char* pic_string = GetStoreValueByKey(OatHeader::kPicKey);
    475   static const char kTrue[] = "true";
    476   return (pic_string != nullptr && strncmp(pic_string, kTrue, sizeof(kTrue)) == 0);
    477 }
    478 
    479 void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
    480   char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
    481   if (key_value_store != nullptr) {
    482     SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
    483     SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
    484     for ( ; it != end; ++it) {
    485       strcpy(data_ptr, it->first.c_str());
    486       data_ptr += it->first.length() + 1;
    487       strcpy(data_ptr, it->second.c_str());
    488       data_ptr += it->second.length() + 1;
    489     }
    490   }
    491   key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
    492 }
    493 
    494 OatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) {
    495 }
    496 
    497 OatMethodOffsets::~OatMethodOffsets() {}
    498 
    499 OatQuickMethodHeader::OatQuickMethodHeader(
    500     uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t gc_map_offset,
    501     uint32_t frame_size_in_bytes, uint32_t core_spill_mask, uint32_t fp_spill_mask,
    502     uint32_t code_size)
    503     : mapping_table_offset_(mapping_table_offset), vmap_table_offset_(vmap_table_offset),
    504       gc_map_offset_(gc_map_offset),
    505       frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask), code_size_(code_size) {
    506 }
    507 
    508 OatQuickMethodHeader::~OatQuickMethodHeader() {}
    509 
    510 }  // namespace art
    511