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