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 
     21 #include "android-base/stringprintf.h"
     22 
     23 #include "arch/instruction_set.h"
     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 const char OatHeader::kTrueValue[];
     33 constexpr const char OatHeader::kFalseValue[];
     34 
     35 static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
     36   size_t estimate = 0U;
     37   if (variable_data != nullptr) {
     38     SafeMap<std::string, std::string>::const_iterator it = variable_data->begin();
     39     SafeMap<std::string, std::string>::const_iterator end = variable_data->end();
     40     for ( ; it != end; ++it) {
     41       estimate += it->first.length() + 1;
     42       estimate += it->second.length() + 1;
     43     }
     44   }
     45   return sizeof(OatHeader) + estimate;
     46 }
     47 
     48 OatHeader* OatHeader::Create(InstructionSet instruction_set,
     49                              const InstructionSetFeatures* instruction_set_features,
     50                              uint32_t dex_file_count,
     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_file_count,
     62                                 variable_data);
     63 }
     64 
     65 OatHeader::OatHeader(InstructionSet instruction_set,
     66                      const InstructionSetFeatures* instruction_set_features,
     67                      uint32_t dex_file_count,
     68                      const SafeMap<std::string, std::string>* variable_data)
     69     : oat_checksum_(0u),
     70       instruction_set_(instruction_set),
     71       instruction_set_features_bitmap_(instruction_set_features->AsBitmap()),
     72       dex_file_count_(dex_file_count),
     73       oat_dex_files_offset_(0),
     74       executable_offset_(0),
     75       jni_dlsym_lookup_offset_(0),
     76       quick_generic_jni_trampoline_offset_(0),
     77       quick_imt_conflict_trampoline_offset_(0),
     78       quick_resolution_trampoline_offset_(0),
     79       quick_to_interpreter_bridge_offset_(0) {
     80   // Don't want asserts in header as they would be checked in each file that includes it. But the
     81   // fields are private, so we check inside a method.
     82   static_assert(sizeof(magic_) == sizeof(kOatMagic),
     83                 "Oat magic and magic_ have different lengths.");
     84   static_assert(sizeof(version_) == sizeof(kOatVersion),
     85                 "Oat version and version_ have different lengths.");
     86 
     87   magic_ = kOatMagic;
     88   version_ = kOatVersion;
     89 
     90   CHECK_NE(instruction_set, InstructionSet::kNone);
     91 
     92   // Flatten the map. Will also update variable_size_data_size_.
     93   Flatten(variable_data);
     94 }
     95 
     96 bool OatHeader::IsValid() const {
     97   if (magic_ != kOatMagic) {
     98     return false;
     99   }
    100   if (version_ != kOatVersion) {
    101     return false;
    102   }
    103   if (!IsAligned<kPageSize>(executable_offset_)) {
    104     return false;
    105   }
    106   if (!IsValidInstructionSet(instruction_set_)) {
    107     return false;
    108   }
    109   return true;
    110 }
    111 
    112 std::string OatHeader::GetValidationErrorMessage() const {
    113   if (magic_ != kOatMagic) {
    114     static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length");
    115     return StringPrintf("Invalid oat magic, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
    116                         kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
    117                         magic_[0], magic_[1], magic_[2], magic_[3]);
    118   }
    119   if (version_ != kOatVersion) {
    120     static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length");
    121     return StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
    122                         kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
    123                         version_[0], version_[1], version_[2], version_[3]);
    124   }
    125   if (!IsAligned<kPageSize>(executable_offset_)) {
    126     return "Executable offset not page-aligned.";
    127   }
    128   if (!IsValidInstructionSet(instruction_set_)) {
    129     return StringPrintf("Invalid instruction set, %d.", static_cast<int>(instruction_set_));
    130   }
    131   return "";
    132 }
    133 
    134 // Do not move this into the header.  The method must be compiled in the runtime library,
    135 // so that we can check that the compile-time oat version matches the version in the caller.
    136 void OatHeader::CheckOatVersion(std::array<uint8_t, 4> version) {
    137   constexpr std::array<uint8_t, 4> expected = kOatVersion;  // Runtime oat version.
    138   if (version != kOatVersion) {
    139     LOG(FATAL) << StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
    140                                expected[0], expected[1], expected[2], expected[3],
    141                                version[0], version[1], version[2], version[3]);
    142   }
    143 }
    144 
    145 const char* OatHeader::GetMagic() const {
    146   CHECK(IsValid());
    147   return reinterpret_cast<const char*>(magic_.data());
    148 }
    149 
    150 uint32_t OatHeader::GetChecksum() const {
    151   CHECK(IsValid());
    152   return oat_checksum_;
    153 }
    154 
    155 void OatHeader::SetChecksum(uint32_t oat_checksum) {
    156   oat_checksum_ = oat_checksum;
    157 }
    158 
    159 InstructionSet OatHeader::GetInstructionSet() const {
    160   CHECK(IsValid());
    161   return instruction_set_;
    162 }
    163 
    164 uint32_t OatHeader::GetInstructionSetFeaturesBitmap() const {
    165   CHECK(IsValid());
    166   return instruction_set_features_bitmap_;
    167 }
    168 
    169 uint32_t OatHeader::GetOatDexFilesOffset() const {
    170   DCHECK(IsValid());
    171   DCHECK_GT(oat_dex_files_offset_, sizeof(OatHeader));
    172   return oat_dex_files_offset_;
    173 }
    174 
    175 void OatHeader::SetOatDexFilesOffset(uint32_t oat_dex_files_offset) {
    176   DCHECK_GT(oat_dex_files_offset, sizeof(OatHeader));
    177   DCHECK(IsValid());
    178   DCHECK_EQ(oat_dex_files_offset_, 0u);
    179 
    180   oat_dex_files_offset_ = oat_dex_files_offset;
    181 }
    182 
    183 uint32_t OatHeader::GetExecutableOffset() const {
    184   DCHECK(IsValid());
    185   DCHECK_ALIGNED(executable_offset_, kPageSize);
    186   CHECK_GT(executable_offset_, sizeof(OatHeader));
    187   return executable_offset_;
    188 }
    189 
    190 void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
    191   DCHECK_ALIGNED(executable_offset, kPageSize);
    192   CHECK_GT(executable_offset, sizeof(OatHeader));
    193   DCHECK(IsValid());
    194   DCHECK_EQ(executable_offset_, 0U);
    195 
    196   executable_offset_ = executable_offset;
    197 }
    198 
    199 static const void* GetTrampoline(const OatHeader& header, uint32_t offset) {
    200   return (offset != 0u) ? reinterpret_cast<const uint8_t*>(&header) + offset : nullptr;
    201 }
    202 
    203 const void* OatHeader::GetJniDlsymLookup() const {
    204   return GetTrampoline(*this, GetJniDlsymLookupOffset());
    205 }
    206 
    207 uint32_t OatHeader::GetJniDlsymLookupOffset() const {
    208   DCHECK(IsValid());
    209   return jni_dlsym_lookup_offset_;
    210 }
    211 
    212 void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
    213   DCHECK(IsValid());
    214   DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
    215 
    216   jni_dlsym_lookup_offset_ = offset;
    217 }
    218 
    219 const void* OatHeader::GetQuickGenericJniTrampoline() const {
    220   return GetTrampoline(*this, GetQuickGenericJniTrampolineOffset());
    221 }
    222 
    223 uint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
    224   DCHECK(IsValid());
    225   CHECK_GE(quick_generic_jni_trampoline_offset_, jni_dlsym_lookup_offset_);
    226   return quick_generic_jni_trampoline_offset_;
    227 }
    228 
    229 void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
    230   CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
    231   DCHECK(IsValid());
    232   DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
    233 
    234   quick_generic_jni_trampoline_offset_ = offset;
    235 }
    236 
    237 const void* OatHeader::GetQuickImtConflictTrampoline() const {
    238   return GetTrampoline(*this, GetQuickImtConflictTrampolineOffset());
    239 }
    240 
    241 uint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
    242   DCHECK(IsValid());
    243   CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
    244   return quick_imt_conflict_trampoline_offset_;
    245 }
    246 
    247 void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
    248   CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
    249   DCHECK(IsValid());
    250   DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
    251 
    252   quick_imt_conflict_trampoline_offset_ = offset;
    253 }
    254 
    255 const void* OatHeader::GetQuickResolutionTrampoline() const {
    256   return GetTrampoline(*this, GetQuickResolutionTrampolineOffset());
    257 }
    258 
    259 uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
    260   DCHECK(IsValid());
    261   CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
    262   return quick_resolution_trampoline_offset_;
    263 }
    264 
    265 void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
    266   CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
    267   DCHECK(IsValid());
    268   DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
    269 
    270   quick_resolution_trampoline_offset_ = offset;
    271 }
    272 
    273 const void* OatHeader::GetQuickToInterpreterBridge() const {
    274   return GetTrampoline(*this, GetQuickToInterpreterBridgeOffset());
    275 }
    276 
    277 uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
    278   DCHECK(IsValid());
    279   CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
    280   return quick_to_interpreter_bridge_offset_;
    281 }
    282 
    283 void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
    284   CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
    285   DCHECK(IsValid());
    286   DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
    287 
    288   quick_to_interpreter_bridge_offset_ = offset;
    289 }
    290 
    291 uint32_t OatHeader::GetKeyValueStoreSize() const {
    292   CHECK(IsValid());
    293   return key_value_store_size_;
    294 }
    295 
    296 const uint8_t* OatHeader::GetKeyValueStore() const {
    297   CHECK(IsValid());
    298   return key_value_store_;
    299 }
    300 
    301 // Advance start until it is either end or \0.
    302 static const char* ParseString(const char* start, const char* end) {
    303   while (start < end && *start != 0) {
    304     start++;
    305   }
    306   return start;
    307 }
    308 
    309 const char* OatHeader::GetStoreValueByKey(const char* key) const {
    310   const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
    311   const char* end = ptr + key_value_store_size_;
    312 
    313   while (ptr < end) {
    314     // Scan for a closing zero.
    315     const char* str_end = ParseString(ptr, end);
    316     if (str_end < end) {
    317       if (strcmp(key, ptr) == 0) {
    318         // Same as key. Check if value is OK.
    319         if (ParseString(str_end + 1, end) < end) {
    320           return str_end + 1;
    321         }
    322       } else {
    323         // Different from key. Advance over the value.
    324         ptr = ParseString(str_end + 1, end) + 1;
    325       }
    326     } else {
    327       break;
    328     }
    329   }
    330   // Not found.
    331   return nullptr;
    332 }
    333 
    334 bool OatHeader::GetStoreKeyValuePairByIndex(size_t index, const char** key,
    335                                             const char** value) const {
    336   const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
    337   const char* end = ptr + key_value_store_size_;
    338   ssize_t counter = static_cast<ssize_t>(index);
    339 
    340   while (ptr < end && counter >= 0) {
    341     // Scan for a closing zero.
    342     const char* str_end = ParseString(ptr, end);
    343     if (str_end < end) {
    344       const char* maybe_key = ptr;
    345       ptr = ParseString(str_end + 1, end) + 1;
    346       if (ptr <= end) {
    347         if (counter == 0) {
    348           *key = maybe_key;
    349           *value = str_end + 1;
    350           return true;
    351         } else {
    352           counter--;
    353         }
    354       } else {
    355         return false;
    356       }
    357     } else {
    358       break;
    359     }
    360   }
    361   // Not found.
    362   return false;
    363 }
    364 
    365 size_t OatHeader::GetHeaderSize() const {
    366   return sizeof(OatHeader) + key_value_store_size_;
    367 }
    368 
    369 bool OatHeader::IsDebuggable() const {
    370   return IsKeyEnabled(OatHeader::kDebuggableKey);
    371 }
    372 
    373 bool OatHeader::IsConcurrentCopying() const {
    374   return IsKeyEnabled(OatHeader::kConcurrentCopying);
    375 }
    376 
    377 bool OatHeader::IsNativeDebuggable() const {
    378   return IsKeyEnabled(OatHeader::kNativeDebuggableKey);
    379 }
    380 
    381 CompilerFilter::Filter OatHeader::GetCompilerFilter() const {
    382   CompilerFilter::Filter filter;
    383   const char* key_value = GetStoreValueByKey(kCompilerFilter);
    384   CHECK(key_value != nullptr) << "compiler-filter not found in oat header";
    385   CHECK(CompilerFilter::ParseCompilerFilter(key_value, &filter))
    386       << "Invalid compiler-filter in oat header: " << key_value;
    387   return filter;
    388 }
    389 
    390 bool OatHeader::KeyHasValue(const char* key, const char* value, size_t value_size) const {
    391   const char* key_value = GetStoreValueByKey(key);
    392   return (key_value != nullptr && strncmp(key_value, value, value_size) == 0);
    393 }
    394 
    395 bool OatHeader::IsKeyEnabled(const char* key) const {
    396   return KeyHasValue(key, kTrueValue, sizeof(kTrueValue));
    397 }
    398 
    399 void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
    400   char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
    401   if (key_value_store != nullptr) {
    402     SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
    403     SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
    404     for ( ; it != end; ++it) {
    405       strlcpy(data_ptr, it->first.c_str(), it->first.length() + 1);
    406       data_ptr += it->first.length() + 1;
    407       strlcpy(data_ptr, it->second.c_str(), it->second.length() + 1);
    408       data_ptr += it->second.length() + 1;
    409     }
    410   }
    411   key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
    412 }
    413 
    414 OatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) {
    415 }
    416 
    417 OatMethodOffsets::~OatMethodOffsets() {}
    418 
    419 }  // namespace art
    420