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