• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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