xref: /aosp_15_r20/art/runtime/oat/oat_file.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_file.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <dlfcn.h>
20*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
21*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include <cstdint>
24*795d594fSAndroid Build Coastguard Worker #include <cstdlib>
25*795d594fSAndroid Build Coastguard Worker #include <cstring>
26*795d594fSAndroid Build Coastguard Worker #include <sstream>
27*795d594fSAndroid Build Coastguard Worker #include <type_traits>
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
30*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
31*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set_features.h"
32*795d594fSAndroid Build Coastguard Worker #include "art_method.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/bit_vector.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/file_utils.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/logging.h"  // For VLOG_IS_ON.
36*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
37*795d594fSAndroid Build Coastguard Worker #include "base/os.h"
38*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
39*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
40*795d594fSAndroid Build Coastguard Worker #include "base/systrace.h"
41*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
42*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
43*795d594fSAndroid Build Coastguard Worker #include "class_loader_context.h"
44*795d594fSAndroid Build Coastguard Worker #include "dex/art_dex_file_loader.h"
45*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
46*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
47*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_structs.h"
48*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
49*795d594fSAndroid Build Coastguard Worker #include "dex/standard_dex_file.h"
50*795d594fSAndroid Build Coastguard Worker #include "dex/type_lookup_table.h"
51*795d594fSAndroid Build Coastguard Worker #include "dex/utf-inl.h"
52*795d594fSAndroid Build Coastguard Worker #include "elf/elf_utils.h"
53*795d594fSAndroid Build Coastguard Worker #include "elf_file.h"
54*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
55*795d594fSAndroid Build Coastguard Worker #include "gc/space/image_space.h"
56*795d594fSAndroid Build Coastguard Worker #include "gc_root.h"
57*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
58*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
59*795d594fSAndroid Build Coastguard Worker #include "oat.h"
60*795d594fSAndroid Build Coastguard Worker #include "oat_file-inl.h"
61*795d594fSAndroid Build Coastguard Worker #include "oat_file_manager.h"
62*795d594fSAndroid Build Coastguard Worker #include "runtime-inl.h"
63*795d594fSAndroid Build Coastguard Worker #include "vdex_file.h"
64*795d594fSAndroid Build Coastguard Worker #include "verifier/verifier_deps.h"
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker #ifndef __APPLE__
67*795d594fSAndroid Build Coastguard Worker #include <link.h>  // for dl_iterate_phdr.
68*795d594fSAndroid Build Coastguard Worker #endif
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker // dlopen_ext support from bionic.
71*795d594fSAndroid Build Coastguard Worker #ifdef ART_TARGET_ANDROID
72*795d594fSAndroid Build Coastguard Worker #include "android/dlext.h"
73*795d594fSAndroid Build Coastguard Worker #include "nativeloader/dlext_namespaces.h"
74*795d594fSAndroid Build Coastguard Worker #endif
75*795d594fSAndroid Build Coastguard Worker 
76*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
77*795d594fSAndroid Build Coastguard Worker 
78*795d594fSAndroid Build Coastguard Worker using android::base::StringAppendV;
79*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
80*795d594fSAndroid Build Coastguard Worker 
81*795d594fSAndroid Build Coastguard Worker // Whether OatFile::Open will try dlopen. Fallback is our own ELF loader.
82*795d594fSAndroid Build Coastguard Worker static constexpr bool kUseDlopen = true;
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker // Whether OatFile::Open will try dlopen on the host. On the host we're not linking against
85*795d594fSAndroid Build Coastguard Worker // bionic, so cannot take advantage of the support for changed semantics (loading the same soname
86*795d594fSAndroid Build Coastguard Worker // multiple times). However, if/when we switch the above, we likely want to switch this, too,
87*795d594fSAndroid Build Coastguard Worker // to get test coverage of the code paths.
88*795d594fSAndroid Build Coastguard Worker static constexpr bool kUseDlopenOnHost = true;
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker // For debugging, Open will print DlOpen error message if set to true.
91*795d594fSAndroid Build Coastguard Worker static constexpr bool kPrintDlOpenErrorMessage = false;
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker // Note for OatFileBase and descendents:
94*795d594fSAndroid Build Coastguard Worker //
95*795d594fSAndroid Build Coastguard Worker // These are used in OatFile::Open to try all our loaders.
96*795d594fSAndroid Build Coastguard Worker //
97*795d594fSAndroid Build Coastguard Worker // The process is simple:
98*795d594fSAndroid Build Coastguard Worker //
99*795d594fSAndroid Build Coastguard Worker // 1) Allocate an instance through the standard constructor (location, executable)
100*795d594fSAndroid Build Coastguard Worker // 2) Load() to try to open the file.
101*795d594fSAndroid Build Coastguard Worker // 3) ComputeFields() to populate the OatFile fields like begin_, using FindDynamicSymbolAddress.
102*795d594fSAndroid Build Coastguard Worker // 4) PreSetup() for any steps that should be done before the final setup.
103*795d594fSAndroid Build Coastguard Worker // 5) Setup() to complete the procedure.
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker class OatFileBase : public OatFile {
106*795d594fSAndroid Build Coastguard Worker  public:
~OatFileBase()107*795d594fSAndroid Build Coastguard Worker   virtual ~OatFileBase() {}
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker   template <typename kOatFileBaseSubType>
110*795d594fSAndroid Build Coastguard Worker   static OatFileBase* OpenOatFile(int zip_fd,
111*795d594fSAndroid Build Coastguard Worker                                   const std::string& vdex_filename,
112*795d594fSAndroid Build Coastguard Worker                                   const std::string& elf_filename,
113*795d594fSAndroid Build Coastguard Worker                                   const std::string& location,
114*795d594fSAndroid Build Coastguard Worker                                   bool writable,
115*795d594fSAndroid Build Coastguard Worker                                   bool executable,
116*795d594fSAndroid Build Coastguard Worker                                   bool low_4gb,
117*795d594fSAndroid Build Coastguard Worker                                   ArrayRef<const std::string> dex_filenames,
118*795d594fSAndroid Build Coastguard Worker                                   ArrayRef<File> dex_files,
119*795d594fSAndroid Build Coastguard Worker                                   /*inout*/ MemMap* reservation,  // Where to load if not null.
120*795d594fSAndroid Build Coastguard Worker                                   /*out*/ std::string* error_msg);
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker   template <typename kOatFileBaseSubType>
123*795d594fSAndroid Build Coastguard Worker   static OatFileBase* OpenOatFile(int zip_fd,
124*795d594fSAndroid Build Coastguard Worker                                   int vdex_fd,
125*795d594fSAndroid Build Coastguard Worker                                   int oat_fd,
126*795d594fSAndroid Build Coastguard Worker                                   const std::string& vdex_filename,
127*795d594fSAndroid Build Coastguard Worker                                   const std::string& oat_filename,
128*795d594fSAndroid Build Coastguard Worker                                   bool writable,
129*795d594fSAndroid Build Coastguard Worker                                   bool executable,
130*795d594fSAndroid Build Coastguard Worker                                   bool low_4gb,
131*795d594fSAndroid Build Coastguard Worker                                   ArrayRef<const std::string> dex_filenames,
132*795d594fSAndroid Build Coastguard Worker                                   ArrayRef<File> dex_files,
133*795d594fSAndroid Build Coastguard Worker                                   /*inout*/ MemMap* reservation,  // Where to load if not null.
134*795d594fSAndroid Build Coastguard Worker                                   /*out*/ std::string* error_msg);
135*795d594fSAndroid Build Coastguard Worker 
136*795d594fSAndroid Build Coastguard Worker  protected:
OatFileBase(const std::string & filename,bool executable)137*795d594fSAndroid Build Coastguard Worker   OatFileBase(const std::string& filename, bool executable) : OatFile(filename, executable) {}
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker   virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
140*795d594fSAndroid Build Coastguard Worker                                                   std::string* error_msg) const = 0;
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker   virtual void PreLoad() = 0;
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker   bool LoadVdex(const std::string& vdex_filename,
145*795d594fSAndroid Build Coastguard Worker                 bool writable,
146*795d594fSAndroid Build Coastguard Worker                 bool low_4gb,
147*795d594fSAndroid Build Coastguard Worker                 std::string* error_msg);
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   bool LoadVdex(int vdex_fd,
150*795d594fSAndroid Build Coastguard Worker                 const std::string& vdex_filename,
151*795d594fSAndroid Build Coastguard Worker                 bool writable,
152*795d594fSAndroid Build Coastguard Worker                 bool low_4gb,
153*795d594fSAndroid Build Coastguard Worker                 std::string* error_msg);
154*795d594fSAndroid Build Coastguard Worker 
155*795d594fSAndroid Build Coastguard Worker   virtual bool Load(const std::string& elf_filename,
156*795d594fSAndroid Build Coastguard Worker                     bool writable,
157*795d594fSAndroid Build Coastguard Worker                     bool executable,
158*795d594fSAndroid Build Coastguard Worker                     bool low_4gb,
159*795d594fSAndroid Build Coastguard Worker                     /*inout*/MemMap* reservation,  // Where to load if not null.
160*795d594fSAndroid Build Coastguard Worker                     /*out*/std::string* error_msg) = 0;
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker   virtual bool Load(int oat_fd,
163*795d594fSAndroid Build Coastguard Worker                     bool writable,
164*795d594fSAndroid Build Coastguard Worker                     bool executable,
165*795d594fSAndroid Build Coastguard Worker                     bool low_4gb,
166*795d594fSAndroid Build Coastguard Worker                     /*inout*/MemMap* reservation,  // Where to load if not null.
167*795d594fSAndroid Build Coastguard Worker                     /*out*/std::string* error_msg) = 0;
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker   bool ComputeFields(const std::string& file_path, std::string* error_msg);
170*795d594fSAndroid Build Coastguard Worker 
171*795d594fSAndroid Build Coastguard Worker   virtual void PreSetup(const std::string& elf_filename) = 0;
172*795d594fSAndroid Build Coastguard Worker 
173*795d594fSAndroid Build Coastguard Worker   bool Setup(int zip_fd,
174*795d594fSAndroid Build Coastguard Worker              ArrayRef<const std::string> dex_filenames,
175*795d594fSAndroid Build Coastguard Worker              ArrayRef<File> dex_files,
176*795d594fSAndroid Build Coastguard Worker              std::string* error_msg);
177*795d594fSAndroid Build Coastguard Worker 
178*795d594fSAndroid Build Coastguard Worker   bool Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg);
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker   // Setters exposed for ElfOatFile.
181*795d594fSAndroid Build Coastguard Worker 
SetBegin(const uint8_t * begin)182*795d594fSAndroid Build Coastguard Worker   void SetBegin(const uint8_t* begin) {
183*795d594fSAndroid Build Coastguard Worker     begin_ = begin;
184*795d594fSAndroid Build Coastguard Worker   }
185*795d594fSAndroid Build Coastguard Worker 
SetEnd(const uint8_t * end)186*795d594fSAndroid Build Coastguard Worker   void SetEnd(const uint8_t* end) {
187*795d594fSAndroid Build Coastguard Worker     end_ = end;
188*795d594fSAndroid Build Coastguard Worker   }
189*795d594fSAndroid Build Coastguard Worker 
SetVdex(VdexFile * vdex)190*795d594fSAndroid Build Coastguard Worker   void SetVdex(VdexFile* vdex) {
191*795d594fSAndroid Build Coastguard Worker     vdex_.reset(vdex);
192*795d594fSAndroid Build Coastguard Worker   }
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker  private:
195*795d594fSAndroid Build Coastguard Worker   std::string ErrorPrintf(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
196*795d594fSAndroid Build Coastguard Worker   bool ReadIndexBssMapping(/*inout*/const uint8_t** oat,
197*795d594fSAndroid Build Coastguard Worker                            const char* container_tag,
198*795d594fSAndroid Build Coastguard Worker                            size_t dex_file_index,
199*795d594fSAndroid Build Coastguard Worker                            const std::string& dex_file_location,
200*795d594fSAndroid Build Coastguard Worker                            const char* entry_tag,
201*795d594fSAndroid Build Coastguard Worker                            /*out*/const IndexBssMapping** mapping,
202*795d594fSAndroid Build Coastguard Worker                            std::string* error_msg);
203*795d594fSAndroid Build Coastguard Worker   bool ReadBssMappingInfo(/*inout*/const uint8_t** oat,
204*795d594fSAndroid Build Coastguard Worker                           const char* container_tag,
205*795d594fSAndroid Build Coastguard Worker                           size_t dex_file_index,
206*795d594fSAndroid Build Coastguard Worker                           const std::string& dex_file_location,
207*795d594fSAndroid Build Coastguard Worker                           /*out*/BssMappingInfo* bss_mapping_info,
208*795d594fSAndroid Build Coastguard Worker                           std::string* error_msg);
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(OatFileBase);
211*795d594fSAndroid Build Coastguard Worker };
212*795d594fSAndroid Build Coastguard Worker 
213*795d594fSAndroid Build Coastguard Worker template <typename kOatFileBaseSubType>
OpenOatFile(int zip_fd,const std::string & vdex_filename,const std::string & elf_filename,const std::string & location,bool writable,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,ArrayRef<File> dex_files,MemMap * reservation,std::string * error_msg)214*795d594fSAndroid Build Coastguard Worker OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
215*795d594fSAndroid Build Coastguard Worker                                       const std::string& vdex_filename,
216*795d594fSAndroid Build Coastguard Worker                                       const std::string& elf_filename,
217*795d594fSAndroid Build Coastguard Worker                                       const std::string& location,
218*795d594fSAndroid Build Coastguard Worker                                       bool writable,
219*795d594fSAndroid Build Coastguard Worker                                       bool executable,
220*795d594fSAndroid Build Coastguard Worker                                       bool low_4gb,
221*795d594fSAndroid Build Coastguard Worker                                       ArrayRef<const std::string> dex_filenames,
222*795d594fSAndroid Build Coastguard Worker                                       ArrayRef<File> dex_files,
223*795d594fSAndroid Build Coastguard Worker                                       /*inout*/ MemMap* reservation,
224*795d594fSAndroid Build Coastguard Worker                                       /*out*/ std::string* error_msg) {
225*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable));
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker   ret->PreLoad();
228*795d594fSAndroid Build Coastguard Worker 
229*795d594fSAndroid Build Coastguard Worker   if (!ret->Load(elf_filename,
230*795d594fSAndroid Build Coastguard Worker                  writable,
231*795d594fSAndroid Build Coastguard Worker                  executable,
232*795d594fSAndroid Build Coastguard Worker                  low_4gb,
233*795d594fSAndroid Build Coastguard Worker                  reservation,
234*795d594fSAndroid Build Coastguard Worker                  error_msg)) {
235*795d594fSAndroid Build Coastguard Worker     return nullptr;
236*795d594fSAndroid Build Coastguard Worker   }
237*795d594fSAndroid Build Coastguard Worker 
238*795d594fSAndroid Build Coastguard Worker   if (!ret->ComputeFields(elf_filename, error_msg)) {
239*795d594fSAndroid Build Coastguard Worker     return nullptr;
240*795d594fSAndroid Build Coastguard Worker   }
241*795d594fSAndroid Build Coastguard Worker 
242*795d594fSAndroid Build Coastguard Worker   ret->PreSetup(elf_filename);
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker   if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) {
245*795d594fSAndroid Build Coastguard Worker     return nullptr;
246*795d594fSAndroid Build Coastguard Worker   }
247*795d594fSAndroid Build Coastguard Worker 
248*795d594fSAndroid Build Coastguard Worker   if (!ret->Setup(zip_fd, dex_filenames, dex_files, error_msg)) {
249*795d594fSAndroid Build Coastguard Worker     return nullptr;
250*795d594fSAndroid Build Coastguard Worker   }
251*795d594fSAndroid Build Coastguard Worker 
252*795d594fSAndroid Build Coastguard Worker   return ret.release();
253*795d594fSAndroid Build Coastguard Worker }
254*795d594fSAndroid Build Coastguard Worker 
255*795d594fSAndroid Build Coastguard Worker template <typename kOatFileBaseSubType>
OpenOatFile(int zip_fd,int vdex_fd,int oat_fd,const std::string & vdex_location,const std::string & oat_location,bool writable,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,ArrayRef<File> dex_files,MemMap * reservation,std::string * error_msg)256*795d594fSAndroid Build Coastguard Worker OatFileBase* OatFileBase::OpenOatFile(int zip_fd,
257*795d594fSAndroid Build Coastguard Worker                                       int vdex_fd,
258*795d594fSAndroid Build Coastguard Worker                                       int oat_fd,
259*795d594fSAndroid Build Coastguard Worker                                       const std::string& vdex_location,
260*795d594fSAndroid Build Coastguard Worker                                       const std::string& oat_location,
261*795d594fSAndroid Build Coastguard Worker                                       bool writable,
262*795d594fSAndroid Build Coastguard Worker                                       bool executable,
263*795d594fSAndroid Build Coastguard Worker                                       bool low_4gb,
264*795d594fSAndroid Build Coastguard Worker                                       ArrayRef<const std::string> dex_filenames,
265*795d594fSAndroid Build Coastguard Worker                                       ArrayRef<File> dex_files,
266*795d594fSAndroid Build Coastguard Worker                                       /*inout*/ MemMap* reservation,
267*795d594fSAndroid Build Coastguard Worker                                       /*out*/ std::string* error_msg) {
268*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(oat_location, executable));
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker   if (!ret->Load(oat_fd,
271*795d594fSAndroid Build Coastguard Worker                  writable,
272*795d594fSAndroid Build Coastguard Worker                  executable,
273*795d594fSAndroid Build Coastguard Worker                  low_4gb,
274*795d594fSAndroid Build Coastguard Worker                  reservation,
275*795d594fSAndroid Build Coastguard Worker                  error_msg)) {
276*795d594fSAndroid Build Coastguard Worker     return nullptr;
277*795d594fSAndroid Build Coastguard Worker   }
278*795d594fSAndroid Build Coastguard Worker 
279*795d594fSAndroid Build Coastguard Worker   if (!ret->ComputeFields(oat_location, error_msg)) {
280*795d594fSAndroid Build Coastguard Worker     return nullptr;
281*795d594fSAndroid Build Coastguard Worker   }
282*795d594fSAndroid Build Coastguard Worker 
283*795d594fSAndroid Build Coastguard Worker   ret->PreSetup(oat_location);
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker   if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) {
286*795d594fSAndroid Build Coastguard Worker     return nullptr;
287*795d594fSAndroid Build Coastguard Worker   }
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker   if (!ret->Setup(zip_fd, dex_filenames, dex_files, error_msg)) {
290*795d594fSAndroid Build Coastguard Worker     return nullptr;
291*795d594fSAndroid Build Coastguard Worker   }
292*795d594fSAndroid Build Coastguard Worker 
293*795d594fSAndroid Build Coastguard Worker   return ret.release();
294*795d594fSAndroid Build Coastguard Worker }
295*795d594fSAndroid Build Coastguard Worker 
LoadVdex(const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)296*795d594fSAndroid Build Coastguard Worker bool OatFileBase::LoadVdex(const std::string& vdex_filename,
297*795d594fSAndroid Build Coastguard Worker                            bool writable,
298*795d594fSAndroid Build Coastguard Worker                            bool low_4gb,
299*795d594fSAndroid Build Coastguard Worker                            std::string* error_msg) {
300*795d594fSAndroid Build Coastguard Worker   vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
301*795d594fSAndroid Build Coastguard Worker                                   vdex_end_ - vdex_begin_,
302*795d594fSAndroid Build Coastguard Worker                                   /*mmap_reuse=*/vdex_begin_ != nullptr,
303*795d594fSAndroid Build Coastguard Worker                                   vdex_filename,
304*795d594fSAndroid Build Coastguard Worker                                   writable,
305*795d594fSAndroid Build Coastguard Worker                                   low_4gb,
306*795d594fSAndroid Build Coastguard Worker                                   error_msg);
307*795d594fSAndroid Build Coastguard Worker   if (vdex_.get() == nullptr) {
308*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to load vdex file '%s' %s",
309*795d594fSAndroid Build Coastguard Worker                               vdex_filename.c_str(),
310*795d594fSAndroid Build Coastguard Worker                               error_msg->c_str());
311*795d594fSAndroid Build Coastguard Worker     return false;
312*795d594fSAndroid Build Coastguard Worker   }
313*795d594fSAndroid Build Coastguard Worker   return true;
314*795d594fSAndroid Build Coastguard Worker }
315*795d594fSAndroid Build Coastguard Worker 
LoadVdex(int vdex_fd,const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)316*795d594fSAndroid Build Coastguard Worker bool OatFileBase::LoadVdex(int vdex_fd,
317*795d594fSAndroid Build Coastguard Worker                            const std::string& vdex_filename,
318*795d594fSAndroid Build Coastguard Worker                            bool writable,
319*795d594fSAndroid Build Coastguard Worker                            bool low_4gb,
320*795d594fSAndroid Build Coastguard Worker                            std::string* error_msg) {
321*795d594fSAndroid Build Coastguard Worker   if (vdex_fd != -1) {
322*795d594fSAndroid Build Coastguard Worker     struct stat s;
323*795d594fSAndroid Build Coastguard Worker     int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd, &s));
324*795d594fSAndroid Build Coastguard Worker     if (rc == -1) {
325*795d594fSAndroid Build Coastguard Worker       PLOG(WARNING) << "Failed getting length of vdex file";
326*795d594fSAndroid Build Coastguard Worker     } else {
327*795d594fSAndroid Build Coastguard Worker       vdex_ = VdexFile::OpenAtAddress(vdex_begin_,
328*795d594fSAndroid Build Coastguard Worker                                       vdex_end_ - vdex_begin_,
329*795d594fSAndroid Build Coastguard Worker                                       /*mmap_reuse=*/vdex_begin_ != nullptr,
330*795d594fSAndroid Build Coastguard Worker                                       vdex_fd,
331*795d594fSAndroid Build Coastguard Worker                                       s.st_size,
332*795d594fSAndroid Build Coastguard Worker                                       vdex_filename,
333*795d594fSAndroid Build Coastguard Worker                                       writable,
334*795d594fSAndroid Build Coastguard Worker                                       low_4gb,
335*795d594fSAndroid Build Coastguard Worker                                       error_msg);
336*795d594fSAndroid Build Coastguard Worker       if (vdex_.get() == nullptr) {
337*795d594fSAndroid Build Coastguard Worker         *error_msg = "Failed opening vdex file.";
338*795d594fSAndroid Build Coastguard Worker         return false;
339*795d594fSAndroid Build Coastguard Worker       }
340*795d594fSAndroid Build Coastguard Worker     }
341*795d594fSAndroid Build Coastguard Worker   }
342*795d594fSAndroid Build Coastguard Worker   return true;
343*795d594fSAndroid Build Coastguard Worker }
344*795d594fSAndroid Build Coastguard Worker 
ComputeFields(const std::string & file_path,std::string * error_msg)345*795d594fSAndroid Build Coastguard Worker bool OatFileBase::ComputeFields(const std::string& file_path, std::string* error_msg) {
346*795d594fSAndroid Build Coastguard Worker   std::string symbol_error_msg;
347*795d594fSAndroid Build Coastguard Worker   begin_ = FindDynamicSymbolAddress("oatdata", &symbol_error_msg);
348*795d594fSAndroid Build Coastguard Worker   if (begin_ == nullptr) {
349*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find oatdata symbol in '%s' %s",
350*795d594fSAndroid Build Coastguard Worker                               file_path.c_str(),
351*795d594fSAndroid Build Coastguard Worker                               symbol_error_msg.c_str());
352*795d594fSAndroid Build Coastguard Worker     return false;
353*795d594fSAndroid Build Coastguard Worker   }
354*795d594fSAndroid Build Coastguard Worker   end_ = FindDynamicSymbolAddress("oatlastword", &symbol_error_msg);
355*795d594fSAndroid Build Coastguard Worker   if (end_ == nullptr) {
356*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to find oatlastword symbol in '%s' %s",
357*795d594fSAndroid Build Coastguard Worker                               file_path.c_str(),
358*795d594fSAndroid Build Coastguard Worker                               symbol_error_msg.c_str());
359*795d594fSAndroid Build Coastguard Worker     return false;
360*795d594fSAndroid Build Coastguard Worker   }
361*795d594fSAndroid Build Coastguard Worker   // Readjust to be non-inclusive upper bound.
362*795d594fSAndroid Build Coastguard Worker   end_ += sizeof(uint32_t);
363*795d594fSAndroid Build Coastguard Worker 
364*795d594fSAndroid Build Coastguard Worker   data_img_rel_ro_begin_ = FindDynamicSymbolAddress("oatdataimgrelro", &symbol_error_msg);
365*795d594fSAndroid Build Coastguard Worker   if (data_img_rel_ro_begin_ != nullptr) {
366*795d594fSAndroid Build Coastguard Worker     data_img_rel_ro_end_ =
367*795d594fSAndroid Build Coastguard Worker         FindDynamicSymbolAddress("oatdataimgrelrolastword", &symbol_error_msg);
368*795d594fSAndroid Build Coastguard Worker     if (data_img_rel_ro_end_ == nullptr) {
369*795d594fSAndroid Build Coastguard Worker       *error_msg =
370*795d594fSAndroid Build Coastguard Worker           StringPrintf("Failed to find oatdataimgrelrolastword symbol in '%s'", file_path.c_str());
371*795d594fSAndroid Build Coastguard Worker       return false;
372*795d594fSAndroid Build Coastguard Worker     }
373*795d594fSAndroid Build Coastguard Worker     // Readjust to be non-inclusive upper bound.
374*795d594fSAndroid Build Coastguard Worker     data_img_rel_ro_end_ += sizeof(uint32_t);
375*795d594fSAndroid Build Coastguard Worker     data_img_rel_ro_app_image_ =
376*795d594fSAndroid Build Coastguard Worker         FindDynamicSymbolAddress("oatdataimgrelroappimage", &symbol_error_msg);
377*795d594fSAndroid Build Coastguard Worker     if (data_img_rel_ro_app_image_ == nullptr) {
378*795d594fSAndroid Build Coastguard Worker       data_img_rel_ro_app_image_ = data_img_rel_ro_end_;
379*795d594fSAndroid Build Coastguard Worker     }
380*795d594fSAndroid Build Coastguard Worker   }
381*795d594fSAndroid Build Coastguard Worker 
382*795d594fSAndroid Build Coastguard Worker   bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg));
383*795d594fSAndroid Build Coastguard Worker   if (bss_begin_ == nullptr) {
384*795d594fSAndroid Build Coastguard Worker     // No .bss section.
385*795d594fSAndroid Build Coastguard Worker     bss_end_ = nullptr;
386*795d594fSAndroid Build Coastguard Worker   } else {
387*795d594fSAndroid Build Coastguard Worker     bss_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbsslastword", &symbol_error_msg));
388*795d594fSAndroid Build Coastguard Worker     if (bss_end_ == nullptr) {
389*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to find oatbsslastword symbol in '%s'", file_path.c_str());
390*795d594fSAndroid Build Coastguard Worker       return false;
391*795d594fSAndroid Build Coastguard Worker     }
392*795d594fSAndroid Build Coastguard Worker     // Readjust to be non-inclusive upper bound.
393*795d594fSAndroid Build Coastguard Worker     bss_end_ += sizeof(uint32_t);
394*795d594fSAndroid Build Coastguard Worker     // Find bss methods if present.
395*795d594fSAndroid Build Coastguard Worker     bss_methods_ =
396*795d594fSAndroid Build Coastguard Worker         const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssmethods", &symbol_error_msg));
397*795d594fSAndroid Build Coastguard Worker     // Find bss roots if present.
398*795d594fSAndroid Build Coastguard Worker     bss_roots_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbssroots", &symbol_error_msg));
399*795d594fSAndroid Build Coastguard Worker   }
400*795d594fSAndroid Build Coastguard Worker 
401*795d594fSAndroid Build Coastguard Worker   vdex_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdex", &symbol_error_msg));
402*795d594fSAndroid Build Coastguard Worker   if (vdex_begin_ == nullptr) {
403*795d594fSAndroid Build Coastguard Worker     // No .vdex section.
404*795d594fSAndroid Build Coastguard Worker     vdex_end_ = nullptr;
405*795d594fSAndroid Build Coastguard Worker   } else {
406*795d594fSAndroid Build Coastguard Worker     vdex_end_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatdexlastword", &symbol_error_msg));
407*795d594fSAndroid Build Coastguard Worker     if (vdex_end_ == nullptr) {
408*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to find oatdexlastword symbol in '%s'", file_path.c_str());
409*795d594fSAndroid Build Coastguard Worker       return false;
410*795d594fSAndroid Build Coastguard Worker     }
411*795d594fSAndroid Build Coastguard Worker     // Readjust to be non-inclusive upper bound.
412*795d594fSAndroid Build Coastguard Worker     vdex_end_ += sizeof(uint32_t);
413*795d594fSAndroid Build Coastguard Worker   }
414*795d594fSAndroid Build Coastguard Worker 
415*795d594fSAndroid Build Coastguard Worker   return true;
416*795d594fSAndroid Build Coastguard Worker }
417*795d594fSAndroid Build Coastguard Worker 
418*795d594fSAndroid Build Coastguard Worker // Read an unaligned entry from the OatDexFile data in OatFile and advance the read
419*795d594fSAndroid Build Coastguard Worker // position by the number of bytes read, i.e. sizeof(T).
420*795d594fSAndroid Build Coastguard Worker // Return true on success, false if the read would go beyond the end of the OatFile.
421*795d594fSAndroid Build Coastguard Worker template <typename T>
ReadOatDexFileData(const OatFile & oat_file,const uint8_t ** oat,T * value)422*795d594fSAndroid Build Coastguard Worker inline static bool ReadOatDexFileData(const OatFile& oat_file,
423*795d594fSAndroid Build Coastguard Worker                                       /*inout*/const uint8_t** oat,
424*795d594fSAndroid Build Coastguard Worker                                       /*out*/T* value) {
425*795d594fSAndroid Build Coastguard Worker   DCHECK(oat != nullptr);
426*795d594fSAndroid Build Coastguard Worker   DCHECK(value != nullptr);
427*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(*oat, oat_file.End());
428*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(static_cast<size_t>(oat_file.End() - *oat) < sizeof(T))) {
429*795d594fSAndroid Build Coastguard Worker     return false;
430*795d594fSAndroid Build Coastguard Worker   }
431*795d594fSAndroid Build Coastguard Worker   static_assert(std::is_trivial<T>::value, "T must be a trivial type");
432*795d594fSAndroid Build Coastguard Worker   using unaligned_type __attribute__((__aligned__(1))) = T;
433*795d594fSAndroid Build Coastguard Worker   *value = *reinterpret_cast<const unaligned_type*>(*oat);
434*795d594fSAndroid Build Coastguard Worker   *oat += sizeof(T);
435*795d594fSAndroid Build Coastguard Worker   return true;
436*795d594fSAndroid Build Coastguard Worker }
437*795d594fSAndroid Build Coastguard Worker 
ErrorPrintf(const char * fmt,...)438*795d594fSAndroid Build Coastguard Worker std::string OatFileBase::ErrorPrintf(const char* fmt, ...) {
439*795d594fSAndroid Build Coastguard Worker   std::string error_msg = StringPrintf("In oat file '%s': ", GetLocation().c_str());
440*795d594fSAndroid Build Coastguard Worker   va_list args;
441*795d594fSAndroid Build Coastguard Worker   va_start(args, fmt);
442*795d594fSAndroid Build Coastguard Worker   StringAppendV(&error_msg, fmt, args);
443*795d594fSAndroid Build Coastguard Worker   va_end(args);
444*795d594fSAndroid Build Coastguard Worker   return error_msg;
445*795d594fSAndroid Build Coastguard Worker }
446*795d594fSAndroid Build Coastguard Worker 
ReadIndexBssMapping(const uint8_t ** oat,const char * container_tag,size_t dex_file_index,const std::string & dex_file_location,const char * entry_tag,const IndexBssMapping ** mapping,std::string * error_msg)447*795d594fSAndroid Build Coastguard Worker bool OatFileBase::ReadIndexBssMapping(/*inout*/const uint8_t** oat,
448*795d594fSAndroid Build Coastguard Worker                                       const char* container_tag,
449*795d594fSAndroid Build Coastguard Worker                                       size_t dex_file_index,
450*795d594fSAndroid Build Coastguard Worker                                       const std::string& dex_file_location,
451*795d594fSAndroid Build Coastguard Worker                                       const char* entry_tag,
452*795d594fSAndroid Build Coastguard Worker                                       /*out*/const IndexBssMapping** mapping,
453*795d594fSAndroid Build Coastguard Worker                                       std::string* error_msg) {
454*795d594fSAndroid Build Coastguard Worker   uint32_t index_bss_mapping_offset;
455*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!ReadOatDexFileData(*this, oat, &index_bss_mapping_offset))) {
456*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf("%s #%zd for '%s' truncated, missing %s bss mapping offset",
457*795d594fSAndroid Build Coastguard Worker                              container_tag,
458*795d594fSAndroid Build Coastguard Worker                              dex_file_index,
459*795d594fSAndroid Build Coastguard Worker                              dex_file_location.c_str(),
460*795d594fSAndroid Build Coastguard Worker                              entry_tag);
461*795d594fSAndroid Build Coastguard Worker     return false;
462*795d594fSAndroid Build Coastguard Worker   }
463*795d594fSAndroid Build Coastguard Worker   const bool readable_index_bss_mapping_size =
464*795d594fSAndroid Build Coastguard Worker       index_bss_mapping_offset != 0u &&
465*795d594fSAndroid Build Coastguard Worker       index_bss_mapping_offset <= Size() &&
466*795d594fSAndroid Build Coastguard Worker       IsAligned<alignof(IndexBssMapping)>(index_bss_mapping_offset) &&
467*795d594fSAndroid Build Coastguard Worker       Size() - index_bss_mapping_offset >= IndexBssMapping::ComputeSize(0);
468*795d594fSAndroid Build Coastguard Worker   const IndexBssMapping* index_bss_mapping = readable_index_bss_mapping_size
469*795d594fSAndroid Build Coastguard Worker       ? reinterpret_cast<const IndexBssMapping*>(Begin() + index_bss_mapping_offset)
470*795d594fSAndroid Build Coastguard Worker       : nullptr;
471*795d594fSAndroid Build Coastguard Worker   if (index_bss_mapping_offset != 0u &&
472*795d594fSAndroid Build Coastguard Worker       (UNLIKELY(index_bss_mapping == nullptr) ||
473*795d594fSAndroid Build Coastguard Worker           UNLIKELY(index_bss_mapping->size() == 0u) ||
474*795d594fSAndroid Build Coastguard Worker           UNLIKELY(Size() - index_bss_mapping_offset <
475*795d594fSAndroid Build Coastguard Worker                    IndexBssMapping::ComputeSize(index_bss_mapping->size())))) {
476*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf("%s #%zu for '%s' with unaligned or "
477*795d594fSAndroid Build Coastguard Worker                                  "truncated %s bss mapping, offset %u of %zu, length %zu",
478*795d594fSAndroid Build Coastguard Worker                              container_tag,
479*795d594fSAndroid Build Coastguard Worker                              dex_file_index,
480*795d594fSAndroid Build Coastguard Worker                              dex_file_location.c_str(),
481*795d594fSAndroid Build Coastguard Worker                              entry_tag,
482*795d594fSAndroid Build Coastguard Worker                              index_bss_mapping_offset,
483*795d594fSAndroid Build Coastguard Worker                              Size(),
484*795d594fSAndroid Build Coastguard Worker                              index_bss_mapping != nullptr ? index_bss_mapping->size() : 0u);
485*795d594fSAndroid Build Coastguard Worker     return false;
486*795d594fSAndroid Build Coastguard Worker   }
487*795d594fSAndroid Build Coastguard Worker 
488*795d594fSAndroid Build Coastguard Worker   *mapping = index_bss_mapping;
489*795d594fSAndroid Build Coastguard Worker   return true;
490*795d594fSAndroid Build Coastguard Worker }
491*795d594fSAndroid Build Coastguard Worker 
ReadBssMappingInfo(const uint8_t ** oat,const char * container_tag,size_t dex_file_index,const std::string & dex_file_location,BssMappingInfo * bss_mapping_info,std::string * error_msg)492*795d594fSAndroid Build Coastguard Worker bool OatFileBase::ReadBssMappingInfo(/*inout*/const uint8_t** oat,
493*795d594fSAndroid Build Coastguard Worker                                      const char* container_tag,
494*795d594fSAndroid Build Coastguard Worker                                      size_t dex_file_index,
495*795d594fSAndroid Build Coastguard Worker                                      const std::string& dex_file_location,
496*795d594fSAndroid Build Coastguard Worker                                      /*out*/BssMappingInfo* bss_mapping_info,
497*795d594fSAndroid Build Coastguard Worker                                      std::string* error_msg) {
498*795d594fSAndroid Build Coastguard Worker   auto read_index_bss_mapping = [&](const char* tag, /*out*/const IndexBssMapping** mapping) {
499*795d594fSAndroid Build Coastguard Worker     return ReadIndexBssMapping(
500*795d594fSAndroid Build Coastguard Worker         oat, container_tag, dex_file_index, dex_file_location, tag, mapping, error_msg);
501*795d594fSAndroid Build Coastguard Worker   };
502*795d594fSAndroid Build Coastguard Worker   return read_index_bss_mapping("method", &bss_mapping_info->method_bss_mapping) &&
503*795d594fSAndroid Build Coastguard Worker          read_index_bss_mapping("type", &bss_mapping_info->type_bss_mapping) &&
504*795d594fSAndroid Build Coastguard Worker          read_index_bss_mapping("public type", &bss_mapping_info->public_type_bss_mapping) &&
505*795d594fSAndroid Build Coastguard Worker          read_index_bss_mapping("package type", &bss_mapping_info->package_type_bss_mapping) &&
506*795d594fSAndroid Build Coastguard Worker          read_index_bss_mapping("string", &bss_mapping_info->string_bss_mapping) &&
507*795d594fSAndroid Build Coastguard Worker          read_index_bss_mapping("method type", &bss_mapping_info->method_type_bss_mapping);
508*795d594fSAndroid Build Coastguard Worker }
509*795d594fSAndroid Build Coastguard Worker 
ComputeAndCheckTypeLookupTableData(const DexFile::Header & header,const uint8_t * type_lookup_table_start,const VdexFile * vdex_file,const uint8_t ** type_lookup_table_data,std::string * error_msg)510*795d594fSAndroid Build Coastguard Worker static bool ComputeAndCheckTypeLookupTableData(const DexFile::Header& header,
511*795d594fSAndroid Build Coastguard Worker                                                const uint8_t* type_lookup_table_start,
512*795d594fSAndroid Build Coastguard Worker                                                const VdexFile* vdex_file,
513*795d594fSAndroid Build Coastguard Worker                                                const uint8_t** type_lookup_table_data,
514*795d594fSAndroid Build Coastguard Worker                                                std::string* error_msg) {
515*795d594fSAndroid Build Coastguard Worker   if (type_lookup_table_start == nullptr) {
516*795d594fSAndroid Build Coastguard Worker     *type_lookup_table_data = nullptr;
517*795d594fSAndroid Build Coastguard Worker     return true;
518*795d594fSAndroid Build Coastguard Worker   }
519*795d594fSAndroid Build Coastguard Worker 
520*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!vdex_file->Contains(type_lookup_table_start, sizeof(uint32_t)))) {
521*795d594fSAndroid Build Coastguard Worker     *error_msg =
522*795d594fSAndroid Build Coastguard Worker         StringPrintf("In vdex file '%s' found invalid type lookup table start %p of size %zu "
523*795d594fSAndroid Build Coastguard Worker                          "not in [%p, %p]",
524*795d594fSAndroid Build Coastguard Worker                      vdex_file->GetName().c_str(),
525*795d594fSAndroid Build Coastguard Worker                      type_lookup_table_start,
526*795d594fSAndroid Build Coastguard Worker                      sizeof(uint32_t),
527*795d594fSAndroid Build Coastguard Worker                      vdex_file->Begin(),
528*795d594fSAndroid Build Coastguard Worker                      vdex_file->End());
529*795d594fSAndroid Build Coastguard Worker     return false;
530*795d594fSAndroid Build Coastguard Worker   }
531*795d594fSAndroid Build Coastguard Worker 
532*795d594fSAndroid Build Coastguard Worker   size_t found_size = reinterpret_cast<const uint32_t*>(type_lookup_table_start)[0];
533*795d594fSAndroid Build Coastguard Worker   size_t expected_table_size = TypeLookupTable::RawDataLength(header.class_defs_size_);
534*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(found_size != expected_table_size)) {
535*795d594fSAndroid Build Coastguard Worker     *error_msg =
536*795d594fSAndroid Build Coastguard Worker         StringPrintf("In vdex file '%s' unexpected type lookup table size: found %zu, expected %zu",
537*795d594fSAndroid Build Coastguard Worker                      vdex_file->GetName().c_str(),
538*795d594fSAndroid Build Coastguard Worker                      found_size,
539*795d594fSAndroid Build Coastguard Worker                      expected_table_size);
540*795d594fSAndroid Build Coastguard Worker     return false;
541*795d594fSAndroid Build Coastguard Worker   }
542*795d594fSAndroid Build Coastguard Worker 
543*795d594fSAndroid Build Coastguard Worker   if (found_size == 0) {
544*795d594fSAndroid Build Coastguard Worker     *type_lookup_table_data = nullptr;
545*795d594fSAndroid Build Coastguard Worker     return true;
546*795d594fSAndroid Build Coastguard Worker   }
547*795d594fSAndroid Build Coastguard Worker 
548*795d594fSAndroid Build Coastguard Worker   *type_lookup_table_data = type_lookup_table_start + sizeof(uint32_t);
549*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!vdex_file->Contains(*type_lookup_table_data, found_size))) {
550*795d594fSAndroid Build Coastguard Worker     *error_msg =
551*795d594fSAndroid Build Coastguard Worker         StringPrintf("In vdex file '%s' found invalid type lookup table data %p of size %zu "
552*795d594fSAndroid Build Coastguard Worker                          "not in [%p, %p]",
553*795d594fSAndroid Build Coastguard Worker                      vdex_file->GetName().c_str(),
554*795d594fSAndroid Build Coastguard Worker                      type_lookup_table_data,
555*795d594fSAndroid Build Coastguard Worker                      found_size,
556*795d594fSAndroid Build Coastguard Worker                      vdex_file->Begin(),
557*795d594fSAndroid Build Coastguard Worker                      vdex_file->End());
558*795d594fSAndroid Build Coastguard Worker     return false;
559*795d594fSAndroid Build Coastguard Worker   }
560*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(!IsAligned<4>(type_lookup_table_start))) {
561*795d594fSAndroid Build Coastguard Worker     *error_msg =
562*795d594fSAndroid Build Coastguard Worker         StringPrintf("In vdex file '%s' found invalid type lookup table alignment %p",
563*795d594fSAndroid Build Coastguard Worker                      vdex_file->GetName().c_str(),
564*795d594fSAndroid Build Coastguard Worker                      type_lookup_table_start);
565*795d594fSAndroid Build Coastguard Worker     return false;
566*795d594fSAndroid Build Coastguard Worker   }
567*795d594fSAndroid Build Coastguard Worker   return true;
568*795d594fSAndroid Build Coastguard Worker }
569*795d594fSAndroid Build Coastguard Worker 
Setup(const std::vector<const DexFile * > & dex_files,std::string * error_msg)570*795d594fSAndroid Build Coastguard Worker bool OatFileBase::Setup(const std::vector<const DexFile*>& dex_files, std::string* error_msg) {
571*795d594fSAndroid Build Coastguard Worker   uint32_t i = 0;
572*795d594fSAndroid Build Coastguard Worker   const uint8_t* type_lookup_table_start = nullptr;
573*795d594fSAndroid Build Coastguard Worker   for (const DexFile* dex_file : dex_files) {
574*795d594fSAndroid Build Coastguard Worker     // Defensively verify external dex file checksum. `OatFileAssistant`
575*795d594fSAndroid Build Coastguard Worker     // expects this check to happen during oat file setup when the oat file
576*795d594fSAndroid Build Coastguard Worker     // does not contain dex code.
577*795d594fSAndroid Build Coastguard Worker     if (dex_file->GetLocationChecksum() != vdex_->GetLocationChecksum(i)) {
578*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Dex checksum does not match for %s, dex has %d, vdex has %d",
579*795d594fSAndroid Build Coastguard Worker                                 dex_file->GetLocation().c_str(),
580*795d594fSAndroid Build Coastguard Worker                                 dex_file->GetLocationChecksum(),
581*795d594fSAndroid Build Coastguard Worker                                 vdex_->GetLocationChecksum(i));
582*795d594fSAndroid Build Coastguard Worker       return false;
583*795d594fSAndroid Build Coastguard Worker     }
584*795d594fSAndroid Build Coastguard Worker     std::string dex_location = dex_file->GetLocation();
585*795d594fSAndroid Build Coastguard Worker     std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location.c_str());
586*795d594fSAndroid Build Coastguard Worker 
587*795d594fSAndroid Build Coastguard Worker     type_lookup_table_start = vdex_->GetNextTypeLookupTableData(type_lookup_table_start, i++);
588*795d594fSAndroid Build Coastguard Worker     const uint8_t* type_lookup_table_data = nullptr;
589*795d594fSAndroid Build Coastguard Worker     if (!ComputeAndCheckTypeLookupTableData(dex_file->GetHeader(),
590*795d594fSAndroid Build Coastguard Worker                                             type_lookup_table_start,
591*795d594fSAndroid Build Coastguard Worker                                             vdex_.get(),
592*795d594fSAndroid Build Coastguard Worker                                             &type_lookup_table_data,
593*795d594fSAndroid Build Coastguard Worker                                             error_msg)) {
594*795d594fSAndroid Build Coastguard Worker       return false;
595*795d594fSAndroid Build Coastguard Worker     }
596*795d594fSAndroid Build Coastguard Worker     // Create an OatDexFile and add it to the owning container.
597*795d594fSAndroid Build Coastguard Worker     OatDexFile* oat_dex_file = new OatDexFile(this,
598*795d594fSAndroid Build Coastguard Worker                                               dex_file->GetContainer(),
599*795d594fSAndroid Build Coastguard Worker                                               dex_file->Begin(),
600*795d594fSAndroid Build Coastguard Worker                                               dex_file->GetHeader().magic_,
601*795d594fSAndroid Build Coastguard Worker                                               dex_file->GetLocationChecksum(),
602*795d594fSAndroid Build Coastguard Worker                                               dex_file->GetSha1(),
603*795d594fSAndroid Build Coastguard Worker                                               dex_location,
604*795d594fSAndroid Build Coastguard Worker                                               canonical_location,
605*795d594fSAndroid Build Coastguard Worker                                               type_lookup_table_data);
606*795d594fSAndroid Build Coastguard Worker     oat_dex_files_storage_.push_back(oat_dex_file);
607*795d594fSAndroid Build Coastguard Worker 
608*795d594fSAndroid Build Coastguard Worker     // Add the location and canonical location (if different) to the oat_dex_files_ table.
609*795d594fSAndroid Build Coastguard Worker     std::string_view key(oat_dex_file->GetDexFileLocation());
610*795d594fSAndroid Build Coastguard Worker     oat_dex_files_.Put(key, oat_dex_file);
611*795d594fSAndroid Build Coastguard Worker     if (canonical_location != dex_location) {
612*795d594fSAndroid Build Coastguard Worker       std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
613*795d594fSAndroid Build Coastguard Worker       oat_dex_files_.Put(canonical_key, oat_dex_file);
614*795d594fSAndroid Build Coastguard Worker     }
615*795d594fSAndroid Build Coastguard Worker   }
616*795d594fSAndroid Build Coastguard Worker   // Now that we've created all the OatDexFile, update the dex files.
617*795d594fSAndroid Build Coastguard Worker   for (i = 0; i < dex_files.size(); ++i) {
618*795d594fSAndroid Build Coastguard Worker     dex_files[i]->SetOatDexFile(oat_dex_files_storage_[i]);
619*795d594fSAndroid Build Coastguard Worker   }
620*795d594fSAndroid Build Coastguard Worker   return true;
621*795d594fSAndroid Build Coastguard Worker }
622*795d594fSAndroid Build Coastguard Worker 
Setup(int zip_fd,ArrayRef<const std::string> dex_filenames,ArrayRef<File> dex_files,std::string * error_msg)623*795d594fSAndroid Build Coastguard Worker bool OatFileBase::Setup(int zip_fd,
624*795d594fSAndroid Build Coastguard Worker                         ArrayRef<const std::string> dex_filenames,
625*795d594fSAndroid Build Coastguard Worker                         ArrayRef<File> dex_files,
626*795d594fSAndroid Build Coastguard Worker                         std::string* error_msg) {
627*795d594fSAndroid Build Coastguard Worker   if (!GetOatHeader().IsValid()) {
628*795d594fSAndroid Build Coastguard Worker     std::string cause = GetOatHeader().GetValidationErrorMessage();
629*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf("invalid oat header: %s", cause.c_str());
630*795d594fSAndroid Build Coastguard Worker     return false;
631*795d594fSAndroid Build Coastguard Worker   }
632*795d594fSAndroid Build Coastguard Worker   PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
633*795d594fSAndroid Build Coastguard Worker   size_t key_value_store_size =
634*795d594fSAndroid Build Coastguard Worker       (Size() >= sizeof(OatHeader)) ? GetOatHeader().GetKeyValueStoreSize() : 0u;
635*795d594fSAndroid Build Coastguard Worker   if (Size() < sizeof(OatHeader) + key_value_store_size) {
636*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf("truncated oat header, size = %zu < %zu + %zu",
637*795d594fSAndroid Build Coastguard Worker                              Size(),
638*795d594fSAndroid Build Coastguard Worker                              sizeof(OatHeader),
639*795d594fSAndroid Build Coastguard Worker                              key_value_store_size);
640*795d594fSAndroid Build Coastguard Worker     return false;
641*795d594fSAndroid Build Coastguard Worker   }
642*795d594fSAndroid Build Coastguard Worker 
643*795d594fSAndroid Build Coastguard Worker   size_t oat_dex_files_offset = GetOatHeader().GetOatDexFilesOffset();
644*795d594fSAndroid Build Coastguard Worker   if (oat_dex_files_offset < GetOatHeader().GetHeaderSize() || oat_dex_files_offset > Size()) {
645*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf("invalid oat dex files offset: %zu is not in [%zu, %zu]",
646*795d594fSAndroid Build Coastguard Worker                              oat_dex_files_offset,
647*795d594fSAndroid Build Coastguard Worker                              GetOatHeader().GetHeaderSize(),
648*795d594fSAndroid Build Coastguard Worker                              Size());
649*795d594fSAndroid Build Coastguard Worker     return false;
650*795d594fSAndroid Build Coastguard Worker   }
651*795d594fSAndroid Build Coastguard Worker   const uint8_t* oat = Begin() + oat_dex_files_offset;  // Jump to the OatDexFile records.
652*795d594fSAndroid Build Coastguard Worker 
653*795d594fSAndroid Build Coastguard Worker   if (!IsAligned<sizeof(uint32_t)>(data_img_rel_ro_begin_) ||
654*795d594fSAndroid Build Coastguard Worker       !IsAligned<sizeof(uint32_t)>(data_img_rel_ro_end_) ||
655*795d594fSAndroid Build Coastguard Worker       !IsAligned<sizeof(uint32_t)>(data_img_rel_ro_app_image_) ||
656*795d594fSAndroid Build Coastguard Worker       data_img_rel_ro_begin_ > data_img_rel_ro_end_ ||
657*795d594fSAndroid Build Coastguard Worker       data_img_rel_ro_begin_ > data_img_rel_ro_app_image_ ||
658*795d594fSAndroid Build Coastguard Worker       data_img_rel_ro_app_image_ > data_img_rel_ro_end_) {
659*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf(
660*795d594fSAndroid Build Coastguard Worker         "unaligned or unordered databimgrelro symbol(s): begin = %p, end = %p, app_image = %p",
661*795d594fSAndroid Build Coastguard Worker         data_img_rel_ro_begin_,
662*795d594fSAndroid Build Coastguard Worker         data_img_rel_ro_end_,
663*795d594fSAndroid Build Coastguard Worker         data_img_rel_ro_app_image_);
664*795d594fSAndroid Build Coastguard Worker     return false;
665*795d594fSAndroid Build Coastguard Worker   }
666*795d594fSAndroid Build Coastguard Worker 
667*795d594fSAndroid Build Coastguard Worker   DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>));
668*795d594fSAndroid Build Coastguard Worker   // In certain cases, ELF can be mapped at an address which is page aligned,
669*795d594fSAndroid Build Coastguard Worker   // however not aligned to kElfSegmentAlignment. While technically this isn't
670*795d594fSAndroid Build Coastguard Worker   // correct as per requirement in the ELF header, it has to be supported for
671*795d594fSAndroid Build Coastguard Worker   // now. See also the comment at ImageHeader::RelocateImageReferences.
672*795d594fSAndroid Build Coastguard Worker   if (!IsAlignedParam(bss_begin_, MemMap::GetPageSize()) ||
673*795d594fSAndroid Build Coastguard Worker       !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) ||
674*795d594fSAndroid Build Coastguard Worker       !IsAlignedParam(bss_roots_, static_cast<size_t>(pointer_size)) ||
675*795d594fSAndroid Build Coastguard Worker       !IsAligned<alignof(GcRoot<mirror::Object>)>(bss_end_)) {
676*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf(
677*795d594fSAndroid Build Coastguard Worker         "unaligned bss symbol(s): begin = %p, methods_ = %p, roots = %p, end = %p",
678*795d594fSAndroid Build Coastguard Worker         bss_begin_,
679*795d594fSAndroid Build Coastguard Worker         bss_methods_,
680*795d594fSAndroid Build Coastguard Worker         bss_roots_,
681*795d594fSAndroid Build Coastguard Worker         bss_end_);
682*795d594fSAndroid Build Coastguard Worker     return false;
683*795d594fSAndroid Build Coastguard Worker   }
684*795d594fSAndroid Build Coastguard Worker 
685*795d594fSAndroid Build Coastguard Worker   if ((bss_methods_ != nullptr && (bss_methods_ < bss_begin_ || bss_methods_ > bss_end_)) ||
686*795d594fSAndroid Build Coastguard Worker       (bss_roots_ != nullptr && (bss_roots_ < bss_begin_ || bss_roots_ > bss_end_)) ||
687*795d594fSAndroid Build Coastguard Worker       (bss_methods_ != nullptr && bss_roots_ != nullptr && bss_methods_ > bss_roots_)) {
688*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf(
689*795d594fSAndroid Build Coastguard Worker         "bss symbol(s) outside .bss or unordered: begin = %p, methods = %p, roots = %p, end = %p",
690*795d594fSAndroid Build Coastguard Worker         bss_begin_,
691*795d594fSAndroid Build Coastguard Worker         bss_methods_,
692*795d594fSAndroid Build Coastguard Worker         bss_roots_,
693*795d594fSAndroid Build Coastguard Worker         bss_end_);
694*795d594fSAndroid Build Coastguard Worker     return false;
695*795d594fSAndroid Build Coastguard Worker   }
696*795d594fSAndroid Build Coastguard Worker 
697*795d594fSAndroid Build Coastguard Worker   if (bss_methods_ != nullptr && bss_methods_ != bss_begin_) {
698*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf("unexpected .bss gap before 'oatbssmethods': begin = %p, methods = %p",
699*795d594fSAndroid Build Coastguard Worker                              bss_begin_,
700*795d594fSAndroid Build Coastguard Worker                              bss_methods_);
701*795d594fSAndroid Build Coastguard Worker     return false;
702*795d594fSAndroid Build Coastguard Worker   }
703*795d594fSAndroid Build Coastguard Worker 
704*795d594fSAndroid Build Coastguard Worker   std::string_view primary_location;
705*795d594fSAndroid Build Coastguard Worker   std::string_view primary_location_replacement;
706*795d594fSAndroid Build Coastguard Worker   File no_file;
707*795d594fSAndroid Build Coastguard Worker   File* dex_file = &no_file;
708*795d594fSAndroid Build Coastguard Worker   size_t dex_filenames_pos = 0u;
709*795d594fSAndroid Build Coastguard Worker   uint32_t dex_file_count = GetOatHeader().GetDexFileCount();
710*795d594fSAndroid Build Coastguard Worker   oat_dex_files_storage_.reserve(dex_file_count);
711*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < dex_file_count; i++) {
712*795d594fSAndroid Build Coastguard Worker     uint32_t dex_file_location_size;
713*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_location_size))) {
714*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu truncated after dex file location size", i);
715*795d594fSAndroid Build Coastguard Worker       return false;
716*795d594fSAndroid Build Coastguard Worker     }
717*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(dex_file_location_size == 0U)) {
718*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu with empty location name", i);
719*795d594fSAndroid Build Coastguard Worker       return false;
720*795d594fSAndroid Build Coastguard Worker     }
721*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(static_cast<size_t>(End() - oat) < dex_file_location_size)) {
722*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu with truncated dex file location", i);
723*795d594fSAndroid Build Coastguard Worker       return false;
724*795d594fSAndroid Build Coastguard Worker     }
725*795d594fSAndroid Build Coastguard Worker     const char* dex_file_location_data = reinterpret_cast<const char*>(oat);
726*795d594fSAndroid Build Coastguard Worker     oat += dex_file_location_size;
727*795d594fSAndroid Build Coastguard Worker 
728*795d594fSAndroid Build Coastguard Worker     // Location encoded in the oat file. We will use this for multidex naming.
729*795d594fSAndroid Build Coastguard Worker     std::string_view oat_dex_file_location(dex_file_location_data, dex_file_location_size);
730*795d594fSAndroid Build Coastguard Worker     std::string dex_file_location(oat_dex_file_location);
731*795d594fSAndroid Build Coastguard Worker     bool is_multidex = DexFileLoader::IsMultiDexLocation(dex_file_location);
732*795d594fSAndroid Build Coastguard Worker     // Check that `is_multidex` does not clash with other indicators. The first dex location
733*795d594fSAndroid Build Coastguard Worker     // must be primary location and, if we're opening external dex files, the location must
734*795d594fSAndroid Build Coastguard Worker     // be multi-dex if and only if we already have a dex file opened for it.
735*795d594fSAndroid Build Coastguard Worker     if ((i == 0 && is_multidex) ||
736*795d594fSAndroid Build Coastguard Worker         (!external_dex_files_.empty() && (is_multidex != (i < external_dex_files_.size())))) {
737*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("unexpected %s location '%s'",
738*795d594fSAndroid Build Coastguard Worker                                is_multidex ? "multi-dex" : "primary",
739*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
740*795d594fSAndroid Build Coastguard Worker       return false;
741*795d594fSAndroid Build Coastguard Worker     }
742*795d594fSAndroid Build Coastguard Worker     // Remember the primary location and, if provided, the replacement from `dex_filenames`.
743*795d594fSAndroid Build Coastguard Worker     if (!is_multidex) {
744*795d594fSAndroid Build Coastguard Worker       primary_location = oat_dex_file_location;
745*795d594fSAndroid Build Coastguard Worker       if (!dex_filenames.empty()) {
746*795d594fSAndroid Build Coastguard Worker         if (dex_filenames_pos == dex_filenames.size()) {
747*795d594fSAndroid Build Coastguard Worker           *error_msg = ErrorPrintf(
748*795d594fSAndroid Build Coastguard Worker               "excessive primary location '%s', expected only %zu primary locations",
749*795d594fSAndroid Build Coastguard Worker               dex_file_location.c_str(),
750*795d594fSAndroid Build Coastguard Worker               dex_filenames.size());
751*795d594fSAndroid Build Coastguard Worker           return false;
752*795d594fSAndroid Build Coastguard Worker         }
753*795d594fSAndroid Build Coastguard Worker         primary_location_replacement = dex_filenames[dex_filenames_pos];
754*795d594fSAndroid Build Coastguard Worker         dex_file = dex_filenames_pos < dex_files.size() ? &dex_files[dex_filenames_pos] : &no_file;
755*795d594fSAndroid Build Coastguard Worker         ++dex_filenames_pos;
756*795d594fSAndroid Build Coastguard Worker       }
757*795d594fSAndroid Build Coastguard Worker     }
758*795d594fSAndroid Build Coastguard Worker     // Check that the base location of a multidex location matches the last seen primary location.
759*795d594fSAndroid Build Coastguard Worker     if (is_multidex &&
760*795d594fSAndroid Build Coastguard Worker         (!dex_file_location.starts_with(primary_location) ||
761*795d594fSAndroid Build Coastguard Worker              dex_file_location[primary_location.size()] != DexFileLoader::kMultiDexSeparator)) {
762*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("unexpected multidex location '%s', unrelated to '%s'",
763*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str(),
764*795d594fSAndroid Build Coastguard Worker                                std::string(primary_location).c_str());
765*795d594fSAndroid Build Coastguard Worker       return false;
766*795d594fSAndroid Build Coastguard Worker     }
767*795d594fSAndroid Build Coastguard Worker     std::string dex_file_name = dex_file_location;
768*795d594fSAndroid Build Coastguard Worker     if (!dex_filenames.empty()) {
769*795d594fSAndroid Build Coastguard Worker       dex_file_name.replace(/*pos*/ 0u, primary_location.size(), primary_location_replacement);
770*795d594fSAndroid Build Coastguard Worker       // If the location does not contain path and matches the file name component,
771*795d594fSAndroid Build Coastguard Worker       // use the provided file name also as the location.
772*795d594fSAndroid Build Coastguard Worker       // TODO: Do we need this for anything other than tests?
773*795d594fSAndroid Build Coastguard Worker       if (dex_file_location.find('/') == std::string::npos &&
774*795d594fSAndroid Build Coastguard Worker           dex_file_name.size() > dex_file_location.size() &&
775*795d594fSAndroid Build Coastguard Worker           dex_file_name[dex_file_name.size() - dex_file_location.size() - 1u] == '/' &&
776*795d594fSAndroid Build Coastguard Worker           dex_file_name.ends_with(dex_file_location)) {
777*795d594fSAndroid Build Coastguard Worker         dex_file_location = dex_file_name;
778*795d594fSAndroid Build Coastguard Worker       }
779*795d594fSAndroid Build Coastguard Worker     }
780*795d594fSAndroid Build Coastguard Worker 
781*795d594fSAndroid Build Coastguard Worker     DexFile::Magic dex_file_magic;
782*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_magic))) {
783*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' truncated after dex file magic",
784*795d594fSAndroid Build Coastguard Worker                                i,
785*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
786*795d594fSAndroid Build Coastguard Worker       return false;
787*795d594fSAndroid Build Coastguard Worker     }
788*795d594fSAndroid Build Coastguard Worker 
789*795d594fSAndroid Build Coastguard Worker     uint32_t dex_file_checksum;
790*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_checksum))) {
791*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' truncated after dex file checksum",
792*795d594fSAndroid Build Coastguard Worker                                i,
793*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
794*795d594fSAndroid Build Coastguard Worker       return false;
795*795d594fSAndroid Build Coastguard Worker     }
796*795d594fSAndroid Build Coastguard Worker 
797*795d594fSAndroid Build Coastguard Worker     DexFile::Sha1 dex_file_sha1;
798*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_sha1))) {
799*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' truncated after dex file sha1",
800*795d594fSAndroid Build Coastguard Worker                                i,
801*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
802*795d594fSAndroid Build Coastguard Worker       return false;
803*795d594fSAndroid Build Coastguard Worker     }
804*795d594fSAndroid Build Coastguard Worker 
805*795d594fSAndroid Build Coastguard Worker     uint32_t dex_file_offset;
806*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_file_offset))) {
807*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' truncated after dex file offsets",
808*795d594fSAndroid Build Coastguard Worker                                i,
809*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
810*795d594fSAndroid Build Coastguard Worker       return false;
811*795d594fSAndroid Build Coastguard Worker     }
812*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(dex_file_offset > DexSize())) {
813*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' with dex file offset %u > %zu",
814*795d594fSAndroid Build Coastguard Worker                                i,
815*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str(),
816*795d594fSAndroid Build Coastguard Worker                                dex_file_offset,
817*795d594fSAndroid Build Coastguard Worker                                DexSize());
818*795d594fSAndroid Build Coastguard Worker       return false;
819*795d594fSAndroid Build Coastguard Worker     }
820*795d594fSAndroid Build Coastguard Worker     std::shared_ptr<DexFileContainer> dex_file_container;
821*795d594fSAndroid Build Coastguard Worker     const uint8_t* dex_file_pointer = nullptr;
822*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(dex_file_offset == 0U)) {
823*795d594fSAndroid Build Coastguard Worker       // Do not support mixed-mode oat files.
824*795d594fSAndroid Build Coastguard Worker       if (i != 0u && external_dex_files_.empty()) {
825*795d594fSAndroid Build Coastguard Worker         *error_msg = ErrorPrintf("unsupported uncompressed-dex-file for dex file %zu (%s)",
826*795d594fSAndroid Build Coastguard Worker                                  i,
827*795d594fSAndroid Build Coastguard Worker                                  dex_file_location.c_str());
828*795d594fSAndroid Build Coastguard Worker         return false;
829*795d594fSAndroid Build Coastguard Worker       }
830*795d594fSAndroid Build Coastguard Worker       DCHECK_LE(i, external_dex_files_.size());
831*795d594fSAndroid Build Coastguard Worker       if (i == external_dex_files_.size()) {
832*795d594fSAndroid Build Coastguard Worker         std::vector<std::unique_ptr<const DexFile>> new_dex_files;
833*795d594fSAndroid Build Coastguard Worker         // No dex files, load it from location.
834*795d594fSAndroid Build Coastguard Worker         bool loaded = false;
835*795d594fSAndroid Build Coastguard Worker         CHECK(zip_fd == -1 || dex_files.empty());  // Allow only the supported combinations.
836*795d594fSAndroid Build Coastguard Worker         if (zip_fd != -1) {
837*795d594fSAndroid Build Coastguard Worker           File file(zip_fd, /*check_usage=*/false);
838*795d594fSAndroid Build Coastguard Worker           ArtDexFileLoader dex_file_loader(&file, dex_file_location);
839*795d594fSAndroid Build Coastguard Worker           loaded = dex_file_loader.Open(
840*795d594fSAndroid Build Coastguard Worker               /*verify=*/false, /*verify_checksum=*/false, error_msg, &new_dex_files);
841*795d594fSAndroid Build Coastguard Worker         } else if (dex_file->IsValid()) {
842*795d594fSAndroid Build Coastguard Worker           // Note that we assume dex_fds are backing by jars.
843*795d594fSAndroid Build Coastguard Worker           ArtDexFileLoader dex_file_loader(dex_file, dex_file_location);
844*795d594fSAndroid Build Coastguard Worker           loaded = dex_file_loader.Open(
845*795d594fSAndroid Build Coastguard Worker               /*verify=*/false, /*verify_checksum=*/false, error_msg, &new_dex_files);
846*795d594fSAndroid Build Coastguard Worker         } else {
847*795d594fSAndroid Build Coastguard Worker           ArtDexFileLoader dex_file_loader(dex_file_name.c_str(), dex_file_location);
848*795d594fSAndroid Build Coastguard Worker           loaded = dex_file_loader.Open(
849*795d594fSAndroid Build Coastguard Worker               /*verify=*/false, /*verify_checksum=*/false, error_msg, &new_dex_files);
850*795d594fSAndroid Build Coastguard Worker         }
851*795d594fSAndroid Build Coastguard Worker         if (!loaded) {
852*795d594fSAndroid Build Coastguard Worker           if (Runtime::Current() == nullptr) {
853*795d594fSAndroid Build Coastguard Worker             // If there's no runtime, we're running oatdump, so return
854*795d594fSAndroid Build Coastguard Worker             // a half constructed oat file that oatdump knows how to deal with.
855*795d594fSAndroid Build Coastguard Worker             LOG(WARNING) << "Could not find associated dex files of oat file. "
856*795d594fSAndroid Build Coastguard Worker                          << "Oatdump will only dump the header.";
857*795d594fSAndroid Build Coastguard Worker             return true;
858*795d594fSAndroid Build Coastguard Worker           }
859*795d594fSAndroid Build Coastguard Worker           return false;
860*795d594fSAndroid Build Coastguard Worker         }
861*795d594fSAndroid Build Coastguard Worker         // The oat file may be out of date wrt/ the dex-file location. We need to be defensive
862*795d594fSAndroid Build Coastguard Worker         // here and ensure that at least the number of dex files still matches.
863*795d594fSAndroid Build Coastguard Worker         // If we have a zip_fd, or reached the end of provided `dex_filenames`, we must
864*795d594fSAndroid Build Coastguard Worker         // load all dex files from that file, otherwise we may open multiple files.
865*795d594fSAndroid Build Coastguard Worker         // Note: actual checksum comparisons are the duty of the OatFileAssistant and will be
866*795d594fSAndroid Build Coastguard Worker         //       done after loading the OatFile.
867*795d594fSAndroid Build Coastguard Worker         size_t max_dex_files = dex_file_count - external_dex_files_.size();
868*795d594fSAndroid Build Coastguard Worker         bool expect_all =
869*795d594fSAndroid Build Coastguard Worker             (zip_fd != -1) || (!dex_filenames.empty() && dex_filenames_pos == dex_filenames.size());
870*795d594fSAndroid Build Coastguard Worker         if (expect_all ? new_dex_files.size() != max_dex_files
871*795d594fSAndroid Build Coastguard Worker                        : new_dex_files.size() > max_dex_files) {
872*795d594fSAndroid Build Coastguard Worker           *error_msg = ErrorPrintf("expected %s%zu uncompressed dex files, but found %zu in '%s'",
873*795d594fSAndroid Build Coastguard Worker                                    (expect_all ? "" : "<="),
874*795d594fSAndroid Build Coastguard Worker                                    max_dex_files,
875*795d594fSAndroid Build Coastguard Worker                                    new_dex_files.size(),
876*795d594fSAndroid Build Coastguard Worker                                    dex_file_location.c_str());
877*795d594fSAndroid Build Coastguard Worker           return false;
878*795d594fSAndroid Build Coastguard Worker         }
879*795d594fSAndroid Build Coastguard Worker         for (std::unique_ptr<const DexFile>& dex_file_ptr : new_dex_files) {
880*795d594fSAndroid Build Coastguard Worker           external_dex_files_.push_back(std::move(dex_file_ptr));
881*795d594fSAndroid Build Coastguard Worker         }
882*795d594fSAndroid Build Coastguard Worker       }
883*795d594fSAndroid Build Coastguard Worker       // Defensively verify external dex file checksum. `OatFileAssistant`
884*795d594fSAndroid Build Coastguard Worker       // expects this check to happen during oat file setup when the oat file
885*795d594fSAndroid Build Coastguard Worker       // does not contain dex code.
886*795d594fSAndroid Build Coastguard Worker       if (dex_file_checksum != external_dex_files_[i]->GetLocationChecksum()) {
887*795d594fSAndroid Build Coastguard Worker         CHECK(dex_file_sha1 != external_dex_files_[i]->GetSha1());
888*795d594fSAndroid Build Coastguard Worker         *error_msg = ErrorPrintf("dex file checksum 0x%08x does not match"
889*795d594fSAndroid Build Coastguard Worker                                      " checksum 0x%08x of external dex file '%s'",
890*795d594fSAndroid Build Coastguard Worker                                  dex_file_checksum,
891*795d594fSAndroid Build Coastguard Worker                                  external_dex_files_[i]->GetLocationChecksum(),
892*795d594fSAndroid Build Coastguard Worker                                  external_dex_files_[i]->GetLocation().c_str());
893*795d594fSAndroid Build Coastguard Worker         return false;
894*795d594fSAndroid Build Coastguard Worker       }
895*795d594fSAndroid Build Coastguard Worker       CHECK(dex_file_sha1 == external_dex_files_[i]->GetSha1());
896*795d594fSAndroid Build Coastguard Worker       dex_file_container = external_dex_files_[i]->GetContainer();
897*795d594fSAndroid Build Coastguard Worker       dex_file_pointer = external_dex_files_[i]->Begin();
898*795d594fSAndroid Build Coastguard Worker     } else {
899*795d594fSAndroid Build Coastguard Worker       // Do not support mixed-mode oat files.
900*795d594fSAndroid Build Coastguard Worker       if (!external_dex_files_.empty()) {
901*795d594fSAndroid Build Coastguard Worker         *error_msg = ErrorPrintf("unsupported embedded dex-file for dex file %zu (%s)",
902*795d594fSAndroid Build Coastguard Worker                                  i,
903*795d594fSAndroid Build Coastguard Worker                                  dex_file_location.c_str());
904*795d594fSAndroid Build Coastguard Worker         return false;
905*795d594fSAndroid Build Coastguard Worker       }
906*795d594fSAndroid Build Coastguard Worker       if (UNLIKELY(DexSize() - dex_file_offset < sizeof(DexFile::Header))) {
907*795d594fSAndroid Build Coastguard Worker         *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' with dex file "
908*795d594fSAndroid Build Coastguard Worker                                      "offset %u of %zu but the size of dex file header is %zu",
909*795d594fSAndroid Build Coastguard Worker                                  i,
910*795d594fSAndroid Build Coastguard Worker                                  dex_file_location.c_str(),
911*795d594fSAndroid Build Coastguard Worker                                  dex_file_offset,
912*795d594fSAndroid Build Coastguard Worker                                  DexSize(),
913*795d594fSAndroid Build Coastguard Worker                                  sizeof(DexFile::Header));
914*795d594fSAndroid Build Coastguard Worker         return false;
915*795d594fSAndroid Build Coastguard Worker       }
916*795d594fSAndroid Build Coastguard Worker       dex_file_container = std::make_shared<MemoryDexFileContainer>(DexBegin(), DexEnd());
917*795d594fSAndroid Build Coastguard Worker       dex_file_pointer = DexBegin() + dex_file_offset;
918*795d594fSAndroid Build Coastguard Worker     }
919*795d594fSAndroid Build Coastguard Worker 
920*795d594fSAndroid Build Coastguard Worker     const bool valid_magic = DexFileLoader::IsMagicValid(dex_file_pointer);
921*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!valid_magic)) {
922*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' with invalid dex file magic",
923*795d594fSAndroid Build Coastguard Worker                                i,
924*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
925*795d594fSAndroid Build Coastguard Worker       return false;
926*795d594fSAndroid Build Coastguard Worker     }
927*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_pointer))) {
928*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' with invalid dex file version",
929*795d594fSAndroid Build Coastguard Worker                                i,
930*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
931*795d594fSAndroid Build Coastguard Worker       return false;
932*795d594fSAndroid Build Coastguard Worker     }
933*795d594fSAndroid Build Coastguard Worker     const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
934*795d594fSAndroid Build Coastguard Worker     if (dex_file_offset != 0 && (DexSize() - dex_file_offset < header->file_size_)) {
935*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf(
936*795d594fSAndroid Build Coastguard Worker           "OatDexFile #%zu for '%s' with dex file offset %u and size %u truncated at %zu",
937*795d594fSAndroid Build Coastguard Worker           i,
938*795d594fSAndroid Build Coastguard Worker           dex_file_location.c_str(),
939*795d594fSAndroid Build Coastguard Worker           dex_file_offset,
940*795d594fSAndroid Build Coastguard Worker           header->file_size_,
941*795d594fSAndroid Build Coastguard Worker           DexSize());
942*795d594fSAndroid Build Coastguard Worker       return false;
943*795d594fSAndroid Build Coastguard Worker     }
944*795d594fSAndroid Build Coastguard Worker 
945*795d594fSAndroid Build Coastguard Worker     uint32_t class_offsets_offset;
946*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &class_offsets_offset))) {
947*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' truncated after class offsets offset",
948*795d594fSAndroid Build Coastguard Worker                                i,
949*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
950*795d594fSAndroid Build Coastguard Worker       return false;
951*795d594fSAndroid Build Coastguard Worker     }
952*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(class_offsets_offset > Size()) ||
953*795d594fSAndroid Build Coastguard Worker         UNLIKELY((Size() - class_offsets_offset) / sizeof(uint32_t) < header->class_defs_size_)) {
954*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' with truncated "
955*795d594fSAndroid Build Coastguard Worker                                    "class offsets, offset %u of %zu, class defs %u",
956*795d594fSAndroid Build Coastguard Worker                                i,
957*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str(),
958*795d594fSAndroid Build Coastguard Worker                                class_offsets_offset,
959*795d594fSAndroid Build Coastguard Worker                                Size(),
960*795d594fSAndroid Build Coastguard Worker                                header->class_defs_size_);
961*795d594fSAndroid Build Coastguard Worker       return false;
962*795d594fSAndroid Build Coastguard Worker     }
963*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!IsAligned<alignof(uint32_t)>(class_offsets_offset))) {
964*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' with unaligned "
965*795d594fSAndroid Build Coastguard Worker                                    "class offsets, offset %u",
966*795d594fSAndroid Build Coastguard Worker                                i,
967*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str(),
968*795d594fSAndroid Build Coastguard Worker                                class_offsets_offset);
969*795d594fSAndroid Build Coastguard Worker       return false;
970*795d594fSAndroid Build Coastguard Worker     }
971*795d594fSAndroid Build Coastguard Worker     const uint32_t* class_offsets_pointer =
972*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const uint32_t*>(Begin() + class_offsets_offset);
973*795d594fSAndroid Build Coastguard Worker 
974*795d594fSAndroid Build Coastguard Worker     uint32_t lookup_table_offset;
975*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &lookup_table_offset))) {
976*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zd for '%s' truncated after lookup table offset",
977*795d594fSAndroid Build Coastguard Worker                                i,
978*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str());
979*795d594fSAndroid Build Coastguard Worker       return false;
980*795d594fSAndroid Build Coastguard Worker     }
981*795d594fSAndroid Build Coastguard Worker     const uint8_t* lookup_table_data = lookup_table_offset != 0u
982*795d594fSAndroid Build Coastguard Worker         ? DexBegin() + lookup_table_offset
983*795d594fSAndroid Build Coastguard Worker         : nullptr;
984*795d594fSAndroid Build Coastguard Worker     if (lookup_table_offset != 0u &&
985*795d594fSAndroid Build Coastguard Worker         (UNLIKELY(lookup_table_offset > DexSize()) ||
986*795d594fSAndroid Build Coastguard Worker             UNLIKELY(DexSize() - lookup_table_offset <
987*795d594fSAndroid Build Coastguard Worker                      TypeLookupTable::RawDataLength(header->class_defs_size_)))) {
988*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("OatDexFile #%zu for '%s' with truncated type lookup table, "
989*795d594fSAndroid Build Coastguard Worker                                    "offset %u of %zu, class defs %u",
990*795d594fSAndroid Build Coastguard Worker                                i,
991*795d594fSAndroid Build Coastguard Worker                                dex_file_location.c_str(),
992*795d594fSAndroid Build Coastguard Worker                                lookup_table_offset,
993*795d594fSAndroid Build Coastguard Worker                                Size(),
994*795d594fSAndroid Build Coastguard Worker                                header->class_defs_size_);
995*795d594fSAndroid Build Coastguard Worker       return false;
996*795d594fSAndroid Build Coastguard Worker     }
997*795d594fSAndroid Build Coastguard Worker 
998*795d594fSAndroid Build Coastguard Worker     uint32_t dex_layout_sections_offset;
999*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &oat, &dex_layout_sections_offset))) {
1000*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf(
1001*795d594fSAndroid Build Coastguard Worker           "OatDexFile #%zd for '%s' truncated after dex layout sections offset",
1002*795d594fSAndroid Build Coastguard Worker           i,
1003*795d594fSAndroid Build Coastguard Worker           dex_file_location.c_str());
1004*795d594fSAndroid Build Coastguard Worker       return false;
1005*795d594fSAndroid Build Coastguard Worker     }
1006*795d594fSAndroid Build Coastguard Worker     const DexLayoutSections* const dex_layout_sections = dex_layout_sections_offset != 0
1007*795d594fSAndroid Build Coastguard Worker         ? reinterpret_cast<const DexLayoutSections*>(Begin() + dex_layout_sections_offset)
1008*795d594fSAndroid Build Coastguard Worker         : nullptr;
1009*795d594fSAndroid Build Coastguard Worker 
1010*795d594fSAndroid Build Coastguard Worker     BssMappingInfo bss_mapping_info;
1011*795d594fSAndroid Build Coastguard Worker     if (!ReadBssMappingInfo(
1012*795d594fSAndroid Build Coastguard Worker             &oat, "OatDexFile", i, dex_file_location, &bss_mapping_info, error_msg)) {
1013*795d594fSAndroid Build Coastguard Worker       return false;
1014*795d594fSAndroid Build Coastguard Worker     }
1015*795d594fSAndroid Build Coastguard Worker 
1016*795d594fSAndroid Build Coastguard Worker     // Create the OatDexFile and add it to the owning container.
1017*795d594fSAndroid Build Coastguard Worker     OatDexFile* oat_dex_file =
1018*795d594fSAndroid Build Coastguard Worker         new OatDexFile(this,
1019*795d594fSAndroid Build Coastguard Worker                        dex_file_location,
1020*795d594fSAndroid Build Coastguard Worker                        DexFileLoader::GetDexCanonicalLocation(dex_file_name.c_str()),
1021*795d594fSAndroid Build Coastguard Worker                        dex_file_magic,
1022*795d594fSAndroid Build Coastguard Worker                        dex_file_checksum,
1023*795d594fSAndroid Build Coastguard Worker                        dex_file_sha1,
1024*795d594fSAndroid Build Coastguard Worker                        dex_file_container,
1025*795d594fSAndroid Build Coastguard Worker                        dex_file_pointer,
1026*795d594fSAndroid Build Coastguard Worker                        lookup_table_data,
1027*795d594fSAndroid Build Coastguard Worker                        bss_mapping_info,
1028*795d594fSAndroid Build Coastguard Worker                        class_offsets_pointer,
1029*795d594fSAndroid Build Coastguard Worker                        dex_layout_sections);
1030*795d594fSAndroid Build Coastguard Worker     oat_dex_files_storage_.push_back(oat_dex_file);
1031*795d594fSAndroid Build Coastguard Worker 
1032*795d594fSAndroid Build Coastguard Worker     // Add the location and canonical location (if different) to the oat_dex_files_ table.
1033*795d594fSAndroid Build Coastguard Worker     // Note: We do not add the non-canonical `dex_file_name`. If it is different from both
1034*795d594fSAndroid Build Coastguard Worker     // the location and canonical location, GetOatDexFile() shall canonicalize it when
1035*795d594fSAndroid Build Coastguard Worker     // requested and match the canonical path.
1036*795d594fSAndroid Build Coastguard Worker     std::string_view key = oat_dex_file_location;  // References oat file data.
1037*795d594fSAndroid Build Coastguard Worker     std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1038*795d594fSAndroid Build Coastguard Worker     oat_dex_files_.Put(key, oat_dex_file);
1039*795d594fSAndroid Build Coastguard Worker     if (canonical_key != key) {
1040*795d594fSAndroid Build Coastguard Worker       oat_dex_files_.Put(canonical_key, oat_dex_file);
1041*795d594fSAndroid Build Coastguard Worker     }
1042*795d594fSAndroid Build Coastguard Worker   }
1043*795d594fSAndroid Build Coastguard Worker 
1044*795d594fSAndroid Build Coastguard Worker   size_t bcp_info_offset = GetOatHeader().GetBcpBssInfoOffset();
1045*795d594fSAndroid Build Coastguard Worker   // `bcp_info_offset` will be 0 for multi-image, or for the case of no mappings.
1046*795d594fSAndroid Build Coastguard Worker   if (bcp_info_offset != 0) {
1047*795d594fSAndroid Build Coastguard Worker     // Consistency check.
1048*795d594fSAndroid Build Coastguard Worker     if (bcp_info_offset < GetOatHeader().GetHeaderSize() || bcp_info_offset > Size()) {
1049*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("invalid bcp info offset: %zu is not in [%zu, %zu]",
1050*795d594fSAndroid Build Coastguard Worker                                bcp_info_offset,
1051*795d594fSAndroid Build Coastguard Worker                                GetOatHeader().GetHeaderSize(),
1052*795d594fSAndroid Build Coastguard Worker                                Size());
1053*795d594fSAndroid Build Coastguard Worker       return false;
1054*795d594fSAndroid Build Coastguard Worker     }
1055*795d594fSAndroid Build Coastguard Worker     const uint8_t* bcp_info_begin = Begin() + bcp_info_offset;  // Jump to the BCP_info records.
1056*795d594fSAndroid Build Coastguard Worker 
1057*795d594fSAndroid Build Coastguard Worker     uint32_t number_of_bcp_dexfiles;
1058*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!ReadOatDexFileData(*this, &bcp_info_begin, &number_of_bcp_dexfiles))) {
1059*795d594fSAndroid Build Coastguard Worker       *error_msg = ErrorPrintf("failed to read the number of BCP dex files");
1060*795d594fSAndroid Build Coastguard Worker       return false;
1061*795d594fSAndroid Build Coastguard Worker     }
1062*795d594fSAndroid Build Coastguard Worker     Runtime* const runtime = Runtime::Current();
1063*795d594fSAndroid Build Coastguard Worker     ClassLinker* const linker = runtime != nullptr ? runtime->GetClassLinker() : nullptr;
1064*795d594fSAndroid Build Coastguard Worker     if (linker != nullptr && UNLIKELY(number_of_bcp_dexfiles > linker->GetBootClassPath().size())) {
1065*795d594fSAndroid Build Coastguard Worker       // If we compiled with more DexFiles than what we have at runtime, we expect to discard this
1066*795d594fSAndroid Build Coastguard Worker       // OatFile after verifying its checksum in OatFileAssistant. Therefore, we set
1067*795d594fSAndroid Build Coastguard Worker       // `number_of_bcp_dexfiles` to 0 to avoid reading data that will ultimately be discarded.
1068*795d594fSAndroid Build Coastguard Worker       number_of_bcp_dexfiles = 0;
1069*795d594fSAndroid Build Coastguard Worker     }
1070*795d594fSAndroid Build Coastguard Worker 
1071*795d594fSAndroid Build Coastguard Worker     DCHECK(bcp_bss_info_.empty());
1072*795d594fSAndroid Build Coastguard Worker     bcp_bss_info_.resize(number_of_bcp_dexfiles);
1073*795d594fSAndroid Build Coastguard Worker     // At runtime, there might be more DexFiles added to the BCP that we didn't compile with.
1074*795d594fSAndroid Build Coastguard Worker     // We only care about the ones in [0..number_of_bcp_dexfiles).
1075*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0, size = number_of_bcp_dexfiles; i != size; ++i) {
1076*795d594fSAndroid Build Coastguard Worker       const std::string& dex_file_location = linker != nullptr
1077*795d594fSAndroid Build Coastguard Worker           ? linker->GetBootClassPath()[i]->GetLocation()
1078*795d594fSAndroid Build Coastguard Worker           : "No runtime/linker therefore no DexFile location";
1079*795d594fSAndroid Build Coastguard Worker       if (!ReadBssMappingInfo(
1080*795d594fSAndroid Build Coastguard Worker               &bcp_info_begin, "BcpBssInfo", i, dex_file_location, &bcp_bss_info_[i], error_msg)) {
1081*795d594fSAndroid Build Coastguard Worker         return false;
1082*795d594fSAndroid Build Coastguard Worker       }
1083*795d594fSAndroid Build Coastguard Worker     }
1084*795d594fSAndroid Build Coastguard Worker   }
1085*795d594fSAndroid Build Coastguard Worker 
1086*795d594fSAndroid Build Coastguard Worker   if (!dex_filenames.empty() && dex_filenames_pos != dex_filenames.size()) {
1087*795d594fSAndroid Build Coastguard Worker     *error_msg = ErrorPrintf("only %zu primary dex locations, expected %zu",
1088*795d594fSAndroid Build Coastguard Worker                              dex_filenames_pos,
1089*795d594fSAndroid Build Coastguard Worker                              dex_filenames.size());
1090*795d594fSAndroid Build Coastguard Worker     return false;
1091*795d594fSAndroid Build Coastguard Worker   }
1092*795d594fSAndroid Build Coastguard Worker 
1093*795d594fSAndroid Build Coastguard Worker   if (DataImgRelRoBegin() != nullptr) {
1094*795d594fSAndroid Build Coastguard Worker     // Make .data.img.rel.ro read only. ClassLinker shall temporarily make it writable for
1095*795d594fSAndroid Build Coastguard Worker     // relocation when we register a dex file from this oat file. We do not do the relocation
1096*795d594fSAndroid Build Coastguard Worker     // here to avoid dirtying the pages if the code is never actually ready to be executed.
1097*795d594fSAndroid Build Coastguard Worker     uint8_t* reloc_begin = const_cast<uint8_t*>(DataImgRelRoBegin());
1098*795d594fSAndroid Build Coastguard Worker     CheckedCall(mprotect, "protect relocations", reloc_begin, DataImgRelRoSize(), PROT_READ);
1099*795d594fSAndroid Build Coastguard Worker     // Make sure the file lists a boot image dependency, otherwise the .data.img.rel.ro
1100*795d594fSAndroid Build Coastguard Worker     // section is bogus. The full dependency is checked before the code is executed.
1101*795d594fSAndroid Build Coastguard Worker     // We cannot do this check if we do not have a key-value store, i.e. for secondary
1102*795d594fSAndroid Build Coastguard Worker     // oat files for boot image extensions.
1103*795d594fSAndroid Build Coastguard Worker     if (GetOatHeader().GetKeyValueStoreSize() != 0u) {
1104*795d594fSAndroid Build Coastguard Worker       const char* boot_class_path_checksum =
1105*795d594fSAndroid Build Coastguard Worker           GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey);
1106*795d594fSAndroid Build Coastguard Worker       if (boot_class_path_checksum == nullptr ||
1107*795d594fSAndroid Build Coastguard Worker           boot_class_path_checksum[0] != gc::space::ImageSpace::kImageChecksumPrefix) {
1108*795d594fSAndroid Build Coastguard Worker         *error_msg = ErrorPrintf(".data.img.rel.ro section present without boot image dependency.");
1109*795d594fSAndroid Build Coastguard Worker         return false;
1110*795d594fSAndroid Build Coastguard Worker       }
1111*795d594fSAndroid Build Coastguard Worker     }
1112*795d594fSAndroid Build Coastguard Worker   }
1113*795d594fSAndroid Build Coastguard Worker 
1114*795d594fSAndroid Build Coastguard Worker   return true;
1115*795d594fSAndroid Build Coastguard Worker }
1116*795d594fSAndroid Build Coastguard Worker 
1117*795d594fSAndroid Build Coastguard Worker ////////////////////////
1118*795d594fSAndroid Build Coastguard Worker // OatFile via dlopen //
1119*795d594fSAndroid Build Coastguard Worker ////////////////////////
1120*795d594fSAndroid Build Coastguard Worker 
1121*795d594fSAndroid Build Coastguard Worker class DlOpenOatFile final : public OatFileBase {
1122*795d594fSAndroid Build Coastguard Worker  public:
DlOpenOatFile(const std::string & filename,bool executable)1123*795d594fSAndroid Build Coastguard Worker   DlOpenOatFile(const std::string& filename, bool executable)
1124*795d594fSAndroid Build Coastguard Worker       : OatFileBase(filename, executable),
1125*795d594fSAndroid Build Coastguard Worker         dlopen_handle_(nullptr),
1126*795d594fSAndroid Build Coastguard Worker         shared_objects_before_(0) {
1127*795d594fSAndroid Build Coastguard Worker   }
1128*795d594fSAndroid Build Coastguard Worker 
~DlOpenOatFile()1129*795d594fSAndroid Build Coastguard Worker   ~DlOpenOatFile() {
1130*795d594fSAndroid Build Coastguard Worker     if (dlopen_handle_ != nullptr) {
1131*795d594fSAndroid Build Coastguard Worker       if (!kIsTargetBuild) {
1132*795d594fSAndroid Build Coastguard Worker         MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1133*795d594fSAndroid Build Coastguard Worker         host_dlopen_handles_.erase(dlopen_handle_);
1134*795d594fSAndroid Build Coastguard Worker         dlclose(dlopen_handle_);
1135*795d594fSAndroid Build Coastguard Worker       } else {
1136*795d594fSAndroid Build Coastguard Worker         dlclose(dlopen_handle_);
1137*795d594fSAndroid Build Coastguard Worker       }
1138*795d594fSAndroid Build Coastguard Worker     }
1139*795d594fSAndroid Build Coastguard Worker   }
1140*795d594fSAndroid Build Coastguard Worker 
1141*795d594fSAndroid Build Coastguard Worker  protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1142*795d594fSAndroid Build Coastguard Worker   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1143*795d594fSAndroid Build Coastguard Worker                                           std::string* error_msg) const override {
1144*795d594fSAndroid Build Coastguard Worker     const uint8_t* ptr =
1145*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const uint8_t*>(dlsym(dlopen_handle_, symbol_name.c_str()));
1146*795d594fSAndroid Build Coastguard Worker     if (ptr == nullptr) {
1147*795d594fSAndroid Build Coastguard Worker       *error_msg = dlerror();
1148*795d594fSAndroid Build Coastguard Worker     }
1149*795d594fSAndroid Build Coastguard Worker     return ptr;
1150*795d594fSAndroid Build Coastguard Worker   }
1151*795d594fSAndroid Build Coastguard Worker 
1152*795d594fSAndroid Build Coastguard Worker   void PreLoad() override;
1153*795d594fSAndroid Build Coastguard Worker 
1154*795d594fSAndroid Build Coastguard Worker   bool Load(const std::string& elf_filename,
1155*795d594fSAndroid Build Coastguard Worker             bool writable,
1156*795d594fSAndroid Build Coastguard Worker             bool executable,
1157*795d594fSAndroid Build Coastguard Worker             bool low_4gb,
1158*795d594fSAndroid Build Coastguard Worker             /*inout*/MemMap* reservation,  // Where to load if not null.
1159*795d594fSAndroid Build Coastguard Worker             /*out*/std::string* error_msg) override;
1160*795d594fSAndroid Build Coastguard Worker 
Load(int oat_fd,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1161*795d594fSAndroid Build Coastguard Worker   bool Load([[maybe_unused]] int oat_fd,
1162*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool writable,
1163*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool executable,
1164*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool low_4gb,
1165*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] /*inout*/ MemMap* reservation,
1166*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] /*out*/ std::string* error_msg) override {
1167*795d594fSAndroid Build Coastguard Worker     return false;
1168*795d594fSAndroid Build Coastguard Worker   }
1169*795d594fSAndroid Build Coastguard Worker 
1170*795d594fSAndroid Build Coastguard Worker   // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
1171*795d594fSAndroid Build Coastguard Worker   void PreSetup(const std::string& elf_filename) override;
1172*795d594fSAndroid Build Coastguard Worker 
ComputeElfBegin(std::string * error_msg) const1173*795d594fSAndroid Build Coastguard Worker   const uint8_t* ComputeElfBegin(std::string* error_msg) const override {
1174*795d594fSAndroid Build Coastguard Worker     Dl_info info;
1175*795d594fSAndroid Build Coastguard Worker     if (dladdr(Begin(), &info) == 0) {
1176*795d594fSAndroid Build Coastguard Worker       *error_msg =
1177*795d594fSAndroid Build Coastguard Worker           StringPrintf("Failed to dladdr '%s': %s", GetLocation().c_str(), strerror(errno));
1178*795d594fSAndroid Build Coastguard Worker       return nullptr;
1179*795d594fSAndroid Build Coastguard Worker     }
1180*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<const uint8_t*>(info.dli_fbase);
1181*795d594fSAndroid Build Coastguard Worker   }
1182*795d594fSAndroid Build Coastguard Worker 
1183*795d594fSAndroid Build Coastguard Worker  private:
1184*795d594fSAndroid Build Coastguard Worker   bool Dlopen(const std::string& elf_filename,
1185*795d594fSAndroid Build Coastguard Worker               /*inout*/MemMap* reservation,  // Where to load if not null.
1186*795d594fSAndroid Build Coastguard Worker               /*out*/std::string* error_msg);
1187*795d594fSAndroid Build Coastguard Worker 
1188*795d594fSAndroid Build Coastguard Worker   // On the host, if the same library is loaded again with dlopen the same
1189*795d594fSAndroid Build Coastguard Worker   // file handle is returned. This differs from the behavior of dlopen on the
1190*795d594fSAndroid Build Coastguard Worker   // target, where dlopen reloads the library at a different address every
1191*795d594fSAndroid Build Coastguard Worker   // time you load it. The runtime relies on the target behavior to ensure
1192*795d594fSAndroid Build Coastguard Worker   // each instance of the loaded library has a unique dex cache. To avoid
1193*795d594fSAndroid Build Coastguard Worker   // problems, we fall back to our own linker in the case when the same
1194*795d594fSAndroid Build Coastguard Worker   // library is opened multiple times on host. dlopen_handles_ is used to
1195*795d594fSAndroid Build Coastguard Worker   // detect that case.
1196*795d594fSAndroid Build Coastguard Worker   // Guarded by host_dlopen_handles_lock_;
1197*795d594fSAndroid Build Coastguard Worker   static std::unordered_set<void*> host_dlopen_handles_;
1198*795d594fSAndroid Build Coastguard Worker 
1199*795d594fSAndroid Build Coastguard Worker   // Reservation and placeholder memory map objects corresponding to the regions mapped by dlopen.
1200*795d594fSAndroid Build Coastguard Worker   // Note: Must be destroyed after dlclose() as it can hold the owning reservation.
1201*795d594fSAndroid Build Coastguard Worker   std::vector<MemMap> dlopen_mmaps_;
1202*795d594fSAndroid Build Coastguard Worker 
1203*795d594fSAndroid Build Coastguard Worker   // dlopen handle during runtime.
1204*795d594fSAndroid Build Coastguard Worker   void* dlopen_handle_;  // TODO: Unique_ptr with custom deleter.
1205*795d594fSAndroid Build Coastguard Worker 
1206*795d594fSAndroid Build Coastguard Worker   // The number of shared objects the linker told us about before loading. Used to
1207*795d594fSAndroid Build Coastguard Worker   // (optimistically) optimize the PreSetup stage (see comment there).
1208*795d594fSAndroid Build Coastguard Worker   size_t shared_objects_before_;
1209*795d594fSAndroid Build Coastguard Worker 
1210*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile);
1211*795d594fSAndroid Build Coastguard Worker };
1212*795d594fSAndroid Build Coastguard Worker 
1213*795d594fSAndroid Build Coastguard Worker std::unordered_set<void*> DlOpenOatFile::host_dlopen_handles_;
1214*795d594fSAndroid Build Coastguard Worker 
PreLoad()1215*795d594fSAndroid Build Coastguard Worker void DlOpenOatFile::PreLoad() {
1216*795d594fSAndroid Build Coastguard Worker #ifdef __APPLE__
1217*795d594fSAndroid Build Coastguard Worker   UNUSED(shared_objects_before_);
1218*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "Should not reach here.";
1219*795d594fSAndroid Build Coastguard Worker   UNREACHABLE();
1220*795d594fSAndroid Build Coastguard Worker #else
1221*795d594fSAndroid Build Coastguard Worker   // Count the entries in dl_iterate_phdr we get at this point in time.
1222*795d594fSAndroid Build Coastguard Worker   struct dl_iterate_context {
1223*795d594fSAndroid Build Coastguard Worker     static int callback([[maybe_unused]] dl_phdr_info* info,
1224*795d594fSAndroid Build Coastguard Worker                         [[maybe_unused]] size_t size,
1225*795d594fSAndroid Build Coastguard Worker                         void* data) {
1226*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<dl_iterate_context*>(data)->count++;
1227*795d594fSAndroid Build Coastguard Worker       return 0;  // Continue iteration.
1228*795d594fSAndroid Build Coastguard Worker     }
1229*795d594fSAndroid Build Coastguard Worker     size_t count = 0;
1230*795d594fSAndroid Build Coastguard Worker   } context;
1231*795d594fSAndroid Build Coastguard Worker 
1232*795d594fSAndroid Build Coastguard Worker   dl_iterate_phdr(dl_iterate_context::callback, &context);
1233*795d594fSAndroid Build Coastguard Worker   shared_objects_before_ = context.count;
1234*795d594fSAndroid Build Coastguard Worker #endif
1235*795d594fSAndroid Build Coastguard Worker }
1236*795d594fSAndroid Build Coastguard Worker 
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1237*795d594fSAndroid Build Coastguard Worker bool DlOpenOatFile::Load(const std::string& elf_filename,
1238*795d594fSAndroid Build Coastguard Worker                          bool writable,
1239*795d594fSAndroid Build Coastguard Worker                          bool executable,
1240*795d594fSAndroid Build Coastguard Worker                          bool low_4gb,
1241*795d594fSAndroid Build Coastguard Worker                          /*inout*/MemMap* reservation,  // Where to load if not null.
1242*795d594fSAndroid Build Coastguard Worker                          /*out*/std::string* error_msg) {
1243*795d594fSAndroid Build Coastguard Worker   // Use dlopen only when flagged to do so, and when it's OK to load things executable.
1244*795d594fSAndroid Build Coastguard Worker   // TODO: Also try when not executable? The issue here could be re-mapping as writable (as
1245*795d594fSAndroid Build Coastguard Worker   //       !executable is a sign that we may want to patch), which may not be allowed for
1246*795d594fSAndroid Build Coastguard Worker   //       various reasons.
1247*795d594fSAndroid Build Coastguard Worker   if (!kUseDlopen) {
1248*795d594fSAndroid Build Coastguard Worker     *error_msg = "DlOpen is disabled.";
1249*795d594fSAndroid Build Coastguard Worker     return false;
1250*795d594fSAndroid Build Coastguard Worker   }
1251*795d594fSAndroid Build Coastguard Worker   if (low_4gb) {
1252*795d594fSAndroid Build Coastguard Worker     *error_msg = "DlOpen does not support low 4gb loading.";
1253*795d594fSAndroid Build Coastguard Worker     return false;
1254*795d594fSAndroid Build Coastguard Worker   }
1255*795d594fSAndroid Build Coastguard Worker   if (writable) {
1256*795d594fSAndroid Build Coastguard Worker     *error_msg = "DlOpen does not support writable loading.";
1257*795d594fSAndroid Build Coastguard Worker     return false;
1258*795d594fSAndroid Build Coastguard Worker   }
1259*795d594fSAndroid Build Coastguard Worker   if (!executable) {
1260*795d594fSAndroid Build Coastguard Worker     *error_msg = "DlOpen does not support non-executable loading.";
1261*795d594fSAndroid Build Coastguard Worker     return false;
1262*795d594fSAndroid Build Coastguard Worker   }
1263*795d594fSAndroid Build Coastguard Worker 
1264*795d594fSAndroid Build Coastguard Worker   // dlopen always returns the same library if it is already opened on the host. For this reason
1265*795d594fSAndroid Build Coastguard Worker   // we only use dlopen if we are the target or we do not already have the dex file opened. Having
1266*795d594fSAndroid Build Coastguard Worker   // the same library loaded multiple times at different addresses is required for class unloading
1267*795d594fSAndroid Build Coastguard Worker   // and for having dex caches arrays in the .bss section.
1268*795d594fSAndroid Build Coastguard Worker   if (!kIsTargetBuild) {
1269*795d594fSAndroid Build Coastguard Worker     if (!kUseDlopenOnHost) {
1270*795d594fSAndroid Build Coastguard Worker       *error_msg = "DlOpen disabled for host.";
1271*795d594fSAndroid Build Coastguard Worker       return false;
1272*795d594fSAndroid Build Coastguard Worker     }
1273*795d594fSAndroid Build Coastguard Worker   }
1274*795d594fSAndroid Build Coastguard Worker 
1275*795d594fSAndroid Build Coastguard Worker   bool success = Dlopen(elf_filename, reservation, error_msg);
1276*795d594fSAndroid Build Coastguard Worker   DCHECK_IMPLIES(dlopen_handle_ == nullptr, !success);
1277*795d594fSAndroid Build Coastguard Worker 
1278*795d594fSAndroid Build Coastguard Worker   return success;
1279*795d594fSAndroid Build Coastguard Worker }
1280*795d594fSAndroid Build Coastguard Worker 
1281*795d594fSAndroid Build Coastguard Worker #ifdef ART_TARGET_ANDROID
GetSystemLinkerNamespace()1282*795d594fSAndroid Build Coastguard Worker static struct android_namespace_t* GetSystemLinkerNamespace() {
1283*795d594fSAndroid Build Coastguard Worker   static struct android_namespace_t* system_ns = []() {
1284*795d594fSAndroid Build Coastguard Worker     // The system namespace is called "default" for binaries in /system and
1285*795d594fSAndroid Build Coastguard Worker     // "system" for those in the ART APEX. Try "system" first since "default"
1286*795d594fSAndroid Build Coastguard Worker     // always exists.
1287*795d594fSAndroid Build Coastguard Worker     // TODO(b/185587109): Get rid of this error prone logic.
1288*795d594fSAndroid Build Coastguard Worker     struct android_namespace_t* ns = android_get_exported_namespace("system");
1289*795d594fSAndroid Build Coastguard Worker     if (ns == nullptr) {
1290*795d594fSAndroid Build Coastguard Worker       ns = android_get_exported_namespace("default");
1291*795d594fSAndroid Build Coastguard Worker       if (ns == nullptr) {
1292*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Failed to get system namespace for loading OAT files";
1293*795d594fSAndroid Build Coastguard Worker       }
1294*795d594fSAndroid Build Coastguard Worker     }
1295*795d594fSAndroid Build Coastguard Worker     return ns;
1296*795d594fSAndroid Build Coastguard Worker   }();
1297*795d594fSAndroid Build Coastguard Worker   return system_ns;
1298*795d594fSAndroid Build Coastguard Worker }
1299*795d594fSAndroid Build Coastguard Worker #endif  // ART_TARGET_ANDROID
1300*795d594fSAndroid Build Coastguard Worker 
Dlopen(const std::string & elf_filename,MemMap * reservation,std::string * error_msg)1301*795d594fSAndroid Build Coastguard Worker bool DlOpenOatFile::Dlopen(const std::string& elf_filename,
1302*795d594fSAndroid Build Coastguard Worker                            /*inout*/MemMap* reservation,
1303*795d594fSAndroid Build Coastguard Worker                            /*out*/std::string* error_msg) {
1304*795d594fSAndroid Build Coastguard Worker #ifdef __APPLE__
1305*795d594fSAndroid Build Coastguard Worker   // The dl_iterate_phdr syscall is missing.  There is similar API on OSX,
1306*795d594fSAndroid Build Coastguard Worker   // but let's fallback to the custom loading code for the time being.
1307*795d594fSAndroid Build Coastguard Worker   UNUSED(elf_filename, reservation);
1308*795d594fSAndroid Build Coastguard Worker   *error_msg = "Dlopen unsupported on Mac.";
1309*795d594fSAndroid Build Coastguard Worker   return false;
1310*795d594fSAndroid Build Coastguard Worker #else
1311*795d594fSAndroid Build Coastguard Worker   {
1312*795d594fSAndroid Build Coastguard Worker     UniqueCPtr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
1313*795d594fSAndroid Build Coastguard Worker     if (absolute_path == nullptr) {
1314*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
1315*795d594fSAndroid Build Coastguard Worker       return false;
1316*795d594fSAndroid Build Coastguard Worker     }
1317*795d594fSAndroid Build Coastguard Worker #ifdef ART_TARGET_ANDROID
1318*795d594fSAndroid Build Coastguard Worker     android_dlextinfo extinfo = {};
1319*795d594fSAndroid Build Coastguard Worker     extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;   // Force-load, don't reuse handle
1320*795d594fSAndroid Build Coastguard Worker                                                 //   (open oat files multiple times).
1321*795d594fSAndroid Build Coastguard Worker     if (reservation != nullptr) {
1322*795d594fSAndroid Build Coastguard Worker       if (!reservation->IsValid()) {
1323*795d594fSAndroid Build Coastguard Worker         *error_msg = StringPrintf("Invalid reservation for %s", elf_filename.c_str());
1324*795d594fSAndroid Build Coastguard Worker         return false;
1325*795d594fSAndroid Build Coastguard Worker       }
1326*795d594fSAndroid Build Coastguard Worker       extinfo.flags |= ANDROID_DLEXT_RESERVED_ADDRESS;          // Use the reserved memory range.
1327*795d594fSAndroid Build Coastguard Worker       extinfo.reserved_addr = reservation->Begin();
1328*795d594fSAndroid Build Coastguard Worker       extinfo.reserved_size = reservation->Size();
1329*795d594fSAndroid Build Coastguard Worker     }
1330*795d594fSAndroid Build Coastguard Worker 
1331*795d594fSAndroid Build Coastguard Worker     if (strncmp(kAndroidArtApexDefaultPath,
1332*795d594fSAndroid Build Coastguard Worker                 absolute_path.get(),
1333*795d594fSAndroid Build Coastguard Worker                 sizeof(kAndroidArtApexDefaultPath) - 1) != 0 ||
1334*795d594fSAndroid Build Coastguard Worker         absolute_path.get()[sizeof(kAndroidArtApexDefaultPath) - 1] != '/') {
1335*795d594fSAndroid Build Coastguard Worker       // Use the system namespace for OAT files outside the ART APEX. Search
1336*795d594fSAndroid Build Coastguard Worker       // paths and links don't matter here, but permitted paths do, and the
1337*795d594fSAndroid Build Coastguard Worker       // system namespace is configured to allow loading from all appropriate
1338*795d594fSAndroid Build Coastguard Worker       // locations.
1339*795d594fSAndroid Build Coastguard Worker       extinfo.flags |= ANDROID_DLEXT_USE_NAMESPACE;
1340*795d594fSAndroid Build Coastguard Worker       extinfo.library_namespace = GetSystemLinkerNamespace();
1341*795d594fSAndroid Build Coastguard Worker     }
1342*795d594fSAndroid Build Coastguard Worker 
1343*795d594fSAndroid Build Coastguard Worker     dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
1344*795d594fSAndroid Build Coastguard Worker     if (reservation != nullptr && dlopen_handle_ != nullptr) {
1345*795d594fSAndroid Build Coastguard Worker       // Find used pages from the reservation.
1346*795d594fSAndroid Build Coastguard Worker       struct dl_iterate_context {
1347*795d594fSAndroid Build Coastguard Worker         static int callback(dl_phdr_info* info, [[maybe_unused]] size_t size, void* data) {
1348*795d594fSAndroid Build Coastguard Worker           auto* context = reinterpret_cast<dl_iterate_context*>(data);
1349*795d594fSAndroid Build Coastguard Worker           static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1350*795d594fSAndroid Build Coastguard Worker           using Elf_Half = Elf64_Half;
1351*795d594fSAndroid Build Coastguard Worker 
1352*795d594fSAndroid Build Coastguard Worker           // See whether this callback corresponds to the file which we have just loaded.
1353*795d594fSAndroid Build Coastguard Worker           uint8_t* reservation_begin = context->reservation->Begin();
1354*795d594fSAndroid Build Coastguard Worker           bool contained_in_reservation = false;
1355*795d594fSAndroid Build Coastguard Worker           for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1356*795d594fSAndroid Build Coastguard Worker             if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1357*795d594fSAndroid Build Coastguard Worker               uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1358*795d594fSAndroid Build Coastguard Worker                   info->dlpi_phdr[i].p_vaddr);
1359*795d594fSAndroid Build Coastguard Worker               size_t memsz = info->dlpi_phdr[i].p_memsz;
1360*795d594fSAndroid Build Coastguard Worker               size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1361*795d594fSAndroid Build Coastguard Worker               if (offset < context->reservation->Size()) {
1362*795d594fSAndroid Build Coastguard Worker                 contained_in_reservation = true;
1363*795d594fSAndroid Build Coastguard Worker                 DCHECK_LE(memsz, context->reservation->Size() - offset);
1364*795d594fSAndroid Build Coastguard Worker               } else if (vaddr < reservation_begin) {
1365*795d594fSAndroid Build Coastguard Worker                 // Check that there's no overlap with the reservation.
1366*795d594fSAndroid Build Coastguard Worker                 DCHECK_LE(memsz, static_cast<size_t>(reservation_begin - vaddr));
1367*795d594fSAndroid Build Coastguard Worker               }
1368*795d594fSAndroid Build Coastguard Worker               break;  // It is sufficient to check the first PT_LOAD header.
1369*795d594fSAndroid Build Coastguard Worker             }
1370*795d594fSAndroid Build Coastguard Worker           }
1371*795d594fSAndroid Build Coastguard Worker 
1372*795d594fSAndroid Build Coastguard Worker           if (contained_in_reservation) {
1373*795d594fSAndroid Build Coastguard Worker             for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1374*795d594fSAndroid Build Coastguard Worker               if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1375*795d594fSAndroid Build Coastguard Worker                 uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1376*795d594fSAndroid Build Coastguard Worker                     info->dlpi_phdr[i].p_vaddr);
1377*795d594fSAndroid Build Coastguard Worker                 size_t memsz = info->dlpi_phdr[i].p_memsz;
1378*795d594fSAndroid Build Coastguard Worker                 size_t offset = static_cast<size_t>(vaddr - reservation_begin);
1379*795d594fSAndroid Build Coastguard Worker                 DCHECK_LT(offset, context->reservation->Size());
1380*795d594fSAndroid Build Coastguard Worker                 DCHECK_LE(memsz, context->reservation->Size() - offset);
1381*795d594fSAndroid Build Coastguard Worker                 context->max_size = std::max(context->max_size, offset + memsz);
1382*795d594fSAndroid Build Coastguard Worker               }
1383*795d594fSAndroid Build Coastguard Worker             }
1384*795d594fSAndroid Build Coastguard Worker 
1385*795d594fSAndroid Build Coastguard Worker             return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
1386*795d594fSAndroid Build Coastguard Worker           }
1387*795d594fSAndroid Build Coastguard Worker           return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
1388*795d594fSAndroid Build Coastguard Worker         }
1389*795d594fSAndroid Build Coastguard Worker 
1390*795d594fSAndroid Build Coastguard Worker         const MemMap* const reservation;
1391*795d594fSAndroid Build Coastguard Worker         size_t max_size = 0u;
1392*795d594fSAndroid Build Coastguard Worker       };
1393*795d594fSAndroid Build Coastguard Worker       dl_iterate_context context = { reservation };
1394*795d594fSAndroid Build Coastguard Worker 
1395*795d594fSAndroid Build Coastguard Worker       if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1396*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Could not find the shared object mmapped to the reservation.";
1397*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
1398*795d594fSAndroid Build Coastguard Worker       }
1399*795d594fSAndroid Build Coastguard Worker 
1400*795d594fSAndroid Build Coastguard Worker       // Take ownership of the memory used by the shared object. dlopen() does not assume
1401*795d594fSAndroid Build Coastguard Worker       // full ownership of this memory and dlclose() shall just remap it as zero pages with
1402*795d594fSAndroid Build Coastguard Worker       // PROT_NONE. We need to unmap the memory when destroying this oat file.
1403*795d594fSAndroid Build Coastguard Worker       // The reserved memory size is aligned up to kElfSegmentAlignment to ensure
1404*795d594fSAndroid Build Coastguard Worker       // that the next reserved area will be aligned to the value.
1405*795d594fSAndroid Build Coastguard Worker       dlopen_mmaps_.push_back(reservation->TakeReservedMemory(
1406*795d594fSAndroid Build Coastguard Worker           CondRoundUp<kPageSizeAgnostic>(context.max_size, kElfSegmentAlignment)));
1407*795d594fSAndroid Build Coastguard Worker     }
1408*795d594fSAndroid Build Coastguard Worker #else
1409*795d594fSAndroid Build Coastguard Worker     static_assert(!kIsTargetBuild || kIsTargetLinux || kIsTargetFuchsia,
1410*795d594fSAndroid Build Coastguard Worker                   "host_dlopen_handles_ will leak handles");
1411*795d594fSAndroid Build Coastguard Worker     if (reservation != nullptr) {
1412*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("dlopen() into reserved memory is unsupported on host for '%s'.",
1413*795d594fSAndroid Build Coastguard Worker                                 elf_filename.c_str());
1414*795d594fSAndroid Build Coastguard Worker       return false;
1415*795d594fSAndroid Build Coastguard Worker     }
1416*795d594fSAndroid Build Coastguard Worker     MutexLock mu(Thread::Current(), *Locks::host_dlopen_handles_lock_);
1417*795d594fSAndroid Build Coastguard Worker     dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
1418*795d594fSAndroid Build Coastguard Worker     if (dlopen_handle_ != nullptr) {
1419*795d594fSAndroid Build Coastguard Worker       if (!host_dlopen_handles_.insert(dlopen_handle_).second) {
1420*795d594fSAndroid Build Coastguard Worker         dlclose(dlopen_handle_);
1421*795d594fSAndroid Build Coastguard Worker         dlopen_handle_ = nullptr;
1422*795d594fSAndroid Build Coastguard Worker         *error_msg = StringPrintf("host dlopen re-opened '%s'", elf_filename.c_str());
1423*795d594fSAndroid Build Coastguard Worker         return false;
1424*795d594fSAndroid Build Coastguard Worker       }
1425*795d594fSAndroid Build Coastguard Worker     }
1426*795d594fSAndroid Build Coastguard Worker #endif  // ART_TARGET_ANDROID
1427*795d594fSAndroid Build Coastguard Worker   }
1428*795d594fSAndroid Build Coastguard Worker   if (dlopen_handle_ == nullptr) {
1429*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to dlopen '%s': %s", elf_filename.c_str(), dlerror());
1430*795d594fSAndroid Build Coastguard Worker     return false;
1431*795d594fSAndroid Build Coastguard Worker   }
1432*795d594fSAndroid Build Coastguard Worker   return true;
1433*795d594fSAndroid Build Coastguard Worker #endif
1434*795d594fSAndroid Build Coastguard Worker }
1435*795d594fSAndroid Build Coastguard Worker 
PreSetup(const std::string & elf_filename)1436*795d594fSAndroid Build Coastguard Worker void DlOpenOatFile::PreSetup(const std::string& elf_filename) {
1437*795d594fSAndroid Build Coastguard Worker #ifdef __APPLE__
1438*795d594fSAndroid Build Coastguard Worker   UNUSED(elf_filename);
1439*795d594fSAndroid Build Coastguard Worker   LOG(FATAL) << "Should not reach here.";
1440*795d594fSAndroid Build Coastguard Worker   UNREACHABLE();
1441*795d594fSAndroid Build Coastguard Worker #else
1442*795d594fSAndroid Build Coastguard Worker   struct PlaceholderMapData {
1443*795d594fSAndroid Build Coastguard Worker     const char* name;
1444*795d594fSAndroid Build Coastguard Worker     uint8_t* vaddr;
1445*795d594fSAndroid Build Coastguard Worker     size_t memsz;
1446*795d594fSAndroid Build Coastguard Worker   };
1447*795d594fSAndroid Build Coastguard Worker   struct dl_iterate_context {
1448*795d594fSAndroid Build Coastguard Worker     static int callback(dl_phdr_info* info, [[maybe_unused]] size_t size, void* data) {
1449*795d594fSAndroid Build Coastguard Worker       auto* context = reinterpret_cast<dl_iterate_context*>(data);
1450*795d594fSAndroid Build Coastguard Worker       static_assert(std::is_same<Elf32_Half, Elf64_Half>::value, "Half must match");
1451*795d594fSAndroid Build Coastguard Worker       using Elf_Half = Elf64_Half;
1452*795d594fSAndroid Build Coastguard Worker 
1453*795d594fSAndroid Build Coastguard Worker       context->shared_objects_seen++;
1454*795d594fSAndroid Build Coastguard Worker       if (context->shared_objects_seen < context->shared_objects_before) {
1455*795d594fSAndroid Build Coastguard Worker         // We haven't been called yet for anything we haven't seen before. Just continue.
1456*795d594fSAndroid Build Coastguard Worker         // Note: this is aggressively optimistic. If another thread was unloading a library,
1457*795d594fSAndroid Build Coastguard Worker         //       we may miss out here. However, this does not happen often in practice.
1458*795d594fSAndroid Build Coastguard Worker         return 0;
1459*795d594fSAndroid Build Coastguard Worker       }
1460*795d594fSAndroid Build Coastguard Worker 
1461*795d594fSAndroid Build Coastguard Worker       // See whether this callback corresponds to the file which we have just loaded.
1462*795d594fSAndroid Build Coastguard Worker       bool contains_begin = false;
1463*795d594fSAndroid Build Coastguard Worker       for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1464*795d594fSAndroid Build Coastguard Worker         if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1465*795d594fSAndroid Build Coastguard Worker           uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1466*795d594fSAndroid Build Coastguard Worker               info->dlpi_phdr[i].p_vaddr);
1467*795d594fSAndroid Build Coastguard Worker           size_t memsz = info->dlpi_phdr[i].p_memsz;
1468*795d594fSAndroid Build Coastguard Worker           if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
1469*795d594fSAndroid Build Coastguard Worker             contains_begin = true;
1470*795d594fSAndroid Build Coastguard Worker             break;
1471*795d594fSAndroid Build Coastguard Worker           }
1472*795d594fSAndroid Build Coastguard Worker         }
1473*795d594fSAndroid Build Coastguard Worker       }
1474*795d594fSAndroid Build Coastguard Worker       // Add placeholder mmaps for this file.
1475*795d594fSAndroid Build Coastguard Worker       if (contains_begin) {
1476*795d594fSAndroid Build Coastguard Worker         for (Elf_Half i = 0; i < info->dlpi_phnum; i++) {
1477*795d594fSAndroid Build Coastguard Worker           if (info->dlpi_phdr[i].p_type == PT_LOAD) {
1478*795d594fSAndroid Build Coastguard Worker             uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
1479*795d594fSAndroid Build Coastguard Worker                 info->dlpi_phdr[i].p_vaddr);
1480*795d594fSAndroid Build Coastguard Worker             size_t memsz = info->dlpi_phdr[i].p_memsz;
1481*795d594fSAndroid Build Coastguard Worker             size_t name_size = strlen(info->dlpi_name) + 1u;
1482*795d594fSAndroid Build Coastguard Worker             std::vector<char>* placeholder_maps_names = context->placeholder_maps_names_;
1483*795d594fSAndroid Build Coastguard Worker             // We must not allocate any memory in the callback, see b/156312036 .
1484*795d594fSAndroid Build Coastguard Worker             if (name_size < placeholder_maps_names->capacity() - placeholder_maps_names->size() &&
1485*795d594fSAndroid Build Coastguard Worker                 context->placeholder_maps_data_->size() <
1486*795d594fSAndroid Build Coastguard Worker                     context->placeholder_maps_data_->capacity()) {
1487*795d594fSAndroid Build Coastguard Worker               placeholder_maps_names->insert(
1488*795d594fSAndroid Build Coastguard Worker                   placeholder_maps_names->end(), info->dlpi_name, info->dlpi_name + name_size);
1489*795d594fSAndroid Build Coastguard Worker               const char* name =
1490*795d594fSAndroid Build Coastguard Worker                   &(*placeholder_maps_names)[placeholder_maps_names->size() - name_size];
1491*795d594fSAndroid Build Coastguard Worker               context->placeholder_maps_data_->push_back({ name, vaddr, memsz });
1492*795d594fSAndroid Build Coastguard Worker             }
1493*795d594fSAndroid Build Coastguard Worker             context->num_placeholder_maps_ += 1u;
1494*795d594fSAndroid Build Coastguard Worker             context->placeholder_maps_names_size_ += name_size;
1495*795d594fSAndroid Build Coastguard Worker           }
1496*795d594fSAndroid Build Coastguard Worker         }
1497*795d594fSAndroid Build Coastguard Worker         return 1;  // Stop iteration and return 1 from dl_iterate_phdr.
1498*795d594fSAndroid Build Coastguard Worker       }
1499*795d594fSAndroid Build Coastguard Worker       return 0;  // Continue iteration and return 0 from dl_iterate_phdr when finished.
1500*795d594fSAndroid Build Coastguard Worker     }
1501*795d594fSAndroid Build Coastguard Worker     const uint8_t* const begin_;
1502*795d594fSAndroid Build Coastguard Worker     std::vector<PlaceholderMapData>* placeholder_maps_data_;
1503*795d594fSAndroid Build Coastguard Worker     size_t num_placeholder_maps_;
1504*795d594fSAndroid Build Coastguard Worker     std::vector<char>* placeholder_maps_names_;
1505*795d594fSAndroid Build Coastguard Worker     size_t placeholder_maps_names_size_;
1506*795d594fSAndroid Build Coastguard Worker     size_t shared_objects_before;
1507*795d594fSAndroid Build Coastguard Worker     size_t shared_objects_seen;
1508*795d594fSAndroid Build Coastguard Worker   };
1509*795d594fSAndroid Build Coastguard Worker 
1510*795d594fSAndroid Build Coastguard Worker   // We must not allocate any memory in the callback, see b/156312036 .
1511*795d594fSAndroid Build Coastguard Worker   // Therefore we pre-allocate storage for the data we need for creating the placeholder maps.
1512*795d594fSAndroid Build Coastguard Worker   std::vector<PlaceholderMapData> placeholder_maps_data;
1513*795d594fSAndroid Build Coastguard Worker   placeholder_maps_data.reserve(32);  // 32 should be enough. If not, we'll retry.
1514*795d594fSAndroid Build Coastguard Worker   std::vector<char> placeholder_maps_names;
1515*795d594fSAndroid Build Coastguard Worker   placeholder_maps_names.reserve(4 * KB);  // 4KiB should be enough. If not, we'll retry.
1516*795d594fSAndroid Build Coastguard Worker 
1517*795d594fSAndroid Build Coastguard Worker   dl_iterate_context context = {
1518*795d594fSAndroid Build Coastguard Worker       Begin(),
1519*795d594fSAndroid Build Coastguard Worker       &placeholder_maps_data,
1520*795d594fSAndroid Build Coastguard Worker       /*num_placeholder_maps_*/ 0u,
1521*795d594fSAndroid Build Coastguard Worker       &placeholder_maps_names,
1522*795d594fSAndroid Build Coastguard Worker       /*placeholder_maps_names_size_*/ 0u,
1523*795d594fSAndroid Build Coastguard Worker       shared_objects_before_,
1524*795d594fSAndroid Build Coastguard Worker       /*shared_objects_seen*/ 0u
1525*795d594fSAndroid Build Coastguard Worker   };
1526*795d594fSAndroid Build Coastguard Worker 
1527*795d594fSAndroid Build Coastguard Worker   if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1528*795d594fSAndroid Build Coastguard Worker     // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0
1529*795d594fSAndroid Build Coastguard Worker     // before giving up. This should be unusual.
1530*795d594fSAndroid Build Coastguard Worker     VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before="
1531*795d594fSAndroid Build Coastguard Worker               << shared_objects_before_;
1532*795d594fSAndroid Build Coastguard Worker     DCHECK(placeholder_maps_data.empty());
1533*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(context.num_placeholder_maps_, 0u);
1534*795d594fSAndroid Build Coastguard Worker     DCHECK(placeholder_maps_names.empty());
1535*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(context.placeholder_maps_names_size_, 0u);
1536*795d594fSAndroid Build Coastguard Worker     context.shared_objects_before = 0u;
1537*795d594fSAndroid Build Coastguard Worker     context.shared_objects_seen = 0u;
1538*795d594fSAndroid Build Coastguard Worker     if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
1539*795d594fSAndroid Build Coastguard Worker       // OK, give up and print an error.
1540*795d594fSAndroid Build Coastguard Worker       PrintFileToLog("/proc/self/maps", android::base::LogSeverity::WARNING);
1541*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps.";
1542*795d594fSAndroid Build Coastguard Worker     }
1543*795d594fSAndroid Build Coastguard Worker   }
1544*795d594fSAndroid Build Coastguard Worker 
1545*795d594fSAndroid Build Coastguard Worker   if (placeholder_maps_data.size() < context.num_placeholder_maps_) {
1546*795d594fSAndroid Build Coastguard Worker     // Insufficient capacity. Reserve more space and retry.
1547*795d594fSAndroid Build Coastguard Worker     placeholder_maps_data.clear();
1548*795d594fSAndroid Build Coastguard Worker     placeholder_maps_data.reserve(context.num_placeholder_maps_);
1549*795d594fSAndroid Build Coastguard Worker     context.num_placeholder_maps_ = 0u;
1550*795d594fSAndroid Build Coastguard Worker     placeholder_maps_names.clear();
1551*795d594fSAndroid Build Coastguard Worker     placeholder_maps_names.reserve(context.placeholder_maps_names_size_);
1552*795d594fSAndroid Build Coastguard Worker     context.placeholder_maps_names_size_ = 0u;
1553*795d594fSAndroid Build Coastguard Worker     context.shared_objects_before = 0u;
1554*795d594fSAndroid Build Coastguard Worker     context.shared_objects_seen = 0u;
1555*795d594fSAndroid Build Coastguard Worker     bool success = (dl_iterate_phdr(dl_iterate_context::callback, &context) != 0);
1556*795d594fSAndroid Build Coastguard Worker     CHECK(success);
1557*795d594fSAndroid Build Coastguard Worker   }
1558*795d594fSAndroid Build Coastguard Worker 
1559*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(placeholder_maps_data.size(), context.num_placeholder_maps_);
1560*795d594fSAndroid Build Coastguard Worker   CHECK_EQ(placeholder_maps_names.size(), context.placeholder_maps_names_size_);
1561*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(static_cast<size_t>(std::count(placeholder_maps_names.begin(),
1562*795d594fSAndroid Build Coastguard Worker                                            placeholder_maps_names.end(), '\0')),
1563*795d594fSAndroid Build Coastguard Worker             context.num_placeholder_maps_);
1564*795d594fSAndroid Build Coastguard Worker   for (const PlaceholderMapData& data : placeholder_maps_data) {
1565*795d594fSAndroid Build Coastguard Worker     MemMap mmap = MemMap::MapPlaceholder(data.name, data.vaddr, data.memsz);
1566*795d594fSAndroid Build Coastguard Worker     dlopen_mmaps_.push_back(std::move(mmap));
1567*795d594fSAndroid Build Coastguard Worker   }
1568*795d594fSAndroid Build Coastguard Worker #endif
1569*795d594fSAndroid Build Coastguard Worker }
1570*795d594fSAndroid Build Coastguard Worker 
1571*795d594fSAndroid Build Coastguard Worker ////////////////////////////////////////////////
1572*795d594fSAndroid Build Coastguard Worker // OatFile via our own ElfFile implementation //
1573*795d594fSAndroid Build Coastguard Worker ////////////////////////////////////////////////
1574*795d594fSAndroid Build Coastguard Worker 
1575*795d594fSAndroid Build Coastguard Worker class ElfOatFile final : public OatFileBase {
1576*795d594fSAndroid Build Coastguard Worker  public:
ElfOatFile(const std::string & filename,bool executable)1577*795d594fSAndroid Build Coastguard Worker   ElfOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable) {}
1578*795d594fSAndroid Build Coastguard Worker 
1579*795d594fSAndroid Build Coastguard Worker   bool InitializeFromElfFile(int zip_fd,
1580*795d594fSAndroid Build Coastguard Worker                              ElfFile* elf_file,
1581*795d594fSAndroid Build Coastguard Worker                              VdexFile* vdex_file,
1582*795d594fSAndroid Build Coastguard Worker                              ArrayRef<const std::string> dex_filenames,
1583*795d594fSAndroid Build Coastguard Worker                              std::string* error_msg);
1584*795d594fSAndroid Build Coastguard Worker 
1585*795d594fSAndroid Build Coastguard Worker  protected:
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1586*795d594fSAndroid Build Coastguard Worker   const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name,
1587*795d594fSAndroid Build Coastguard Worker                                           std::string* error_msg) const override {
1588*795d594fSAndroid Build Coastguard Worker     const uint8_t* ptr = elf_file_->FindDynamicSymbolAddress(symbol_name);
1589*795d594fSAndroid Build Coastguard Worker     if (ptr == nullptr) {
1590*795d594fSAndroid Build Coastguard Worker       *error_msg = "(Internal implementation could not find symbol)";
1591*795d594fSAndroid Build Coastguard Worker     }
1592*795d594fSAndroid Build Coastguard Worker     return ptr;
1593*795d594fSAndroid Build Coastguard Worker   }
1594*795d594fSAndroid Build Coastguard Worker 
PreLoad()1595*795d594fSAndroid Build Coastguard Worker   void PreLoad() override {
1596*795d594fSAndroid Build Coastguard Worker   }
1597*795d594fSAndroid Build Coastguard Worker 
1598*795d594fSAndroid Build Coastguard Worker   bool Load(const std::string& elf_filename,
1599*795d594fSAndroid Build Coastguard Worker             bool writable,
1600*795d594fSAndroid Build Coastguard Worker             bool executable,
1601*795d594fSAndroid Build Coastguard Worker             bool low_4gb,
1602*795d594fSAndroid Build Coastguard Worker             /*inout*/MemMap* reservation,  // Where to load if not null.
1603*795d594fSAndroid Build Coastguard Worker             /*out*/std::string* error_msg) override;
1604*795d594fSAndroid Build Coastguard Worker 
1605*795d594fSAndroid Build Coastguard Worker   bool Load(int oat_fd,
1606*795d594fSAndroid Build Coastguard Worker             bool writable,
1607*795d594fSAndroid Build Coastguard Worker             bool executable,
1608*795d594fSAndroid Build Coastguard Worker             bool low_4gb,
1609*795d594fSAndroid Build Coastguard Worker             /*inout*/MemMap* reservation,  // Where to load if not null.
1610*795d594fSAndroid Build Coastguard Worker             /*out*/std::string* error_msg) override;
1611*795d594fSAndroid Build Coastguard Worker 
PreSetup(const std::string & elf_filename)1612*795d594fSAndroid Build Coastguard Worker   void PreSetup([[maybe_unused]] const std::string& elf_filename) override {}
1613*795d594fSAndroid Build Coastguard Worker 
ComputeElfBegin(std::string *) const1614*795d594fSAndroid Build Coastguard Worker   const uint8_t* ComputeElfBegin(std::string*) const override {
1615*795d594fSAndroid Build Coastguard Worker     return elf_file_->GetBaseAddress();
1616*795d594fSAndroid Build Coastguard Worker   }
1617*795d594fSAndroid Build Coastguard Worker 
1618*795d594fSAndroid Build Coastguard Worker  private:
1619*795d594fSAndroid Build Coastguard Worker   bool ElfFileOpen(File* file,
1620*795d594fSAndroid Build Coastguard Worker                    bool writable,
1621*795d594fSAndroid Build Coastguard Worker                    bool executable,
1622*795d594fSAndroid Build Coastguard Worker                    bool low_4gb,
1623*795d594fSAndroid Build Coastguard Worker                    /*inout*/MemMap* reservation,  // Where to load if not null.
1624*795d594fSAndroid Build Coastguard Worker                    /*out*/std::string* error_msg);
1625*795d594fSAndroid Build Coastguard Worker 
1626*795d594fSAndroid Build Coastguard Worker  private:
1627*795d594fSAndroid Build Coastguard Worker   // Backing memory map for oat file during cross compilation.
1628*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ElfFile> elf_file_;
1629*795d594fSAndroid Build Coastguard Worker 
1630*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ElfOatFile);
1631*795d594fSAndroid Build Coastguard Worker };
1632*795d594fSAndroid Build Coastguard Worker 
InitializeFromElfFile(int zip_fd,ElfFile * elf_file,VdexFile * vdex_file,ArrayRef<const std::string> dex_filenames,std::string * error_msg)1633*795d594fSAndroid Build Coastguard Worker bool ElfOatFile::InitializeFromElfFile(int zip_fd,
1634*795d594fSAndroid Build Coastguard Worker                                        ElfFile* elf_file,
1635*795d594fSAndroid Build Coastguard Worker                                        VdexFile* vdex_file,
1636*795d594fSAndroid Build Coastguard Worker                                        ArrayRef<const std::string> dex_filenames,
1637*795d594fSAndroid Build Coastguard Worker                                        std::string* error_msg) {
1638*795d594fSAndroid Build Coastguard Worker   ScopedTrace trace(__PRETTY_FUNCTION__);
1639*795d594fSAndroid Build Coastguard Worker   if (IsExecutable()) {
1640*795d594fSAndroid Build Coastguard Worker     *error_msg = "Cannot initialize from elf file in executable mode.";
1641*795d594fSAndroid Build Coastguard Worker     return false;
1642*795d594fSAndroid Build Coastguard Worker   }
1643*795d594fSAndroid Build Coastguard Worker   elf_file_.reset(elf_file);
1644*795d594fSAndroid Build Coastguard Worker   SetVdex(vdex_file);
1645*795d594fSAndroid Build Coastguard Worker   uint64_t offset, size;
1646*795d594fSAndroid Build Coastguard Worker   bool has_section = elf_file->GetSectionOffsetAndSize(".rodata", &offset, &size);
1647*795d594fSAndroid Build Coastguard Worker   CHECK(has_section);
1648*795d594fSAndroid Build Coastguard Worker   SetBegin(elf_file->Begin() + offset);
1649*795d594fSAndroid Build Coastguard Worker   SetEnd(elf_file->Begin() + size + offset);
1650*795d594fSAndroid Build Coastguard Worker   // Ignore the optional .bss section when opening non-executable.
1651*795d594fSAndroid Build Coastguard Worker   return Setup(zip_fd, dex_filenames, /*dex_files=*/{}, error_msg);
1652*795d594fSAndroid Build Coastguard Worker }
1653*795d594fSAndroid Build Coastguard Worker 
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1654*795d594fSAndroid Build Coastguard Worker bool ElfOatFile::Load(const std::string& elf_filename,
1655*795d594fSAndroid Build Coastguard Worker                       bool writable,
1656*795d594fSAndroid Build Coastguard Worker                       bool executable,
1657*795d594fSAndroid Build Coastguard Worker                       bool low_4gb,
1658*795d594fSAndroid Build Coastguard Worker                       /*inout*/MemMap* reservation,
1659*795d594fSAndroid Build Coastguard Worker                       /*out*/std::string* error_msg) {
1660*795d594fSAndroid Build Coastguard Worker   ScopedTrace trace(__PRETTY_FUNCTION__);
1661*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
1662*795d594fSAndroid Build Coastguard Worker   if (file == nullptr) {
1663*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno));
1664*795d594fSAndroid Build Coastguard Worker     return false;
1665*795d594fSAndroid Build Coastguard Worker   }
1666*795d594fSAndroid Build Coastguard Worker   return ElfOatFile::ElfFileOpen(file.get(),
1667*795d594fSAndroid Build Coastguard Worker                                  writable,
1668*795d594fSAndroid Build Coastguard Worker                                  executable,
1669*795d594fSAndroid Build Coastguard Worker                                  low_4gb,
1670*795d594fSAndroid Build Coastguard Worker                                  reservation,
1671*795d594fSAndroid Build Coastguard Worker                                  error_msg);
1672*795d594fSAndroid Build Coastguard Worker }
1673*795d594fSAndroid Build Coastguard Worker 
Load(int oat_fd,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1674*795d594fSAndroid Build Coastguard Worker bool ElfOatFile::Load(int oat_fd,
1675*795d594fSAndroid Build Coastguard Worker                       bool writable,
1676*795d594fSAndroid Build Coastguard Worker                       bool executable,
1677*795d594fSAndroid Build Coastguard Worker                       bool low_4gb,
1678*795d594fSAndroid Build Coastguard Worker                       /*inout*/MemMap* reservation,
1679*795d594fSAndroid Build Coastguard Worker                       /*out*/std::string* error_msg) {
1680*795d594fSAndroid Build Coastguard Worker   ScopedTrace trace(__PRETTY_FUNCTION__);
1681*795d594fSAndroid Build Coastguard Worker   if (oat_fd != -1) {
1682*795d594fSAndroid Build Coastguard Worker     int duped_fd = DupCloexec(oat_fd);
1683*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<File> file = std::make_unique<File>(duped_fd, false);
1684*795d594fSAndroid Build Coastguard Worker     if (file == nullptr) {
1685*795d594fSAndroid Build Coastguard Worker       *error_msg = StringPrintf("Failed to open oat filename for reading: %s",
1686*795d594fSAndroid Build Coastguard Worker                                 strerror(errno));
1687*795d594fSAndroid Build Coastguard Worker       return false;
1688*795d594fSAndroid Build Coastguard Worker     }
1689*795d594fSAndroid Build Coastguard Worker     return ElfOatFile::ElfFileOpen(file.get(),
1690*795d594fSAndroid Build Coastguard Worker                                    writable,
1691*795d594fSAndroid Build Coastguard Worker                                    executable,
1692*795d594fSAndroid Build Coastguard Worker                                    low_4gb,
1693*795d594fSAndroid Build Coastguard Worker                                    reservation,
1694*795d594fSAndroid Build Coastguard Worker                                    error_msg);
1695*795d594fSAndroid Build Coastguard Worker   }
1696*795d594fSAndroid Build Coastguard Worker   return false;
1697*795d594fSAndroid Build Coastguard Worker }
1698*795d594fSAndroid Build Coastguard Worker 
ElfFileOpen(File * file,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1699*795d594fSAndroid Build Coastguard Worker bool ElfOatFile::ElfFileOpen(File* file,
1700*795d594fSAndroid Build Coastguard Worker                              bool writable,
1701*795d594fSAndroid Build Coastguard Worker                              bool executable,
1702*795d594fSAndroid Build Coastguard Worker                              bool low_4gb,
1703*795d594fSAndroid Build Coastguard Worker                              /*inout*/MemMap* reservation,
1704*795d594fSAndroid Build Coastguard Worker                              /*out*/std::string* error_msg) {
1705*795d594fSAndroid Build Coastguard Worker   ScopedTrace trace(__PRETTY_FUNCTION__);
1706*795d594fSAndroid Build Coastguard Worker   elf_file_.reset(ElfFile::Open(file,
1707*795d594fSAndroid Build Coastguard Worker                                 writable,
1708*795d594fSAndroid Build Coastguard Worker                                 /*program_header_only=*/true,
1709*795d594fSAndroid Build Coastguard Worker                                 low_4gb,
1710*795d594fSAndroid Build Coastguard Worker                                 error_msg));
1711*795d594fSAndroid Build Coastguard Worker   if (elf_file_ == nullptr) {
1712*795d594fSAndroid Build Coastguard Worker     DCHECK(!error_msg->empty());
1713*795d594fSAndroid Build Coastguard Worker     return false;
1714*795d594fSAndroid Build Coastguard Worker   }
1715*795d594fSAndroid Build Coastguard Worker   bool loaded = elf_file_->Load(file, executable, low_4gb, reservation, error_msg);
1716*795d594fSAndroid Build Coastguard Worker   DCHECK(loaded || !error_msg->empty());
1717*795d594fSAndroid Build Coastguard Worker   return loaded;
1718*795d594fSAndroid Build Coastguard Worker }
1719*795d594fSAndroid Build Coastguard Worker 
1720*795d594fSAndroid Build Coastguard Worker class OatFileBackedByVdex final : public OatFileBase {
1721*795d594fSAndroid Build Coastguard Worker  public:
OatFileBackedByVdex(const std::string & filename)1722*795d594fSAndroid Build Coastguard Worker   explicit OatFileBackedByVdex(const std::string& filename)
1723*795d594fSAndroid Build Coastguard Worker       : OatFileBase(filename, /*executable=*/false) {}
1724*795d594fSAndroid Build Coastguard Worker 
Open(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,ClassLoaderContext * context)1725*795d594fSAndroid Build Coastguard Worker   static OatFileBackedByVdex* Open(const std::vector<const DexFile*>& dex_files,
1726*795d594fSAndroid Build Coastguard Worker                                    std::unique_ptr<VdexFile>&& vdex_file,
1727*795d594fSAndroid Build Coastguard Worker                                    const std::string& location,
1728*795d594fSAndroid Build Coastguard Worker                                    ClassLoaderContext* context) {
1729*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(location));
1730*795d594fSAndroid Build Coastguard Worker     // SetVdex will take ownership of the VdexFile.
1731*795d594fSAndroid Build Coastguard Worker     oat_file->SetVdex(vdex_file.release());
1732*795d594fSAndroid Build Coastguard Worker     oat_file->SetupHeader(dex_files.size(), context);
1733*795d594fSAndroid Build Coastguard Worker     // Initialize OatDexFiles.
1734*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
1735*795d594fSAndroid Build Coastguard Worker     if (!oat_file->Setup(dex_files, &error_msg)) {
1736*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "Could not create in-memory vdex file: " << error_msg;
1737*795d594fSAndroid Build Coastguard Worker       return nullptr;
1738*795d594fSAndroid Build Coastguard Worker     }
1739*795d594fSAndroid Build Coastguard Worker     return oat_file.release();
1740*795d594fSAndroid Build Coastguard Worker   }
1741*795d594fSAndroid Build Coastguard Worker 
Open(int zip_fd,std::unique_ptr<VdexFile> && unique_vdex_file,const std::string & dex_location,ClassLoaderContext * context,std::string * error_msg)1742*795d594fSAndroid Build Coastguard Worker   static OatFileBackedByVdex* Open(int zip_fd,
1743*795d594fSAndroid Build Coastguard Worker                                    std::unique_ptr<VdexFile>&& unique_vdex_file,
1744*795d594fSAndroid Build Coastguard Worker                                    const std::string& dex_location,
1745*795d594fSAndroid Build Coastguard Worker                                    ClassLoaderContext* context,
1746*795d594fSAndroid Build Coastguard Worker                                    std::string* error_msg) {
1747*795d594fSAndroid Build Coastguard Worker     VdexFile* vdex_file = unique_vdex_file.get();
1748*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<OatFileBackedByVdex> oat_file(new OatFileBackedByVdex(vdex_file->GetName()));
1749*795d594fSAndroid Build Coastguard Worker     // SetVdex will take ownership of the VdexFile.
1750*795d594fSAndroid Build Coastguard Worker     oat_file->SetVdex(unique_vdex_file.release());
1751*795d594fSAndroid Build Coastguard Worker     if (vdex_file->HasDexSection()) {
1752*795d594fSAndroid Build Coastguard Worker       uint32_t i = 0;
1753*795d594fSAndroid Build Coastguard Worker       const uint8_t* type_lookup_table_start = nullptr;
1754*795d594fSAndroid Build Coastguard Worker       auto dex_file_container =
1755*795d594fSAndroid Build Coastguard Worker           std::make_shared<MemoryDexFileContainer>(vdex_file->Begin(), vdex_file->End());
1756*795d594fSAndroid Build Coastguard Worker       for (const uint8_t* dex_file_start = vdex_file->GetNextDexFileData(nullptr, i);
1757*795d594fSAndroid Build Coastguard Worker            dex_file_start != nullptr;
1758*795d594fSAndroid Build Coastguard Worker            dex_file_start = vdex_file->GetNextDexFileData(dex_file_start, ++i)) {
1759*795d594fSAndroid Build Coastguard Worker         if (UNLIKELY(!vdex_file->Contains(dex_file_start, sizeof(DexFile::Header)))) {
1760*795d594fSAndroid Build Coastguard Worker           *error_msg =
1761*795d594fSAndroid Build Coastguard Worker               StringPrintf("In vdex file '%s' found invalid dex header %p of size %zu "
1762*795d594fSAndroid Build Coastguard Worker                                "not in [%p, %p]",
1763*795d594fSAndroid Build Coastguard Worker                            dex_location.c_str(),
1764*795d594fSAndroid Build Coastguard Worker                            dex_file_start,
1765*795d594fSAndroid Build Coastguard Worker                            sizeof(DexFile::Header),
1766*795d594fSAndroid Build Coastguard Worker                            vdex_file->Begin(),
1767*795d594fSAndroid Build Coastguard Worker                            vdex_file->End());
1768*795d594fSAndroid Build Coastguard Worker           return nullptr;
1769*795d594fSAndroid Build Coastguard Worker         }
1770*795d594fSAndroid Build Coastguard Worker         const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_start);
1771*795d594fSAndroid Build Coastguard Worker         if (UNLIKELY(!vdex_file->Contains(dex_file_start, header->file_size_))) {
1772*795d594fSAndroid Build Coastguard Worker           *error_msg =
1773*795d594fSAndroid Build Coastguard Worker               StringPrintf("In vdex file '%s' found invalid dex file pointer %p of size %d "
1774*795d594fSAndroid Build Coastguard Worker                                "not in [%p, %p]",
1775*795d594fSAndroid Build Coastguard Worker                            dex_location.c_str(),
1776*795d594fSAndroid Build Coastguard Worker                            dex_file_start,
1777*795d594fSAndroid Build Coastguard Worker                            header->file_size_,
1778*795d594fSAndroid Build Coastguard Worker                            vdex_file->Begin(),
1779*795d594fSAndroid Build Coastguard Worker                            vdex_file->End());
1780*795d594fSAndroid Build Coastguard Worker           return nullptr;
1781*795d594fSAndroid Build Coastguard Worker         }
1782*795d594fSAndroid Build Coastguard Worker         if (UNLIKELY(!DexFileLoader::IsVersionAndMagicValid(dex_file_start))) {
1783*795d594fSAndroid Build Coastguard Worker           *error_msg =
1784*795d594fSAndroid Build Coastguard Worker               StringPrintf("In vdex file '%s' found dex file with invalid dex file version",
1785*795d594fSAndroid Build Coastguard Worker                            dex_location.c_str());
1786*795d594fSAndroid Build Coastguard Worker           return nullptr;
1787*795d594fSAndroid Build Coastguard Worker         }
1788*795d594fSAndroid Build Coastguard Worker         // Create the OatDexFile and add it to the owning container.
1789*795d594fSAndroid Build Coastguard Worker         std::string location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
1790*795d594fSAndroid Build Coastguard Worker         std::string canonical_location = DexFileLoader::GetDexCanonicalLocation(location.c_str());
1791*795d594fSAndroid Build Coastguard Worker         type_lookup_table_start = vdex_file->GetNextTypeLookupTableData(type_lookup_table_start, i);
1792*795d594fSAndroid Build Coastguard Worker         const uint8_t* type_lookup_table_data = nullptr;
1793*795d594fSAndroid Build Coastguard Worker         if (!ComputeAndCheckTypeLookupTableData(*header,
1794*795d594fSAndroid Build Coastguard Worker                                                 type_lookup_table_start,
1795*795d594fSAndroid Build Coastguard Worker                                                 vdex_file,
1796*795d594fSAndroid Build Coastguard Worker                                                 &type_lookup_table_data,
1797*795d594fSAndroid Build Coastguard Worker                                                 error_msg)) {
1798*795d594fSAndroid Build Coastguard Worker           return nullptr;
1799*795d594fSAndroid Build Coastguard Worker         }
1800*795d594fSAndroid Build Coastguard Worker 
1801*795d594fSAndroid Build Coastguard Worker         OatDexFile* oat_dex_file = new OatDexFile(oat_file.get(),
1802*795d594fSAndroid Build Coastguard Worker                                                   dex_file_container,
1803*795d594fSAndroid Build Coastguard Worker                                                   dex_file_start,
1804*795d594fSAndroid Build Coastguard Worker                                                   header->magic_,
1805*795d594fSAndroid Build Coastguard Worker                                                   vdex_file->GetLocationChecksum(i),
1806*795d594fSAndroid Build Coastguard Worker                                                   header->signature_,
1807*795d594fSAndroid Build Coastguard Worker                                                   location,
1808*795d594fSAndroid Build Coastguard Worker                                                   canonical_location,
1809*795d594fSAndroid Build Coastguard Worker                                                   type_lookup_table_data);
1810*795d594fSAndroid Build Coastguard Worker         oat_file->oat_dex_files_storage_.push_back(oat_dex_file);
1811*795d594fSAndroid Build Coastguard Worker 
1812*795d594fSAndroid Build Coastguard Worker         std::string_view key(oat_dex_file->GetDexFileLocation());
1813*795d594fSAndroid Build Coastguard Worker         oat_file->oat_dex_files_.Put(key, oat_dex_file);
1814*795d594fSAndroid Build Coastguard Worker         if (canonical_location != location) {
1815*795d594fSAndroid Build Coastguard Worker           std::string_view canonical_key(oat_dex_file->GetCanonicalDexFileLocation());
1816*795d594fSAndroid Build Coastguard Worker           oat_file->oat_dex_files_.Put(canonical_key, oat_dex_file);
1817*795d594fSAndroid Build Coastguard Worker         }
1818*795d594fSAndroid Build Coastguard Worker       }
1819*795d594fSAndroid Build Coastguard Worker       oat_file->SetupHeader(oat_file->oat_dex_files_storage_.size(), context);
1820*795d594fSAndroid Build Coastguard Worker     } else {
1821*795d594fSAndroid Build Coastguard Worker       // No need for any verification when loading dex files as we already have
1822*795d594fSAndroid Build Coastguard Worker       // a vdex file.
1823*795d594fSAndroid Build Coastguard Worker       bool loaded = false;
1824*795d594fSAndroid Build Coastguard Worker       if (zip_fd != -1) {
1825*795d594fSAndroid Build Coastguard Worker         File file(zip_fd, /*check_usage=*/false);
1826*795d594fSAndroid Build Coastguard Worker         ArtDexFileLoader dex_file_loader(&file, dex_location);
1827*795d594fSAndroid Build Coastguard Worker         loaded = dex_file_loader.Open(/*verify=*/false,
1828*795d594fSAndroid Build Coastguard Worker                                       /*verify_checksum=*/false,
1829*795d594fSAndroid Build Coastguard Worker                                       error_msg,
1830*795d594fSAndroid Build Coastguard Worker                                       &oat_file->external_dex_files_);
1831*795d594fSAndroid Build Coastguard Worker       } else {
1832*795d594fSAndroid Build Coastguard Worker         ArtDexFileLoader dex_file_loader(dex_location);
1833*795d594fSAndroid Build Coastguard Worker         loaded = dex_file_loader.Open(/*verify=*/false,
1834*795d594fSAndroid Build Coastguard Worker                                       /*verify_checksum=*/false,
1835*795d594fSAndroid Build Coastguard Worker                                       error_msg,
1836*795d594fSAndroid Build Coastguard Worker                                       &oat_file->external_dex_files_);
1837*795d594fSAndroid Build Coastguard Worker       }
1838*795d594fSAndroid Build Coastguard Worker       if (!loaded) {
1839*795d594fSAndroid Build Coastguard Worker         return nullptr;
1840*795d594fSAndroid Build Coastguard Worker       }
1841*795d594fSAndroid Build Coastguard Worker       oat_file->SetupHeader(oat_file->external_dex_files_.size(), context);
1842*795d594fSAndroid Build Coastguard Worker       if (!oat_file->Setup(MakeNonOwningPointerVector(oat_file->external_dex_files_), error_msg)) {
1843*795d594fSAndroid Build Coastguard Worker         return nullptr;
1844*795d594fSAndroid Build Coastguard Worker       }
1845*795d594fSAndroid Build Coastguard Worker     }
1846*795d594fSAndroid Build Coastguard Worker 
1847*795d594fSAndroid Build Coastguard Worker     return oat_file.release();
1848*795d594fSAndroid Build Coastguard Worker   }
1849*795d594fSAndroid Build Coastguard Worker 
SetupHeader(size_t number_of_dex_files,ClassLoaderContext * context)1850*795d594fSAndroid Build Coastguard Worker   void SetupHeader(size_t number_of_dex_files, ClassLoaderContext* context) {
1851*795d594fSAndroid Build Coastguard Worker     DCHECK(!IsExecutable());
1852*795d594fSAndroid Build Coastguard Worker 
1853*795d594fSAndroid Build Coastguard Worker     // Create a fake OatHeader with a key store to help debugging.
1854*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<const InstructionSetFeatures> isa_features =
1855*795d594fSAndroid Build Coastguard Worker         InstructionSetFeatures::FromCppDefines();
1856*795d594fSAndroid Build Coastguard Worker     SafeMap<std::string, std::string> store;
1857*795d594fSAndroid Build Coastguard Worker     store.Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(CompilerFilter::kVerify));
1858*795d594fSAndroid Build Coastguard Worker     store.Put(OatHeader::kCompilationReasonKey, kReasonVdex);
1859*795d594fSAndroid Build Coastguard Worker     store.Put(OatHeader::kConcurrentCopying,
1860*795d594fSAndroid Build Coastguard Worker               gUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
1861*795d594fSAndroid Build Coastguard Worker     if (context != nullptr) {
1862*795d594fSAndroid Build Coastguard Worker       store.Put(OatHeader::kClassPathKey, context->EncodeContextForOatFile(""));
1863*795d594fSAndroid Build Coastguard Worker     }
1864*795d594fSAndroid Build Coastguard Worker 
1865*795d594fSAndroid Build Coastguard Worker     oat_header_.reset(OatHeader::Create(kRuntimeQuickCodeISA,
1866*795d594fSAndroid Build Coastguard Worker                                         isa_features.get(),
1867*795d594fSAndroid Build Coastguard Worker                                         number_of_dex_files,
1868*795d594fSAndroid Build Coastguard Worker                                         &store));
1869*795d594fSAndroid Build Coastguard Worker     const uint8_t* begin = reinterpret_cast<const uint8_t*>(oat_header_.get());
1870*795d594fSAndroid Build Coastguard Worker     SetBegin(begin);
1871*795d594fSAndroid Build Coastguard Worker     SetEnd(begin + oat_header_->GetHeaderSize());
1872*795d594fSAndroid Build Coastguard Worker   }
1873*795d594fSAndroid Build Coastguard Worker 
1874*795d594fSAndroid Build Coastguard Worker  protected:
PreLoad()1875*795d594fSAndroid Build Coastguard Worker   void PreLoad() override {}
1876*795d594fSAndroid Build Coastguard Worker 
Load(const std::string & elf_filename,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1877*795d594fSAndroid Build Coastguard Worker   bool Load([[maybe_unused]] const std::string& elf_filename,
1878*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool writable,
1879*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool executable,
1880*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool low_4gb,
1881*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] MemMap* reservation,
1882*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] std::string* error_msg) override {
1883*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Unsupported";
1884*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
1885*795d594fSAndroid Build Coastguard Worker   }
1886*795d594fSAndroid Build Coastguard Worker 
Load(int oat_fd,bool writable,bool executable,bool low_4gb,MemMap * reservation,std::string * error_msg)1887*795d594fSAndroid Build Coastguard Worker   bool Load([[maybe_unused]] int oat_fd,
1888*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool writable,
1889*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool executable,
1890*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] bool low_4gb,
1891*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] MemMap* reservation,
1892*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] std::string* error_msg) override {
1893*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Unsupported";
1894*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
1895*795d594fSAndroid Build Coastguard Worker   }
1896*795d594fSAndroid Build Coastguard Worker 
PreSetup(const std::string & elf_filename)1897*795d594fSAndroid Build Coastguard Worker   void PreSetup([[maybe_unused]] const std::string& elf_filename) override {}
1898*795d594fSAndroid Build Coastguard Worker 
FindDynamicSymbolAddress(const std::string & symbol_name,std::string * error_msg) const1899*795d594fSAndroid Build Coastguard Worker   const uint8_t* FindDynamicSymbolAddress([[maybe_unused]] const std::string& symbol_name,
1900*795d594fSAndroid Build Coastguard Worker                                           std::string* error_msg) const override {
1901*795d594fSAndroid Build Coastguard Worker     *error_msg = "Unsupported";
1902*795d594fSAndroid Build Coastguard Worker     return nullptr;
1903*795d594fSAndroid Build Coastguard Worker   }
1904*795d594fSAndroid Build Coastguard Worker 
ComputeElfBegin(std::string * error_msg) const1905*795d594fSAndroid Build Coastguard Worker   const uint8_t* ComputeElfBegin(std::string* error_msg) const override {
1906*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Cannot get ELF begin because '%s' is not backed by an ELF file",
1907*795d594fSAndroid Build Coastguard Worker                               GetLocation().c_str());
1908*795d594fSAndroid Build Coastguard Worker     return nullptr;
1909*795d594fSAndroid Build Coastguard Worker   }
1910*795d594fSAndroid Build Coastguard Worker 
1911*795d594fSAndroid Build Coastguard Worker  private:
1912*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<OatHeader> oat_header_;
1913*795d594fSAndroid Build Coastguard Worker 
1914*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(OatFileBackedByVdex);
1915*795d594fSAndroid Build Coastguard Worker };
1916*795d594fSAndroid Build Coastguard Worker 
1917*795d594fSAndroid Build Coastguard Worker //////////////////////////
1918*795d594fSAndroid Build Coastguard Worker // General OatFile code //
1919*795d594fSAndroid Build Coastguard Worker //////////////////////////
1920*795d594fSAndroid Build Coastguard Worker 
CheckLocation(const std::string & location)1921*795d594fSAndroid Build Coastguard Worker static void CheckLocation(const std::string& location) {
1922*795d594fSAndroid Build Coastguard Worker   CHECK(!location.empty());
1923*795d594fSAndroid Build Coastguard Worker }
1924*795d594fSAndroid Build Coastguard Worker 
Open(int zip_fd,const std::string & oat_filename,const std::string & oat_location,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,ArrayRef<File> dex_files,MemMap * reservation,std::string * error_msg)1925*795d594fSAndroid Build Coastguard Worker OatFile* OatFile::Open(int zip_fd,
1926*795d594fSAndroid Build Coastguard Worker                        const std::string& oat_filename,
1927*795d594fSAndroid Build Coastguard Worker                        const std::string& oat_location,
1928*795d594fSAndroid Build Coastguard Worker                        bool executable,
1929*795d594fSAndroid Build Coastguard Worker                        bool low_4gb,
1930*795d594fSAndroid Build Coastguard Worker                        ArrayRef<const std::string> dex_filenames,
1931*795d594fSAndroid Build Coastguard Worker                        ArrayRef<File> dex_files,
1932*795d594fSAndroid Build Coastguard Worker                        /*inout*/ MemMap* reservation,
1933*795d594fSAndroid Build Coastguard Worker                        /*out*/ std::string* error_msg) {
1934*795d594fSAndroid Build Coastguard Worker   ScopedTrace trace("Open oat file " + oat_location);
1935*795d594fSAndroid Build Coastguard Worker   CHECK(!oat_filename.empty()) << oat_location;
1936*795d594fSAndroid Build Coastguard Worker   CheckLocation(oat_location);
1937*795d594fSAndroid Build Coastguard Worker 
1938*795d594fSAndroid Build Coastguard Worker   std::string vdex_filename = GetVdexFilename(oat_filename);
1939*795d594fSAndroid Build Coastguard Worker 
1940*795d594fSAndroid Build Coastguard Worker   // Check that the vdex file even exists, fast-fail. We don't check the odex
1941*795d594fSAndroid Build Coastguard Worker   // file as we use the absence of an odex file for test the functionality of
1942*795d594fSAndroid Build Coastguard Worker   // vdex-only.
1943*795d594fSAndroid Build Coastguard Worker   if (!OS::FileExists(vdex_filename.c_str())) {
1944*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("File %s does not exist.", vdex_filename.c_str());
1945*795d594fSAndroid Build Coastguard Worker     return nullptr;
1946*795d594fSAndroid Build Coastguard Worker   }
1947*795d594fSAndroid Build Coastguard Worker 
1948*795d594fSAndroid Build Coastguard Worker   // Try dlopen first, as it is required for native debuggability. This will fail fast if dlopen is
1949*795d594fSAndroid Build Coastguard Worker   // disabled.
1950*795d594fSAndroid Build Coastguard Worker   OatFile* with_dlopen = OatFileBase::OpenOatFile<DlOpenOatFile>(zip_fd,
1951*795d594fSAndroid Build Coastguard Worker                                                                  vdex_filename,
1952*795d594fSAndroid Build Coastguard Worker                                                                  oat_filename,
1953*795d594fSAndroid Build Coastguard Worker                                                                  oat_location,
1954*795d594fSAndroid Build Coastguard Worker                                                                  /*writable=*/false,
1955*795d594fSAndroid Build Coastguard Worker                                                                  executable,
1956*795d594fSAndroid Build Coastguard Worker                                                                  low_4gb,
1957*795d594fSAndroid Build Coastguard Worker                                                                  dex_filenames,
1958*795d594fSAndroid Build Coastguard Worker                                                                  dex_files,
1959*795d594fSAndroid Build Coastguard Worker                                                                  reservation,
1960*795d594fSAndroid Build Coastguard Worker                                                                  error_msg);
1961*795d594fSAndroid Build Coastguard Worker   if (with_dlopen != nullptr) {
1962*795d594fSAndroid Build Coastguard Worker     return with_dlopen;
1963*795d594fSAndroid Build Coastguard Worker   }
1964*795d594fSAndroid Build Coastguard Worker   if (kPrintDlOpenErrorMessage) {
1965*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to dlopen: " << oat_filename << " with error " << *error_msg;
1966*795d594fSAndroid Build Coastguard Worker   }
1967*795d594fSAndroid Build Coastguard Worker   // If we aren't trying to execute, we just use our own ElfFile loader for a couple reasons:
1968*795d594fSAndroid Build Coastguard Worker   //
1969*795d594fSAndroid Build Coastguard Worker   // On target, dlopen may fail when compiling due to selinux restrictions on installd.
1970*795d594fSAndroid Build Coastguard Worker   //
1971*795d594fSAndroid Build Coastguard Worker   // We use our own ELF loader for Quick to deal with legacy apps that
1972*795d594fSAndroid Build Coastguard Worker   // open a generated dex file by name, remove the file, then open
1973*795d594fSAndroid Build Coastguard Worker   // another generated dex file with the same name. http://b/10614658
1974*795d594fSAndroid Build Coastguard Worker   //
1975*795d594fSAndroid Build Coastguard Worker   // On host, dlopen is expected to fail when cross compiling, so fall back to ElfOatFile.
1976*795d594fSAndroid Build Coastguard Worker   //
1977*795d594fSAndroid Build Coastguard Worker   //
1978*795d594fSAndroid Build Coastguard Worker   // Another independent reason is the absolute placement of boot.oat. dlopen on the host usually
1979*795d594fSAndroid Build Coastguard Worker   // does honor the virtual address encoded in the ELF file only for ET_EXEC files, not ET_DYN.
1980*795d594fSAndroid Build Coastguard Worker   OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
1981*795d594fSAndroid Build Coastguard Worker                                                                 vdex_filename,
1982*795d594fSAndroid Build Coastguard Worker                                                                 oat_filename,
1983*795d594fSAndroid Build Coastguard Worker                                                                 oat_location,
1984*795d594fSAndroid Build Coastguard Worker                                                                 /*writable=*/false,
1985*795d594fSAndroid Build Coastguard Worker                                                                 executable,
1986*795d594fSAndroid Build Coastguard Worker                                                                 low_4gb,
1987*795d594fSAndroid Build Coastguard Worker                                                                 dex_filenames,
1988*795d594fSAndroid Build Coastguard Worker                                                                 dex_files,
1989*795d594fSAndroid Build Coastguard Worker                                                                 reservation,
1990*795d594fSAndroid Build Coastguard Worker                                                                 error_msg);
1991*795d594fSAndroid Build Coastguard Worker   return with_internal;
1992*795d594fSAndroid Build Coastguard Worker }
1993*795d594fSAndroid Build Coastguard Worker 
Open(int zip_fd,int vdex_fd,int oat_fd,const std::string & oat_location,bool executable,bool low_4gb,ArrayRef<const std::string> dex_filenames,ArrayRef<File> dex_files,MemMap * reservation,std::string * error_msg)1994*795d594fSAndroid Build Coastguard Worker OatFile* OatFile::Open(int zip_fd,
1995*795d594fSAndroid Build Coastguard Worker                        int vdex_fd,
1996*795d594fSAndroid Build Coastguard Worker                        int oat_fd,
1997*795d594fSAndroid Build Coastguard Worker                        const std::string& oat_location,
1998*795d594fSAndroid Build Coastguard Worker                        bool executable,
1999*795d594fSAndroid Build Coastguard Worker                        bool low_4gb,
2000*795d594fSAndroid Build Coastguard Worker                        ArrayRef<const std::string> dex_filenames,
2001*795d594fSAndroid Build Coastguard Worker                        ArrayRef<File> dex_files,
2002*795d594fSAndroid Build Coastguard Worker                        /*inout*/ MemMap* reservation,
2003*795d594fSAndroid Build Coastguard Worker                        /*out*/ std::string* error_msg) {
2004*795d594fSAndroid Build Coastguard Worker   CHECK(!oat_location.empty()) << oat_location;
2005*795d594fSAndroid Build Coastguard Worker 
2006*795d594fSAndroid Build Coastguard Worker   std::string vdex_location = GetVdexFilename(oat_location);
2007*795d594fSAndroid Build Coastguard Worker 
2008*795d594fSAndroid Build Coastguard Worker   OatFile* with_internal = OatFileBase::OpenOatFile<ElfOatFile>(zip_fd,
2009*795d594fSAndroid Build Coastguard Worker                                                                 vdex_fd,
2010*795d594fSAndroid Build Coastguard Worker                                                                 oat_fd,
2011*795d594fSAndroid Build Coastguard Worker                                                                 vdex_location,
2012*795d594fSAndroid Build Coastguard Worker                                                                 oat_location,
2013*795d594fSAndroid Build Coastguard Worker                                                                 /*writable=*/false,
2014*795d594fSAndroid Build Coastguard Worker                                                                 executable,
2015*795d594fSAndroid Build Coastguard Worker                                                                 low_4gb,
2016*795d594fSAndroid Build Coastguard Worker                                                                 dex_filenames,
2017*795d594fSAndroid Build Coastguard Worker                                                                 dex_files,
2018*795d594fSAndroid Build Coastguard Worker                                                                 reservation,
2019*795d594fSAndroid Build Coastguard Worker                                                                 error_msg);
2020*795d594fSAndroid Build Coastguard Worker   return with_internal;
2021*795d594fSAndroid Build Coastguard Worker }
2022*795d594fSAndroid Build Coastguard Worker 
OpenFromVdex(const std::vector<const DexFile * > & dex_files,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,ClassLoaderContext * context)2023*795d594fSAndroid Build Coastguard Worker OatFile* OatFile::OpenFromVdex(const std::vector<const DexFile*>& dex_files,
2024*795d594fSAndroid Build Coastguard Worker                                std::unique_ptr<VdexFile>&& vdex_file,
2025*795d594fSAndroid Build Coastguard Worker                                const std::string& location,
2026*795d594fSAndroid Build Coastguard Worker                                ClassLoaderContext* context) {
2027*795d594fSAndroid Build Coastguard Worker   CheckLocation(location);
2028*795d594fSAndroid Build Coastguard Worker   return OatFileBackedByVdex::Open(dex_files, std::move(vdex_file), location, context);
2029*795d594fSAndroid Build Coastguard Worker }
2030*795d594fSAndroid Build Coastguard Worker 
OpenFromVdex(int zip_fd,std::unique_ptr<VdexFile> && vdex_file,const std::string & location,ClassLoaderContext * context,std::string * error_msg)2031*795d594fSAndroid Build Coastguard Worker OatFile* OatFile::OpenFromVdex(int zip_fd,
2032*795d594fSAndroid Build Coastguard Worker                                std::unique_ptr<VdexFile>&& vdex_file,
2033*795d594fSAndroid Build Coastguard Worker                                const std::string& location,
2034*795d594fSAndroid Build Coastguard Worker                                ClassLoaderContext* context,
2035*795d594fSAndroid Build Coastguard Worker                                std::string* error_msg) {
2036*795d594fSAndroid Build Coastguard Worker   CheckLocation(location);
2037*795d594fSAndroid Build Coastguard Worker   return OatFileBackedByVdex::Open(zip_fd, std::move(vdex_file), location, context, error_msg);
2038*795d594fSAndroid Build Coastguard Worker }
2039*795d594fSAndroid Build Coastguard Worker 
OatFile(const std::string & location,bool is_executable)2040*795d594fSAndroid Build Coastguard Worker OatFile::OatFile(const std::string& location, bool is_executable)
2041*795d594fSAndroid Build Coastguard Worker     : location_(location),
2042*795d594fSAndroid Build Coastguard Worker       vdex_(nullptr),
2043*795d594fSAndroid Build Coastguard Worker       begin_(nullptr),
2044*795d594fSAndroid Build Coastguard Worker       end_(nullptr),
2045*795d594fSAndroid Build Coastguard Worker       data_img_rel_ro_begin_(nullptr),
2046*795d594fSAndroid Build Coastguard Worker       data_img_rel_ro_end_(nullptr),
2047*795d594fSAndroid Build Coastguard Worker       data_img_rel_ro_app_image_(nullptr),
2048*795d594fSAndroid Build Coastguard Worker       bss_begin_(nullptr),
2049*795d594fSAndroid Build Coastguard Worker       bss_end_(nullptr),
2050*795d594fSAndroid Build Coastguard Worker       bss_methods_(nullptr),
2051*795d594fSAndroid Build Coastguard Worker       bss_roots_(nullptr),
2052*795d594fSAndroid Build Coastguard Worker       is_executable_(is_executable),
2053*795d594fSAndroid Build Coastguard Worker       vdex_begin_(nullptr),
2054*795d594fSAndroid Build Coastguard Worker       vdex_end_(nullptr),
2055*795d594fSAndroid Build Coastguard Worker       app_image_begin_(nullptr),
2056*795d594fSAndroid Build Coastguard Worker       secondary_lookup_lock_("OatFile secondary lookup lock", kOatFileSecondaryLookupLock) {
2057*795d594fSAndroid Build Coastguard Worker   CHECK(!location_.empty());
2058*795d594fSAndroid Build Coastguard Worker }
2059*795d594fSAndroid Build Coastguard Worker 
~OatFile()2060*795d594fSAndroid Build Coastguard Worker OatFile::~OatFile() {
2061*795d594fSAndroid Build Coastguard Worker   STLDeleteElements(&oat_dex_files_storage_);
2062*795d594fSAndroid Build Coastguard Worker }
2063*795d594fSAndroid Build Coastguard Worker 
GetOatHeader() const2064*795d594fSAndroid Build Coastguard Worker const OatHeader& OatFile::GetOatHeader() const {
2065*795d594fSAndroid Build Coastguard Worker   return *reinterpret_cast<const OatHeader*>(Begin());
2066*795d594fSAndroid Build Coastguard Worker }
2067*795d594fSAndroid Build Coastguard Worker 
Begin() const2068*795d594fSAndroid Build Coastguard Worker const uint8_t* OatFile::Begin() const {
2069*795d594fSAndroid Build Coastguard Worker   CHECK(begin_ != nullptr);
2070*795d594fSAndroid Build Coastguard Worker   return begin_;
2071*795d594fSAndroid Build Coastguard Worker }
2072*795d594fSAndroid Build Coastguard Worker 
End() const2073*795d594fSAndroid Build Coastguard Worker const uint8_t* OatFile::End() const {
2074*795d594fSAndroid Build Coastguard Worker   CHECK(end_ != nullptr);
2075*795d594fSAndroid Build Coastguard Worker   return end_;
2076*795d594fSAndroid Build Coastguard Worker }
2077*795d594fSAndroid Build Coastguard Worker 
DexBegin() const2078*795d594fSAndroid Build Coastguard Worker const uint8_t* OatFile::DexBegin() const {
2079*795d594fSAndroid Build Coastguard Worker   return vdex_->Begin();
2080*795d594fSAndroid Build Coastguard Worker }
2081*795d594fSAndroid Build Coastguard Worker 
DexEnd() const2082*795d594fSAndroid Build Coastguard Worker const uint8_t* OatFile::DexEnd() const {
2083*795d594fSAndroid Build Coastguard Worker   return vdex_->End();
2084*795d594fSAndroid Build Coastguard Worker }
2085*795d594fSAndroid Build Coastguard Worker 
GetBootImageRelocations() const2086*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const {
2087*795d594fSAndroid Build Coastguard Worker   if (data_img_rel_ro_begin_ != nullptr) {
2088*795d594fSAndroid Build Coastguard Worker     const uint32_t* boot_image_relocations =
2089*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const uint32_t*>(data_img_rel_ro_begin_);
2090*795d594fSAndroid Build Coastguard Worker     const uint32_t* boot_image_relocations_end =
2091*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const uint32_t*>(data_img_rel_ro_app_image_);
2092*795d594fSAndroid Build Coastguard Worker     return ArrayRef<const uint32_t>(
2093*795d594fSAndroid Build Coastguard Worker         boot_image_relocations, boot_image_relocations_end - boot_image_relocations);
2094*795d594fSAndroid Build Coastguard Worker   } else {
2095*795d594fSAndroid Build Coastguard Worker     return ArrayRef<const uint32_t>();
2096*795d594fSAndroid Build Coastguard Worker   }
2097*795d594fSAndroid Build Coastguard Worker }
2098*795d594fSAndroid Build Coastguard Worker 
GetAppImageRelocations() const2099*795d594fSAndroid Build Coastguard Worker ArrayRef<const uint32_t> OatFile::GetAppImageRelocations() const {
2100*795d594fSAndroid Build Coastguard Worker   if (data_img_rel_ro_begin_ != nullptr) {
2101*795d594fSAndroid Build Coastguard Worker     const uint32_t* app_image_relocations =
2102*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const uint32_t*>(data_img_rel_ro_app_image_);
2103*795d594fSAndroid Build Coastguard Worker     const uint32_t* app_image_relocations_end =
2104*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const uint32_t*>(data_img_rel_ro_end_);
2105*795d594fSAndroid Build Coastguard Worker     return ArrayRef<const uint32_t>(
2106*795d594fSAndroid Build Coastguard Worker         app_image_relocations, app_image_relocations_end - app_image_relocations);
2107*795d594fSAndroid Build Coastguard Worker   } else {
2108*795d594fSAndroid Build Coastguard Worker     return ArrayRef<const uint32_t>();
2109*795d594fSAndroid Build Coastguard Worker   }
2110*795d594fSAndroid Build Coastguard Worker }
2111*795d594fSAndroid Build Coastguard Worker 
GetBssMethods() const2112*795d594fSAndroid Build Coastguard Worker ArrayRef<ArtMethod*> OatFile::GetBssMethods() const {
2113*795d594fSAndroid Build Coastguard Worker   if (bss_methods_ != nullptr) {
2114*795d594fSAndroid Build Coastguard Worker     ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_);
2115*795d594fSAndroid Build Coastguard Worker     ArtMethod** methods_end =
2116*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<ArtMethod**>(bss_roots_ != nullptr ? bss_roots_ : bss_end_);
2117*795d594fSAndroid Build Coastguard Worker     return ArrayRef<ArtMethod*>(methods, methods_end - methods);
2118*795d594fSAndroid Build Coastguard Worker   } else {
2119*795d594fSAndroid Build Coastguard Worker     return ArrayRef<ArtMethod*>();
2120*795d594fSAndroid Build Coastguard Worker   }
2121*795d594fSAndroid Build Coastguard Worker }
2122*795d594fSAndroid Build Coastguard Worker 
GetBssGcRoots() const2123*795d594fSAndroid Build Coastguard Worker ArrayRef<GcRoot<mirror::Object>> OatFile::GetBssGcRoots() const {
2124*795d594fSAndroid Build Coastguard Worker   if (bss_roots_ != nullptr) {
2125*795d594fSAndroid Build Coastguard Worker     auto* roots = reinterpret_cast<GcRoot<mirror::Object>*>(bss_roots_);
2126*795d594fSAndroid Build Coastguard Worker     auto* roots_end = reinterpret_cast<GcRoot<mirror::Object>*>(bss_end_);
2127*795d594fSAndroid Build Coastguard Worker     return ArrayRef<GcRoot<mirror::Object>>(roots, roots_end - roots);
2128*795d594fSAndroid Build Coastguard Worker   } else {
2129*795d594fSAndroid Build Coastguard Worker     return ArrayRef<GcRoot<mirror::Object>>();
2130*795d594fSAndroid Build Coastguard Worker   }
2131*795d594fSAndroid Build Coastguard Worker }
2132*795d594fSAndroid Build Coastguard Worker 
GetOatDexFile(const char * dex_location,std::string * error_msg) const2133*795d594fSAndroid Build Coastguard Worker const OatDexFile* OatFile::GetOatDexFile(const char* dex_location, std::string* error_msg) const {
2134*795d594fSAndroid Build Coastguard Worker   // NOTE: We assume here that the canonical location for a given dex_location never
2135*795d594fSAndroid Build Coastguard Worker   // changes. If it does (i.e. some symlink used by the filename changes) we may return
2136*795d594fSAndroid Build Coastguard Worker   // an incorrect OatDexFile. As long as we have a checksum to check, we shall return
2137*795d594fSAndroid Build Coastguard Worker   // an identical file or fail; otherwise we may see some unpredictable failures.
2138*795d594fSAndroid Build Coastguard Worker 
2139*795d594fSAndroid Build Coastguard Worker   // TODO: Additional analysis of usage patterns to see if this can be simplified
2140*795d594fSAndroid Build Coastguard Worker   // without any performance loss, for example by not doing the first lock-free lookup.
2141*795d594fSAndroid Build Coastguard Worker 
2142*795d594fSAndroid Build Coastguard Worker   const OatDexFile* oat_dex_file = nullptr;
2143*795d594fSAndroid Build Coastguard Worker   std::string_view key(dex_location);
2144*795d594fSAndroid Build Coastguard Worker   // Try to find the key cheaply in the oat_dex_files_ map which holds dex locations
2145*795d594fSAndroid Build Coastguard Worker   // directly mentioned in the oat file and doesn't require locking.
2146*795d594fSAndroid Build Coastguard Worker   auto primary_it = oat_dex_files_.find(key);
2147*795d594fSAndroid Build Coastguard Worker   if (primary_it != oat_dex_files_.end()) {
2148*795d594fSAndroid Build Coastguard Worker     oat_dex_file = primary_it->second;
2149*795d594fSAndroid Build Coastguard Worker     DCHECK(oat_dex_file != nullptr);
2150*795d594fSAndroid Build Coastguard Worker   } else {
2151*795d594fSAndroid Build Coastguard Worker     // This dex_location is not one of the dex locations directly mentioned in the
2152*795d594fSAndroid Build Coastguard Worker     // oat file. The correct lookup is via the canonical location but first see in
2153*795d594fSAndroid Build Coastguard Worker     // the secondary_oat_dex_files_ whether we've looked up this location before.
2154*795d594fSAndroid Build Coastguard Worker     MutexLock mu(Thread::Current(), secondary_lookup_lock_);
2155*795d594fSAndroid Build Coastguard Worker     auto secondary_lb = secondary_oat_dex_files_.lower_bound(key);
2156*795d594fSAndroid Build Coastguard Worker     if (secondary_lb != secondary_oat_dex_files_.end() && key == secondary_lb->first) {
2157*795d594fSAndroid Build Coastguard Worker       oat_dex_file = secondary_lb->second;  // May be null.
2158*795d594fSAndroid Build Coastguard Worker     } else {
2159*795d594fSAndroid Build Coastguard Worker       // We haven't seen this dex_location before, we must check the canonical location.
2160*795d594fSAndroid Build Coastguard Worker       std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2161*795d594fSAndroid Build Coastguard Worker       if (dex_canonical_location != dex_location) {
2162*795d594fSAndroid Build Coastguard Worker         std::string_view canonical_key(dex_canonical_location);
2163*795d594fSAndroid Build Coastguard Worker         auto canonical_it = oat_dex_files_.find(canonical_key);
2164*795d594fSAndroid Build Coastguard Worker         if (canonical_it != oat_dex_files_.end()) {
2165*795d594fSAndroid Build Coastguard Worker           oat_dex_file = canonical_it->second;
2166*795d594fSAndroid Build Coastguard Worker         }  // else keep null.
2167*795d594fSAndroid Build Coastguard Worker       }  // else keep null.
2168*795d594fSAndroid Build Coastguard Worker 
2169*795d594fSAndroid Build Coastguard Worker       // Copy the key to the string_cache_ and store the result in secondary map.
2170*795d594fSAndroid Build Coastguard Worker       string_cache_.emplace_back(key.data(), key.length());
2171*795d594fSAndroid Build Coastguard Worker       std::string_view key_copy(string_cache_.back());
2172*795d594fSAndroid Build Coastguard Worker       secondary_oat_dex_files_.PutBefore(secondary_lb, key_copy, oat_dex_file);
2173*795d594fSAndroid Build Coastguard Worker     }
2174*795d594fSAndroid Build Coastguard Worker   }
2175*795d594fSAndroid Build Coastguard Worker 
2176*795d594fSAndroid Build Coastguard Worker   if (oat_dex_file == nullptr) {
2177*795d594fSAndroid Build Coastguard Worker     if (error_msg != nullptr) {
2178*795d594fSAndroid Build Coastguard Worker       std::string dex_canonical_location = DexFileLoader::GetDexCanonicalLocation(dex_location);
2179*795d594fSAndroid Build Coastguard Worker       *error_msg = "Failed to find OatDexFile for DexFile " + std::string(dex_location)
2180*795d594fSAndroid Build Coastguard Worker           + " (canonical path " + dex_canonical_location + ") in OatFile " + GetLocation();
2181*795d594fSAndroid Build Coastguard Worker     }
2182*795d594fSAndroid Build Coastguard Worker     return nullptr;
2183*795d594fSAndroid Build Coastguard Worker   }
2184*795d594fSAndroid Build Coastguard Worker 
2185*795d594fSAndroid Build Coastguard Worker   return oat_dex_file;
2186*795d594fSAndroid Build Coastguard Worker }
2187*795d594fSAndroid Build Coastguard Worker 
OatDexFile(const OatFile * oat_file,const std::string & dex_file_location,const std::string & canonical_dex_file_location,DexFile::Magic dex_file_magic,uint32_t dex_file_location_checksum,DexFile::Sha1 dex_file_sha1,const std::shared_ptr<DexFileContainer> & dex_file_container,const uint8_t * dex_file_pointer,const uint8_t * lookup_table_data,const OatFile::BssMappingInfo & bss_mapping_info,const uint32_t * oat_class_offsets_pointer,const DexLayoutSections * dex_layout_sections)2188*795d594fSAndroid Build Coastguard Worker OatDexFile::OatDexFile(const OatFile* oat_file,
2189*795d594fSAndroid Build Coastguard Worker                        const std::string& dex_file_location,
2190*795d594fSAndroid Build Coastguard Worker                        const std::string& canonical_dex_file_location,
2191*795d594fSAndroid Build Coastguard Worker                        DexFile::Magic dex_file_magic,
2192*795d594fSAndroid Build Coastguard Worker                        uint32_t dex_file_location_checksum,
2193*795d594fSAndroid Build Coastguard Worker                        DexFile::Sha1 dex_file_sha1,
2194*795d594fSAndroid Build Coastguard Worker                        const std::shared_ptr<DexFileContainer>& dex_file_container,
2195*795d594fSAndroid Build Coastguard Worker                        const uint8_t* dex_file_pointer,
2196*795d594fSAndroid Build Coastguard Worker                        const uint8_t* lookup_table_data,
2197*795d594fSAndroid Build Coastguard Worker                        const OatFile::BssMappingInfo& bss_mapping_info,
2198*795d594fSAndroid Build Coastguard Worker                        const uint32_t* oat_class_offsets_pointer,
2199*795d594fSAndroid Build Coastguard Worker                        const DexLayoutSections* dex_layout_sections)
2200*795d594fSAndroid Build Coastguard Worker     : oat_file_(oat_file),
2201*795d594fSAndroid Build Coastguard Worker       dex_file_location_(dex_file_location),
2202*795d594fSAndroid Build Coastguard Worker       canonical_dex_file_location_(canonical_dex_file_location),
2203*795d594fSAndroid Build Coastguard Worker       dex_file_magic_(dex_file_magic),
2204*795d594fSAndroid Build Coastguard Worker       dex_file_location_checksum_(dex_file_location_checksum),
2205*795d594fSAndroid Build Coastguard Worker       dex_file_sha1_(dex_file_sha1),
2206*795d594fSAndroid Build Coastguard Worker       dex_file_container_(dex_file_container),
2207*795d594fSAndroid Build Coastguard Worker       dex_file_pointer_(dex_file_pointer),
2208*795d594fSAndroid Build Coastguard Worker       lookup_table_data_(lookup_table_data),
2209*795d594fSAndroid Build Coastguard Worker       bss_mapping_info_(bss_mapping_info),
2210*795d594fSAndroid Build Coastguard Worker       oat_class_offsets_pointer_(oat_class_offsets_pointer),
2211*795d594fSAndroid Build Coastguard Worker       lookup_table_(),
2212*795d594fSAndroid Build Coastguard Worker       dex_layout_sections_(dex_layout_sections) {
2213*795d594fSAndroid Build Coastguard Worker   InitializeTypeLookupTable();
2214*795d594fSAndroid Build Coastguard Worker   DCHECK(!IsBackedByVdexOnly());
2215*795d594fSAndroid Build Coastguard Worker }
2216*795d594fSAndroid Build Coastguard Worker 
InitializeTypeLookupTable()2217*795d594fSAndroid Build Coastguard Worker void OatDexFile::InitializeTypeLookupTable() {
2218*795d594fSAndroid Build Coastguard Worker   // Initialize TypeLookupTable.
2219*795d594fSAndroid Build Coastguard Worker   if (lookup_table_data_ != nullptr) {
2220*795d594fSAndroid Build Coastguard Worker     // Peek the number of classes from the DexFile.
2221*795d594fSAndroid Build Coastguard Worker     auto* dex_header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer_);
2222*795d594fSAndroid Build Coastguard Worker     const uint32_t num_class_defs = dex_header->class_defs_size_;
2223*795d594fSAndroid Build Coastguard Worker     if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) >
2224*795d594fSAndroid Build Coastguard Worker             GetOatFile()->DexEnd()) {
2225*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
2226*795d594fSAndroid Build Coastguard Worker     } else {
2227*795d594fSAndroid Build Coastguard Worker       const uint8_t* dex_data = dex_file_pointer_;
2228*795d594fSAndroid Build Coastguard Worker       // TODO: Clean this up to create the type lookup table after the dex file has been created?
2229*795d594fSAndroid Build Coastguard Worker       if (StandardDexFile::IsMagicValid(dex_header->magic_)) {
2230*795d594fSAndroid Build Coastguard Worker         dex_data -= dex_header->HeaderOffset();
2231*795d594fSAndroid Build Coastguard Worker       }
2232*795d594fSAndroid Build Coastguard Worker       if (CompactDexFile::IsMagicValid(dex_header->magic_)) {
2233*795d594fSAndroid Build Coastguard Worker         dex_data += dex_header->data_off_;
2234*795d594fSAndroid Build Coastguard Worker       }
2235*795d594fSAndroid Build Coastguard Worker       lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs);
2236*795d594fSAndroid Build Coastguard Worker     }
2237*795d594fSAndroid Build Coastguard Worker   }
2238*795d594fSAndroid Build Coastguard Worker }
2239*795d594fSAndroid Build Coastguard Worker 
OatDexFile(const OatFile * oat_file,const std::shared_ptr<DexFileContainer> & dex_file_container,const uint8_t * dex_file_pointer,DexFile::Magic dex_file_magic,uint32_t dex_file_location_checksum,DexFile::Sha1 dex_file_sha1,const std::string & dex_file_location,const std::string & canonical_dex_file_location,const uint8_t * lookup_table_data)2240*795d594fSAndroid Build Coastguard Worker OatDexFile::OatDexFile(const OatFile* oat_file,
2241*795d594fSAndroid Build Coastguard Worker                        const std::shared_ptr<DexFileContainer>& dex_file_container,
2242*795d594fSAndroid Build Coastguard Worker                        const uint8_t* dex_file_pointer,
2243*795d594fSAndroid Build Coastguard Worker                        DexFile::Magic dex_file_magic,
2244*795d594fSAndroid Build Coastguard Worker                        uint32_t dex_file_location_checksum,
2245*795d594fSAndroid Build Coastguard Worker                        DexFile::Sha1 dex_file_sha1,
2246*795d594fSAndroid Build Coastguard Worker                        const std::string& dex_file_location,
2247*795d594fSAndroid Build Coastguard Worker                        const std::string& canonical_dex_file_location,
2248*795d594fSAndroid Build Coastguard Worker                        const uint8_t* lookup_table_data)
2249*795d594fSAndroid Build Coastguard Worker     : oat_file_(oat_file),
2250*795d594fSAndroid Build Coastguard Worker       dex_file_location_(dex_file_location),
2251*795d594fSAndroid Build Coastguard Worker       canonical_dex_file_location_(canonical_dex_file_location),
2252*795d594fSAndroid Build Coastguard Worker       dex_file_magic_(dex_file_magic),
2253*795d594fSAndroid Build Coastguard Worker       dex_file_location_checksum_(dex_file_location_checksum),
2254*795d594fSAndroid Build Coastguard Worker       dex_file_sha1_(dex_file_sha1),
2255*795d594fSAndroid Build Coastguard Worker       dex_file_container_(dex_file_container),
2256*795d594fSAndroid Build Coastguard Worker       dex_file_pointer_(dex_file_pointer),
2257*795d594fSAndroid Build Coastguard Worker       lookup_table_data_(lookup_table_data) {
2258*795d594fSAndroid Build Coastguard Worker   InitializeTypeLookupTable();
2259*795d594fSAndroid Build Coastguard Worker   DCHECK(IsBackedByVdexOnly());
2260*795d594fSAndroid Build Coastguard Worker }
2261*795d594fSAndroid Build Coastguard Worker 
OatDexFile(TypeLookupTable && lookup_table)2262*795d594fSAndroid Build Coastguard Worker OatDexFile::OatDexFile(TypeLookupTable&& lookup_table) : lookup_table_(std::move(lookup_table)) {
2263*795d594fSAndroid Build Coastguard Worker   // Stripped-down OatDexFile only allowed in the compiler, the zygote, or the system server.
2264*795d594fSAndroid Build Coastguard Worker   CHECK(Runtime::Current() == nullptr ||
2265*795d594fSAndroid Build Coastguard Worker         Runtime::Current()->IsAotCompiler() ||
2266*795d594fSAndroid Build Coastguard Worker         Runtime::Current()->IsZygote() ||
2267*795d594fSAndroid Build Coastguard Worker         Runtime::Current()->IsSystemServer());
2268*795d594fSAndroid Build Coastguard Worker }
2269*795d594fSAndroid Build Coastguard Worker 
~OatDexFile()2270*795d594fSAndroid Build Coastguard Worker OatDexFile::~OatDexFile() {}
2271*795d594fSAndroid Build Coastguard Worker 
FileSize() const2272*795d594fSAndroid Build Coastguard Worker size_t OatDexFile::FileSize() const {
2273*795d594fSAndroid Build Coastguard Worker   DCHECK(dex_file_pointer_ != nullptr);
2274*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<const DexFile::Header*>(dex_file_pointer_)->file_size_;
2275*795d594fSAndroid Build Coastguard Worker }
2276*795d594fSAndroid Build Coastguard Worker 
OpenDexFile(std::string * error_msg) const2277*795d594fSAndroid Build Coastguard Worker std::unique_ptr<const DexFile> OatDexFile::OpenDexFile(std::string* error_msg) const {
2278*795d594fSAndroid Build Coastguard Worker   ScopedTrace trace(__PRETTY_FUNCTION__);
2279*795d594fSAndroid Build Coastguard Worker   static constexpr bool kVerify = false;
2280*795d594fSAndroid Build Coastguard Worker   static constexpr bool kVerifyChecksum = false;
2281*795d594fSAndroid Build Coastguard Worker   ArtDexFileLoader dex_file_loader(dex_file_container_, dex_file_location_);
2282*795d594fSAndroid Build Coastguard Worker   return dex_file_loader.OpenOne(dex_file_pointer_ - dex_file_container_->Begin(),
2283*795d594fSAndroid Build Coastguard Worker                                  dex_file_location_checksum_,
2284*795d594fSAndroid Build Coastguard Worker                                  this,
2285*795d594fSAndroid Build Coastguard Worker                                  kVerify,
2286*795d594fSAndroid Build Coastguard Worker                                  kVerifyChecksum,
2287*795d594fSAndroid Build Coastguard Worker                                  error_msg);
2288*795d594fSAndroid Build Coastguard Worker }
2289*795d594fSAndroid Build Coastguard Worker 
GetOatClassOffset(uint16_t class_def_index) const2290*795d594fSAndroid Build Coastguard Worker uint32_t OatDexFile::GetOatClassOffset(uint16_t class_def_index) const {
2291*795d594fSAndroid Build Coastguard Worker   DCHECK(oat_class_offsets_pointer_ != nullptr);
2292*795d594fSAndroid Build Coastguard Worker   return oat_class_offsets_pointer_[class_def_index];
2293*795d594fSAndroid Build Coastguard Worker }
2294*795d594fSAndroid Build Coastguard Worker 
IsBackedByVdexOnly() const2295*795d594fSAndroid Build Coastguard Worker bool OatDexFile::IsBackedByVdexOnly() const {
2296*795d594fSAndroid Build Coastguard Worker   return oat_class_offsets_pointer_ == nullptr;
2297*795d594fSAndroid Build Coastguard Worker }
2298*795d594fSAndroid Build Coastguard Worker 
GetOatClass(uint16_t class_def_index) const2299*795d594fSAndroid Build Coastguard Worker OatFile::OatClass OatDexFile::GetOatClass(uint16_t class_def_index) const {
2300*795d594fSAndroid Build Coastguard Worker   if (IsBackedByVdexOnly()) {
2301*795d594fSAndroid Build Coastguard Worker     // If there is only a vdex file, return that the class is not ready. The
2302*795d594fSAndroid Build Coastguard Worker     // caller will have to call `VdexFile::ComputeClassStatus` to compute the
2303*795d594fSAndroid Build Coastguard Worker     // actual class status, because we need to do the assignability type checks.
2304*795d594fSAndroid Build Coastguard Worker     return OatFile::OatClass(oat_file_,
2305*795d594fSAndroid Build Coastguard Worker                              ClassStatus::kNotReady,
2306*795d594fSAndroid Build Coastguard Worker                              /* type= */ OatClassType::kNoneCompiled,
2307*795d594fSAndroid Build Coastguard Worker                              /* num_methods= */ 0u,
2308*795d594fSAndroid Build Coastguard Worker                              /* bitmap_pointer= */ nullptr,
2309*795d594fSAndroid Build Coastguard Worker                              /* methods_pointer= */ nullptr);
2310*795d594fSAndroid Build Coastguard Worker   }
2311*795d594fSAndroid Build Coastguard Worker 
2312*795d594fSAndroid Build Coastguard Worker   uint32_t oat_class_offset = GetOatClassOffset(class_def_index);
2313*795d594fSAndroid Build Coastguard Worker   CHECK_GE(oat_class_offset, sizeof(OatHeader)) << oat_file_->GetLocation();
2314*795d594fSAndroid Build Coastguard Worker   CHECK_LT(oat_class_offset, oat_file_->Size()) << oat_file_->GetLocation();
2315*795d594fSAndroid Build Coastguard Worker   CHECK_LE(/* status */ sizeof(uint16_t) + /* type */ sizeof(uint16_t),
2316*795d594fSAndroid Build Coastguard Worker            oat_file_->Size() - oat_class_offset) << oat_file_->GetLocation();
2317*795d594fSAndroid Build Coastguard Worker   const uint8_t* current_pointer = oat_file_->Begin() + oat_class_offset;
2318*795d594fSAndroid Build Coastguard Worker 
2319*795d594fSAndroid Build Coastguard Worker   uint16_t status_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2320*795d594fSAndroid Build Coastguard Worker   current_pointer += sizeof(uint16_t);
2321*795d594fSAndroid Build Coastguard Worker   uint16_t type_value = *reinterpret_cast<const uint16_t*>(current_pointer);
2322*795d594fSAndroid Build Coastguard Worker   current_pointer += sizeof(uint16_t);
2323*795d594fSAndroid Build Coastguard Worker   CHECK_LE(status_value, enum_cast<uint8_t>(ClassStatus::kLast))
2324*795d594fSAndroid Build Coastguard Worker       << static_cast<uint32_t>(status_value) << " at " << oat_file_->GetLocation();
2325*795d594fSAndroid Build Coastguard Worker   CHECK_LE(type_value, enum_cast<uint8_t>(OatClassType::kLast)) << oat_file_->GetLocation();
2326*795d594fSAndroid Build Coastguard Worker   ClassStatus status = enum_cast<ClassStatus>(status_value);
2327*795d594fSAndroid Build Coastguard Worker   OatClassType type = enum_cast<OatClassType>(type_value);
2328*795d594fSAndroid Build Coastguard Worker 
2329*795d594fSAndroid Build Coastguard Worker   uint32_t num_methods = 0;
2330*795d594fSAndroid Build Coastguard Worker   const uint32_t* bitmap_pointer = nullptr;
2331*795d594fSAndroid Build Coastguard Worker   const OatMethodOffsets* methods_pointer = nullptr;
2332*795d594fSAndroid Build Coastguard Worker   if (type != OatClassType::kNoneCompiled) {
2333*795d594fSAndroid Build Coastguard Worker     CHECK_LE(sizeof(uint32_t), static_cast<size_t>(oat_file_->End() - current_pointer))
2334*795d594fSAndroid Build Coastguard Worker         << oat_file_->GetLocation();
2335*795d594fSAndroid Build Coastguard Worker     num_methods = *reinterpret_cast<const uint32_t*>(current_pointer);
2336*795d594fSAndroid Build Coastguard Worker     current_pointer += sizeof(uint32_t);
2337*795d594fSAndroid Build Coastguard Worker     CHECK_NE(num_methods, 0u) << oat_file_->GetLocation();
2338*795d594fSAndroid Build Coastguard Worker     uint32_t num_method_offsets;
2339*795d594fSAndroid Build Coastguard Worker     if (type == OatClassType::kSomeCompiled) {
2340*795d594fSAndroid Build Coastguard Worker       uint32_t bitmap_size = BitVector::BitsToWords(num_methods) * BitVector::kWordBytes;
2341*795d594fSAndroid Build Coastguard Worker       CHECK_LE(bitmap_size, static_cast<size_t>(oat_file_->End() - current_pointer))
2342*795d594fSAndroid Build Coastguard Worker           << oat_file_->GetLocation();
2343*795d594fSAndroid Build Coastguard Worker       bitmap_pointer = reinterpret_cast<const uint32_t*>(current_pointer);
2344*795d594fSAndroid Build Coastguard Worker       current_pointer += bitmap_size;
2345*795d594fSAndroid Build Coastguard Worker       // Note: The bits in range [num_methods, bitmap_size * kBitsPerByte)
2346*795d594fSAndroid Build Coastguard Worker       // should be zero but we're not verifying that.
2347*795d594fSAndroid Build Coastguard Worker       num_method_offsets = BitVector::NumSetBits(bitmap_pointer, num_methods);
2348*795d594fSAndroid Build Coastguard Worker     } else {
2349*795d594fSAndroid Build Coastguard Worker       num_method_offsets = num_methods;
2350*795d594fSAndroid Build Coastguard Worker     }
2351*795d594fSAndroid Build Coastguard Worker     CHECK_LE(num_method_offsets,
2352*795d594fSAndroid Build Coastguard Worker              static_cast<size_t>(oat_file_->End() - current_pointer) / sizeof(OatMethodOffsets))
2353*795d594fSAndroid Build Coastguard Worker         << oat_file_->GetLocation();
2354*795d594fSAndroid Build Coastguard Worker     methods_pointer = reinterpret_cast<const OatMethodOffsets*>(current_pointer);
2355*795d594fSAndroid Build Coastguard Worker   }
2356*795d594fSAndroid Build Coastguard Worker 
2357*795d594fSAndroid Build Coastguard Worker   return OatFile::OatClass(oat_file_, status, type, num_methods, bitmap_pointer, methods_pointer);
2358*795d594fSAndroid Build Coastguard Worker }
2359*795d594fSAndroid Build Coastguard Worker 
FindClassDef(const DexFile & dex_file,std::string_view descriptor,size_t hash)2360*795d594fSAndroid Build Coastguard Worker const dex::ClassDef* OatDexFile::FindClassDef(const DexFile& dex_file,
2361*795d594fSAndroid Build Coastguard Worker                                               std::string_view descriptor,
2362*795d594fSAndroid Build Coastguard Worker                                               size_t hash) {
2363*795d594fSAndroid Build Coastguard Worker   const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2364*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash);
2365*795d594fSAndroid Build Coastguard Worker   bool used_lookup_table = false;
2366*795d594fSAndroid Build Coastguard Worker   const dex::ClassDef* lookup_table_classdef = nullptr;
2367*795d594fSAndroid Build Coastguard Worker   if (LIKELY((oat_dex_file != nullptr) && oat_dex_file->GetTypeLookupTable().Valid())) {
2368*795d594fSAndroid Build Coastguard Worker     used_lookup_table = true;
2369*795d594fSAndroid Build Coastguard Worker     const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable().Lookup(descriptor, hash);
2370*795d594fSAndroid Build Coastguard Worker     if (class_def_idx != dex::kDexNoIndex) {
2371*795d594fSAndroid Build Coastguard Worker       CHECK_LT(class_def_idx, dex_file.NumClassDefs()) << oat_dex_file->GetOatFile()->GetLocation();
2372*795d594fSAndroid Build Coastguard Worker       lookup_table_classdef = &dex_file.GetClassDef(class_def_idx);
2373*795d594fSAndroid Build Coastguard Worker     }
2374*795d594fSAndroid Build Coastguard Worker     if (!kIsDebugBuild) {
2375*795d594fSAndroid Build Coastguard Worker       return lookup_table_classdef;
2376*795d594fSAndroid Build Coastguard Worker     }
2377*795d594fSAndroid Build Coastguard Worker   }
2378*795d594fSAndroid Build Coastguard Worker   // Fast path for rare no class defs case.
2379*795d594fSAndroid Build Coastguard Worker   const uint32_t num_class_defs = dex_file.NumClassDefs();
2380*795d594fSAndroid Build Coastguard Worker   if (num_class_defs == 0) {
2381*795d594fSAndroid Build Coastguard Worker     DCHECK(!used_lookup_table);
2382*795d594fSAndroid Build Coastguard Worker     return nullptr;
2383*795d594fSAndroid Build Coastguard Worker   }
2384*795d594fSAndroid Build Coastguard Worker   const dex::TypeId* type_id = dex_file.FindTypeId(descriptor);
2385*795d594fSAndroid Build Coastguard Worker   if (type_id != nullptr) {
2386*795d594fSAndroid Build Coastguard Worker     dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id);
2387*795d594fSAndroid Build Coastguard Worker     const dex::ClassDef* found_class_def = dex_file.FindClassDef(type_idx);
2388*795d594fSAndroid Build Coastguard Worker     if (kIsDebugBuild && used_lookup_table) {
2389*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(found_class_def, lookup_table_classdef);
2390*795d594fSAndroid Build Coastguard Worker     }
2391*795d594fSAndroid Build Coastguard Worker     return found_class_def;
2392*795d594fSAndroid Build Coastguard Worker   }
2393*795d594fSAndroid Build Coastguard Worker   return nullptr;
2394*795d594fSAndroid Build Coastguard Worker }
2395*795d594fSAndroid Build Coastguard Worker 
OatClass(const OatFile * oat_file,ClassStatus status,OatClassType type,uint32_t num_methods,const uint32_t * bitmap_pointer,const OatMethodOffsets * methods_pointer)2396*795d594fSAndroid Build Coastguard Worker OatFile::OatClass::OatClass(const OatFile* oat_file,
2397*795d594fSAndroid Build Coastguard Worker                             ClassStatus status,
2398*795d594fSAndroid Build Coastguard Worker                             OatClassType type,
2399*795d594fSAndroid Build Coastguard Worker                             uint32_t num_methods,
2400*795d594fSAndroid Build Coastguard Worker                             const uint32_t* bitmap_pointer,
2401*795d594fSAndroid Build Coastguard Worker                             const OatMethodOffsets* methods_pointer)
2402*795d594fSAndroid Build Coastguard Worker     : oat_file_(oat_file),
2403*795d594fSAndroid Build Coastguard Worker       status_(status),
2404*795d594fSAndroid Build Coastguard Worker       type_(type),
2405*795d594fSAndroid Build Coastguard Worker       num_methods_(num_methods),
2406*795d594fSAndroid Build Coastguard Worker       bitmap_(bitmap_pointer),
2407*795d594fSAndroid Build Coastguard Worker       methods_pointer_(methods_pointer) {
2408*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(num_methods != 0u, type != OatClassType::kNoneCompiled);
2409*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(bitmap_pointer != nullptr, type == OatClassType::kSomeCompiled);
2410*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(methods_pointer != nullptr, type != OatClassType::kNoneCompiled);
2411*795d594fSAndroid Build Coastguard Worker }
2412*795d594fSAndroid Build Coastguard Worker 
GetOatMethodOffsetsOffset(uint32_t method_index) const2413*795d594fSAndroid Build Coastguard Worker uint32_t OatFile::OatClass::GetOatMethodOffsetsOffset(uint32_t method_index) const {
2414*795d594fSAndroid Build Coastguard Worker   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2415*795d594fSAndroid Build Coastguard Worker   if (oat_method_offsets == nullptr) {
2416*795d594fSAndroid Build Coastguard Worker     return 0u;
2417*795d594fSAndroid Build Coastguard Worker   }
2418*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<const uint8_t*>(oat_method_offsets) - oat_file_->Begin();
2419*795d594fSAndroid Build Coastguard Worker }
2420*795d594fSAndroid Build Coastguard Worker 
GetOatMethodOffsets(uint32_t method_index) const2421*795d594fSAndroid Build Coastguard Worker const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_index) const {
2422*795d594fSAndroid Build Coastguard Worker   // NOTE: We don't keep the number of methods for `kNoneCompiled` and cannot do
2423*795d594fSAndroid Build Coastguard Worker   // a bounds check for `method_index` in that case.
2424*795d594fSAndroid Build Coastguard Worker   if (methods_pointer_ == nullptr) {
2425*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(OatClassType::kNoneCompiled, type_);
2426*795d594fSAndroid Build Coastguard Worker     return nullptr;
2427*795d594fSAndroid Build Coastguard Worker   }
2428*795d594fSAndroid Build Coastguard Worker   CHECK_LT(method_index, num_methods_) << oat_file_->GetLocation();
2429*795d594fSAndroid Build Coastguard Worker   size_t methods_pointer_index;
2430*795d594fSAndroid Build Coastguard Worker   if (bitmap_ == nullptr) {
2431*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(OatClassType::kAllCompiled, type_);
2432*795d594fSAndroid Build Coastguard Worker     methods_pointer_index = method_index;
2433*795d594fSAndroid Build Coastguard Worker   } else {
2434*795d594fSAndroid Build Coastguard Worker     CHECK_EQ(OatClassType::kSomeCompiled, type_);
2435*795d594fSAndroid Build Coastguard Worker     if (!BitVector::IsBitSet(bitmap_, method_index)) {
2436*795d594fSAndroid Build Coastguard Worker       return nullptr;
2437*795d594fSAndroid Build Coastguard Worker     }
2438*795d594fSAndroid Build Coastguard Worker     size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
2439*795d594fSAndroid Build Coastguard Worker     methods_pointer_index = num_set_bits;
2440*795d594fSAndroid Build Coastguard Worker   }
2441*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
2442*795d594fSAndroid Build Coastguard Worker     size_t size_until_end = dchecked_integral_cast<size_t>(
2443*795d594fSAndroid Build Coastguard Worker         oat_file_->End() - reinterpret_cast<const uint8_t*>(methods_pointer_));
2444*795d594fSAndroid Build Coastguard Worker     CHECK_LE(methods_pointer_index, size_until_end / sizeof(OatMethodOffsets))
2445*795d594fSAndroid Build Coastguard Worker         << oat_file_->GetLocation();
2446*795d594fSAndroid Build Coastguard Worker   }
2447*795d594fSAndroid Build Coastguard Worker   const OatMethodOffsets& oat_method_offsets = methods_pointer_[methods_pointer_index];
2448*795d594fSAndroid Build Coastguard Worker   return &oat_method_offsets;
2449*795d594fSAndroid Build Coastguard Worker }
2450*795d594fSAndroid Build Coastguard Worker 
GetOatMethod(uint32_t method_index) const2451*795d594fSAndroid Build Coastguard Worker const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
2452*795d594fSAndroid Build Coastguard Worker   const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
2453*795d594fSAndroid Build Coastguard Worker   if (oat_method_offsets == nullptr) {
2454*795d594fSAndroid Build Coastguard Worker     return OatMethod(nullptr, 0);
2455*795d594fSAndroid Build Coastguard Worker   }
2456*795d594fSAndroid Build Coastguard Worker   if (oat_file_->IsExecutable() ||
2457*795d594fSAndroid Build Coastguard Worker       Runtime::Current() == nullptr ||        // This case applies for oatdump.
2458*795d594fSAndroid Build Coastguard Worker       Runtime::Current()->IsAotCompiler()) {
2459*795d594fSAndroid Build Coastguard Worker     return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
2460*795d594fSAndroid Build Coastguard Worker   }
2461*795d594fSAndroid Build Coastguard Worker   // We aren't allowed to use the compiled code. We just force it down the interpreted / jit
2462*795d594fSAndroid Build Coastguard Worker   // version.
2463*795d594fSAndroid Build Coastguard Worker   return OatMethod(oat_file_->Begin(), 0);
2464*795d594fSAndroid Build Coastguard Worker }
2465*795d594fSAndroid Build Coastguard Worker 
IsDebuggable() const2466*795d594fSAndroid Build Coastguard Worker bool OatFile::IsDebuggable() const {
2467*795d594fSAndroid Build Coastguard Worker   return GetOatHeader().IsDebuggable();
2468*795d594fSAndroid Build Coastguard Worker }
2469*795d594fSAndroid Build Coastguard Worker 
GetCompilerFilter() const2470*795d594fSAndroid Build Coastguard Worker CompilerFilter::Filter OatFile::GetCompilerFilter() const {
2471*795d594fSAndroid Build Coastguard Worker   return GetOatHeader().GetCompilerFilter();
2472*795d594fSAndroid Build Coastguard Worker }
2473*795d594fSAndroid Build Coastguard Worker 
GetClassLoaderContext() const2474*795d594fSAndroid Build Coastguard Worker std::string OatFile::GetClassLoaderContext() const {
2475*795d594fSAndroid Build Coastguard Worker   const char* value = GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey);
2476*795d594fSAndroid Build Coastguard Worker   return (value == nullptr) ? "" : value;
2477*795d594fSAndroid Build Coastguard Worker }
2478*795d594fSAndroid Build Coastguard Worker 
GetCompilationReason() const2479*795d594fSAndroid Build Coastguard Worker const char* OatFile::GetCompilationReason() const {
2480*795d594fSAndroid Build Coastguard Worker   return GetOatHeader().GetStoreValueByKey(OatHeader::kCompilationReasonKey);
2481*795d594fSAndroid Build Coastguard Worker }
2482*795d594fSAndroid Build Coastguard Worker 
FindOatClass(const DexFile & dex_file,uint16_t class_def_idx,bool * found)2483*795d594fSAndroid Build Coastguard Worker OatFile::OatClass OatFile::FindOatClass(const DexFile& dex_file,
2484*795d594fSAndroid Build Coastguard Worker                                         uint16_t class_def_idx,
2485*795d594fSAndroid Build Coastguard Worker                                         bool* found) {
2486*795d594fSAndroid Build Coastguard Worker   CHECK_LT(class_def_idx, dex_file.NumClassDefs());
2487*795d594fSAndroid Build Coastguard Worker   const OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
2488*795d594fSAndroid Build Coastguard Worker   if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
2489*795d594fSAndroid Build Coastguard Worker     *found = false;
2490*795d594fSAndroid Build Coastguard Worker     return OatFile::OatClass::Invalid();
2491*795d594fSAndroid Build Coastguard Worker   }
2492*795d594fSAndroid Build Coastguard Worker   *found = true;
2493*795d594fSAndroid Build Coastguard Worker   return oat_dex_file->GetOatClass(class_def_idx);
2494*795d594fSAndroid Build Coastguard Worker }
2495*795d594fSAndroid Build Coastguard Worker 
RequiresImage() const2496*795d594fSAndroid Build Coastguard Worker bool OatFile::RequiresImage() const { return GetOatHeader().RequiresImage(); }
2497*795d594fSAndroid Build Coastguard Worker 
DCheckIndexToBssMapping(const OatFile * oat_file,uint32_t number_of_indexes,size_t slot_size,const IndexBssMapping * index_bss_mapping)2498*795d594fSAndroid Build Coastguard Worker static void DCheckIndexToBssMapping(const OatFile* oat_file,
2499*795d594fSAndroid Build Coastguard Worker                                     uint32_t number_of_indexes,
2500*795d594fSAndroid Build Coastguard Worker                                     size_t slot_size,
2501*795d594fSAndroid Build Coastguard Worker                                     const IndexBssMapping* index_bss_mapping) {
2502*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild && index_bss_mapping != nullptr) {
2503*795d594fSAndroid Build Coastguard Worker     size_t index_bits = IndexBssMappingEntry::IndexBits(number_of_indexes);
2504*795d594fSAndroid Build Coastguard Worker     const IndexBssMappingEntry* prev_entry = nullptr;
2505*795d594fSAndroid Build Coastguard Worker     for (const IndexBssMappingEntry& entry : *index_bss_mapping) {
2506*795d594fSAndroid Build Coastguard Worker       CHECK_ALIGNED_PARAM(entry.bss_offset, slot_size);
2507*795d594fSAndroid Build Coastguard Worker       CHECK_LT(entry.bss_offset, oat_file->BssSize());
2508*795d594fSAndroid Build Coastguard Worker       uint32_t mask = entry.GetMask(index_bits);
2509*795d594fSAndroid Build Coastguard Worker       CHECK_LE(POPCOUNT(mask) * slot_size, entry.bss_offset);
2510*795d594fSAndroid Build Coastguard Worker       size_t index_mask_span = (mask != 0u) ? 32u - index_bits - CTZ(mask) : 0u;
2511*795d594fSAndroid Build Coastguard Worker       CHECK_LE(index_mask_span, entry.GetIndex(index_bits));
2512*795d594fSAndroid Build Coastguard Worker       if (prev_entry != nullptr) {
2513*795d594fSAndroid Build Coastguard Worker         CHECK_LT(prev_entry->GetIndex(index_bits), entry.GetIndex(index_bits) - index_mask_span);
2514*795d594fSAndroid Build Coastguard Worker       }
2515*795d594fSAndroid Build Coastguard Worker       prev_entry = &entry;
2516*795d594fSAndroid Build Coastguard Worker     }
2517*795d594fSAndroid Build Coastguard Worker     CHECK(prev_entry != nullptr);
2518*795d594fSAndroid Build Coastguard Worker     CHECK_LT(prev_entry->GetIndex(index_bits), number_of_indexes);
2519*795d594fSAndroid Build Coastguard Worker   }
2520*795d594fSAndroid Build Coastguard Worker }
2521*795d594fSAndroid Build Coastguard Worker 
InitializeRelocations() const2522*795d594fSAndroid Build Coastguard Worker void OatFile::InitializeRelocations() const {
2523*795d594fSAndroid Build Coastguard Worker   DCHECK(IsExecutable());
2524*795d594fSAndroid Build Coastguard Worker 
2525*795d594fSAndroid Build Coastguard Worker   // Initialize the .data.img.rel.ro section.
2526*795d594fSAndroid Build Coastguard Worker   if (DataImgRelRoEnd() != DataImgRelRoBegin()) {
2527*795d594fSAndroid Build Coastguard Worker     uint8_t* reloc_begin = const_cast<uint8_t*>(DataImgRelRoBegin());
2528*795d594fSAndroid Build Coastguard Worker     CheckedCall(mprotect,
2529*795d594fSAndroid Build Coastguard Worker                 "un-protect boot image relocations",
2530*795d594fSAndroid Build Coastguard Worker                 reloc_begin,
2531*795d594fSAndroid Build Coastguard Worker                 DataImgRelRoSize(),
2532*795d594fSAndroid Build Coastguard Worker                 PROT_READ | PROT_WRITE);
2533*795d594fSAndroid Build Coastguard Worker     uint32_t boot_image_begin = Runtime::Current()->GetHeap()->GetBootImagesStartAddress();
2534*795d594fSAndroid Build Coastguard Worker     for (const uint32_t& relocation : GetBootImageRelocations()) {
2535*795d594fSAndroid Build Coastguard Worker       const_cast<uint32_t&>(relocation) += boot_image_begin;
2536*795d594fSAndroid Build Coastguard Worker     }
2537*795d594fSAndroid Build Coastguard Worker     if (!GetAppImageRelocations().empty()) {
2538*795d594fSAndroid Build Coastguard Worker       CHECK(app_image_begin_ != nullptr);
2539*795d594fSAndroid Build Coastguard Worker       uint32_t app_image_begin = reinterpret_cast32<uint32_t>(app_image_begin_);
2540*795d594fSAndroid Build Coastguard Worker       for (const uint32_t& relocation : GetAppImageRelocations()) {
2541*795d594fSAndroid Build Coastguard Worker         const_cast<uint32_t&>(relocation) += app_image_begin;
2542*795d594fSAndroid Build Coastguard Worker       }
2543*795d594fSAndroid Build Coastguard Worker     }
2544*795d594fSAndroid Build Coastguard Worker     CheckedCall(mprotect,
2545*795d594fSAndroid Build Coastguard Worker                 "protect boot image relocations",
2546*795d594fSAndroid Build Coastguard Worker                 reloc_begin,
2547*795d594fSAndroid Build Coastguard Worker                 DataImgRelRoSize(),
2548*795d594fSAndroid Build Coastguard Worker                 PROT_READ);
2549*795d594fSAndroid Build Coastguard Worker   }
2550*795d594fSAndroid Build Coastguard Worker 
2551*795d594fSAndroid Build Coastguard Worker   // Before initializing .bss, check the .bss mappings in debug mode.
2552*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
2553*795d594fSAndroid Build Coastguard Worker     PointerSize pointer_size = GetInstructionSetPointerSize(GetOatHeader().GetInstructionSet());
2554*795d594fSAndroid Build Coastguard Worker     for (const OatDexFile* odf : GetOatDexFiles()) {
2555*795d594fSAndroid Build Coastguard Worker       const DexFile::Header* header =
2556*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<const DexFile::Header*>(odf->GetDexFilePointer());
2557*795d594fSAndroid Build Coastguard Worker       DCheckIndexToBssMapping(this,
2558*795d594fSAndroid Build Coastguard Worker                               header->method_ids_size_,
2559*795d594fSAndroid Build Coastguard Worker                               static_cast<size_t>(pointer_size),
2560*795d594fSAndroid Build Coastguard Worker                               odf->GetMethodBssMapping());
2561*795d594fSAndroid Build Coastguard Worker       DCheckIndexToBssMapping(this,
2562*795d594fSAndroid Build Coastguard Worker                               header->type_ids_size_,
2563*795d594fSAndroid Build Coastguard Worker                               sizeof(GcRoot<mirror::Class>),
2564*795d594fSAndroid Build Coastguard Worker                               odf->GetTypeBssMapping());
2565*795d594fSAndroid Build Coastguard Worker       DCheckIndexToBssMapping(this,
2566*795d594fSAndroid Build Coastguard Worker                               header->string_ids_size_,
2567*795d594fSAndroid Build Coastguard Worker                               sizeof(GcRoot<mirror::String>),
2568*795d594fSAndroid Build Coastguard Worker                               odf->GetStringBssMapping());
2569*795d594fSAndroid Build Coastguard Worker     }
2570*795d594fSAndroid Build Coastguard Worker   }
2571*795d594fSAndroid Build Coastguard Worker 
2572*795d594fSAndroid Build Coastguard Worker   // Initialize the .bss section.
2573*795d594fSAndroid Build Coastguard Worker   // TODO: Pre-initialize from boot/app image?
2574*795d594fSAndroid Build Coastguard Worker   ArtMethod* resolution_method = Runtime::Current()->GetResolutionMethod();
2575*795d594fSAndroid Build Coastguard Worker   for (ArtMethod*& entry : GetBssMethods()) {
2576*795d594fSAndroid Build Coastguard Worker     entry = resolution_method;
2577*795d594fSAndroid Build Coastguard Worker   }
2578*795d594fSAndroid Build Coastguard Worker }
2579*795d594fSAndroid Build Coastguard Worker 
AssertAotCompiler()2580*795d594fSAndroid Build Coastguard Worker void OatDexFile::AssertAotCompiler() {
2581*795d594fSAndroid Build Coastguard Worker   CHECK(Runtime::Current()->IsAotCompiler());
2582*795d594fSAndroid Build Coastguard Worker }
2583*795d594fSAndroid Build Coastguard Worker 
GetDexVersion() const2584*795d594fSAndroid Build Coastguard Worker uint32_t OatDexFile::GetDexVersion() const {
2585*795d594fSAndroid Build Coastguard Worker   return atoi(reinterpret_cast<const char*>(&dex_file_magic_[4]));
2586*795d594fSAndroid Build Coastguard Worker }
2587*795d594fSAndroid Build Coastguard Worker 
IsBackedByVdexOnly() const2588*795d594fSAndroid Build Coastguard Worker bool OatFile::IsBackedByVdexOnly() const {
2589*795d594fSAndroid Build Coastguard Worker   return oat_dex_files_storage_.size() >= 1 && oat_dex_files_storage_[0]->IsBackedByVdexOnly();
2590*795d594fSAndroid Build Coastguard Worker }
2591*795d594fSAndroid Build Coastguard Worker 
2592*795d594fSAndroid Build Coastguard Worker }  // namespace art
2593