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