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 #ifndef ART_RUNTIME_OAT_OAT_H_ 18 #define ART_RUNTIME_OAT_OAT_H_ 19 20 #include <array> 21 #include <cstddef> 22 #include <string_view> 23 #include <utility> 24 #include <vector> 25 26 #include "base/compiler_filter.h" 27 #include "base/macros.h" 28 #include "base/safe_map.h" 29 30 namespace art HIDDEN { 31 32 enum class InstructionSet; 33 class InstructionSetFeatures; 34 35 enum class StubType { 36 kJNIDlsymLookupTrampoline, 37 kJNIDlsymLookupCriticalTrampoline, 38 kQuickGenericJNITrampoline, 39 kQuickIMTConflictTrampoline, 40 kQuickResolutionTrampoline, 41 kQuickToInterpreterBridge, 42 kNterpTrampoline, 43 kLast = kNterpTrampoline, 44 }; 45 std::ostream& operator<<(std::ostream& stream, StubType stub_type); 46 47 class EXPORT PACKED(4) OatHeader { 48 public: 49 static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } }; 50 // Last oat version changed reason: Ensure oat checksum determinism across hosts and devices. 51 static constexpr std::array<uint8_t, 4> kOatVersion{{'2', '5', '9', '\0'}}; 52 53 static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; 54 static constexpr const char* kDebuggableKey = "debuggable"; 55 static constexpr const char* kNativeDebuggableKey = "native-debuggable"; 56 static constexpr const char* kCompilerFilter = "compiler-filter"; 57 static constexpr const char* kClassPathKey = "classpath"; 58 static constexpr const char* kBootClassPathKey = "bootclasspath"; 59 static constexpr const char* kBootClassPathChecksumsKey = "bootclasspath-checksums"; 60 static constexpr const char* kApexVersionsKey = "apex-versions"; 61 static constexpr const char* kConcurrentCopying = "concurrent-copying"; 62 static constexpr const char* kCompilationReasonKey = "compilation-reason"; 63 static constexpr const char* kRequiresImage = "requires-image"; 64 65 // Fields listed here are key value store fields that are deterministic across hosts and devices, 66 // meaning they should have exactly the same value when the oat file is generated on different 67 // hosts and devices for the same app / boot image and for the same device model with the same 68 // compiler options. If you are adding a new field that doesn't hold this property, put it in 69 // `kNonDeterministicFieldsAndLengths` and assign a length limit. 70 // 71 // When writing the oat header, the non-deterministic fields are padded to their length limits and 72 // excluded from the oat checksum computation. This makes the oat checksum deterministic across 73 // hosts and devices, which is important for Cloud Compilation, where we generate an oat file on a 74 // host and use it on a device. 75 static constexpr std::array<std::string_view, 9> kDeterministicFields{ 76 kDebuggableKey, 77 kNativeDebuggableKey, 78 kCompilerFilter, 79 kClassPathKey, 80 kBootClassPathKey, 81 kBootClassPathChecksumsKey, 82 kConcurrentCopying, 83 kCompilationReasonKey, 84 kRequiresImage, 85 }; 86 87 static constexpr std::array<std::pair<std::string_view, size_t>, 2> 88 kNonDeterministicFieldsAndLengths{ 89 std::make_pair(kDex2OatCmdLineKey, 2048), 90 std::make_pair(kApexVersionsKey, 1024), 91 }; 92 93 static constexpr const char kTrueValue[] = "true"; 94 static constexpr const char kFalseValue[] = "false"; 95 96 97 static OatHeader* Create(InstructionSet instruction_set, 98 const InstructionSetFeatures* instruction_set_features, 99 uint32_t dex_file_count, 100 const SafeMap<std::string, std::string>* variable_data, 101 uint32_t base_oat_offset = 0u); 102 static void Delete(OatHeader* header); 103 IsDeterministicField(std::string_view key)104 static constexpr bool IsDeterministicField(std::string_view key) { 105 for (std::string_view field : kDeterministicFields) { 106 if (field == key) { 107 return true; 108 } 109 } 110 return false; 111 } 112 GetNonDeterministicFieldLength(std::string_view key)113 static constexpr size_t GetNonDeterministicFieldLength(std::string_view key) { 114 for (auto [field, length] : kNonDeterministicFieldsAndLengths) { 115 if (field == key) { 116 return length; 117 } 118 } 119 return 0; 120 } 121 122 bool IsValid() const; 123 std::string GetValidationErrorMessage() const; 124 static void CheckOatVersion(std::array<uint8_t, 4> version); 125 const char* GetMagic() const; 126 uint32_t GetChecksum() const; 127 void SetChecksum(uint32_t checksum); GetDexFileCount()128 uint32_t GetDexFileCount() const { 129 DCHECK(IsValid()); 130 return dex_file_count_; 131 } 132 uint32_t GetOatDexFilesOffset() const; 133 void SetOatDexFilesOffset(uint32_t oat_dex_files_offset); 134 uint32_t GetBcpBssInfoOffset() const; 135 void SetBcpBssInfoOffset(uint32_t bcp_info_offset); 136 uint32_t GetExecutableOffset() const; 137 void SetExecutableOffset(uint32_t executable_offset); 138 139 const void* GetJniDlsymLookupTrampoline() const; 140 uint32_t GetJniDlsymLookupTrampolineOffset() const; 141 void SetJniDlsymLookupTrampolineOffset(uint32_t offset); 142 const void* GetJniDlsymLookupCriticalTrampoline() const; 143 uint32_t GetJniDlsymLookupCriticalTrampolineOffset() const; 144 void SetJniDlsymLookupCriticalTrampolineOffset(uint32_t offset); 145 146 const void* GetQuickGenericJniTrampoline() const; 147 uint32_t GetQuickGenericJniTrampolineOffset() const; 148 void SetQuickGenericJniTrampolineOffset(uint32_t offset); 149 const void* GetQuickResolutionTrampoline() const; 150 uint32_t GetQuickResolutionTrampolineOffset() const; 151 void SetQuickResolutionTrampolineOffset(uint32_t offset); 152 const void* GetQuickImtConflictTrampoline() const; 153 uint32_t GetQuickImtConflictTrampolineOffset() const; 154 void SetQuickImtConflictTrampolineOffset(uint32_t offset); 155 const void* GetQuickToInterpreterBridge() const; 156 uint32_t GetQuickToInterpreterBridgeOffset() const; 157 void SetQuickToInterpreterBridgeOffset(uint32_t offset); 158 const void* GetNterpTrampoline() const; 159 uint32_t GetNterpTrampolineOffset() const; 160 void SetNterpTrampolineOffset(uint32_t offset); 161 162 InstructionSet GetInstructionSet() const; 163 uint32_t GetInstructionSetFeaturesBitmap() const; 164 165 uint32_t GetKeyValueStoreSize() const; 166 const uint8_t* GetKeyValueStore() const; 167 const char* GetStoreValueByKeyUnsafe(const char* key) const; 168 GetStoreValueByKey(const char * key)169 const char* GetStoreValueByKey(const char* key) const { 170 // Do not get apex versions from the oat header directly. Use `OatFile::GetApexVersions` 171 // instead. 172 DCHECK_NE(std::string_view(key), kApexVersionsKey); 173 return GetStoreValueByKeyUnsafe(key); 174 } 175 176 // Returns the next key-value pair, at the given offset. On success, updates `offset`. 177 // The expected use case is to start the iteration with an offset initialized to zero and 178 // repeatedly call this function with the same offset pointer, until the function returns false. 179 bool GetNextStoreKeyValuePair(/*inout*/ uint32_t* offset, 180 /*out*/ const char** key, 181 /*out*/ const char** value) const; 182 183 size_t GetHeaderSize() const; 184 bool IsDebuggable() const; 185 bool IsNativeDebuggable() const; 186 CompilerFilter::Filter GetCompilerFilter() const; 187 bool IsConcurrentCopying() const; 188 bool RequiresImage() const; 189 190 const uint8_t* GetOatAddress(StubType type) const; 191 192 void ComputeChecksum(/*inout*/ uint32_t* checksum) const; 193 194 private: 195 bool KeyHasValue(const char* key, const char* value, size_t value_size) const; 196 197 OatHeader(InstructionSet instruction_set, 198 const InstructionSetFeatures* instruction_set_features, 199 uint32_t dex_file_count, 200 const SafeMap<std::string, std::string>* variable_data, 201 uint32_t base_oat_offset); 202 203 // Returns true if the value of the given key is "true", false otherwise. 204 bool IsKeyEnabled(const char* key) const; 205 206 void Flatten(const SafeMap<std::string, std::string>* variable_data); 207 208 std::array<uint8_t, 4> magic_; 209 std::array<uint8_t, 4> version_; 210 uint32_t oat_checksum_; 211 212 InstructionSet instruction_set_; 213 uint32_t instruction_set_features_bitmap_; 214 uint32_t dex_file_count_; 215 uint32_t oat_dex_files_offset_; 216 uint32_t bcp_bss_info_offset_; 217 // Offset of the oat header (i.e. start of the oat data) in the ELF file. 218 // It is used to additional validation of the oat header as it is not 219 // page-aligned in the memory. 220 uint32_t base_oat_offset_; 221 uint32_t executable_offset_; 222 uint32_t jni_dlsym_lookup_trampoline_offset_; 223 uint32_t jni_dlsym_lookup_critical_trampoline_offset_; 224 uint32_t quick_generic_jni_trampoline_offset_; 225 uint32_t quick_imt_conflict_trampoline_offset_; 226 uint32_t quick_resolution_trampoline_offset_; 227 uint32_t quick_to_interpreter_bridge_offset_; 228 uint32_t nterp_trampoline_offset_; 229 230 uint32_t key_value_store_size_; 231 uint8_t key_value_store_[0]; // note variable width data at end 232 233 DISALLOW_COPY_AND_ASSIGN(OatHeader); 234 }; 235 236 } // namespace art 237 238 #endif // ART_RUNTIME_OAT_OAT_H_ 239