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