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