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 <zlib.h>
21
22namespace art {
23
24const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
25const uint8_t OatHeader::kOatVersion[] = { '0', '0', '7', '\0' };
26
27OatHeader::OatHeader() {
28  memset(this, 0, sizeof(*this));
29}
30
31OatHeader::OatHeader(InstructionSet instruction_set,
32                     const std::vector<const DexFile*>* dex_files,
33                     uint32_t image_file_location_oat_checksum,
34                     uint32_t image_file_location_oat_data_begin,
35                     const std::string& image_file_location) {
36  memcpy(magic_, kOatMagic, sizeof(kOatMagic));
37  memcpy(version_, kOatVersion, sizeof(kOatVersion));
38
39  adler32_checksum_ = adler32(0L, Z_NULL, 0);
40
41  CHECK_NE(instruction_set, kNone);
42  instruction_set_ = instruction_set;
43  UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
44
45  dex_file_count_ = dex_files->size();
46  UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
47
48  image_file_location_oat_checksum_ = image_file_location_oat_checksum;
49  UpdateChecksum(&image_file_location_oat_checksum_, sizeof(image_file_location_oat_checksum_));
50
51  CHECK(IsAligned<kPageSize>(image_file_location_oat_data_begin));
52  image_file_location_oat_data_begin_ = image_file_location_oat_data_begin;
53  UpdateChecksum(&image_file_location_oat_data_begin_, sizeof(image_file_location_oat_data_begin_));
54
55  image_file_location_size_ = image_file_location.size();
56  UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_));
57  UpdateChecksum(image_file_location.data(), image_file_location_size_);
58
59  executable_offset_ = 0;
60  interpreter_to_interpreter_bridge_offset_ = 0;
61  interpreter_to_compiled_code_bridge_offset_ = 0;
62  jni_dlsym_lookup_offset_ = 0;
63  portable_resolution_trampoline_offset_ = 0;
64  portable_to_interpreter_bridge_offset_ = 0;
65  quick_resolution_trampoline_offset_ = 0;
66  quick_to_interpreter_bridge_offset_ = 0;
67}
68
69bool OatHeader::IsValid() const {
70  if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
71    return false;
72  }
73  if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
74    return false;
75  }
76  return true;
77}
78
79const char* OatHeader::GetMagic() const {
80  CHECK(IsValid());
81  return reinterpret_cast<const char*>(magic_);
82}
83
84uint32_t OatHeader::GetChecksum() const {
85  CHECK(IsValid());
86  return adler32_checksum_;
87}
88
89void OatHeader::UpdateChecksum(const void* data, size_t length) {
90  DCHECK(IsValid());
91  const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
92  adler32_checksum_ = adler32(adler32_checksum_, bytes, length);
93}
94
95InstructionSet OatHeader::GetInstructionSet() const {
96  CHECK(IsValid());
97  return instruction_set_;
98}
99
100uint32_t OatHeader::GetExecutableOffset() const {
101  DCHECK(IsValid());
102  DCHECK_ALIGNED(executable_offset_, kPageSize);
103  CHECK_GT(executable_offset_, sizeof(OatHeader));
104  return executable_offset_;
105}
106
107void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
108  DCHECK_ALIGNED(executable_offset, kPageSize);
109  CHECK_GT(executable_offset, sizeof(OatHeader));
110  DCHECK(IsValid());
111  DCHECK_EQ(executable_offset_, 0U);
112
113  executable_offset_ = executable_offset;
114  UpdateChecksum(&executable_offset_, sizeof(executable_offset));
115}
116
117const void* OatHeader::GetInterpreterToInterpreterBridge() const {
118  return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToInterpreterBridgeOffset();
119}
120
121uint32_t OatHeader::GetInterpreterToInterpreterBridgeOffset() const {
122  DCHECK(IsValid());
123  CHECK_GE(interpreter_to_interpreter_bridge_offset_, executable_offset_);
124  return interpreter_to_interpreter_bridge_offset_;
125}
126
127void OatHeader::SetInterpreterToInterpreterBridgeOffset(uint32_t offset) {
128  CHECK(offset == 0 || offset >= executable_offset_);
129  DCHECK(IsValid());
130  DCHECK_EQ(interpreter_to_interpreter_bridge_offset_, 0U) << offset;
131
132  interpreter_to_interpreter_bridge_offset_ = offset;
133  UpdateChecksum(&interpreter_to_interpreter_bridge_offset_, sizeof(offset));
134}
135
136const void* OatHeader::GetInterpreterToCompiledCodeBridge() const {
137  return reinterpret_cast<const uint8_t*>(this) + GetInterpreterToCompiledCodeBridgeOffset();
138}
139
140uint32_t OatHeader::GetInterpreterToCompiledCodeBridgeOffset() const {
141  DCHECK(IsValid());
142  CHECK_GE(interpreter_to_compiled_code_bridge_offset_, interpreter_to_interpreter_bridge_offset_);
143  return interpreter_to_compiled_code_bridge_offset_;
144}
145
146void OatHeader::SetInterpreterToCompiledCodeBridgeOffset(uint32_t offset) {
147  CHECK(offset == 0 || offset >= interpreter_to_interpreter_bridge_offset_);
148  DCHECK(IsValid());
149  DCHECK_EQ(interpreter_to_compiled_code_bridge_offset_, 0U) << offset;
150
151  interpreter_to_compiled_code_bridge_offset_ = offset;
152  UpdateChecksum(&interpreter_to_compiled_code_bridge_offset_, sizeof(offset));
153}
154
155const void* OatHeader::GetJniDlsymLookup() const {
156  return reinterpret_cast<const uint8_t*>(this) + GetJniDlsymLookupOffset();
157}
158
159uint32_t OatHeader::GetJniDlsymLookupOffset() const {
160  DCHECK(IsValid());
161  CHECK_GE(jni_dlsym_lookup_offset_, interpreter_to_compiled_code_bridge_offset_);
162  return jni_dlsym_lookup_offset_;
163}
164
165void OatHeader::SetJniDlsymLookupOffset(uint32_t offset) {
166  CHECK(offset == 0 || offset >= interpreter_to_compiled_code_bridge_offset_);
167  DCHECK(IsValid());
168  DCHECK_EQ(jni_dlsym_lookup_offset_, 0U) << offset;
169
170  jni_dlsym_lookup_offset_ = offset;
171  UpdateChecksum(&jni_dlsym_lookup_offset_, sizeof(offset));
172}
173
174const void* OatHeader::GetPortableResolutionTrampoline() const {
175  return reinterpret_cast<const uint8_t*>(this) + GetPortableResolutionTrampolineOffset();
176}
177
178uint32_t OatHeader::GetPortableResolutionTrampolineOffset() const {
179  DCHECK(IsValid());
180  CHECK_GE(portable_resolution_trampoline_offset_, jni_dlsym_lookup_offset_);
181  return portable_resolution_trampoline_offset_;
182}
183
184void OatHeader::SetPortableResolutionTrampolineOffset(uint32_t offset) {
185  CHECK(offset == 0 || offset >= jni_dlsym_lookup_offset_);
186  DCHECK(IsValid());
187  DCHECK_EQ(portable_resolution_trampoline_offset_, 0U) << offset;
188
189  portable_resolution_trampoline_offset_ = offset;
190  UpdateChecksum(&portable_resolution_trampoline_offset_, sizeof(offset));
191}
192
193const void* OatHeader::GetPortableToInterpreterBridge() const {
194  return reinterpret_cast<const uint8_t*>(this) + GetPortableToInterpreterBridgeOffset();
195}
196
197uint32_t OatHeader::GetPortableToInterpreterBridgeOffset() const {
198  DCHECK(IsValid());
199  CHECK_GE(portable_to_interpreter_bridge_offset_, portable_resolution_trampoline_offset_);
200  return portable_to_interpreter_bridge_offset_;
201}
202
203void OatHeader::SetPortableToInterpreterBridgeOffset(uint32_t offset) {
204  CHECK(offset == 0 || offset >= portable_resolution_trampoline_offset_);
205  DCHECK(IsValid());
206  DCHECK_EQ(portable_to_interpreter_bridge_offset_, 0U) << offset;
207
208  portable_to_interpreter_bridge_offset_ = offset;
209  UpdateChecksum(&portable_to_interpreter_bridge_offset_, sizeof(offset));
210}
211
212const void* OatHeader::GetQuickResolutionTrampoline() const {
213  return reinterpret_cast<const uint8_t*>(this) + GetQuickResolutionTrampolineOffset();
214}
215
216uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
217  DCHECK(IsValid());
218  CHECK_GE(quick_resolution_trampoline_offset_, portable_to_interpreter_bridge_offset_);
219  return quick_resolution_trampoline_offset_;
220}
221
222void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
223  CHECK(offset == 0 || offset >= portable_to_interpreter_bridge_offset_);
224  DCHECK(IsValid());
225  DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
226
227  quick_resolution_trampoline_offset_ = offset;
228  UpdateChecksum(&quick_resolution_trampoline_offset_, sizeof(offset));
229}
230
231const void* OatHeader::GetQuickToInterpreterBridge() const {
232  return reinterpret_cast<const uint8_t*>(this) + GetQuickToInterpreterBridgeOffset();
233}
234
235uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
236  DCHECK(IsValid());
237  CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
238  return quick_to_interpreter_bridge_offset_;
239}
240
241void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
242  CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
243  DCHECK(IsValid());
244  DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
245
246  quick_to_interpreter_bridge_offset_ = offset;
247  UpdateChecksum(&quick_to_interpreter_bridge_offset_, sizeof(offset));
248}
249
250uint32_t OatHeader::GetImageFileLocationOatChecksum() const {
251  CHECK(IsValid());
252  return image_file_location_oat_checksum_;
253}
254
255uint32_t OatHeader::GetImageFileLocationOatDataBegin() const {
256  CHECK(IsValid());
257  return image_file_location_oat_data_begin_;
258}
259
260uint32_t OatHeader::GetImageFileLocationSize() const {
261  CHECK(IsValid());
262  return image_file_location_size_;
263}
264
265const uint8_t* OatHeader::GetImageFileLocationData() const {
266  CHECK(IsValid());
267  return image_file_location_data_;
268}
269
270std::string OatHeader::GetImageFileLocation() const {
271  CHECK(IsValid());
272  return std::string(reinterpret_cast<const char*>(GetImageFileLocationData()),
273                     GetImageFileLocationSize());
274}
275
276OatMethodOffsets::OatMethodOffsets()
277  : code_offset_(0),
278    frame_size_in_bytes_(0),
279    core_spill_mask_(0),
280    fp_spill_mask_(0),
281    mapping_table_offset_(0),
282    vmap_table_offset_(0),
283    gc_map_offset_(0)
284{}
285
286OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
287                                   uint32_t frame_size_in_bytes,
288                                   uint32_t core_spill_mask,
289                                   uint32_t fp_spill_mask,
290                                   uint32_t mapping_table_offset,
291                                   uint32_t vmap_table_offset,
292                                   uint32_t gc_map_offset
293                                   )
294  : code_offset_(code_offset),
295    frame_size_in_bytes_(frame_size_in_bytes),
296    core_spill_mask_(core_spill_mask),
297    fp_spill_mask_(fp_spill_mask),
298    mapping_table_offset_(mapping_table_offset),
299    vmap_table_offset_(vmap_table_offset),
300    gc_map_offset_(gc_map_offset)
301{}
302
303OatMethodOffsets::~OatMethodOffsets() {}
304
305}  // namespace art
306