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