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