xref: /aosp_15_r20/art/runtime/vdex_file.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 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 "vdex_file.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <sys/mman.h>  // For the PROT_* and MAP_* constants.
20*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>  // for mkdir()
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <memory>
23*795d594fSAndroid Build Coastguard Worker #include <unordered_set>
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
26*795d594fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
27*795d594fSAndroid Build Coastguard Worker #include <log/log.h>
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/leb128.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/systrace.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/zip_archive.h"
35*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
36*795d594fSAndroid Build Coastguard Worker #include "class_loader_context.h"
37*795d594fSAndroid Build Coastguard Worker #include "dex/art_dex_file_loader.h"
38*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
40*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
41*795d594fSAndroid Build Coastguard Worker #include "gc/space/image_space.h"
42*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
44*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
45*795d594fSAndroid Build Coastguard Worker #include "verifier/verifier_deps.h"
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
48*795d594fSAndroid Build Coastguard Worker 
49*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
50*795d594fSAndroid Build Coastguard Worker 
IsMagicValid() const51*795d594fSAndroid Build Coastguard Worker bool VdexFile::VdexFileHeader::IsMagicValid() const {
52*795d594fSAndroid Build Coastguard Worker   return (memcmp(magic_, kVdexMagic, sizeof(kVdexMagic)) == 0);
53*795d594fSAndroid Build Coastguard Worker }
54*795d594fSAndroid Build Coastguard Worker 
IsVdexVersionValid() const55*795d594fSAndroid Build Coastguard Worker bool VdexFile::VdexFileHeader::IsVdexVersionValid() const {
56*795d594fSAndroid Build Coastguard Worker   return (memcmp(vdex_version_, kVdexVersion, sizeof(kVdexVersion)) == 0);
57*795d594fSAndroid Build Coastguard Worker }
58*795d594fSAndroid Build Coastguard Worker 
VdexFileHeader(bool has_dex_section)59*795d594fSAndroid Build Coastguard Worker VdexFile::VdexFileHeader::VdexFileHeader([[maybe_unused]] bool has_dex_section)
60*795d594fSAndroid Build Coastguard Worker     : number_of_sections_(static_cast<uint32_t>(VdexSection::kNumberOfSections)) {
61*795d594fSAndroid Build Coastguard Worker   memcpy(magic_, kVdexMagic, sizeof(kVdexMagic));
62*795d594fSAndroid Build Coastguard Worker   memcpy(vdex_version_, kVdexVersion, sizeof(kVdexVersion));
63*795d594fSAndroid Build Coastguard Worker   DCHECK(IsMagicValid());
64*795d594fSAndroid Build Coastguard Worker   DCHECK(IsVdexVersionValid());
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker 
OpenAtAddress(uint8_t * mmap_addr,size_t mmap_size,bool mmap_reuse,const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)67*795d594fSAndroid Build Coastguard Worker std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr,
68*795d594fSAndroid Build Coastguard Worker                                                   size_t mmap_size,
69*795d594fSAndroid Build Coastguard Worker                                                   bool mmap_reuse,
70*795d594fSAndroid Build Coastguard Worker                                                   const std::string& vdex_filename,
71*795d594fSAndroid Build Coastguard Worker                                                   bool writable,
72*795d594fSAndroid Build Coastguard Worker                                                   bool low_4gb,
73*795d594fSAndroid Build Coastguard Worker                                                   std::string* error_msg) {
74*795d594fSAndroid Build Coastguard Worker   ScopedTrace trace(("VdexFile::OpenAtAddress " + vdex_filename).c_str());
75*795d594fSAndroid Build Coastguard Worker   if (!OS::FileExists(vdex_filename.c_str())) {
76*795d594fSAndroid Build Coastguard Worker     *error_msg = "File " + vdex_filename + " does not exist.";
77*795d594fSAndroid Build Coastguard Worker     return nullptr;
78*795d594fSAndroid Build Coastguard Worker   }
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> vdex_file;
81*795d594fSAndroid Build Coastguard Worker   if (writable) {
82*795d594fSAndroid Build Coastguard Worker     vdex_file.reset(OS::OpenFileReadWrite(vdex_filename.c_str()));
83*795d594fSAndroid Build Coastguard Worker   } else {
84*795d594fSAndroid Build Coastguard Worker     vdex_file.reset(OS::OpenFileForReading(vdex_filename.c_str()));
85*795d594fSAndroid Build Coastguard Worker   }
86*795d594fSAndroid Build Coastguard Worker   if (vdex_file == nullptr) {
87*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not open file " + vdex_filename +
88*795d594fSAndroid Build Coastguard Worker                  (writable ? " for read/write" : "for reading");
89*795d594fSAndroid Build Coastguard Worker     return nullptr;
90*795d594fSAndroid Build Coastguard Worker   }
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   int64_t vdex_length = vdex_file->GetLength();
93*795d594fSAndroid Build Coastguard Worker   if (vdex_length == -1) {
94*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not read the length of file " + vdex_filename;
95*795d594fSAndroid Build Coastguard Worker     return nullptr;
96*795d594fSAndroid Build Coastguard Worker   }
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   return OpenAtAddress(mmap_addr,
99*795d594fSAndroid Build Coastguard Worker                        mmap_size,
100*795d594fSAndroid Build Coastguard Worker                        mmap_reuse,
101*795d594fSAndroid Build Coastguard Worker                        vdex_file->Fd(),
102*795d594fSAndroid Build Coastguard Worker                        vdex_length,
103*795d594fSAndroid Build Coastguard Worker                        vdex_filename,
104*795d594fSAndroid Build Coastguard Worker                        writable,
105*795d594fSAndroid Build Coastguard Worker                        low_4gb,
106*795d594fSAndroid Build Coastguard Worker                        error_msg);
107*795d594fSAndroid Build Coastguard Worker }
108*795d594fSAndroid Build Coastguard Worker 
OpenAtAddress(uint8_t * mmap_addr,size_t mmap_size,bool mmap_reuse,int file_fd,size_t vdex_length,const std::string & vdex_filename,bool writable,bool low_4gb,std::string * error_msg)109*795d594fSAndroid Build Coastguard Worker std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr,
110*795d594fSAndroid Build Coastguard Worker                                                   size_t mmap_size,
111*795d594fSAndroid Build Coastguard Worker                                                   bool mmap_reuse,
112*795d594fSAndroid Build Coastguard Worker                                                   int file_fd,
113*795d594fSAndroid Build Coastguard Worker                                                   size_t vdex_length,
114*795d594fSAndroid Build Coastguard Worker                                                   const std::string& vdex_filename,
115*795d594fSAndroid Build Coastguard Worker                                                   bool writable,
116*795d594fSAndroid Build Coastguard Worker                                                   bool low_4gb,
117*795d594fSAndroid Build Coastguard Worker                                                   std::string* error_msg) {
118*795d594fSAndroid Build Coastguard Worker   if (mmap_addr != nullptr && mmap_size < vdex_length) {
119*795d594fSAndroid Build Coastguard Worker     *error_msg = StringPrintf("Insufficient pre-allocated space to mmap vdex: %zu and %zu",
120*795d594fSAndroid Build Coastguard Worker                               mmap_size,
121*795d594fSAndroid Build Coastguard Worker                               vdex_length);
122*795d594fSAndroid Build Coastguard Worker     return nullptr;
123*795d594fSAndroid Build Coastguard Worker   }
124*795d594fSAndroid Build Coastguard Worker   CHECK_IMPLIES(mmap_reuse, mmap_addr != nullptr);
125*795d594fSAndroid Build Coastguard Worker   // Start as PROT_WRITE so we can mprotect back to it if we want to.
126*795d594fSAndroid Build Coastguard Worker   MemMap mmap = MemMap::MapFileAtAddress(
127*795d594fSAndroid Build Coastguard Worker       mmap_addr,
128*795d594fSAndroid Build Coastguard Worker       vdex_length,
129*795d594fSAndroid Build Coastguard Worker       PROT_READ | PROT_WRITE,
130*795d594fSAndroid Build Coastguard Worker       writable ? MAP_SHARED : MAP_PRIVATE,
131*795d594fSAndroid Build Coastguard Worker       file_fd,
132*795d594fSAndroid Build Coastguard Worker       /* start= */ 0u,
133*795d594fSAndroid Build Coastguard Worker       low_4gb,
134*795d594fSAndroid Build Coastguard Worker       vdex_filename.c_str(),
135*795d594fSAndroid Build Coastguard Worker       mmap_reuse,
136*795d594fSAndroid Build Coastguard Worker       /* reservation= */ nullptr,
137*795d594fSAndroid Build Coastguard Worker       error_msg);
138*795d594fSAndroid Build Coastguard Worker   if (!mmap.IsValid()) {
139*795d594fSAndroid Build Coastguard Worker     *error_msg = "Failed to mmap file " + vdex_filename + " : " + *error_msg;
140*795d594fSAndroid Build Coastguard Worker     return nullptr;
141*795d594fSAndroid Build Coastguard Worker   }
142*795d594fSAndroid Build Coastguard Worker 
143*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<VdexFile> vdex(new VdexFile(std::move(mmap)));
144*795d594fSAndroid Build Coastguard Worker   if (!vdex->IsValid()) {
145*795d594fSAndroid Build Coastguard Worker     *error_msg = "Vdex file is not valid";
146*795d594fSAndroid Build Coastguard Worker     return nullptr;
147*795d594fSAndroid Build Coastguard Worker   }
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   return vdex;
150*795d594fSAndroid Build Coastguard Worker }
151*795d594fSAndroid Build Coastguard Worker 
OpenFromDm(const std::string & filename,const ZipArchive & archive)152*795d594fSAndroid Build Coastguard Worker std::unique_ptr<VdexFile> VdexFile::OpenFromDm(const std::string& filename,
153*795d594fSAndroid Build Coastguard Worker                                                const ZipArchive& archive) {
154*795d594fSAndroid Build Coastguard Worker   std::string error_msg;
155*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<ZipEntry> zip_entry(archive.Find(VdexFile::kVdexNameInDmFile, &error_msg));
156*795d594fSAndroid Build Coastguard Worker   if (zip_entry == nullptr) {
157*795d594fSAndroid Build Coastguard Worker     LOG(INFO) << "No " << VdexFile::kVdexNameInDmFile << " file in DexMetadata archive. "
158*795d594fSAndroid Build Coastguard Worker               << "Not doing fast verification.";
159*795d594fSAndroid Build Coastguard Worker     return nullptr;
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker   MemMap input_file = zip_entry->MapDirectlyOrExtract(
162*795d594fSAndroid Build Coastguard Worker       filename.c_str(),
163*795d594fSAndroid Build Coastguard Worker       VdexFile::kVdexNameInDmFile,
164*795d594fSAndroid Build Coastguard Worker       &error_msg,
165*795d594fSAndroid Build Coastguard Worker       alignof(VdexFile));
166*795d594fSAndroid Build Coastguard Worker   if (!input_file.IsValid()) {
167*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "Could not open vdex file in DexMetadata archive: " << error_msg;
168*795d594fSAndroid Build Coastguard Worker     return nullptr;
169*795d594fSAndroid Build Coastguard Worker   }
170*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<VdexFile> vdex_file = std::make_unique<VdexFile>(std::move(input_file));
171*795d594fSAndroid Build Coastguard Worker   if (!vdex_file->IsValid()) {
172*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "The dex metadata .vdex is not valid. Ignoring it.";
173*795d594fSAndroid Build Coastguard Worker     return nullptr;
174*795d594fSAndroid Build Coastguard Worker   }
175*795d594fSAndroid Build Coastguard Worker   if (vdex_file->HasDexSection()) {
176*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << "The dex metadata is not allowed to contain dex files";
177*795d594fSAndroid Build Coastguard Worker     android_errorWriteLog(0x534e4554, "178055795");  // Report to SafetyNet.
178*795d594fSAndroid Build Coastguard Worker     return nullptr;
179*795d594fSAndroid Build Coastguard Worker   }
180*795d594fSAndroid Build Coastguard Worker   return vdex_file;
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker 
GetNextDexFileData(const uint8_t * cursor,uint32_t dex_file_index) const183*795d594fSAndroid Build Coastguard Worker const uint8_t* VdexFile::GetNextDexFileData(const uint8_t* cursor, uint32_t dex_file_index) const {
184*795d594fSAndroid Build Coastguard Worker   DCHECK(cursor == nullptr || (cursor > Begin() && cursor <= End()));
185*795d594fSAndroid Build Coastguard Worker   if (cursor == nullptr) {
186*795d594fSAndroid Build Coastguard Worker     // Beginning of the iteration, return the first dex file if there is one.
187*795d594fSAndroid Build Coastguard Worker     return HasDexSection() ? DexBegin() : nullptr;
188*795d594fSAndroid Build Coastguard Worker   } else if (dex_file_index >= GetNumberOfDexFiles()) {
189*795d594fSAndroid Build Coastguard Worker     return nullptr;
190*795d594fSAndroid Build Coastguard Worker   } else {
191*795d594fSAndroid Build Coastguard Worker     // Fetch the next dex file. Return null if there is none.
192*795d594fSAndroid Build Coastguard Worker     const uint8_t* data = cursor + reinterpret_cast<const DexFile::Header*>(cursor)->file_size_;
193*795d594fSAndroid Build Coastguard Worker     // Dex files are required to be 4 byte aligned. the OatWriter makes sure they are, see
194*795d594fSAndroid Build Coastguard Worker     // OatWriter::SeekToDexFiles.
195*795d594fSAndroid Build Coastguard Worker     return AlignUp(data, 4);
196*795d594fSAndroid Build Coastguard Worker   }
197*795d594fSAndroid Build Coastguard Worker }
198*795d594fSAndroid Build Coastguard Worker 
GetNextTypeLookupTableData(const uint8_t * cursor,uint32_t dex_file_index) const199*795d594fSAndroid Build Coastguard Worker const uint8_t* VdexFile::GetNextTypeLookupTableData(const uint8_t* cursor,
200*795d594fSAndroid Build Coastguard Worker                                                     uint32_t dex_file_index) const {
201*795d594fSAndroid Build Coastguard Worker   if (cursor == nullptr) {
202*795d594fSAndroid Build Coastguard Worker     // Beginning of the iteration, return the first dex file if there is one.
203*795d594fSAndroid Build Coastguard Worker     return HasTypeLookupTableSection() ? TypeLookupTableDataBegin() : nullptr;
204*795d594fSAndroid Build Coastguard Worker   } else if (dex_file_index >= GetNumberOfDexFiles()) {
205*795d594fSAndroid Build Coastguard Worker     return nullptr;
206*795d594fSAndroid Build Coastguard Worker   } else {
207*795d594fSAndroid Build Coastguard Worker     const uint8_t* data = cursor + sizeof(uint32_t) + reinterpret_cast<const uint32_t*>(cursor)[0];
208*795d594fSAndroid Build Coastguard Worker     // TypeLookupTables are required to be 4 byte aligned. the OatWriter makes sure they are.
209*795d594fSAndroid Build Coastguard Worker     // We don't check this here to be defensive against corrupted vdex files.
210*795d594fSAndroid Build Coastguard Worker     // Callers should check the returned value matches their expectations.
211*795d594fSAndroid Build Coastguard Worker     return data;
212*795d594fSAndroid Build Coastguard Worker   }
213*795d594fSAndroid Build Coastguard Worker }
214*795d594fSAndroid Build Coastguard Worker 
OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>> * dex_files,std::string * error_msg) const215*795d594fSAndroid Build Coastguard Worker bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
216*795d594fSAndroid Build Coastguard Worker                                std::string* error_msg) const {
217*795d594fSAndroid Build Coastguard Worker   size_t i = 0;
218*795d594fSAndroid Build Coastguard Worker   auto dex_file_container = std::make_shared<MemoryDexFileContainer>(Begin(), End());
219*795d594fSAndroid Build Coastguard Worker   for (const uint8_t* dex_file_start = GetNextDexFileData(nullptr, i);
220*795d594fSAndroid Build Coastguard Worker        dex_file_start != nullptr;
221*795d594fSAndroid Build Coastguard Worker        dex_file_start = GetNextDexFileData(dex_file_start, ++i)) {
222*795d594fSAndroid Build Coastguard Worker     // TODO: Supply the location information for a vdex file.
223*795d594fSAndroid Build Coastguard Worker     static constexpr char kVdexLocation[] = "";
224*795d594fSAndroid Build Coastguard Worker     std::string location = DexFileLoader::GetMultiDexLocation(i, kVdexLocation);
225*795d594fSAndroid Build Coastguard Worker     ArtDexFileLoader dex_file_loader(dex_file_container, location);
226*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<const DexFile> dex(dex_file_loader.OpenOne(dex_file_start - Begin(),
227*795d594fSAndroid Build Coastguard Worker                                                                GetLocationChecksum(i),
228*795d594fSAndroid Build Coastguard Worker                                                                /*oat_dex_file=*/nullptr,
229*795d594fSAndroid Build Coastguard Worker                                                                /*verify=*/false,
230*795d594fSAndroid Build Coastguard Worker                                                                /*verify_checksum=*/false,
231*795d594fSAndroid Build Coastguard Worker                                                                error_msg));
232*795d594fSAndroid Build Coastguard Worker     if (dex == nullptr) {
233*795d594fSAndroid Build Coastguard Worker       return false;
234*795d594fSAndroid Build Coastguard Worker     }
235*795d594fSAndroid Build Coastguard Worker     dex_files->push_back(std::move(dex));
236*795d594fSAndroid Build Coastguard Worker   }
237*795d594fSAndroid Build Coastguard Worker   return true;
238*795d594fSAndroid Build Coastguard Worker }
239*795d594fSAndroid Build Coastguard Worker 
CreateDirectories(const std::string & child_path,std::string * error_msg)240*795d594fSAndroid Build Coastguard Worker static bool CreateDirectories(const std::string& child_path, /* out */ std::string* error_msg) {
241*795d594fSAndroid Build Coastguard Worker   size_t last_slash_pos = child_path.find_last_of('/');
242*795d594fSAndroid Build Coastguard Worker   CHECK_NE(last_slash_pos, std::string::npos) << "Invalid path: " << child_path;
243*795d594fSAndroid Build Coastguard Worker   std::string parent_path = child_path.substr(0, last_slash_pos);
244*795d594fSAndroid Build Coastguard Worker   if (OS::DirectoryExists(parent_path.c_str())) {
245*795d594fSAndroid Build Coastguard Worker     return true;
246*795d594fSAndroid Build Coastguard Worker   } else if (CreateDirectories(parent_path, error_msg)) {
247*795d594fSAndroid Build Coastguard Worker     if (mkdir(parent_path.c_str(), 0700) == 0) {
248*795d594fSAndroid Build Coastguard Worker       return true;
249*795d594fSAndroid Build Coastguard Worker     }
250*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not create directory " + parent_path;
251*795d594fSAndroid Build Coastguard Worker     return false;
252*795d594fSAndroid Build Coastguard Worker   } else {
253*795d594fSAndroid Build Coastguard Worker     return false;
254*795d594fSAndroid Build Coastguard Worker   }
255*795d594fSAndroid Build Coastguard Worker }
256*795d594fSAndroid Build Coastguard Worker 
WriteToDisk(const std::string & path,const std::vector<const DexFile * > & dex_files,const verifier::VerifierDeps & verifier_deps,std::string * error_msg)257*795d594fSAndroid Build Coastguard Worker bool VdexFile::WriteToDisk(const std::string& path,
258*795d594fSAndroid Build Coastguard Worker                            const std::vector<const DexFile*>& dex_files,
259*795d594fSAndroid Build Coastguard Worker                            const verifier::VerifierDeps& verifier_deps,
260*795d594fSAndroid Build Coastguard Worker                            std::string* error_msg) {
261*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> verifier_deps_data;
262*795d594fSAndroid Build Coastguard Worker   verifier_deps.Encode(dex_files, &verifier_deps_data);
263*795d594fSAndroid Build Coastguard Worker   uint32_t verifier_deps_size = verifier_deps_data.size();
264*795d594fSAndroid Build Coastguard Worker   // Add padding so the type lookup tables are 4 byte aligned.
265*795d594fSAndroid Build Coastguard Worker   uint32_t verifier_deps_with_padding_size = RoundUp(verifier_deps_data.size(), 4);
266*795d594fSAndroid Build Coastguard Worker   DCHECK_GE(verifier_deps_with_padding_size, verifier_deps_data.size());
267*795d594fSAndroid Build Coastguard Worker   verifier_deps_data.resize(verifier_deps_with_padding_size, 0);
268*795d594fSAndroid Build Coastguard Worker 
269*795d594fSAndroid Build Coastguard Worker   size_t type_lookup_table_size = 0u;
270*795d594fSAndroid Build Coastguard Worker   for (const DexFile* dex_file : dex_files) {
271*795d594fSAndroid Build Coastguard Worker     type_lookup_table_size +=
272*795d594fSAndroid Build Coastguard Worker         sizeof(uint32_t) + TypeLookupTable::RawDataLength(dex_file->NumClassDefs());
273*795d594fSAndroid Build Coastguard Worker   }
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   VdexFile::VdexFileHeader vdex_header(/* has_dex_section= */ false);
276*795d594fSAndroid Build Coastguard Worker   VdexFile::VdexSectionHeader sections[static_cast<uint32_t>(VdexSection::kNumberOfSections)];
277*795d594fSAndroid Build Coastguard Worker 
278*795d594fSAndroid Build Coastguard Worker   // Set checksum section.
279*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kChecksumSection].section_kind = VdexSection::kChecksumSection;
280*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kChecksumSection].section_offset = GetChecksumsOffset();
281*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kChecksumSection].section_size =
282*795d594fSAndroid Build Coastguard Worker       sizeof(VdexFile::VdexChecksum) * dex_files.size();
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker   // Set dex section.
285*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kDexFileSection].section_kind = VdexSection::kDexFileSection;
286*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kDexFileSection].section_offset = 0u;
287*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kDexFileSection].section_size = 0u;
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker   // Set VerifierDeps section.
290*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kVerifierDepsSection].section_kind = VdexSection::kVerifierDepsSection;
291*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kVerifierDepsSection].section_offset =
292*795d594fSAndroid Build Coastguard Worker       GetChecksumsOffset() + sections[kChecksumSection].section_size;
293*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kVerifierDepsSection].section_size = verifier_deps_size;
294*795d594fSAndroid Build Coastguard Worker 
295*795d594fSAndroid Build Coastguard Worker   // Set TypeLookupTable section.
296*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kTypeLookupTableSection].section_kind =
297*795d594fSAndroid Build Coastguard Worker       VdexSection::kTypeLookupTableSection;
298*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kTypeLookupTableSection].section_offset =
299*795d594fSAndroid Build Coastguard Worker       sections[VdexSection::kVerifierDepsSection].section_offset + verifier_deps_with_padding_size;
300*795d594fSAndroid Build Coastguard Worker   sections[VdexSection::kTypeLookupTableSection].section_size = type_lookup_table_size;
301*795d594fSAndroid Build Coastguard Worker 
302*795d594fSAndroid Build Coastguard Worker   if (!CreateDirectories(path, error_msg)) {
303*795d594fSAndroid Build Coastguard Worker     return false;
304*795d594fSAndroid Build Coastguard Worker   }
305*795d594fSAndroid Build Coastguard Worker 
306*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<File> out(OS::CreateEmptyFileWriteOnly(path.c_str()));
307*795d594fSAndroid Build Coastguard Worker   if (out == nullptr) {
308*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not open " + path + " for writing";
309*795d594fSAndroid Build Coastguard Worker     return false;
310*795d594fSAndroid Build Coastguard Worker   }
311*795d594fSAndroid Build Coastguard Worker 
312*795d594fSAndroid Build Coastguard Worker   // Write header.
313*795d594fSAndroid Build Coastguard Worker   if (!out->WriteFully(reinterpret_cast<const char*>(&vdex_header), sizeof(vdex_header))) {
314*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not write vdex header to " + path;
315*795d594fSAndroid Build Coastguard Worker     out->Unlink();
316*795d594fSAndroid Build Coastguard Worker     return false;
317*795d594fSAndroid Build Coastguard Worker   }
318*795d594fSAndroid Build Coastguard Worker 
319*795d594fSAndroid Build Coastguard Worker   // Write section infos.
320*795d594fSAndroid Build Coastguard Worker   if (!out->WriteFully(reinterpret_cast<const char*>(&sections), sizeof(sections))) {
321*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not write vdex sections to " + path;
322*795d594fSAndroid Build Coastguard Worker     out->Unlink();
323*795d594fSAndroid Build Coastguard Worker     return false;
324*795d594fSAndroid Build Coastguard Worker   }
325*795d594fSAndroid Build Coastguard Worker 
326*795d594fSAndroid Build Coastguard Worker   // Write checksum section.
327*795d594fSAndroid Build Coastguard Worker   for (const DexFile* dex_file : dex_files) {
328*795d594fSAndroid Build Coastguard Worker     uint32_t checksum = dex_file->GetLocationChecksum();
329*795d594fSAndroid Build Coastguard Worker     const uint32_t* checksum_ptr = &checksum;
330*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(*checksum_ptr) == sizeof(VdexFile::VdexChecksum));
331*795d594fSAndroid Build Coastguard Worker     if (!out->WriteFully(reinterpret_cast<const char*>(checksum_ptr),
332*795d594fSAndroid Build Coastguard Worker                          sizeof(VdexFile::VdexChecksum))) {
333*795d594fSAndroid Build Coastguard Worker       *error_msg = "Could not write dex checksums to " + path;
334*795d594fSAndroid Build Coastguard Worker       out->Unlink();
335*795d594fSAndroid Build Coastguard Worker       return false;
336*795d594fSAndroid Build Coastguard Worker     }
337*795d594fSAndroid Build Coastguard Worker   }
338*795d594fSAndroid Build Coastguard Worker 
339*795d594fSAndroid Build Coastguard Worker   if (!out->WriteFully(reinterpret_cast<const char*>(verifier_deps_data.data()),
340*795d594fSAndroid Build Coastguard Worker                        verifier_deps_with_padding_size)) {
341*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not write verifier deps to " + path;
342*795d594fSAndroid Build Coastguard Worker     out->Unlink();
343*795d594fSAndroid Build Coastguard Worker     return false;
344*795d594fSAndroid Build Coastguard Worker   }
345*795d594fSAndroid Build Coastguard Worker 
346*795d594fSAndroid Build Coastguard Worker   size_t written_type_lookup_table_size = 0;
347*795d594fSAndroid Build Coastguard Worker   for (const DexFile* dex_file : dex_files) {
348*795d594fSAndroid Build Coastguard Worker     TypeLookupTable type_lookup_table = TypeLookupTable::Create(*dex_file);
349*795d594fSAndroid Build Coastguard Worker     uint32_t size = type_lookup_table.RawDataLength();
350*795d594fSAndroid Build Coastguard Worker     DCHECK_ALIGNED(size, 4);
351*795d594fSAndroid Build Coastguard Worker     if (!out->WriteFully(reinterpret_cast<const char*>(&size), sizeof(uint32_t)) ||
352*795d594fSAndroid Build Coastguard Worker         !out->WriteFully(reinterpret_cast<const char*>(type_lookup_table.RawData()), size)) {
353*795d594fSAndroid Build Coastguard Worker       *error_msg = "Could not write type lookup table " + path;
354*795d594fSAndroid Build Coastguard Worker       out->Unlink();
355*795d594fSAndroid Build Coastguard Worker       return false;
356*795d594fSAndroid Build Coastguard Worker     }
357*795d594fSAndroid Build Coastguard Worker     written_type_lookup_table_size += sizeof(uint32_t) + size;
358*795d594fSAndroid Build Coastguard Worker   }
359*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(written_type_lookup_table_size, type_lookup_table_size);
360*795d594fSAndroid Build Coastguard Worker 
361*795d594fSAndroid Build Coastguard Worker   if (out->FlushClose() != 0) {
362*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not flush and close " + path;
363*795d594fSAndroid Build Coastguard Worker     out->Unlink();
364*795d594fSAndroid Build Coastguard Worker     return false;
365*795d594fSAndroid Build Coastguard Worker   }
366*795d594fSAndroid Build Coastguard Worker 
367*795d594fSAndroid Build Coastguard Worker   return true;
368*795d594fSAndroid Build Coastguard Worker }
369*795d594fSAndroid Build Coastguard Worker 
MatchesDexFileChecksums(const std::vector<const DexFile::Header * > & dex_headers) const370*795d594fSAndroid Build Coastguard Worker bool VdexFile::MatchesDexFileChecksums(const std::vector<const DexFile::Header*>& dex_headers)
371*795d594fSAndroid Build Coastguard Worker     const {
372*795d594fSAndroid Build Coastguard Worker   if (dex_headers.size() != GetNumberOfDexFiles()) {
373*795d594fSAndroid Build Coastguard Worker     LOG(WARNING) << "Mismatch of number of dex files in vdex (expected="
374*795d594fSAndroid Build Coastguard Worker         << GetNumberOfDexFiles() << ", actual=" << dex_headers.size() << ")";
375*795d594fSAndroid Build Coastguard Worker     return false;
376*795d594fSAndroid Build Coastguard Worker   }
377*795d594fSAndroid Build Coastguard Worker   const VdexChecksum* checksums = GetDexChecksumsArray();
378*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < dex_headers.size(); ++i) {
379*795d594fSAndroid Build Coastguard Worker     if (checksums[i] != dex_headers[i]->checksum_) {
380*795d594fSAndroid Build Coastguard Worker       LOG(WARNING) << "Mismatch of dex file checksum in vdex (index=" << i << ")";
381*795d594fSAndroid Build Coastguard Worker       return false;
382*795d594fSAndroid Build Coastguard Worker     }
383*795d594fSAndroid Build Coastguard Worker   }
384*795d594fSAndroid Build Coastguard Worker   return true;
385*795d594fSAndroid Build Coastguard Worker }
386*795d594fSAndroid Build Coastguard Worker 
HasOnlyStandardDexFiles() const387*795d594fSAndroid Build Coastguard Worker bool VdexFile::HasOnlyStandardDexFiles() const {
388*795d594fSAndroid Build Coastguard Worker   // All are the same so it's enough to check the first one.
389*795d594fSAndroid Build Coastguard Worker   const uint8_t* dex_file_start = GetNextDexFileData(nullptr, 0);
390*795d594fSAndroid Build Coastguard Worker   return dex_file_start == nullptr || StandardDexFile::IsMagicValid(dex_file_start);
391*795d594fSAndroid Build Coastguard Worker }
392*795d594fSAndroid Build Coastguard Worker 
FindClassAndClearException(ClassLinker * class_linker,Thread * self,const char * descriptor,size_t descriptor_length,Handle<mirror::ClassLoader> class_loader)393*795d594fSAndroid Build Coastguard Worker static ObjPtr<mirror::Class> FindClassAndClearException(ClassLinker* class_linker,
394*795d594fSAndroid Build Coastguard Worker                                                         Thread* self,
395*795d594fSAndroid Build Coastguard Worker                                                         const char* descriptor,
396*795d594fSAndroid Build Coastguard Worker                                                         size_t descriptor_length,
397*795d594fSAndroid Build Coastguard Worker                                                         Handle<mirror::ClassLoader> class_loader)
398*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
399*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> result =
400*795d594fSAndroid Build Coastguard Worker       class_linker->FindClass(self, descriptor, descriptor_length, class_loader);
401*795d594fSAndroid Build Coastguard Worker   if (result == nullptr) {
402*795d594fSAndroid Build Coastguard Worker     DCHECK(self->IsExceptionPending());
403*795d594fSAndroid Build Coastguard Worker     self->ClearException();
404*795d594fSAndroid Build Coastguard Worker   }
405*795d594fSAndroid Build Coastguard Worker   return result;
406*795d594fSAndroid Build Coastguard Worker }
407*795d594fSAndroid Build Coastguard Worker 
GetStringFromIndex(const DexFile & dex_file,dex::StringIndex string_id,uint32_t number_of_extra_strings,const uint32_t * extra_strings_offsets,const uint8_t * verifier_deps,size_t * utf8_length)408*795d594fSAndroid Build Coastguard Worker static const char* GetStringFromIndex(const DexFile& dex_file,
409*795d594fSAndroid Build Coastguard Worker                                       dex::StringIndex string_id,
410*795d594fSAndroid Build Coastguard Worker                                       uint32_t number_of_extra_strings,
411*795d594fSAndroid Build Coastguard Worker                                       const uint32_t* extra_strings_offsets,
412*795d594fSAndroid Build Coastguard Worker                                       const uint8_t* verifier_deps,
413*795d594fSAndroid Build Coastguard Worker                                       /*out*/ size_t* utf8_length) {
414*795d594fSAndroid Build Coastguard Worker   uint32_t num_ids_in_dex = dex_file.NumStringIds();
415*795d594fSAndroid Build Coastguard Worker   if (string_id.index_ < num_ids_in_dex) {
416*795d594fSAndroid Build Coastguard Worker     uint32_t utf16_length;
417*795d594fSAndroid Build Coastguard Worker     const char* str = dex_file.GetStringDataAndUtf16Length(string_id, &utf16_length);
418*795d594fSAndroid Build Coastguard Worker     *utf8_length = DexFile::Utf8Length(str, utf16_length);
419*795d594fSAndroid Build Coastguard Worker     return str;
420*795d594fSAndroid Build Coastguard Worker   } else {
421*795d594fSAndroid Build Coastguard Worker     CHECK_LT(string_id.index_ - num_ids_in_dex, number_of_extra_strings);
422*795d594fSAndroid Build Coastguard Worker     uint32_t offset = extra_strings_offsets[string_id.index_ - num_ids_in_dex];
423*795d594fSAndroid Build Coastguard Worker     const char* str = reinterpret_cast<const char*>(verifier_deps) + offset;
424*795d594fSAndroid Build Coastguard Worker     *utf8_length = strlen(str);
425*795d594fSAndroid Build Coastguard Worker     return str;
426*795d594fSAndroid Build Coastguard Worker   }
427*795d594fSAndroid Build Coastguard Worker }
428*795d594fSAndroid Build Coastguard Worker 
429*795d594fSAndroid Build Coastguard Worker // Returns an array of offsets where the assignability checks for each class
430*795d594fSAndroid Build Coastguard Worker // definition are stored.
GetDexFileClassDefs(const uint8_t * verifier_deps,uint32_t index)431*795d594fSAndroid Build Coastguard Worker static const uint32_t* GetDexFileClassDefs(const uint8_t* verifier_deps, uint32_t index) {
432*795d594fSAndroid Build Coastguard Worker   uint32_t dex_file_offset = reinterpret_cast<const uint32_t*>(verifier_deps)[index];
433*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<const uint32_t*>(verifier_deps + dex_file_offset);
434*795d594fSAndroid Build Coastguard Worker }
435*795d594fSAndroid Build Coastguard Worker 
436*795d594fSAndroid Build Coastguard Worker // Returns an array of offsets where extra strings are stored.
GetExtraStringsOffsets(const DexFile & dex_file,const uint8_t * verifier_deps,const uint32_t * dex_file_class_defs,uint32_t * number_of_extra_strings)437*795d594fSAndroid Build Coastguard Worker static const uint32_t* GetExtraStringsOffsets(const DexFile& dex_file,
438*795d594fSAndroid Build Coastguard Worker                                               const uint8_t* verifier_deps,
439*795d594fSAndroid Build Coastguard Worker                                               const uint32_t* dex_file_class_defs,
440*795d594fSAndroid Build Coastguard Worker                                               /*out*/ uint32_t* number_of_extra_strings) {
441*795d594fSAndroid Build Coastguard Worker   // The information for strings is right after dex_file_class_defs, 4-byte
442*795d594fSAndroid Build Coastguard Worker   // aligned
443*795d594fSAndroid Build Coastguard Worker   uint32_t end_of_assignability_types = dex_file_class_defs[dex_file.NumClassDefs()];
444*795d594fSAndroid Build Coastguard Worker   const uint8_t* strings_data_start =
445*795d594fSAndroid Build Coastguard Worker       AlignUp(verifier_deps + end_of_assignability_types, sizeof(uint32_t));
446*795d594fSAndroid Build Coastguard Worker   // First entry is the number of extra strings for this dex file.
447*795d594fSAndroid Build Coastguard Worker   *number_of_extra_strings = *reinterpret_cast<const uint32_t*>(strings_data_start);
448*795d594fSAndroid Build Coastguard Worker   // Then an array of offsets in `verifier_deps` for the extra strings.
449*795d594fSAndroid Build Coastguard Worker   return reinterpret_cast<const uint32_t*>(strings_data_start + sizeof(uint32_t));
450*795d594fSAndroid Build Coastguard Worker }
451*795d594fSAndroid Build Coastguard Worker 
ComputeClassStatus(Thread * self,Handle<mirror::Class> cls) const452*795d594fSAndroid Build Coastguard Worker ClassStatus VdexFile::ComputeClassStatus(Thread* self, Handle<mirror::Class> cls) const {
453*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file = cls->GetDexFile();
454*795d594fSAndroid Build Coastguard Worker   uint16_t class_def_index = cls->GetDexClassDefIndex();
455*795d594fSAndroid Build Coastguard Worker 
456*795d594fSAndroid Build Coastguard Worker   // Find which dex file index from within the vdex file.
457*795d594fSAndroid Build Coastguard Worker   uint32_t index = 0;
458*795d594fSAndroid Build Coastguard Worker   for (; index < GetNumberOfDexFiles(); ++index) {
459*795d594fSAndroid Build Coastguard Worker     if (dex_file.GetLocationChecksum() == GetLocationChecksum(index)) {
460*795d594fSAndroid Build Coastguard Worker       break;
461*795d594fSAndroid Build Coastguard Worker     }
462*795d594fSAndroid Build Coastguard Worker   }
463*795d594fSAndroid Build Coastguard Worker 
464*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(index, GetNumberOfDexFiles());
465*795d594fSAndroid Build Coastguard Worker 
466*795d594fSAndroid Build Coastguard Worker   const uint8_t* verifier_deps = GetVerifierDepsData().data();
467*795d594fSAndroid Build Coastguard Worker   const uint32_t* dex_file_class_defs = GetDexFileClassDefs(verifier_deps, index);
468*795d594fSAndroid Build Coastguard Worker 
469*795d594fSAndroid Build Coastguard Worker   // Fetch type checks offsets.
470*795d594fSAndroid Build Coastguard Worker   uint32_t class_def_offset = dex_file_class_defs[class_def_index];
471*795d594fSAndroid Build Coastguard Worker   if (class_def_offset == verifier::VerifierDeps::kNotVerifiedMarker) {
472*795d594fSAndroid Build Coastguard Worker     // Return a status that needs re-verification.
473*795d594fSAndroid Build Coastguard Worker     return ClassStatus::kResolved;
474*795d594fSAndroid Build Coastguard Worker   }
475*795d594fSAndroid Build Coastguard Worker   // End offset for this class's type checks. We know there is one and the loop
476*795d594fSAndroid Build Coastguard Worker   // will terminate.
477*795d594fSAndroid Build Coastguard Worker   uint32_t end_offset = verifier::VerifierDeps::kNotVerifiedMarker;
478*795d594fSAndroid Build Coastguard Worker   for (uint32_t i = class_def_index + 1; i < dex_file.NumClassDefs() + 1; ++i) {
479*795d594fSAndroid Build Coastguard Worker     end_offset = dex_file_class_defs[i];
480*795d594fSAndroid Build Coastguard Worker     if (end_offset != verifier::VerifierDeps::kNotVerifiedMarker) {
481*795d594fSAndroid Build Coastguard Worker       break;
482*795d594fSAndroid Build Coastguard Worker     }
483*795d594fSAndroid Build Coastguard Worker   }
484*795d594fSAndroid Build Coastguard Worker   DCHECK_NE(end_offset, verifier::VerifierDeps::kNotVerifiedMarker);
485*795d594fSAndroid Build Coastguard Worker 
486*795d594fSAndroid Build Coastguard Worker   uint32_t number_of_extra_strings = 0;
487*795d594fSAndroid Build Coastguard Worker   // Offset where extra strings are stored.
488*795d594fSAndroid Build Coastguard Worker   const uint32_t* extra_strings_offsets = GetExtraStringsOffsets(dex_file,
489*795d594fSAndroid Build Coastguard Worker                                                                  verifier_deps,
490*795d594fSAndroid Build Coastguard Worker                                                                  dex_file_class_defs,
491*795d594fSAndroid Build Coastguard Worker                                                                  &number_of_extra_strings);
492*795d594fSAndroid Build Coastguard Worker 
493*795d594fSAndroid Build Coastguard Worker   // Loop over and perform each assignability check.
494*795d594fSAndroid Build Coastguard Worker   StackHandleScope<3> hs(self);
495*795d594fSAndroid Build Coastguard Worker   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
496*795d594fSAndroid Build Coastguard Worker   Handle<mirror::ClassLoader> class_loader(hs.NewHandle(cls->GetClassLoader()));
497*795d594fSAndroid Build Coastguard Worker   MutableHandle<mirror::Class> source(hs.NewHandle<mirror::Class>(nullptr));
498*795d594fSAndroid Build Coastguard Worker   MutableHandle<mirror::Class> destination(hs.NewHandle<mirror::Class>(nullptr));
499*795d594fSAndroid Build Coastguard Worker 
500*795d594fSAndroid Build Coastguard Worker   const uint8_t* cursor = verifier_deps + class_def_offset;
501*795d594fSAndroid Build Coastguard Worker   const uint8_t* end = verifier_deps + end_offset;
502*795d594fSAndroid Build Coastguard Worker   while (cursor < end) {
503*795d594fSAndroid Build Coastguard Worker     uint32_t destination_index;
504*795d594fSAndroid Build Coastguard Worker     uint32_t source_index;
505*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(!DecodeUnsignedLeb128Checked(&cursor, end, &destination_index) ||
506*795d594fSAndroid Build Coastguard Worker                  !DecodeUnsignedLeb128Checked(&cursor, end, &source_index))) {
507*795d594fSAndroid Build Coastguard Worker       // Error parsing the data, just return that we are not verified.
508*795d594fSAndroid Build Coastguard Worker       return ClassStatus::kResolved;
509*795d594fSAndroid Build Coastguard Worker     }
510*795d594fSAndroid Build Coastguard Worker     size_t destination_desc_length;
511*795d594fSAndroid Build Coastguard Worker     const char* destination_desc = GetStringFromIndex(dex_file,
512*795d594fSAndroid Build Coastguard Worker                                                       dex::StringIndex(destination_index),
513*795d594fSAndroid Build Coastguard Worker                                                       number_of_extra_strings,
514*795d594fSAndroid Build Coastguard Worker                                                       extra_strings_offsets,
515*795d594fSAndroid Build Coastguard Worker                                                       verifier_deps,
516*795d594fSAndroid Build Coastguard Worker                                                       &destination_desc_length);
517*795d594fSAndroid Build Coastguard Worker     destination.Assign(FindClassAndClearException(
518*795d594fSAndroid Build Coastguard Worker         class_linker, self, destination_desc, destination_desc_length, class_loader));
519*795d594fSAndroid Build Coastguard Worker 
520*795d594fSAndroid Build Coastguard Worker     size_t source_desc_length;
521*795d594fSAndroid Build Coastguard Worker     const char* source_desc = GetStringFromIndex(dex_file,
522*795d594fSAndroid Build Coastguard Worker                                                  dex::StringIndex(source_index),
523*795d594fSAndroid Build Coastguard Worker                                                  number_of_extra_strings,
524*795d594fSAndroid Build Coastguard Worker                                                  extra_strings_offsets,
525*795d594fSAndroid Build Coastguard Worker                                                  verifier_deps,
526*795d594fSAndroid Build Coastguard Worker                                                  &source_desc_length);
527*795d594fSAndroid Build Coastguard Worker     source.Assign(FindClassAndClearException(
528*795d594fSAndroid Build Coastguard Worker         class_linker, self, source_desc, source_desc_length, class_loader));
529*795d594fSAndroid Build Coastguard Worker 
530*795d594fSAndroid Build Coastguard Worker     if (destination == nullptr || source == nullptr) {
531*795d594fSAndroid Build Coastguard Worker       // The interpreter / compiler can handle a missing class.
532*795d594fSAndroid Build Coastguard Worker       continue;
533*795d594fSAndroid Build Coastguard Worker     }
534*795d594fSAndroid Build Coastguard Worker 
535*795d594fSAndroid Build Coastguard Worker     DCHECK(destination->IsResolved() && source->IsResolved());
536*795d594fSAndroid Build Coastguard Worker     if (!destination->IsAssignableFrom(source.Get())) {
537*795d594fSAndroid Build Coastguard Worker       VLOG(verifier) << "Vdex checking failed for " << cls->PrettyClass()
538*795d594fSAndroid Build Coastguard Worker                      << ": expected " << destination->PrettyClass()
539*795d594fSAndroid Build Coastguard Worker                      << " to be assignable from " << source->PrettyClass();
540*795d594fSAndroid Build Coastguard Worker       // An implicit assignability check is failing in the code, return that the
541*795d594fSAndroid Build Coastguard Worker       // class is not verified.
542*795d594fSAndroid Build Coastguard Worker       return ClassStatus::kResolved;
543*795d594fSAndroid Build Coastguard Worker     }
544*795d594fSAndroid Build Coastguard Worker   }
545*795d594fSAndroid Build Coastguard Worker 
546*795d594fSAndroid Build Coastguard Worker   return ClassStatus::kVerifiedNeedsAccessChecks;
547*795d594fSAndroid Build Coastguard Worker }
548*795d594fSAndroid Build Coastguard Worker 
549*795d594fSAndroid Build Coastguard Worker }  // namespace art
550