xref: /aosp_15_r20/art/runtime/oat/oat.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "oat.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <string.h>
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
24*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set_features.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/strlcpy.h"
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
31*795d594fSAndroid Build Coastguard Worker 
ComputeOatHeaderSize(const SafeMap<std::string,std::string> * variable_data)32*795d594fSAndroid Build Coastguard Worker static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
33*795d594fSAndroid Build Coastguard Worker   size_t estimate = 0U;
34*795d594fSAndroid Build Coastguard Worker   if (variable_data != nullptr) {
35*795d594fSAndroid Build Coastguard Worker     SafeMap<std::string, std::string>::const_iterator it = variable_data->begin();
36*795d594fSAndroid Build Coastguard Worker     SafeMap<std::string, std::string>::const_iterator end = variable_data->end();
37*795d594fSAndroid Build Coastguard Worker     for ( ; it != end; ++it) {
38*795d594fSAndroid Build Coastguard Worker       estimate += it->first.length() + 1;
39*795d594fSAndroid Build Coastguard Worker       estimate += it->second.length() + 1;
40*795d594fSAndroid Build Coastguard Worker     }
41*795d594fSAndroid Build Coastguard Worker   }
42*795d594fSAndroid Build Coastguard Worker   return sizeof(OatHeader) + estimate;
43*795d594fSAndroid Build Coastguard Worker }
44*795d594fSAndroid Build Coastguard Worker 
Create(InstructionSet instruction_set,const InstructionSetFeatures * instruction_set_features,uint32_t dex_file_count,const SafeMap<std::string,std::string> * variable_data)45*795d594fSAndroid Build Coastguard Worker OatHeader* OatHeader::Create(InstructionSet instruction_set,
46*795d594fSAndroid Build Coastguard Worker                              const InstructionSetFeatures* instruction_set_features,
47*795d594fSAndroid Build Coastguard Worker                              uint32_t dex_file_count,
48*795d594fSAndroid Build Coastguard Worker                              const SafeMap<std::string, std::string>* variable_data) {
49*795d594fSAndroid Build Coastguard Worker   // Estimate size of optional data.
50*795d594fSAndroid Build Coastguard Worker   size_t needed_size = ComputeOatHeaderSize(variable_data);
51*795d594fSAndroid Build Coastguard Worker 
52*795d594fSAndroid Build Coastguard Worker   // Reserve enough memory.
53*795d594fSAndroid Build Coastguard Worker   void* memory = operator new (needed_size);
54*795d594fSAndroid Build Coastguard Worker 
55*795d594fSAndroid Build Coastguard Worker   // Create the OatHeader in-place.
56*795d594fSAndroid Build Coastguard Worker   return new (memory) OatHeader(instruction_set,
57*795d594fSAndroid Build Coastguard Worker                                 instruction_set_features,
58*795d594fSAndroid Build Coastguard Worker                                 dex_file_count,
59*795d594fSAndroid Build Coastguard Worker                                 variable_data);
60*795d594fSAndroid Build Coastguard Worker }
61*795d594fSAndroid Build Coastguard Worker 
OatHeader(InstructionSet instruction_set,const InstructionSetFeatures * instruction_set_features,uint32_t dex_file_count,const SafeMap<std::string,std::string> * variable_data)62*795d594fSAndroid Build Coastguard Worker OatHeader::OatHeader(InstructionSet instruction_set,
63*795d594fSAndroid Build Coastguard Worker                      const InstructionSetFeatures* instruction_set_features,
64*795d594fSAndroid Build Coastguard Worker                      uint32_t dex_file_count,
65*795d594fSAndroid Build Coastguard Worker                      const SafeMap<std::string, std::string>* variable_data)
66*795d594fSAndroid Build Coastguard Worker     : oat_checksum_(0u),
67*795d594fSAndroid Build Coastguard Worker       instruction_set_(instruction_set),
68*795d594fSAndroid Build Coastguard Worker       instruction_set_features_bitmap_(instruction_set_features->AsBitmap()),
69*795d594fSAndroid Build Coastguard Worker       dex_file_count_(dex_file_count),
70*795d594fSAndroid Build Coastguard Worker       oat_dex_files_offset_(0),
71*795d594fSAndroid Build Coastguard Worker       bcp_bss_info_offset_(0),
72*795d594fSAndroid Build Coastguard Worker       executable_offset_(0),
73*795d594fSAndroid Build Coastguard Worker       jni_dlsym_lookup_trampoline_offset_(0),
74*795d594fSAndroid Build Coastguard Worker       jni_dlsym_lookup_critical_trampoline_offset_(0),
75*795d594fSAndroid Build Coastguard Worker       quick_generic_jni_trampoline_offset_(0),
76*795d594fSAndroid Build Coastguard Worker       quick_imt_conflict_trampoline_offset_(0),
77*795d594fSAndroid Build Coastguard Worker       quick_resolution_trampoline_offset_(0),
78*795d594fSAndroid Build Coastguard Worker       quick_to_interpreter_bridge_offset_(0),
79*795d594fSAndroid Build Coastguard Worker       nterp_trampoline_offset_(0) {
80*795d594fSAndroid Build Coastguard Worker   // Don't want asserts in header as they would be checked in each file that includes it. But the
81*795d594fSAndroid Build Coastguard Worker   // fields are private, so we check inside a method.
82*795d594fSAndroid Build Coastguard Worker   static_assert(decltype(magic_)().size() == kOatMagic.size(),
83*795d594fSAndroid Build Coastguard Worker                 "Oat magic and magic_ have different lengths.");
84*795d594fSAndroid Build Coastguard Worker   static_assert(decltype(version_)().size() == kOatVersion.size(),
85*795d594fSAndroid Build Coastguard Worker                 "Oat version and version_ have different lengths.");
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker   magic_ = kOatMagic;
88*795d594fSAndroid Build Coastguard Worker   version_ = kOatVersion;
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker   CHECK_NE(instruction_set, InstructionSet::kNone);
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   // Flatten the map. Will also update variable_size_data_size_.
93*795d594fSAndroid Build Coastguard Worker   Flatten(variable_data);
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker 
IsValid() const96*795d594fSAndroid Build Coastguard Worker bool OatHeader::IsValid() const {
97*795d594fSAndroid Build Coastguard Worker   if (magic_ != kOatMagic) {
98*795d594fSAndroid Build Coastguard Worker     return false;
99*795d594fSAndroid Build Coastguard Worker   }
100*795d594fSAndroid Build Coastguard Worker   if (version_ != kOatVersion) {
101*795d594fSAndroid Build Coastguard Worker     return false;
102*795d594fSAndroid Build Coastguard Worker   }
103*795d594fSAndroid Build Coastguard Worker   if (!IsAligned<kElfSegmentAlignment>(executable_offset_)) {
104*795d594fSAndroid Build Coastguard Worker     return false;
105*795d594fSAndroid Build Coastguard Worker   }
106*795d594fSAndroid Build Coastguard Worker   if (!IsValidInstructionSet(instruction_set_)) {
107*795d594fSAndroid Build Coastguard Worker     return false;
108*795d594fSAndroid Build Coastguard Worker   }
109*795d594fSAndroid Build Coastguard Worker   return true;
110*795d594fSAndroid Build Coastguard Worker }
111*795d594fSAndroid Build Coastguard Worker 
GetValidationErrorMessage() const112*795d594fSAndroid Build Coastguard Worker std::string OatHeader::GetValidationErrorMessage() const {
113*795d594fSAndroid Build Coastguard Worker   if (magic_ != kOatMagic) {
114*795d594fSAndroid Build Coastguard Worker     static_assert(kOatMagic.size() == 4, "kOatMagic has unexpected length");
115*795d594fSAndroid Build Coastguard Worker     return StringPrintf("Invalid oat magic, expected 0x%02x%02x%02x%02x, got 0x%02x%02x%02x%02x.",
116*795d594fSAndroid Build Coastguard Worker                         kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
117*795d594fSAndroid Build Coastguard Worker                         magic_[0], magic_[1], magic_[2], magic_[3]);
118*795d594fSAndroid Build Coastguard Worker   }
119*795d594fSAndroid Build Coastguard Worker   if (version_ != kOatVersion) {
120*795d594fSAndroid Build Coastguard Worker     static_assert(kOatVersion.size() == 4, "kOatVersion has unexpected length");
121*795d594fSAndroid Build Coastguard Worker     return StringPrintf("Invalid oat version, expected 0x%02x%02x%02x%02x, got 0x%02x%02x%02x%02x.",
122*795d594fSAndroid Build Coastguard Worker                         kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
123*795d594fSAndroid Build Coastguard Worker                         version_[0], version_[1], version_[2], version_[3]);
124*795d594fSAndroid Build Coastguard Worker   }
125*795d594fSAndroid Build Coastguard Worker   if (!IsAligned<kElfSegmentAlignment>(executable_offset_)) {
126*795d594fSAndroid Build Coastguard Worker     return "Executable offset not properly aligned.";
127*795d594fSAndroid Build Coastguard Worker   }
128*795d594fSAndroid Build Coastguard Worker   if (!IsValidInstructionSet(instruction_set_)) {
129*795d594fSAndroid Build Coastguard Worker     return StringPrintf("Invalid instruction set, %d.", static_cast<int>(instruction_set_));
130*795d594fSAndroid Build Coastguard Worker   }
131*795d594fSAndroid Build Coastguard Worker   return "";
132*795d594fSAndroid Build Coastguard Worker }
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker // Do not move this into the header.  The method must be compiled in the runtime library,
135*795d594fSAndroid Build Coastguard Worker // so that we can check that the compile-time oat version matches the version in the caller.
CheckOatVersion(std::array<uint8_t,4> version)136*795d594fSAndroid Build Coastguard Worker void OatHeader::CheckOatVersion(std::array<uint8_t, 4> version) {
137*795d594fSAndroid Build Coastguard Worker   constexpr std::array<uint8_t, 4> expected = kOatVersion;  // Runtime oat version.
138*795d594fSAndroid Build Coastguard Worker   if (version != kOatVersion) {
139*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << StringPrintf("Invalid oat version, expected 0x%02x%02x%02x%02x, "
140*795d594fSAndroid Build Coastguard Worker                                    "got 0x%02x%02x%02x%02x.",
141*795d594fSAndroid Build Coastguard Worker                                expected[0], expected[1], expected[2], expected[3],
142*795d594fSAndroid Build Coastguard Worker                                version[0], version[1], version[2], version[3]);
143*795d594fSAndroid Build Coastguard Worker   }
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker 
GetMagic() const146*795d594fSAndroid Build Coastguard Worker const char* OatHeader::GetMagic() const {
147*795d594fSAndroid Build Coastguard Worker   CHECK(IsValid());
148*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<const char*>(magic_.data());
149*795d594fSAndroid Build Coastguard Worker }
150*795d594fSAndroid Build Coastguard Worker 
GetChecksum() const151*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetChecksum() const {
152*795d594fSAndroid Build Coastguard Worker   CHECK(IsValid());
153*795d594fSAndroid Build Coastguard Worker   return oat_checksum_;
154*795d594fSAndroid Build Coastguard Worker }
155*795d594fSAndroid Build Coastguard Worker 
SetChecksum(uint32_t oat_checksum)156*795d594fSAndroid Build Coastguard Worker void OatHeader::SetChecksum(uint32_t oat_checksum) {
157*795d594fSAndroid Build Coastguard Worker   oat_checksum_ = oat_checksum;
158*795d594fSAndroid Build Coastguard Worker }
159*795d594fSAndroid Build Coastguard Worker 
GetInstructionSet() const160*795d594fSAndroid Build Coastguard Worker InstructionSet OatHeader::GetInstructionSet() const {
161*795d594fSAndroid Build Coastguard Worker   CHECK(IsValid());
162*795d594fSAndroid Build Coastguard Worker   return instruction_set_;
163*795d594fSAndroid Build Coastguard Worker }
164*795d594fSAndroid Build Coastguard Worker 
GetInstructionSetFeaturesBitmap() const165*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetInstructionSetFeaturesBitmap() const {
166*795d594fSAndroid Build Coastguard Worker   CHECK(IsValid());
167*795d594fSAndroid Build Coastguard Worker   return instruction_set_features_bitmap_;
168*795d594fSAndroid Build Coastguard Worker }
169*795d594fSAndroid Build Coastguard Worker 
GetOatDexFilesOffset() const170*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetOatDexFilesOffset() const {
171*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
172*795d594fSAndroid Build Coastguard Worker   DCHECK_GT(oat_dex_files_offset_, sizeof(OatHeader));
173*795d594fSAndroid Build Coastguard Worker   return oat_dex_files_offset_;
174*795d594fSAndroid Build Coastguard Worker }
175*795d594fSAndroid Build Coastguard Worker 
SetOatDexFilesOffset(uint32_t oat_dex_files_offset)176*795d594fSAndroid Build Coastguard Worker void OatHeader::SetOatDexFilesOffset(uint32_t oat_dex_files_offset) {
177*795d594fSAndroid Build Coastguard Worker   DCHECK_GT(oat_dex_files_offset, sizeof(OatHeader));
178*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
179*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(oat_dex_files_offset_, 0u);
180*795d594fSAndroid Build Coastguard Worker 
181*795d594fSAndroid Build Coastguard Worker   oat_dex_files_offset_ = oat_dex_files_offset;
182*795d594fSAndroid Build Coastguard Worker }
183*795d594fSAndroid Build Coastguard Worker 
GetBcpBssInfoOffset() const184*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetBcpBssInfoOffset() const {
185*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
186*795d594fSAndroid Build Coastguard Worker   DCHECK(bcp_bss_info_offset_ == 0u || bcp_bss_info_offset_ > sizeof(OatHeader))
187*795d594fSAndroid Build Coastguard Worker       << "bcp_bss_info_offset_: " << bcp_bss_info_offset_
188*795d594fSAndroid Build Coastguard Worker       << "sizeof(OatHeader): " << sizeof(OatHeader);
189*795d594fSAndroid Build Coastguard Worker   return bcp_bss_info_offset_;
190*795d594fSAndroid Build Coastguard Worker }
191*795d594fSAndroid Build Coastguard Worker 
SetBcpBssInfoOffset(uint32_t bcp_info_offset)192*795d594fSAndroid Build Coastguard Worker void OatHeader::SetBcpBssInfoOffset(uint32_t bcp_info_offset) {
193*795d594fSAndroid Build Coastguard Worker   DCHECK_GT(bcp_info_offset, sizeof(OatHeader));
194*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
195*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(bcp_bss_info_offset_, 0u);
196*795d594fSAndroid Build Coastguard Worker 
197*795d594fSAndroid Build Coastguard Worker   bcp_bss_info_offset_ = bcp_info_offset;
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker 
GetExecutableOffset() const200*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetExecutableOffset() const {
201*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
202*795d594fSAndroid Build Coastguard Worker   DCHECK_ALIGNED(executable_offset_, kElfSegmentAlignment);
203*795d594fSAndroid Build Coastguard Worker   CHECK_GT(executable_offset_, sizeof(OatHeader));
204*795d594fSAndroid Build Coastguard Worker   return executable_offset_;
205*795d594fSAndroid Build Coastguard Worker }
206*795d594fSAndroid Build Coastguard Worker 
SetExecutableOffset(uint32_t executable_offset)207*795d594fSAndroid Build Coastguard Worker void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
208*795d594fSAndroid Build Coastguard Worker   DCHECK_ALIGNED(executable_offset, kElfSegmentAlignment);
209*795d594fSAndroid Build Coastguard Worker   CHECK_GT(executable_offset, sizeof(OatHeader));
210*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
211*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(executable_offset_, 0U);
212*795d594fSAndroid Build Coastguard Worker 
213*795d594fSAndroid Build Coastguard Worker   executable_offset_ = executable_offset;
214*795d594fSAndroid Build Coastguard Worker }
215*795d594fSAndroid Build Coastguard Worker 
GetTrampoline(const OatHeader & header,uint32_t offset)216*795d594fSAndroid Build Coastguard Worker static const void* GetTrampoline(const OatHeader& header, uint32_t offset) {
217*795d594fSAndroid Build Coastguard Worker   return (offset != 0u) ? reinterpret_cast<const uint8_t*>(&header) + offset : nullptr;
218*795d594fSAndroid Build Coastguard Worker }
219*795d594fSAndroid Build Coastguard Worker 
GetJniDlsymLookupTrampoline() const220*795d594fSAndroid Build Coastguard Worker const void* OatHeader::GetJniDlsymLookupTrampoline() const {
221*795d594fSAndroid Build Coastguard Worker   return GetTrampoline(*this, GetJniDlsymLookupTrampolineOffset());
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker 
GetJniDlsymLookupTrampolineOffset() const224*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetJniDlsymLookupTrampolineOffset() const {
225*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
226*795d594fSAndroid Build Coastguard Worker   return jni_dlsym_lookup_trampoline_offset_;
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker 
SetJniDlsymLookupTrampolineOffset(uint32_t offset)229*795d594fSAndroid Build Coastguard Worker void OatHeader::SetJniDlsymLookupTrampolineOffset(uint32_t offset) {
230*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
231*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(jni_dlsym_lookup_trampoline_offset_, 0U) << offset;
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   jni_dlsym_lookup_trampoline_offset_ = offset;
234*795d594fSAndroid Build Coastguard Worker }
235*795d594fSAndroid Build Coastguard Worker 
GetJniDlsymLookupCriticalTrampoline() const236*795d594fSAndroid Build Coastguard Worker const void* OatHeader::GetJniDlsymLookupCriticalTrampoline() const {
237*795d594fSAndroid Build Coastguard Worker   return GetTrampoline(*this, GetJniDlsymLookupCriticalTrampolineOffset());
238*795d594fSAndroid Build Coastguard Worker }
239*795d594fSAndroid Build Coastguard Worker 
GetJniDlsymLookupCriticalTrampolineOffset() const240*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetJniDlsymLookupCriticalTrampolineOffset() const {
241*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
242*795d594fSAndroid Build Coastguard Worker   return jni_dlsym_lookup_critical_trampoline_offset_;
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker 
SetJniDlsymLookupCriticalTrampolineOffset(uint32_t offset)245*795d594fSAndroid Build Coastguard Worker void OatHeader::SetJniDlsymLookupCriticalTrampolineOffset(uint32_t offset) {
246*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
247*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(jni_dlsym_lookup_critical_trampoline_offset_, 0U) << offset;
248*795d594fSAndroid Build Coastguard Worker 
249*795d594fSAndroid Build Coastguard Worker   jni_dlsym_lookup_critical_trampoline_offset_ = offset;
250*795d594fSAndroid Build Coastguard Worker }
251*795d594fSAndroid Build Coastguard Worker 
GetQuickGenericJniTrampoline() const252*795d594fSAndroid Build Coastguard Worker const void* OatHeader::GetQuickGenericJniTrampoline() const {
253*795d594fSAndroid Build Coastguard Worker   return GetTrampoline(*this, GetQuickGenericJniTrampolineOffset());
254*795d594fSAndroid Build Coastguard Worker }
255*795d594fSAndroid Build Coastguard Worker 
GetQuickGenericJniTrampolineOffset() const256*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetQuickGenericJniTrampolineOffset() const {
257*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
258*795d594fSAndroid Build Coastguard Worker   CHECK_GE(quick_generic_jni_trampoline_offset_, jni_dlsym_lookup_trampoline_offset_);
259*795d594fSAndroid Build Coastguard Worker   return quick_generic_jni_trampoline_offset_;
260*795d594fSAndroid Build Coastguard Worker }
261*795d594fSAndroid Build Coastguard Worker 
SetQuickGenericJniTrampolineOffset(uint32_t offset)262*795d594fSAndroid Build Coastguard Worker void OatHeader::SetQuickGenericJniTrampolineOffset(uint32_t offset) {
263*795d594fSAndroid Build Coastguard Worker   CHECK(offset == 0 || offset >= jni_dlsym_lookup_trampoline_offset_);
264*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
265*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(quick_generic_jni_trampoline_offset_, 0U) << offset;
266*795d594fSAndroid Build Coastguard Worker 
267*795d594fSAndroid Build Coastguard Worker   quick_generic_jni_trampoline_offset_ = offset;
268*795d594fSAndroid Build Coastguard Worker }
269*795d594fSAndroid Build Coastguard Worker 
GetQuickImtConflictTrampoline() const270*795d594fSAndroid Build Coastguard Worker const void* OatHeader::GetQuickImtConflictTrampoline() const {
271*795d594fSAndroid Build Coastguard Worker   return GetTrampoline(*this, GetQuickImtConflictTrampolineOffset());
272*795d594fSAndroid Build Coastguard Worker }
273*795d594fSAndroid Build Coastguard Worker 
GetQuickImtConflictTrampolineOffset() const274*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetQuickImtConflictTrampolineOffset() const {
275*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
276*795d594fSAndroid Build Coastguard Worker   CHECK_GE(quick_imt_conflict_trampoline_offset_, quick_generic_jni_trampoline_offset_);
277*795d594fSAndroid Build Coastguard Worker   return quick_imt_conflict_trampoline_offset_;
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker 
SetQuickImtConflictTrampolineOffset(uint32_t offset)280*795d594fSAndroid Build Coastguard Worker void OatHeader::SetQuickImtConflictTrampolineOffset(uint32_t offset) {
281*795d594fSAndroid Build Coastguard Worker   CHECK(offset == 0 || offset >= quick_generic_jni_trampoline_offset_);
282*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
283*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(quick_imt_conflict_trampoline_offset_, 0U) << offset;
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker   quick_imt_conflict_trampoline_offset_ = offset;
286*795d594fSAndroid Build Coastguard Worker }
287*795d594fSAndroid Build Coastguard Worker 
GetQuickResolutionTrampoline() const288*795d594fSAndroid Build Coastguard Worker const void* OatHeader::GetQuickResolutionTrampoline() const {
289*795d594fSAndroid Build Coastguard Worker   return GetTrampoline(*this, GetQuickResolutionTrampolineOffset());
290*795d594fSAndroid Build Coastguard Worker }
291*795d594fSAndroid Build Coastguard Worker 
GetQuickResolutionTrampolineOffset() const292*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetQuickResolutionTrampolineOffset() const {
293*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
294*795d594fSAndroid Build Coastguard Worker   CHECK_GE(quick_resolution_trampoline_offset_, quick_imt_conflict_trampoline_offset_);
295*795d594fSAndroid Build Coastguard Worker   return quick_resolution_trampoline_offset_;
296*795d594fSAndroid Build Coastguard Worker }
297*795d594fSAndroid Build Coastguard Worker 
SetQuickResolutionTrampolineOffset(uint32_t offset)298*795d594fSAndroid Build Coastguard Worker void OatHeader::SetQuickResolutionTrampolineOffset(uint32_t offset) {
299*795d594fSAndroid Build Coastguard Worker   CHECK(offset == 0 || offset >= quick_imt_conflict_trampoline_offset_);
300*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
301*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(quick_resolution_trampoline_offset_, 0U) << offset;
302*795d594fSAndroid Build Coastguard Worker 
303*795d594fSAndroid Build Coastguard Worker   quick_resolution_trampoline_offset_ = offset;
304*795d594fSAndroid Build Coastguard Worker }
305*795d594fSAndroid Build Coastguard Worker 
GetQuickToInterpreterBridge() const306*795d594fSAndroid Build Coastguard Worker const void* OatHeader::GetQuickToInterpreterBridge() const {
307*795d594fSAndroid Build Coastguard Worker   return GetTrampoline(*this, GetQuickToInterpreterBridgeOffset());
308*795d594fSAndroid Build Coastguard Worker }
309*795d594fSAndroid Build Coastguard Worker 
GetQuickToInterpreterBridgeOffset() const310*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetQuickToInterpreterBridgeOffset() const {
311*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
312*795d594fSAndroid Build Coastguard Worker   CHECK_GE(quick_to_interpreter_bridge_offset_, quick_resolution_trampoline_offset_);
313*795d594fSAndroid Build Coastguard Worker   return quick_to_interpreter_bridge_offset_;
314*795d594fSAndroid Build Coastguard Worker }
315*795d594fSAndroid Build Coastguard Worker 
SetQuickToInterpreterBridgeOffset(uint32_t offset)316*795d594fSAndroid Build Coastguard Worker void OatHeader::SetQuickToInterpreterBridgeOffset(uint32_t offset) {
317*795d594fSAndroid Build Coastguard Worker   CHECK(offset == 0 || offset >= quick_resolution_trampoline_offset_);
318*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
319*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(quick_to_interpreter_bridge_offset_, 0U) << offset;
320*795d594fSAndroid Build Coastguard Worker 
321*795d594fSAndroid Build Coastguard Worker   quick_to_interpreter_bridge_offset_ = offset;
322*795d594fSAndroid Build Coastguard Worker }
323*795d594fSAndroid Build Coastguard Worker 
GetNterpTrampoline() const324*795d594fSAndroid Build Coastguard Worker const void* OatHeader::GetNterpTrampoline() const {
325*795d594fSAndroid Build Coastguard Worker   return GetTrampoline(*this, GetNterpTrampolineOffset());
326*795d594fSAndroid Build Coastguard Worker }
327*795d594fSAndroid Build Coastguard Worker 
GetNterpTrampolineOffset() const328*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetNterpTrampolineOffset() const {
329*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
330*795d594fSAndroid Build Coastguard Worker   CHECK_GE(nterp_trampoline_offset_, quick_to_interpreter_bridge_offset_);
331*795d594fSAndroid Build Coastguard Worker   return nterp_trampoline_offset_;
332*795d594fSAndroid Build Coastguard Worker }
333*795d594fSAndroid Build Coastguard Worker 
SetNterpTrampolineOffset(uint32_t offset)334*795d594fSAndroid Build Coastguard Worker void OatHeader::SetNterpTrampolineOffset(uint32_t offset) {
335*795d594fSAndroid Build Coastguard Worker   CHECK(offset == 0 || offset >= quick_to_interpreter_bridge_offset_);
336*795d594fSAndroid Build Coastguard Worker   DCHECK(IsValid());
337*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(nterp_trampoline_offset_, 0U) << offset;
338*795d594fSAndroid Build Coastguard Worker 
339*795d594fSAndroid Build Coastguard Worker   nterp_trampoline_offset_ = offset;
340*795d594fSAndroid Build Coastguard Worker }
341*795d594fSAndroid Build Coastguard Worker 
GetKeyValueStoreSize() const342*795d594fSAndroid Build Coastguard Worker uint32_t OatHeader::GetKeyValueStoreSize() const {
343*795d594fSAndroid Build Coastguard Worker   CHECK(IsValid());
344*795d594fSAndroid Build Coastguard Worker   return key_value_store_size_;
345*795d594fSAndroid Build Coastguard Worker }
346*795d594fSAndroid Build Coastguard Worker 
GetKeyValueStore() const347*795d594fSAndroid Build Coastguard Worker const uint8_t* OatHeader::GetKeyValueStore() const {
348*795d594fSAndroid Build Coastguard Worker   CHECK(IsValid());
349*795d594fSAndroid Build Coastguard Worker   return key_value_store_;
350*795d594fSAndroid Build Coastguard Worker }
351*795d594fSAndroid Build Coastguard Worker 
GetStoreValueByKey(const char * key) const352*795d594fSAndroid Build Coastguard Worker const char* OatHeader::GetStoreValueByKey(const char* key) const {
353*795d594fSAndroid Build Coastguard Worker   std::string_view key_view(key);
354*795d594fSAndroid Build Coastguard Worker   const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
355*795d594fSAndroid Build Coastguard Worker   const char* end = ptr + key_value_store_size_;
356*795d594fSAndroid Build Coastguard Worker 
357*795d594fSAndroid Build Coastguard Worker   while (ptr < end) {
358*795d594fSAndroid Build Coastguard Worker     // Scan for a closing zero.
359*795d594fSAndroid Build Coastguard Worker     const char* str_end = reinterpret_cast<const char*>(memchr(ptr, 0, end - ptr));
360*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(str_end == nullptr)) {
361*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "OatHeader: Unterminated key in key value store.";
362*795d594fSAndroid Build Coastguard Worker       return nullptr;
363*795d594fSAndroid Build Coastguard Worker     }
364*795d594fSAndroid Build Coastguard Worker     const char* value_start = str_end + 1;
365*795d594fSAndroid Build Coastguard Worker     const char* value_end =
366*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const char*>(memchr(value_start, 0, end - value_start));
367*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(value_end == nullptr)) {
368*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "OatHeader: Unterminated value in key value store.";
369*795d594fSAndroid Build Coastguard Worker       return nullptr;
370*795d594fSAndroid Build Coastguard Worker     }
371*795d594fSAndroid Build Coastguard Worker     if (key_view == std::string_view(ptr, str_end - ptr)) {
372*795d594fSAndroid Build Coastguard Worker       // Same as key.
373*795d594fSAndroid Build Coastguard Worker       return value_start;
374*795d594fSAndroid Build Coastguard Worker     }
375*795d594fSAndroid Build Coastguard Worker     // Different from key. Advance over the value.
376*795d594fSAndroid Build Coastguard Worker     ptr = value_end + 1;
377*795d594fSAndroid Build Coastguard Worker   }
378*795d594fSAndroid Build Coastguard Worker   // Not found.
379*795d594fSAndroid Build Coastguard Worker   return nullptr;
380*795d594fSAndroid Build Coastguard Worker }
381*795d594fSAndroid Build Coastguard Worker 
GetStoreKeyValuePairByIndex(size_t index,const char ** key,const char ** value) const382*795d594fSAndroid Build Coastguard Worker bool OatHeader::GetStoreKeyValuePairByIndex(size_t index,
383*795d594fSAndroid Build Coastguard Worker                                             const char** key,
384*795d594fSAndroid Build Coastguard Worker                                             const char** value) const {
385*795d594fSAndroid Build Coastguard Worker   const char* ptr = reinterpret_cast<const char*>(&key_value_store_);
386*795d594fSAndroid Build Coastguard Worker   const char* end = ptr + key_value_store_size_;
387*795d594fSAndroid Build Coastguard Worker   size_t counter = index;
388*795d594fSAndroid Build Coastguard Worker 
389*795d594fSAndroid Build Coastguard Worker   while (ptr < end) {
390*795d594fSAndroid Build Coastguard Worker     // Scan for a closing zero.
391*795d594fSAndroid Build Coastguard Worker     const char* str_end = reinterpret_cast<const char*>(memchr(ptr, 0, end - ptr));
392*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(str_end == nullptr)) {
393*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "OatHeader: Unterminated key in key value store.";
394*795d594fSAndroid Build Coastguard Worker       return false;
395*795d594fSAndroid Build Coastguard Worker     }
396*795d594fSAndroid Build Coastguard Worker     const char* value_start = str_end + 1;
397*795d594fSAndroid Build Coastguard Worker     const char* value_end =
398*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const char*>(memchr(value_start, 0, end - value_start));
399*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(value_end == nullptr)) {
400*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "OatHeader: Unterminated value in key value store.";
401*795d594fSAndroid Build Coastguard Worker       return false;
402*795d594fSAndroid Build Coastguard Worker     }
403*795d594fSAndroid Build Coastguard Worker     if (counter == 0) {
404*795d594fSAndroid Build Coastguard Worker       *key = ptr;
405*795d594fSAndroid Build Coastguard Worker       *value = value_start;
406*795d594fSAndroid Build Coastguard Worker       return true;
407*795d594fSAndroid Build Coastguard Worker     } else {
408*795d594fSAndroid Build Coastguard Worker       --counter;
409*795d594fSAndroid Build Coastguard Worker     }
410*795d594fSAndroid Build Coastguard Worker     // Advance over the value.
411*795d594fSAndroid Build Coastguard Worker     ptr = value_end + 1;
412*795d594fSAndroid Build Coastguard Worker   }
413*795d594fSAndroid Build Coastguard Worker   // Not found.
414*795d594fSAndroid Build Coastguard Worker   return false;
415*795d594fSAndroid Build Coastguard Worker }
416*795d594fSAndroid Build Coastguard Worker 
GetHeaderSize() const417*795d594fSAndroid Build Coastguard Worker size_t OatHeader::GetHeaderSize() const {
418*795d594fSAndroid Build Coastguard Worker   return sizeof(OatHeader) + key_value_store_size_;
419*795d594fSAndroid Build Coastguard Worker }
420*795d594fSAndroid Build Coastguard Worker 
IsDebuggable() const421*795d594fSAndroid Build Coastguard Worker bool OatHeader::IsDebuggable() const {
422*795d594fSAndroid Build Coastguard Worker   return IsKeyEnabled(OatHeader::kDebuggableKey);
423*795d594fSAndroid Build Coastguard Worker }
424*795d594fSAndroid Build Coastguard Worker 
IsConcurrentCopying() const425*795d594fSAndroid Build Coastguard Worker bool OatHeader::IsConcurrentCopying() const {
426*795d594fSAndroid Build Coastguard Worker   return IsKeyEnabled(OatHeader::kConcurrentCopying);
427*795d594fSAndroid Build Coastguard Worker }
428*795d594fSAndroid Build Coastguard Worker 
IsNativeDebuggable() const429*795d594fSAndroid Build Coastguard Worker bool OatHeader::IsNativeDebuggable() const {
430*795d594fSAndroid Build Coastguard Worker   return IsKeyEnabled(OatHeader::kNativeDebuggableKey);
431*795d594fSAndroid Build Coastguard Worker }
432*795d594fSAndroid Build Coastguard Worker 
RequiresImage() const433*795d594fSAndroid Build Coastguard Worker bool OatHeader::RequiresImage() const {
434*795d594fSAndroid Build Coastguard Worker   return IsKeyEnabled(OatHeader::kRequiresImage);
435*795d594fSAndroid Build Coastguard Worker }
436*795d594fSAndroid Build Coastguard Worker 
GetCompilerFilter() const437*795d594fSAndroid Build Coastguard Worker CompilerFilter::Filter OatHeader::GetCompilerFilter() const {
438*795d594fSAndroid Build Coastguard Worker   CompilerFilter::Filter filter;
439*795d594fSAndroid Build Coastguard Worker   const char* key_value = GetStoreValueByKey(kCompilerFilter);
440*795d594fSAndroid Build Coastguard Worker   CHECK(key_value != nullptr) << "compiler-filter not found in oat header";
441*795d594fSAndroid Build Coastguard Worker   CHECK(CompilerFilter::ParseCompilerFilter(key_value, &filter))
442*795d594fSAndroid Build Coastguard Worker       << "Invalid compiler-filter in oat header: " << key_value;
443*795d594fSAndroid Build Coastguard Worker   return filter;
444*795d594fSAndroid Build Coastguard Worker }
445*795d594fSAndroid Build Coastguard Worker 
KeyHasValue(const char * key,const char * value,size_t value_size) const446*795d594fSAndroid Build Coastguard Worker bool OatHeader::KeyHasValue(const char* key, const char* value, size_t value_size) const {
447*795d594fSAndroid Build Coastguard Worker   const char* key_value = GetStoreValueByKey(key);
448*795d594fSAndroid Build Coastguard Worker   return (key_value != nullptr && strncmp(key_value, value, value_size) == 0);
449*795d594fSAndroid Build Coastguard Worker }
450*795d594fSAndroid Build Coastguard Worker 
IsKeyEnabled(const char * key) const451*795d594fSAndroid Build Coastguard Worker bool OatHeader::IsKeyEnabled(const char* key) const {
452*795d594fSAndroid Build Coastguard Worker   return KeyHasValue(key, kTrueValue, sizeof(kTrueValue));
453*795d594fSAndroid Build Coastguard Worker }
454*795d594fSAndroid Build Coastguard Worker 
Flatten(const SafeMap<std::string,std::string> * key_value_store)455*795d594fSAndroid Build Coastguard Worker void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store) {
456*795d594fSAndroid Build Coastguard Worker   char* data_ptr = reinterpret_cast<char*>(&key_value_store_);
457*795d594fSAndroid Build Coastguard Worker   if (key_value_store != nullptr) {
458*795d594fSAndroid Build Coastguard Worker     SafeMap<std::string, std::string>::const_iterator it = key_value_store->begin();
459*795d594fSAndroid Build Coastguard Worker     SafeMap<std::string, std::string>::const_iterator end = key_value_store->end();
460*795d594fSAndroid Build Coastguard Worker     for ( ; it != end; ++it) {
461*795d594fSAndroid Build Coastguard Worker       strlcpy(data_ptr, it->first.c_str(), it->first.length() + 1);
462*795d594fSAndroid Build Coastguard Worker       data_ptr += it->first.length() + 1;
463*795d594fSAndroid Build Coastguard Worker       strlcpy(data_ptr, it->second.c_str(), it->second.length() + 1);
464*795d594fSAndroid Build Coastguard Worker       data_ptr += it->second.length() + 1;
465*795d594fSAndroid Build Coastguard Worker     }
466*795d594fSAndroid Build Coastguard Worker   }
467*795d594fSAndroid Build Coastguard Worker   key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
468*795d594fSAndroid Build Coastguard Worker }
469*795d594fSAndroid Build Coastguard Worker 
GetOatAddress(StubType type) const470*795d594fSAndroid Build Coastguard Worker const uint8_t* OatHeader::GetOatAddress(StubType type) const {
471*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(type, StubType::kLast);
472*795d594fSAndroid Build Coastguard Worker   switch (type) {
473*795d594fSAndroid Build Coastguard Worker     // TODO: We could maybe clean this up if we stored them in an array in the oat header.
474*795d594fSAndroid Build Coastguard Worker     case StubType::kQuickGenericJNITrampoline:
475*795d594fSAndroid Build Coastguard Worker       return static_cast<const uint8_t*>(GetQuickGenericJniTrampoline());
476*795d594fSAndroid Build Coastguard Worker     case StubType::kJNIDlsymLookupTrampoline:
477*795d594fSAndroid Build Coastguard Worker       return static_cast<const uint8_t*>(GetJniDlsymLookupTrampoline());
478*795d594fSAndroid Build Coastguard Worker     case StubType::kJNIDlsymLookupCriticalTrampoline:
479*795d594fSAndroid Build Coastguard Worker       return static_cast<const uint8_t*>(GetJniDlsymLookupCriticalTrampoline());
480*795d594fSAndroid Build Coastguard Worker     case StubType::kQuickIMTConflictTrampoline:
481*795d594fSAndroid Build Coastguard Worker       return static_cast<const uint8_t*>(GetQuickImtConflictTrampoline());
482*795d594fSAndroid Build Coastguard Worker     case StubType::kQuickResolutionTrampoline:
483*795d594fSAndroid Build Coastguard Worker       return static_cast<const uint8_t*>(GetQuickResolutionTrampoline());
484*795d594fSAndroid Build Coastguard Worker     case StubType::kQuickToInterpreterBridge:
485*795d594fSAndroid Build Coastguard Worker       return static_cast<const uint8_t*>(GetQuickToInterpreterBridge());
486*795d594fSAndroid Build Coastguard Worker     case StubType::kNterpTrampoline:
487*795d594fSAndroid Build Coastguard Worker       return static_cast<const uint8_t*>(GetNterpTrampoline());
488*795d594fSAndroid Build Coastguard Worker   }
489*795d594fSAndroid Build Coastguard Worker }
490*795d594fSAndroid Build Coastguard Worker 
491*795d594fSAndroid Build Coastguard Worker }  // namespace art
492