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