• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "method_verifier.h"
18 
19 #include <iostream>
20 
21 #include "base/logging.h"
22 #include "base/mutex-inl.h"
23 #include "base/stringpiece.h"
24 #include "class_linker.h"
25 #include "dex_file-inl.h"
26 #include "dex_instruction-inl.h"
27 #include "dex_instruction_visitor.h"
28 #include "gc/accounting/card_table-inl.h"
29 #include "indenter.h"
30 #include "intern_table.h"
31 #include "leb128.h"
32 #include "mirror/art_field-inl.h"
33 #include "mirror/art_method-inl.h"
34 #include "mirror/class.h"
35 #include "mirror/class-inl.h"
36 #include "mirror/dex_cache-inl.h"
37 #include "mirror/object-inl.h"
38 #include "mirror/object_array-inl.h"
39 #include "object_utils.h"
40 #include "register_line-inl.h"
41 #include "runtime.h"
42 #include "verifier/dex_gc_map.h"
43 
44 namespace art {
45 namespace verifier {
46 
47 static const bool gDebugVerify = false;
48 // TODO: Add a constant to method_verifier to turn on verbose logging?
49 
Init(RegisterTrackingMode mode,InstructionFlags * flags,uint32_t insns_size,uint16_t registers_size,MethodVerifier * verifier)50 void PcToRegisterLineTable::Init(RegisterTrackingMode mode, InstructionFlags* flags,
51                                  uint32_t insns_size, uint16_t registers_size,
52                                  MethodVerifier* verifier) {
53   DCHECK_GT(insns_size, 0U);
54 
55   for (uint32_t i = 0; i < insns_size; i++) {
56     bool interesting = false;
57     switch (mode) {
58       case kTrackRegsAll:
59         interesting = flags[i].IsOpcode();
60         break;
61       case kTrackCompilerInterestPoints:
62         interesting = flags[i].IsCompileTimeInfoPoint() || flags[i].IsBranchTarget();
63         break;
64       case kTrackRegsBranches:
65         interesting = flags[i].IsBranchTarget();
66         break;
67       default:
68         break;
69     }
70     if (interesting) {
71       pc_to_register_line_.Put(i, new RegisterLine(registers_size, verifier));
72     }
73   }
74 }
75 
VerifyClass(const mirror::Class * klass,bool allow_soft_failures,std::string * error)76 MethodVerifier::FailureKind MethodVerifier::VerifyClass(const mirror::Class* klass,
77                                                         bool allow_soft_failures,
78                                                         std::string* error) {
79   if (klass->IsVerified()) {
80     return kNoFailure;
81   }
82   mirror::Class* super = klass->GetSuperClass();
83   if (super == NULL && StringPiece(ClassHelper(klass).GetDescriptor()) != "Ljava/lang/Object;") {
84     *error = "Verifier rejected class ";
85     *error += PrettyDescriptor(klass);
86     *error += " that has no super class";
87     return kHardFailure;
88   }
89   if (super != NULL && super->IsFinal()) {
90     *error = "Verifier rejected class ";
91     *error += PrettyDescriptor(klass);
92     *error += " that attempts to sub-class final class ";
93     *error += PrettyDescriptor(super);
94     return kHardFailure;
95   }
96   ClassHelper kh(klass);
97   const DexFile& dex_file = kh.GetDexFile();
98   const DexFile::ClassDef* class_def = kh.GetClassDef();
99   if (class_def == NULL) {
100     *error = "Verifier rejected class ";
101     *error += PrettyDescriptor(klass);
102     *error += " that isn't present in dex file ";
103     *error += dex_file.GetLocation();
104     return kHardFailure;
105   }
106   return VerifyClass(&dex_file,
107                      kh.GetDexCache(),
108                      klass->GetClassLoader(),
109                      class_def,
110                      allow_soft_failures,
111                      error);
112 }
113 
VerifyClass(const DexFile * dex_file,mirror::DexCache * dex_cache,mirror::ClassLoader * class_loader,const DexFile::ClassDef * class_def,bool allow_soft_failures,std::string * error)114 MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file,
115                                                         mirror::DexCache* dex_cache,
116                                                         mirror::ClassLoader* class_loader,
117                                                         const DexFile::ClassDef* class_def,
118                                                         bool allow_soft_failures,
119                                                         std::string* error) {
120   DCHECK(class_def != nullptr);
121   const byte* class_data = dex_file->GetClassData(*class_def);
122   if (class_data == NULL) {
123     // empty class, probably a marker interface
124     return kNoFailure;
125   }
126   ClassDataItemIterator it(*dex_file, class_data);
127   while (it.HasNextStaticField() || it.HasNextInstanceField()) {
128     it.Next();
129   }
130   size_t error_count = 0;
131   bool hard_fail = false;
132   ClassLinker* linker = Runtime::Current()->GetClassLinker();
133   int64_t previous_direct_method_idx = -1;
134   while (it.HasNextDirectMethod()) {
135     uint32_t method_idx = it.GetMemberIndex();
136     if (method_idx == previous_direct_method_idx) {
137       // smali can create dex files with two encoded_methods sharing the same method_idx
138       // http://code.google.com/p/smali/issues/detail?id=119
139       it.Next();
140       continue;
141     }
142     previous_direct_method_idx = method_idx;
143     InvokeType type = it.GetMethodInvokeType(*class_def);
144     mirror::ArtMethod* method =
145         linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type);
146     if (method == NULL) {
147       DCHECK(Thread::Current()->IsExceptionPending());
148       // We couldn't resolve the method, but continue regardless.
149       Thread::Current()->ClearException();
150     }
151     MethodVerifier::FailureKind result = VerifyMethod(method_idx,
152                                                       dex_file,
153                                                       dex_cache,
154                                                       class_loader,
155                                                       class_def,
156                                                       it.GetMethodCodeItem(),
157                                                       method,
158                                                       it.GetMemberAccessFlags(),
159                                                       allow_soft_failures);
160     if (result != kNoFailure) {
161       if (result == kHardFailure) {
162         hard_fail = true;
163         if (error_count > 0) {
164           *error += "\n";
165         }
166         *error = "Verifier rejected class ";
167         *error += PrettyDescriptor(dex_file->GetClassDescriptor(*class_def));
168         *error += " due to bad method ";
169         *error += PrettyMethod(method_idx, *dex_file);
170       }
171       ++error_count;
172     }
173     it.Next();
174   }
175   int64_t previous_virtual_method_idx = -1;
176   while (it.HasNextVirtualMethod()) {
177     uint32_t method_idx = it.GetMemberIndex();
178     if (method_idx == previous_virtual_method_idx) {
179       // smali can create dex files with two encoded_methods sharing the same method_idx
180       // http://code.google.com/p/smali/issues/detail?id=119
181       it.Next();
182       continue;
183     }
184     previous_virtual_method_idx = method_idx;
185     InvokeType type = it.GetMethodInvokeType(*class_def);
186     mirror::ArtMethod* method =
187         linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader, NULL, type);
188     if (method == NULL) {
189       DCHECK(Thread::Current()->IsExceptionPending());
190       // We couldn't resolve the method, but continue regardless.
191       Thread::Current()->ClearException();
192     }
193     MethodVerifier::FailureKind result = VerifyMethod(method_idx,
194                                                       dex_file,
195                                                       dex_cache,
196                                                       class_loader,
197                                                       class_def,
198                                                       it.GetMethodCodeItem(),
199                                                       method,
200                                                       it.GetMemberAccessFlags(),
201                                                       allow_soft_failures);
202     if (result != kNoFailure) {
203       if (result == kHardFailure) {
204         hard_fail = true;
205         if (error_count > 0) {
206           *error += "\n";
207         }
208         *error = "Verifier rejected class ";
209         *error += PrettyDescriptor(dex_file->GetClassDescriptor(*class_def));
210         *error += " due to bad method ";
211         *error += PrettyMethod(method_idx, *dex_file);
212       }
213       ++error_count;
214     }
215     it.Next();
216   }
217   if (error_count == 0) {
218     return kNoFailure;
219   } else {
220     return hard_fail ? kHardFailure : kSoftFailure;
221   }
222 }
223 
VerifyMethod(uint32_t method_idx,const DexFile * dex_file,mirror::DexCache * dex_cache,mirror::ClassLoader * class_loader,const DexFile::ClassDef * class_def,const DexFile::CodeItem * code_item,mirror::ArtMethod * method,uint32_t method_access_flags,bool allow_soft_failures)224 MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx,
225                                                          const DexFile* dex_file,
226                                                          mirror::DexCache* dex_cache,
227                                                          mirror::ClassLoader* class_loader,
228                                                          const DexFile::ClassDef* class_def,
229                                                          const DexFile::CodeItem* code_item,
230                                                          mirror::ArtMethod* method,
231                                                          uint32_t method_access_flags,
232                                                          bool allow_soft_failures) {
233   MethodVerifier::FailureKind result = kNoFailure;
234   uint64_t start_ns = NanoTime();
235 
236   MethodVerifier verifier_(dex_file, dex_cache, class_loader, class_def, code_item, method_idx,
237                            method, method_access_flags, true, allow_soft_failures);
238   if (verifier_.Verify()) {
239     // Verification completed, however failures may be pending that didn't cause the verification
240     // to hard fail.
241     CHECK(!verifier_.have_pending_hard_failure_);
242     if (verifier_.failures_.size() != 0) {
243       if (VLOG_IS_ON(verifier)) {
244           verifier_.DumpFailures(VLOG_STREAM(verifier) << "Soft verification failures in "
245                                 << PrettyMethod(method_idx, *dex_file) << "\n");
246       }
247       result = kSoftFailure;
248     }
249   } else {
250     // Bad method data.
251     CHECK_NE(verifier_.failures_.size(), 0U);
252     CHECK(verifier_.have_pending_hard_failure_);
253     verifier_.DumpFailures(LOG(INFO) << "Verification error in "
254                                     << PrettyMethod(method_idx, *dex_file) << "\n");
255     if (gDebugVerify) {
256       std::cout << "\n" << verifier_.info_messages_.str();
257       verifier_.Dump(std::cout);
258     }
259     result = kHardFailure;
260   }
261   uint64_t duration_ns = NanoTime() - start_ns;
262   if (duration_ns > MsToNs(100)) {
263     LOG(WARNING) << "Verification of " << PrettyMethod(method_idx, *dex_file)
264                  << " took " << PrettyDuration(duration_ns);
265   }
266   return result;
267 }
268 
VerifyMethodAndDump(std::ostream & os,uint32_t dex_method_idx,const DexFile * dex_file,mirror::DexCache * dex_cache,mirror::ClassLoader * class_loader,const DexFile::ClassDef * class_def,const DexFile::CodeItem * code_item,mirror::ArtMethod * method,uint32_t method_access_flags)269 void MethodVerifier::VerifyMethodAndDump(std::ostream& os, uint32_t dex_method_idx,
270                                          const DexFile* dex_file, mirror::DexCache* dex_cache,
271                                          mirror::ClassLoader* class_loader,
272                                          const DexFile::ClassDef* class_def,
273                                          const DexFile::CodeItem* code_item,
274                                          mirror::ArtMethod* method,
275                                          uint32_t method_access_flags) {
276   MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def, code_item,
277                           dex_method_idx, method, method_access_flags, true, true);
278   verifier.Verify();
279   verifier.DumpFailures(os);
280   os << verifier.info_messages_.str();
281   verifier.Dump(os);
282 }
283 
MethodVerifier(const DexFile * dex_file,mirror::DexCache * dex_cache,mirror::ClassLoader * class_loader,const DexFile::ClassDef * class_def,const DexFile::CodeItem * code_item,uint32_t dex_method_idx,mirror::ArtMethod * method,uint32_t method_access_flags,bool can_load_classes,bool allow_soft_failures)284 MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache,
285                                mirror::ClassLoader* class_loader,
286                                const DexFile::ClassDef* class_def,
287                                const DexFile::CodeItem* code_item,
288                                uint32_t dex_method_idx, mirror::ArtMethod* method,
289                                uint32_t method_access_flags, bool can_load_classes,
290                                bool allow_soft_failures)
291     : reg_types_(can_load_classes),
292       work_insn_idx_(-1),
293       dex_method_idx_(dex_method_idx),
294       mirror_method_(method),
295       method_access_flags_(method_access_flags),
296       dex_file_(dex_file),
297       dex_cache_(dex_cache),
298       class_loader_(class_loader),
299       class_def_(class_def),
300       code_item_(code_item),
301       declaring_class_(NULL),
302       interesting_dex_pc_(-1),
303       monitor_enter_dex_pcs_(NULL),
304       have_pending_hard_failure_(false),
305       have_pending_runtime_throw_failure_(false),
306       new_instance_count_(0),
307       monitor_enter_count_(0),
308       can_load_classes_(can_load_classes),
309       allow_soft_failures_(allow_soft_failures),
310       has_check_casts_(false),
311       has_virtual_or_interface_invokes_(false) {
312   DCHECK(class_def != NULL);
313 }
314 
FindLocksAtDexPc(mirror::ArtMethod * m,uint32_t dex_pc,std::vector<uint32_t> & monitor_enter_dex_pcs)315 void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc,
316                                       std::vector<uint32_t>& monitor_enter_dex_pcs) {
317   MethodHelper mh(m);
318   MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
319                           &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(),
320                           m, m->GetAccessFlags(), false, true);
321   verifier.interesting_dex_pc_ = dex_pc;
322   verifier.monitor_enter_dex_pcs_ = &monitor_enter_dex_pcs;
323   verifier.FindLocksAtDexPc();
324 }
325 
FindLocksAtDexPc()326 void MethodVerifier::FindLocksAtDexPc() {
327   CHECK(monitor_enter_dex_pcs_ != NULL);
328   CHECK(code_item_ != NULL);  // This only makes sense for methods with code.
329 
330   // Strictly speaking, we ought to be able to get away with doing a subset of the full method
331   // verification. In practice, the phase we want relies on data structures set up by all the
332   // earlier passes, so we just run the full method verification and bail out early when we've
333   // got what we wanted.
334   Verify();
335 }
336 
FindAccessedFieldAtDexPc(mirror::ArtMethod * m,uint32_t dex_pc)337 mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m,
338                                                         uint32_t dex_pc) {
339   MethodHelper mh(m);
340   MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
341                           &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(),
342                           m, m->GetAccessFlags(), false, true);
343   return verifier.FindAccessedFieldAtDexPc(dex_pc);
344 }
345 
FindAccessedFieldAtDexPc(uint32_t dex_pc)346 mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(uint32_t dex_pc) {
347   CHECK(code_item_ != NULL);  // This only makes sense for methods with code.
348 
349   // Strictly speaking, we ought to be able to get away with doing a subset of the full method
350   // verification. In practice, the phase we want relies on data structures set up by all the
351   // earlier passes, so we just run the full method verification and bail out early when we've
352   // got what we wanted.
353   bool success = Verify();
354   if (!success) {
355     return NULL;
356   }
357   RegisterLine* register_line = reg_table_.GetLine(dex_pc);
358   if (register_line == NULL) {
359     return NULL;
360   }
361   const Instruction* inst = Instruction::At(code_item_->insns_ + dex_pc);
362   return GetQuickFieldAccess(inst, register_line);
363 }
364 
FindInvokedMethodAtDexPc(mirror::ArtMethod * m,uint32_t dex_pc)365 mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(mirror::ArtMethod* m,
366                                                                  uint32_t dex_pc) {
367   MethodHelper mh(m);
368   MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
369                           &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(),
370                           m, m->GetAccessFlags(), false, true);
371   return verifier.FindInvokedMethodAtDexPc(dex_pc);
372 }
373 
FindInvokedMethodAtDexPc(uint32_t dex_pc)374 mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(uint32_t dex_pc) {
375   CHECK(code_item_ != NULL);  // This only makes sense for methods with code.
376 
377   // Strictly speaking, we ought to be able to get away with doing a subset of the full method
378   // verification. In practice, the phase we want relies on data structures set up by all the
379   // earlier passes, so we just run the full method verification and bail out early when we've
380   // got what we wanted.
381   bool success = Verify();
382   if (!success) {
383     return NULL;
384   }
385   RegisterLine* register_line = reg_table_.GetLine(dex_pc);
386   if (register_line == NULL) {
387     return NULL;
388   }
389   const Instruction* inst = Instruction::At(code_item_->insns_ + dex_pc);
390   const bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
391   return GetQuickInvokedMethod(inst, register_line, is_range);
392 }
393 
Verify()394 bool MethodVerifier::Verify() {
395   // If there aren't any instructions, make sure that's expected, then exit successfully.
396   if (code_item_ == NULL) {
397     if ((method_access_flags_ & (kAccNative | kAccAbstract)) == 0) {
398       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "zero-length code in concrete non-native method";
399       return false;
400     } else {
401       return true;
402     }
403   }
404   // Sanity-check the register counts. ins + locals = registers, so make sure that ins <= registers.
405   if (code_item_->ins_size_ > code_item_->registers_size_) {
406     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad register counts (ins=" << code_item_->ins_size_
407                                       << " regs=" << code_item_->registers_size_;
408     return false;
409   }
410   // Allocate and initialize an array to hold instruction data.
411   insn_flags_.reset(new InstructionFlags[code_item_->insns_size_in_code_units_]());
412   // Run through the instructions and see if the width checks out.
413   bool result = ComputeWidthsAndCountOps();
414   // Flag instructions guarded by a "try" block and check exception handlers.
415   result = result && ScanTryCatchBlocks();
416   // Perform static instruction verification.
417   result = result && VerifyInstructions();
418   // Perform code-flow analysis and return.
419   return result && VerifyCodeFlow();
420 }
421 
Fail(VerifyError error)422 std::ostream& MethodVerifier::Fail(VerifyError error) {
423   switch (error) {
424     case VERIFY_ERROR_NO_CLASS:
425     case VERIFY_ERROR_NO_FIELD:
426     case VERIFY_ERROR_NO_METHOD:
427     case VERIFY_ERROR_ACCESS_CLASS:
428     case VERIFY_ERROR_ACCESS_FIELD:
429     case VERIFY_ERROR_ACCESS_METHOD:
430     case VERIFY_ERROR_INSTANTIATION:
431     case VERIFY_ERROR_CLASS_CHANGE:
432       if (Runtime::Current()->IsCompiler() || !can_load_classes_) {
433         // If we're optimistically running verification at compile time, turn NO_xxx, ACCESS_xxx,
434         // class change and instantiation errors into soft verification errors so that we re-verify
435         // at runtime. We may fail to find or to agree on access because of not yet available class
436         // loaders, or class loaders that will differ at runtime. In these cases, we don't want to
437         // affect the soundness of the code being compiled. Instead, the generated code runs "slow
438         // paths" that dynamically perform the verification and cause the behavior to be that akin
439         // to an interpreter.
440         error = VERIFY_ERROR_BAD_CLASS_SOFT;
441       } else {
442         // If we fail again at runtime, mark that this instruction would throw and force this
443         // method to be executed using the interpreter with checks.
444         have_pending_runtime_throw_failure_ = true;
445       }
446       break;
447       // Indication that verification should be retried at runtime.
448     case VERIFY_ERROR_BAD_CLASS_SOFT:
449       if (!allow_soft_failures_) {
450         have_pending_hard_failure_ = true;
451       }
452       break;
453       // Hard verification failures at compile time will still fail at runtime, so the class is
454       // marked as rejected to prevent it from being compiled.
455     case VERIFY_ERROR_BAD_CLASS_HARD: {
456       if (Runtime::Current()->IsCompiler()) {
457         ClassReference ref(dex_file_, dex_file_->GetIndexForClassDef(*class_def_));
458         AddRejectedClass(ref);
459       }
460       have_pending_hard_failure_ = true;
461       break;
462     }
463   }
464   failures_.push_back(error);
465   std::string location(StringPrintf("%s: [0x%X]", PrettyMethod(dex_method_idx_, *dex_file_).c_str(),
466                                     work_insn_idx_));
467   std::ostringstream* failure_message = new std::ostringstream(location);
468   failure_messages_.push_back(failure_message);
469   return *failure_message;
470 }
471 
PrependToLastFailMessage(std::string prepend)472 void MethodVerifier::PrependToLastFailMessage(std::string prepend) {
473   size_t failure_num = failure_messages_.size();
474   DCHECK_NE(failure_num, 0U);
475   std::ostringstream* last_fail_message = failure_messages_[failure_num - 1];
476   prepend += last_fail_message->str();
477   failure_messages_[failure_num - 1] = new std::ostringstream(prepend);
478   delete last_fail_message;
479 }
480 
AppendToLastFailMessage(std::string append)481 void MethodVerifier::AppendToLastFailMessage(std::string append) {
482   size_t failure_num = failure_messages_.size();
483   DCHECK_NE(failure_num, 0U);
484   std::ostringstream* last_fail_message = failure_messages_[failure_num - 1];
485   (*last_fail_message) << append;
486 }
487 
ComputeWidthsAndCountOps()488 bool MethodVerifier::ComputeWidthsAndCountOps() {
489   const uint16_t* insns = code_item_->insns_;
490   size_t insns_size = code_item_->insns_size_in_code_units_;
491   const Instruction* inst = Instruction::At(insns);
492   size_t new_instance_count = 0;
493   size_t monitor_enter_count = 0;
494   size_t dex_pc = 0;
495 
496   while (dex_pc < insns_size) {
497     Instruction::Code opcode = inst->Opcode();
498     if (opcode == Instruction::NEW_INSTANCE) {
499       new_instance_count++;
500     } else if (opcode == Instruction::MONITOR_ENTER) {
501       monitor_enter_count++;
502     } else if (opcode == Instruction::CHECK_CAST) {
503       has_check_casts_ = true;
504     } else if ((inst->Opcode() == Instruction::INVOKE_VIRTUAL) ||
505               (inst->Opcode() ==  Instruction::INVOKE_VIRTUAL_RANGE) ||
506               (inst->Opcode() == Instruction::INVOKE_INTERFACE) ||
507               (inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE)) {
508       has_virtual_or_interface_invokes_ = true;
509     }
510     size_t inst_size = inst->SizeInCodeUnits();
511     insn_flags_[dex_pc].SetLengthInCodeUnits(inst_size);
512     dex_pc += inst_size;
513     inst = inst->Next();
514   }
515 
516   if (dex_pc != insns_size) {
517     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "code did not end where expected ("
518                                       << dex_pc << " vs. " << insns_size << ")";
519     return false;
520   }
521 
522   new_instance_count_ = new_instance_count;
523   monitor_enter_count_ = monitor_enter_count;
524   return true;
525 }
526 
ScanTryCatchBlocks()527 bool MethodVerifier::ScanTryCatchBlocks() {
528   uint32_t tries_size = code_item_->tries_size_;
529   if (tries_size == 0) {
530     return true;
531   }
532   uint32_t insns_size = code_item_->insns_size_in_code_units_;
533   const DexFile::TryItem* tries = DexFile::GetTryItems(*code_item_, 0);
534 
535   for (uint32_t idx = 0; idx < tries_size; idx++) {
536     const DexFile::TryItem* try_item = &tries[idx];
537     uint32_t start = try_item->start_addr_;
538     uint32_t end = start + try_item->insn_count_;
539     if ((start >= end) || (start >= insns_size) || (end > insns_size)) {
540       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad exception entry: startAddr=" << start
541                                         << " endAddr=" << end << " (size=" << insns_size << ")";
542       return false;
543     }
544     if (!insn_flags_[start].IsOpcode()) {
545       Fail(VERIFY_ERROR_BAD_CLASS_HARD)
546           << "'try' block starts inside an instruction (" << start << ")";
547       return false;
548     }
549     for (uint32_t dex_pc = start; dex_pc < end;
550         dex_pc += insn_flags_[dex_pc].GetLengthInCodeUnits()) {
551       insn_flags_[dex_pc].SetInTry();
552     }
553   }
554   // Iterate over each of the handlers to verify target addresses.
555   const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
556   uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
557   ClassLinker* linker = Runtime::Current()->GetClassLinker();
558   for (uint32_t idx = 0; idx < handlers_size; idx++) {
559     CatchHandlerIterator iterator(handlers_ptr);
560     for (; iterator.HasNext(); iterator.Next()) {
561       uint32_t dex_pc= iterator.GetHandlerAddress();
562       if (!insn_flags_[dex_pc].IsOpcode()) {
563         Fail(VERIFY_ERROR_BAD_CLASS_HARD)
564             << "exception handler starts at bad address (" << dex_pc << ")";
565         return false;
566       }
567       insn_flags_[dex_pc].SetBranchTarget();
568       // Ensure exception types are resolved so that they don't need resolution to be delivered,
569       // unresolved exception types will be ignored by exception delivery
570       if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) {
571         mirror::Class* exception_type = linker->ResolveType(*dex_file_,
572                                                             iterator.GetHandlerTypeIndex(),
573                                                             dex_cache_, class_loader_);
574         if (exception_type == NULL) {
575           DCHECK(Thread::Current()->IsExceptionPending());
576           Thread::Current()->ClearException();
577         }
578       }
579     }
580     handlers_ptr = iterator.EndDataPointer();
581   }
582   return true;
583 }
584 
VerifyInstructions()585 bool MethodVerifier::VerifyInstructions() {
586   const Instruction* inst = Instruction::At(code_item_->insns_);
587 
588   /* Flag the start of the method as a branch target, and a GC point due to stack overflow errors */
589   insn_flags_[0].SetBranchTarget();
590   insn_flags_[0].SetCompileTimeInfoPoint();
591 
592   uint32_t insns_size = code_item_->insns_size_in_code_units_;
593   for (uint32_t dex_pc = 0; dex_pc < insns_size;) {
594     if (!VerifyInstruction(inst, dex_pc)) {
595       DCHECK_NE(failures_.size(), 0U);
596       return false;
597     }
598     /* Flag instructions that are garbage collection points */
599     // All invoke points are marked as "Throw" points already.
600     // We are relying on this to also count all the invokes as interesting.
601     if (inst->IsBranch() || inst->IsSwitch() || inst->IsThrow()) {
602       insn_flags_[dex_pc].SetCompileTimeInfoPoint();
603     } else if (inst->IsReturn()) {
604       insn_flags_[dex_pc].SetCompileTimeInfoPointAndReturn();
605     }
606     dex_pc += inst->SizeInCodeUnits();
607     inst = inst->Next();
608   }
609   return true;
610 }
611 
VerifyInstruction(const Instruction * inst,uint32_t code_offset)612 bool MethodVerifier::VerifyInstruction(const Instruction* inst, uint32_t code_offset) {
613   DecodedInstruction dec_insn(inst);
614   bool result = true;
615   switch (inst->GetVerifyTypeArgumentA()) {
616     case Instruction::kVerifyRegA:
617       result = result && CheckRegisterIndex(dec_insn.vA);
618       break;
619     case Instruction::kVerifyRegAWide:
620       result = result && CheckWideRegisterIndex(dec_insn.vA);
621       break;
622   }
623   switch (inst->GetVerifyTypeArgumentB()) {
624     case Instruction::kVerifyRegB:
625       result = result && CheckRegisterIndex(dec_insn.vB);
626       break;
627     case Instruction::kVerifyRegBField:
628       result = result && CheckFieldIndex(dec_insn.vB);
629       break;
630     case Instruction::kVerifyRegBMethod:
631       result = result && CheckMethodIndex(dec_insn.vB);
632       break;
633     case Instruction::kVerifyRegBNewInstance:
634       result = result && CheckNewInstance(dec_insn.vB);
635       break;
636     case Instruction::kVerifyRegBString:
637       result = result && CheckStringIndex(dec_insn.vB);
638       break;
639     case Instruction::kVerifyRegBType:
640       result = result && CheckTypeIndex(dec_insn.vB);
641       break;
642     case Instruction::kVerifyRegBWide:
643       result = result && CheckWideRegisterIndex(dec_insn.vB);
644       break;
645   }
646   switch (inst->GetVerifyTypeArgumentC()) {
647     case Instruction::kVerifyRegC:
648       result = result && CheckRegisterIndex(dec_insn.vC);
649       break;
650     case Instruction::kVerifyRegCField:
651       result = result && CheckFieldIndex(dec_insn.vC);
652       break;
653     case Instruction::kVerifyRegCNewArray:
654       result = result && CheckNewArray(dec_insn.vC);
655       break;
656     case Instruction::kVerifyRegCType:
657       result = result && CheckTypeIndex(dec_insn.vC);
658       break;
659     case Instruction::kVerifyRegCWide:
660       result = result && CheckWideRegisterIndex(dec_insn.vC);
661       break;
662   }
663   switch (inst->GetVerifyExtraFlags()) {
664     case Instruction::kVerifyArrayData:
665       result = result && CheckArrayData(code_offset);
666       break;
667     case Instruction::kVerifyBranchTarget:
668       result = result && CheckBranchTarget(code_offset);
669       break;
670     case Instruction::kVerifySwitchTargets:
671       result = result && CheckSwitchTargets(code_offset);
672       break;
673     case Instruction::kVerifyVarArg:
674       result = result && CheckVarArgRegs(dec_insn.vA, dec_insn.arg);
675       break;
676     case Instruction::kVerifyVarArgRange:
677       result = result && CheckVarArgRangeRegs(dec_insn.vA, dec_insn.vC);
678       break;
679     case Instruction::kVerifyError:
680       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected opcode " << inst->Name();
681       result = false;
682       break;
683   }
684   return result;
685 }
686 
CheckRegisterIndex(uint32_t idx)687 bool MethodVerifier::CheckRegisterIndex(uint32_t idx) {
688   if (idx >= code_item_->registers_size_) {
689     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "register index out of range (" << idx << " >= "
690                                       << code_item_->registers_size_ << ")";
691     return false;
692   }
693   return true;
694 }
695 
CheckWideRegisterIndex(uint32_t idx)696 bool MethodVerifier::CheckWideRegisterIndex(uint32_t idx) {
697   if (idx + 1 >= code_item_->registers_size_) {
698     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "wide register index out of range (" << idx
699                                       << "+1 >= " << code_item_->registers_size_ << ")";
700     return false;
701   }
702   return true;
703 }
704 
CheckFieldIndex(uint32_t idx)705 bool MethodVerifier::CheckFieldIndex(uint32_t idx) {
706   if (idx >= dex_file_->GetHeader().field_ids_size_) {
707     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad field index " << idx << " (max "
708                                       << dex_file_->GetHeader().field_ids_size_ << ")";
709     return false;
710   }
711   return true;
712 }
713 
CheckMethodIndex(uint32_t idx)714 bool MethodVerifier::CheckMethodIndex(uint32_t idx) {
715   if (idx >= dex_file_->GetHeader().method_ids_size_) {
716     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad method index " << idx << " (max "
717                                       << dex_file_->GetHeader().method_ids_size_ << ")";
718     return false;
719   }
720   return true;
721 }
722 
CheckNewInstance(uint32_t idx)723 bool MethodVerifier::CheckNewInstance(uint32_t idx) {
724   if (idx >= dex_file_->GetHeader().type_ids_size_) {
725     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad type index " << idx << " (max "
726                                       << dex_file_->GetHeader().type_ids_size_ << ")";
727     return false;
728   }
729   // We don't need the actual class, just a pointer to the class name.
730   const char* descriptor = dex_file_->StringByTypeIdx(idx);
731   if (descriptor[0] != 'L') {
732     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "can't call new-instance on type '" << descriptor << "'";
733     return false;
734   }
735   return true;
736 }
737 
CheckStringIndex(uint32_t idx)738 bool MethodVerifier::CheckStringIndex(uint32_t idx) {
739   if (idx >= dex_file_->GetHeader().string_ids_size_) {
740     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad string index " << idx << " (max "
741                                       << dex_file_->GetHeader().string_ids_size_ << ")";
742     return false;
743   }
744   return true;
745 }
746 
CheckTypeIndex(uint32_t idx)747 bool MethodVerifier::CheckTypeIndex(uint32_t idx) {
748   if (idx >= dex_file_->GetHeader().type_ids_size_) {
749     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad type index " << idx << " (max "
750                                       << dex_file_->GetHeader().type_ids_size_ << ")";
751     return false;
752   }
753   return true;
754 }
755 
CheckNewArray(uint32_t idx)756 bool MethodVerifier::CheckNewArray(uint32_t idx) {
757   if (idx >= dex_file_->GetHeader().type_ids_size_) {
758     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad type index " << idx << " (max "
759                                       << dex_file_->GetHeader().type_ids_size_ << ")";
760     return false;
761   }
762   int bracket_count = 0;
763   const char* descriptor = dex_file_->StringByTypeIdx(idx);
764   const char* cp = descriptor;
765   while (*cp++ == '[') {
766     bracket_count++;
767   }
768   if (bracket_count == 0) {
769     /* The given class must be an array type. */
770     Fail(VERIFY_ERROR_BAD_CLASS_HARD)
771         << "can't new-array class '" << descriptor << "' (not an array)";
772     return false;
773   } else if (bracket_count > 255) {
774     /* It is illegal to create an array of more than 255 dimensions. */
775     Fail(VERIFY_ERROR_BAD_CLASS_HARD)
776         << "can't new-array class '" << descriptor << "' (exceeds limit)";
777     return false;
778   }
779   return true;
780 }
781 
CheckArrayData(uint32_t cur_offset)782 bool MethodVerifier::CheckArrayData(uint32_t cur_offset) {
783   const uint32_t insn_count = code_item_->insns_size_in_code_units_;
784   const uint16_t* insns = code_item_->insns_ + cur_offset;
785   const uint16_t* array_data;
786   int32_t array_data_offset;
787 
788   DCHECK_LT(cur_offset, insn_count);
789   /* make sure the start of the array data table is in range */
790   array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
791   if ((int32_t) cur_offset + array_data_offset < 0 ||
792       cur_offset + array_data_offset + 2 >= insn_count) {
793     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid array data start: at " << cur_offset
794                                       << ", data offset " << array_data_offset
795                                       << ", count " << insn_count;
796     return false;
797   }
798   /* offset to array data table is a relative branch-style offset */
799   array_data = insns + array_data_offset;
800   /* make sure the table is 32-bit aligned */
801   if ((((uint32_t) array_data) & 0x03) != 0) {
802     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unaligned array data table: at " << cur_offset
803                                       << ", data offset " << array_data_offset;
804     return false;
805   }
806   uint32_t value_width = array_data[1];
807   uint32_t value_count = *reinterpret_cast<const uint32_t*>(&array_data[2]);
808   uint32_t table_size = 4 + (value_width * value_count + 1) / 2;
809   /* make sure the end of the switch is in range */
810   if (cur_offset + array_data_offset + table_size > insn_count) {
811     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid array data end: at " << cur_offset
812                                       << ", data offset " << array_data_offset << ", end "
813                                       << cur_offset + array_data_offset + table_size
814                                       << ", count " << insn_count;
815     return false;
816   }
817   return true;
818 }
819 
CheckBranchTarget(uint32_t cur_offset)820 bool MethodVerifier::CheckBranchTarget(uint32_t cur_offset) {
821   int32_t offset;
822   bool isConditional, selfOkay;
823   if (!GetBranchOffset(cur_offset, &offset, &isConditional, &selfOkay)) {
824     return false;
825   }
826   if (!selfOkay && offset == 0) {
827     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "branch offset of zero not allowed at"
828                                       << reinterpret_cast<void*>(cur_offset);
829     return false;
830   }
831   // Check for 32-bit overflow. This isn't strictly necessary if we can depend on the runtime
832   // to have identical "wrap-around" behavior, but it's unwise to depend on that.
833   if (((int64_t) cur_offset + (int64_t) offset) != (int64_t) (cur_offset + offset)) {
834     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "branch target overflow "
835                                       << reinterpret_cast<void*>(cur_offset) << " +" << offset;
836     return false;
837   }
838   const uint32_t insn_count = code_item_->insns_size_in_code_units_;
839   int32_t abs_offset = cur_offset + offset;
840   if (abs_offset < 0 ||
841       (uint32_t) abs_offset >= insn_count ||
842       !insn_flags_[abs_offset].IsOpcode()) {
843     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid branch target " << offset << " (-> "
844                                       << reinterpret_cast<void*>(abs_offset) << ") at "
845                                       << reinterpret_cast<void*>(cur_offset);
846     return false;
847   }
848   insn_flags_[abs_offset].SetBranchTarget();
849   return true;
850 }
851 
GetBranchOffset(uint32_t cur_offset,int32_t * pOffset,bool * pConditional,bool * selfOkay)852 bool MethodVerifier::GetBranchOffset(uint32_t cur_offset, int32_t* pOffset, bool* pConditional,
853                                   bool* selfOkay) {
854   const uint16_t* insns = code_item_->insns_ + cur_offset;
855   *pConditional = false;
856   *selfOkay = false;
857   switch (*insns & 0xff) {
858     case Instruction::GOTO:
859       *pOffset = ((int16_t) *insns) >> 8;
860       break;
861     case Instruction::GOTO_32:
862       *pOffset = insns[1] | (((uint32_t) insns[2]) << 16);
863       *selfOkay = true;
864       break;
865     case Instruction::GOTO_16:
866       *pOffset = (int16_t) insns[1];
867       break;
868     case Instruction::IF_EQ:
869     case Instruction::IF_NE:
870     case Instruction::IF_LT:
871     case Instruction::IF_GE:
872     case Instruction::IF_GT:
873     case Instruction::IF_LE:
874     case Instruction::IF_EQZ:
875     case Instruction::IF_NEZ:
876     case Instruction::IF_LTZ:
877     case Instruction::IF_GEZ:
878     case Instruction::IF_GTZ:
879     case Instruction::IF_LEZ:
880       *pOffset = (int16_t) insns[1];
881       *pConditional = true;
882       break;
883     default:
884       return false;
885       break;
886   }
887   return true;
888 }
889 
CheckSwitchTargets(uint32_t cur_offset)890 bool MethodVerifier::CheckSwitchTargets(uint32_t cur_offset) {
891   const uint32_t insn_count = code_item_->insns_size_in_code_units_;
892   DCHECK_LT(cur_offset, insn_count);
893   const uint16_t* insns = code_item_->insns_ + cur_offset;
894   /* make sure the start of the switch is in range */
895   int32_t switch_offset = insns[1] | ((int32_t) insns[2]) << 16;
896   if ((int32_t) cur_offset + switch_offset < 0 || cur_offset + switch_offset + 2 >= insn_count) {
897     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid switch start: at " << cur_offset
898                                       << ", switch offset " << switch_offset
899                                       << ", count " << insn_count;
900     return false;
901   }
902   /* offset to switch table is a relative branch-style offset */
903   const uint16_t* switch_insns = insns + switch_offset;
904   /* make sure the table is 32-bit aligned */
905   if ((((uint32_t) switch_insns) & 0x03) != 0) {
906     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unaligned switch table: at " << cur_offset
907                                       << ", switch offset " << switch_offset;
908     return false;
909   }
910   uint32_t switch_count = switch_insns[1];
911   int32_t keys_offset, targets_offset;
912   uint16_t expected_signature;
913   if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
914     /* 0=sig, 1=count, 2/3=firstKey */
915     targets_offset = 4;
916     keys_offset = -1;
917     expected_signature = Instruction::kPackedSwitchSignature;
918   } else {
919     /* 0=sig, 1=count, 2..count*2 = keys */
920     keys_offset = 2;
921     targets_offset = 2 + 2 * switch_count;
922     expected_signature = Instruction::kSparseSwitchSignature;
923   }
924   uint32_t table_size = targets_offset + switch_count * 2;
925   if (switch_insns[0] != expected_signature) {
926     Fail(VERIFY_ERROR_BAD_CLASS_HARD)
927         << StringPrintf("wrong signature for switch table (%x, wanted %x)",
928                         switch_insns[0], expected_signature);
929     return false;
930   }
931   /* make sure the end of the switch is in range */
932   if (cur_offset + switch_offset + table_size > (uint32_t) insn_count) {
933     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid switch end: at " << cur_offset
934                                       << ", switch offset " << switch_offset
935                                       << ", end " << (cur_offset + switch_offset + table_size)
936                                       << ", count " << insn_count;
937     return false;
938   }
939   /* for a sparse switch, verify the keys are in ascending order */
940   if (keys_offset > 0 && switch_count > 1) {
941     int32_t last_key = switch_insns[keys_offset] | (switch_insns[keys_offset + 1] << 16);
942     for (uint32_t targ = 1; targ < switch_count; targ++) {
943       int32_t key = (int32_t) switch_insns[keys_offset + targ * 2] |
944                     (int32_t) (switch_insns[keys_offset + targ * 2 + 1] << 16);
945       if (key <= last_key) {
946         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid packed switch: last key=" << last_key
947                                           << ", this=" << key;
948         return false;
949       }
950       last_key = key;
951     }
952   }
953   /* verify each switch target */
954   for (uint32_t targ = 0; targ < switch_count; targ++) {
955     int32_t offset = (int32_t) switch_insns[targets_offset + targ * 2] |
956                      (int32_t) (switch_insns[targets_offset + targ * 2 + 1] << 16);
957     int32_t abs_offset = cur_offset + offset;
958     if (abs_offset < 0 ||
959         abs_offset >= (int32_t) insn_count ||
960         !insn_flags_[abs_offset].IsOpcode()) {
961       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid switch target " << offset
962                                         << " (-> " << reinterpret_cast<void*>(abs_offset) << ") at "
963                                         << reinterpret_cast<void*>(cur_offset)
964                                         << "[" << targ << "]";
965       return false;
966     }
967     insn_flags_[abs_offset].SetBranchTarget();
968   }
969   return true;
970 }
971 
CheckVarArgRegs(uint32_t vA,uint32_t arg[])972 bool MethodVerifier::CheckVarArgRegs(uint32_t vA, uint32_t arg[]) {
973   if (vA > 5) {
974     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid arg count (" << vA << ") in non-range invoke)";
975     return false;
976   }
977   uint16_t registers_size = code_item_->registers_size_;
978   for (uint32_t idx = 0; idx < vA; idx++) {
979     if (arg[idx] >= registers_size) {
980       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid reg index (" << arg[idx]
981                                         << ") in non-range invoke (>= " << registers_size << ")";
982       return false;
983     }
984   }
985 
986   return true;
987 }
988 
CheckVarArgRangeRegs(uint32_t vA,uint32_t vC)989 bool MethodVerifier::CheckVarArgRangeRegs(uint32_t vA, uint32_t vC) {
990   uint16_t registers_size = code_item_->registers_size_;
991   // vA/vC are unsigned 8-bit/16-bit quantities for /range instructions, so there's no risk of
992   // integer overflow when adding them here.
993   if (vA + vC > registers_size) {
994     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid reg index " << vA << "+" << vC
995                                       << " in range invoke (> " << registers_size << ")";
996     return false;
997   }
998   return true;
999 }
1000 
CreateLengthPrefixedDexGcMap(const std::vector<uint8_t> & gc_map)1001 static const std::vector<uint8_t>* CreateLengthPrefixedDexGcMap(
1002     const std::vector<uint8_t>& gc_map) {
1003   std::vector<uint8_t>* length_prefixed_gc_map = new std::vector<uint8_t>;
1004   length_prefixed_gc_map->reserve(gc_map.size() + 4);
1005   length_prefixed_gc_map->push_back((gc_map.size() & 0xff000000) >> 24);
1006   length_prefixed_gc_map->push_back((gc_map.size() & 0x00ff0000) >> 16);
1007   length_prefixed_gc_map->push_back((gc_map.size() & 0x0000ff00) >> 8);
1008   length_prefixed_gc_map->push_back((gc_map.size() & 0x000000ff) >> 0);
1009   length_prefixed_gc_map->insert(length_prefixed_gc_map->end(),
1010                                  gc_map.begin(),
1011                                  gc_map.end());
1012   DCHECK_EQ(gc_map.size() + 4, length_prefixed_gc_map->size());
1013   DCHECK_EQ(gc_map.size(),
1014             static_cast<size_t>((length_prefixed_gc_map->at(0) << 24) |
1015                                 (length_prefixed_gc_map->at(1) << 16) |
1016                                 (length_prefixed_gc_map->at(2) << 8) |
1017                                 (length_prefixed_gc_map->at(3) << 0)));
1018   return length_prefixed_gc_map;
1019 }
1020 
VerifyCodeFlow()1021 bool MethodVerifier::VerifyCodeFlow() {
1022   uint16_t registers_size = code_item_->registers_size_;
1023   uint32_t insns_size = code_item_->insns_size_in_code_units_;
1024 
1025   if (registers_size * insns_size > 4*1024*1024) {
1026     LOG(WARNING) << "warning: method is huge (regs=" << registers_size
1027                  << " insns_size=" << insns_size << ")";
1028   }
1029   /* Create and initialize table holding register status */
1030   reg_table_.Init(kTrackCompilerInterestPoints,
1031                   insn_flags_.get(),
1032                   insns_size,
1033                   registers_size,
1034                   this);
1035 
1036 
1037   work_line_.reset(new RegisterLine(registers_size, this));
1038   saved_line_.reset(new RegisterLine(registers_size, this));
1039 
1040   /* Initialize register types of method arguments. */
1041   if (!SetTypesFromSignature()) {
1042     DCHECK_NE(failures_.size(), 0U);
1043     std::string prepend("Bad signature in ");
1044     prepend += PrettyMethod(dex_method_idx_, *dex_file_);
1045     PrependToLastFailMessage(prepend);
1046     return false;
1047   }
1048   /* Perform code flow verification. */
1049   if (!CodeFlowVerifyMethod()) {
1050     DCHECK_NE(failures_.size(), 0U);
1051     return false;
1052   }
1053 
1054   // Compute information for compiler.
1055   if (Runtime::Current()->IsCompiler()) {
1056     MethodReference ref(dex_file_, dex_method_idx_);
1057     bool compile = IsCandidateForCompilation(ref, method_access_flags_);
1058     if (compile) {
1059       /* Generate a register map and add it to the method. */
1060       UniquePtr<const std::vector<uint8_t> > map(GenerateGcMap());
1061       if (map.get() == NULL) {
1062         DCHECK_NE(failures_.size(), 0U);
1063         return false;  // Not a real failure, but a failure to encode
1064       }
1065       if (kIsDebugBuild) {
1066         VerifyGcMap(*map);
1067       }
1068       const std::vector<uint8_t>* dex_gc_map = CreateLengthPrefixedDexGcMap(*(map.get()));
1069       verifier::MethodVerifier::SetDexGcMap(ref, *dex_gc_map);
1070     }
1071 
1072     if (has_check_casts_) {
1073       MethodVerifier::MethodSafeCastSet* method_to_safe_casts = GenerateSafeCastSet();
1074       if (method_to_safe_casts != NULL) {
1075         SetSafeCastMap(ref, method_to_safe_casts);
1076       }
1077     }
1078 
1079     if (has_virtual_or_interface_invokes_) {
1080       MethodVerifier::PcToConcreteMethodMap* pc_to_concrete_method = GenerateDevirtMap();
1081       if (pc_to_concrete_method != NULL) {
1082         SetDevirtMap(ref, pc_to_concrete_method);
1083       }
1084     }
1085   }
1086   return true;
1087 }
1088 
DumpFailures(std::ostream & os)1089 std::ostream& MethodVerifier::DumpFailures(std::ostream& os) {
1090   DCHECK_EQ(failures_.size(), failure_messages_.size());
1091   if (VLOG_IS_ON(verifier)) {
1092       for (size_t i = 0; i < failures_.size(); ++i) {
1093           os << failure_messages_[i]->str() << "\n";
1094       }
1095   }
1096   return os;
1097 }
1098 
MethodVerifierGdbDump(MethodVerifier * v)1099 extern "C" void MethodVerifierGdbDump(MethodVerifier* v)
1100     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1101   v->Dump(std::cerr);
1102 }
1103 
Dump(std::ostream & os)1104 void MethodVerifier::Dump(std::ostream& os) {
1105   if (code_item_ == NULL) {
1106     os << "Native method\n";
1107     return;
1108   }
1109   {
1110     os << "Register Types:\n";
1111     Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
1112     std::ostream indent_os(&indent_filter);
1113     reg_types_.Dump(indent_os);
1114   }
1115   os << "Dumping instructions and register lines:\n";
1116   Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
1117   std::ostream indent_os(&indent_filter);
1118   const Instruction* inst = Instruction::At(code_item_->insns_);
1119   for (size_t dex_pc = 0; dex_pc < code_item_->insns_size_in_code_units_;
1120       dex_pc += insn_flags_[dex_pc].GetLengthInCodeUnits()) {
1121     RegisterLine* reg_line = reg_table_.GetLine(dex_pc);
1122     if (reg_line != NULL) {
1123       indent_os << reg_line->Dump() << "\n";
1124     }
1125     indent_os << StringPrintf("0x%04zx", dex_pc) << ": " << insn_flags_[dex_pc].ToString() << " ";
1126     const bool kDumpHexOfInstruction = false;
1127     if (kDumpHexOfInstruction) {
1128       indent_os << inst->DumpHex(5) << " ";
1129     }
1130     indent_os << inst->DumpString(dex_file_) << "\n";
1131     inst = inst->Next();
1132   }
1133 }
1134 
IsPrimitiveDescriptor(char descriptor)1135 static bool IsPrimitiveDescriptor(char descriptor) {
1136   switch (descriptor) {
1137     case 'I':
1138     case 'C':
1139     case 'S':
1140     case 'B':
1141     case 'Z':
1142     case 'F':
1143     case 'D':
1144     case 'J':
1145       return true;
1146     default:
1147       return false;
1148   }
1149 }
1150 
SetTypesFromSignature()1151 bool MethodVerifier::SetTypesFromSignature() {
1152   RegisterLine* reg_line = reg_table_.GetLine(0);
1153   int arg_start = code_item_->registers_size_ - code_item_->ins_size_;
1154   size_t expected_args = code_item_->ins_size_;   /* long/double count as two */
1155 
1156   DCHECK_GE(arg_start, 0);      /* should have been verified earlier */
1157   // Include the "this" pointer.
1158   size_t cur_arg = 0;
1159   if (!IsStatic()) {
1160     // If this is a constructor for a class other than java.lang.Object, mark the first ("this")
1161     // argument as uninitialized. This restricts field access until the superclass constructor is
1162     // called.
1163     const RegType& declaring_class = GetDeclaringClass();
1164     if (IsConstructor() && !declaring_class.IsJavaLangObject()) {
1165       reg_line->SetRegisterType(arg_start + cur_arg,
1166                                 reg_types_.UninitializedThisArgument(declaring_class));
1167     } else {
1168       reg_line->SetRegisterType(arg_start + cur_arg, declaring_class);
1169     }
1170     cur_arg++;
1171   }
1172 
1173   const DexFile::ProtoId& proto_id =
1174       dex_file_->GetMethodPrototype(dex_file_->GetMethodId(dex_method_idx_));
1175   DexFileParameterIterator iterator(*dex_file_, proto_id);
1176 
1177   for (; iterator.HasNext(); iterator.Next()) {
1178     const char* descriptor = iterator.GetDescriptor();
1179     if (descriptor == NULL) {
1180       LOG(FATAL) << "Null descriptor";
1181     }
1182     if (cur_arg >= expected_args) {
1183       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected " << expected_args
1184                                         << " args, found more (" << descriptor << ")";
1185       return false;
1186     }
1187     switch (descriptor[0]) {
1188       case 'L':
1189       case '[':
1190         // We assume that reference arguments are initialized. The only way it could be otherwise
1191         // (assuming the caller was verified) is if the current method is <init>, but in that case
1192         // it's effectively considered initialized the instant we reach here (in the sense that we
1193         // can return without doing anything or call virtual methods).
1194         {
1195           const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
1196           reg_line->SetRegisterType(arg_start + cur_arg, reg_type);
1197         }
1198         break;
1199       case 'Z':
1200         reg_line->SetRegisterType(arg_start + cur_arg, reg_types_.Boolean());
1201         break;
1202       case 'C':
1203         reg_line->SetRegisterType(arg_start + cur_arg, reg_types_.Char());
1204         break;
1205       case 'B':
1206         reg_line->SetRegisterType(arg_start + cur_arg, reg_types_.Byte());
1207         break;
1208       case 'I':
1209         reg_line->SetRegisterType(arg_start + cur_arg, reg_types_.Integer());
1210         break;
1211       case 'S':
1212         reg_line->SetRegisterType(arg_start + cur_arg, reg_types_.Short());
1213         break;
1214       case 'F':
1215         reg_line->SetRegisterType(arg_start + cur_arg, reg_types_.Float());
1216         break;
1217       case 'J':
1218       case 'D': {
1219         const RegType& lo_half = descriptor[0] == 'J' ? reg_types_.LongLo() : reg_types_.DoubleLo();
1220         const RegType& hi_half = descriptor[0] == 'J' ? reg_types_.LongHi() : reg_types_.DoubleHi();
1221         reg_line->SetRegisterTypeWide(arg_start + cur_arg, lo_half, hi_half);
1222         cur_arg++;
1223         break;
1224       }
1225       default:
1226         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected signature type char '"
1227                                           << descriptor << "'";
1228         return false;
1229     }
1230     cur_arg++;
1231   }
1232   if (cur_arg != expected_args) {
1233     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected " << expected_args
1234                                       << " arguments, found " << cur_arg;
1235     return false;
1236   }
1237   const char* descriptor = dex_file_->GetReturnTypeDescriptor(proto_id);
1238   // Validate return type. We don't do the type lookup; just want to make sure that it has the right
1239   // format. Only major difference from the method argument format is that 'V' is supported.
1240   bool result;
1241   if (IsPrimitiveDescriptor(descriptor[0]) || descriptor[0] == 'V') {
1242     result = descriptor[1] == '\0';
1243   } else if (descriptor[0] == '[') {  // single/multi-dimensional array of object/primitive
1244     size_t i = 0;
1245     do {
1246       i++;
1247     } while (descriptor[i] == '[');  // process leading [
1248     if (descriptor[i] == 'L') {  // object array
1249       do {
1250         i++;  // find closing ;
1251       } while (descriptor[i] != ';' && descriptor[i] != '\0');
1252       result = descriptor[i] == ';';
1253     } else {  // primitive array
1254       result = IsPrimitiveDescriptor(descriptor[i]) && descriptor[i + 1] == '\0';
1255     }
1256   } else if (descriptor[0] == 'L') {
1257     // could be more thorough here, but shouldn't be required
1258     size_t i = 0;
1259     do {
1260       i++;
1261     } while (descriptor[i] != ';' && descriptor[i] != '\0');
1262     result = descriptor[i] == ';';
1263   } else {
1264     result = false;
1265   }
1266   if (!result) {
1267     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected char in return type descriptor '"
1268                                       << descriptor << "'";
1269   }
1270   return result;
1271 }
1272 
CodeFlowVerifyMethod()1273 bool MethodVerifier::CodeFlowVerifyMethod() {
1274   const uint16_t* insns = code_item_->insns_;
1275   const uint32_t insns_size = code_item_->insns_size_in_code_units_;
1276 
1277   /* Begin by marking the first instruction as "changed". */
1278   insn_flags_[0].SetChanged();
1279   uint32_t start_guess = 0;
1280 
1281   /* Continue until no instructions are marked "changed". */
1282   while (true) {
1283     // Find the first marked one. Use "start_guess" as a way to find one quickly.
1284     uint32_t insn_idx = start_guess;
1285     for (; insn_idx < insns_size; insn_idx++) {
1286       if (insn_flags_[insn_idx].IsChanged())
1287         break;
1288     }
1289     if (insn_idx == insns_size) {
1290       if (start_guess != 0) {
1291         /* try again, starting from the top */
1292         start_guess = 0;
1293         continue;
1294       } else {
1295         /* all flags are clear */
1296         break;
1297       }
1298     }
1299     // We carry the working set of registers from instruction to instruction. If this address can
1300     // be the target of a branch (or throw) instruction, or if we're skipping around chasing
1301     // "changed" flags, we need to load the set of registers from the table.
1302     // Because we always prefer to continue on to the next instruction, we should never have a
1303     // situation where we have a stray "changed" flag set on an instruction that isn't a branch
1304     // target.
1305     work_insn_idx_ = insn_idx;
1306     if (insn_flags_[insn_idx].IsBranchTarget()) {
1307       work_line_->CopyFromLine(reg_table_.GetLine(insn_idx));
1308     } else {
1309 #ifndef NDEBUG
1310       /*
1311        * Sanity check: retrieve the stored register line (assuming
1312        * a full table) and make sure it actually matches.
1313        */
1314       RegisterLine* register_line = reg_table_.GetLine(insn_idx);
1315       if (register_line != NULL) {
1316         if (work_line_->CompareLine(register_line) != 0) {
1317           Dump(std::cout);
1318           std::cout << info_messages_.str();
1319           LOG(FATAL) << "work_line diverged in " << PrettyMethod(dex_method_idx_, *dex_file_)
1320                      << "@" << reinterpret_cast<void*>(work_insn_idx_) << "\n"
1321                      << " work_line=" << *work_line_ << "\n"
1322                      << "  expected=" << *register_line;
1323         }
1324       }
1325 #endif
1326     }
1327     if (!CodeFlowVerifyInstruction(&start_guess)) {
1328       std::string prepend(PrettyMethod(dex_method_idx_, *dex_file_));
1329       prepend += " failed to verify: ";
1330       PrependToLastFailMessage(prepend);
1331       return false;
1332     }
1333     /* Clear "changed" and mark as visited. */
1334     insn_flags_[insn_idx].SetVisited();
1335     insn_flags_[insn_idx].ClearChanged();
1336   }
1337 
1338   if (gDebugVerify) {
1339     /*
1340      * Scan for dead code. There's nothing "evil" about dead code
1341      * (besides the wasted space), but it indicates a flaw somewhere
1342      * down the line, possibly in the verifier.
1343      *
1344      * If we've substituted "always throw" instructions into the stream,
1345      * we are almost certainly going to have some dead code.
1346      */
1347     int dead_start = -1;
1348     uint32_t insn_idx = 0;
1349     for (; insn_idx < insns_size; insn_idx += insn_flags_[insn_idx].GetLengthInCodeUnits()) {
1350       /*
1351        * Switch-statement data doesn't get "visited" by scanner. It
1352        * may or may not be preceded by a padding NOP (for alignment).
1353        */
1354       if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
1355           insns[insn_idx] == Instruction::kSparseSwitchSignature ||
1356           insns[insn_idx] == Instruction::kArrayDataSignature ||
1357           (insns[insn_idx] == Instruction::NOP && (insn_idx + 1 < insns_size) &&
1358            (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
1359             insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
1360             insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
1361         insn_flags_[insn_idx].SetVisited();
1362       }
1363 
1364       if (!insn_flags_[insn_idx].IsVisited()) {
1365         if (dead_start < 0)
1366           dead_start = insn_idx;
1367       } else if (dead_start >= 0) {
1368         LogVerifyInfo() << "dead code " << reinterpret_cast<void*>(dead_start)
1369                         << "-" << reinterpret_cast<void*>(insn_idx - 1);
1370         dead_start = -1;
1371       }
1372     }
1373     if (dead_start >= 0) {
1374       LogVerifyInfo() << "dead code " << reinterpret_cast<void*>(dead_start)
1375                       << "-" << reinterpret_cast<void*>(insn_idx - 1);
1376     }
1377     // To dump the state of the verify after a method, do something like:
1378     // if (PrettyMethod(dex_method_idx_, *dex_file_) ==
1379     //     "boolean java.lang.String.equals(java.lang.Object)") {
1380     //   LOG(INFO) << info_messages_.str();
1381     // }
1382   }
1383   return true;
1384 }
1385 
CodeFlowVerifyInstruction(uint32_t * start_guess)1386 bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
1387   // If we're doing FindLocksAtDexPc, check whether we're at the dex pc we care about.
1388   // We want the state _before_ the instruction, for the case where the dex pc we're
1389   // interested in is itself a monitor-enter instruction (which is a likely place
1390   // for a thread to be suspended).
1391   if (monitor_enter_dex_pcs_ != NULL && work_insn_idx_ == interesting_dex_pc_) {
1392     monitor_enter_dex_pcs_->clear();  // The new work line is more accurate than the previous one.
1393     for (size_t i = 0; i < work_line_->GetMonitorEnterCount(); ++i) {
1394       monitor_enter_dex_pcs_->push_back(work_line_->GetMonitorEnterDexPc(i));
1395     }
1396   }
1397 
1398   /*
1399    * Once we finish decoding the instruction, we need to figure out where
1400    * we can go from here. There are three possible ways to transfer
1401    * control to another statement:
1402    *
1403    * (1) Continue to the next instruction. Applies to all but
1404    *     unconditional branches, method returns, and exception throws.
1405    * (2) Branch to one or more possible locations. Applies to branches
1406    *     and switch statements.
1407    * (3) Exception handlers. Applies to any instruction that can
1408    *     throw an exception that is handled by an encompassing "try"
1409    *     block.
1410    *
1411    * We can also return, in which case there is no successor instruction
1412    * from this point.
1413    *
1414    * The behavior can be determined from the opcode flags.
1415    */
1416   const uint16_t* insns = code_item_->insns_ + work_insn_idx_;
1417   const Instruction* inst = Instruction::At(insns);
1418   int opcode_flags = Instruction::FlagsOf(inst->Opcode());
1419 
1420   int32_t branch_target = 0;
1421   bool just_set_result = false;
1422   if (gDebugVerify) {
1423     // Generate processing back trace to debug verifier
1424     LogVerifyInfo() << "Processing " << inst->DumpString(dex_file_) << "\n"
1425                     << *work_line_.get() << "\n";
1426   }
1427 
1428   /*
1429    * Make a copy of the previous register state. If the instruction
1430    * can throw an exception, we will copy/merge this into the "catch"
1431    * address rather than work_line, because we don't want the result
1432    * from the "successful" code path (e.g. a check-cast that "improves"
1433    * a type) to be visible to the exception handler.
1434    */
1435   if ((opcode_flags & Instruction::kThrow) != 0 && CurrentInsnFlags()->IsInTry()) {
1436     saved_line_->CopyFromLine(work_line_.get());
1437   } else {
1438 #ifndef NDEBUG
1439     saved_line_->FillWithGarbage();
1440 #endif
1441   }
1442 
1443 
1444   // We need to ensure the work line is consistent while performing validation. When we spot a
1445   // peephole pattern we compute a new line for either the fallthrough instruction or the
1446   // branch target.
1447   UniquePtr<RegisterLine> branch_line;
1448   UniquePtr<RegisterLine> fallthrough_line;
1449 
1450   switch (inst->Opcode()) {
1451     case Instruction::NOP:
1452       /*
1453        * A "pure" NOP has no effect on anything. Data tables start with
1454        * a signature that looks like a NOP; if we see one of these in
1455        * the course of executing code then we have a problem.
1456        */
1457       if (inst->VRegA_10x() != 0) {
1458         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "encountered data table in instruction stream";
1459       }
1460       break;
1461 
1462     case Instruction::MOVE:
1463       work_line_->CopyRegister1(inst->VRegA_12x(), inst->VRegB_12x(), kTypeCategory1nr);
1464       break;
1465     case Instruction::MOVE_FROM16:
1466       work_line_->CopyRegister1(inst->VRegA_22x(), inst->VRegB_22x(), kTypeCategory1nr);
1467       break;
1468     case Instruction::MOVE_16:
1469       work_line_->CopyRegister1(inst->VRegA_32x(), inst->VRegB_32x(), kTypeCategory1nr);
1470       break;
1471     case Instruction::MOVE_WIDE:
1472       work_line_->CopyRegister2(inst->VRegA_12x(), inst->VRegB_12x());
1473       break;
1474     case Instruction::MOVE_WIDE_FROM16:
1475       work_line_->CopyRegister2(inst->VRegA_22x(), inst->VRegB_22x());
1476       break;
1477     case Instruction::MOVE_WIDE_16:
1478       work_line_->CopyRegister2(inst->VRegA_32x(), inst->VRegB_32x());
1479       break;
1480     case Instruction::MOVE_OBJECT:
1481       work_line_->CopyRegister1(inst->VRegA_12x(), inst->VRegB_12x(), kTypeCategoryRef);
1482       break;
1483     case Instruction::MOVE_OBJECT_FROM16:
1484       work_line_->CopyRegister1(inst->VRegA_22x(), inst->VRegB_22x(), kTypeCategoryRef);
1485       break;
1486     case Instruction::MOVE_OBJECT_16:
1487       work_line_->CopyRegister1(inst->VRegA_32x(), inst->VRegB_32x(), kTypeCategoryRef);
1488       break;
1489 
1490     /*
1491      * The move-result instructions copy data out of a "pseudo-register"
1492      * with the results from the last method invocation. In practice we
1493      * might want to hold the result in an actual CPU register, so the
1494      * Dalvik spec requires that these only appear immediately after an
1495      * invoke or filled-new-array.
1496      *
1497      * These calls invalidate the "result" register. (This is now
1498      * redundant with the reset done below, but it can make the debug info
1499      * easier to read in some cases.)
1500      */
1501     case Instruction::MOVE_RESULT:
1502       work_line_->CopyResultRegister1(inst->VRegA_11x(), false);
1503       break;
1504     case Instruction::MOVE_RESULT_WIDE:
1505       work_line_->CopyResultRegister2(inst->VRegA_11x());
1506       break;
1507     case Instruction::MOVE_RESULT_OBJECT:
1508       work_line_->CopyResultRegister1(inst->VRegA_11x(), true);
1509       break;
1510 
1511     case Instruction::MOVE_EXCEPTION: {
1512       /*
1513        * This statement can only appear as the first instruction in an exception handler. We verify
1514        * that as part of extracting the exception type from the catch block list.
1515        */
1516       const RegType& res_type = GetCaughtExceptionType();
1517       work_line_->SetRegisterType(inst->VRegA_11x(), res_type);
1518       break;
1519     }
1520     case Instruction::RETURN_VOID:
1521       if (!IsConstructor() || work_line_->CheckConstructorReturn()) {
1522         if (!GetMethodReturnType().IsConflict()) {
1523           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void not expected";
1524         }
1525       }
1526       break;
1527     case Instruction::RETURN:
1528       if (!IsConstructor() || work_line_->CheckConstructorReturn()) {
1529         /* check the method signature */
1530         const RegType& return_type = GetMethodReturnType();
1531         if (!return_type.IsCategory1Types()) {
1532           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected non-category 1 return type "
1533                                             << return_type;
1534         } else {
1535           // Compilers may generate synthetic functions that write byte values into boolean fields.
1536           // Also, it may use integer values for boolean, byte, short, and character return types.
1537           const uint32_t vregA = inst->VRegA_11x();
1538           const RegType& src_type = work_line_->GetRegisterType(vregA);
1539           bool use_src = ((return_type.IsBoolean() && src_type.IsByte()) ||
1540                           ((return_type.IsBoolean() || return_type.IsByte() ||
1541                            return_type.IsShort() || return_type.IsChar()) &&
1542                            src_type.IsInteger()));
1543           /* check the register contents */
1544           bool success =
1545               work_line_->VerifyRegisterType(vregA, use_src ? src_type : return_type);
1546           if (!success) {
1547             AppendToLastFailMessage(StringPrintf(" return-1nr on invalid register v%d", vregA));
1548           }
1549         }
1550       }
1551       break;
1552     case Instruction::RETURN_WIDE:
1553       if (!IsConstructor() || work_line_->CheckConstructorReturn()) {
1554         /* check the method signature */
1555         const RegType& return_type = GetMethodReturnType();
1556         if (!return_type.IsCategory2Types()) {
1557           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-wide not expected";
1558         } else {
1559           /* check the register contents */
1560           const uint32_t vregA = inst->VRegA_11x();
1561           bool success = work_line_->VerifyRegisterType(vregA, return_type);
1562           if (!success) {
1563             AppendToLastFailMessage(StringPrintf(" return-wide on invalid register v%d", vregA));
1564           }
1565         }
1566       }
1567       break;
1568     case Instruction::RETURN_OBJECT:
1569       if (!IsConstructor() || work_line_->CheckConstructorReturn()) {
1570         const RegType& return_type = GetMethodReturnType();
1571         if (!return_type.IsReferenceTypes()) {
1572           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-object not expected";
1573         } else {
1574           /* return_type is the *expected* return type, not register value */
1575           DCHECK(!return_type.IsZero());
1576           DCHECK(!return_type.IsUninitializedReference());
1577           const uint32_t vregA = inst->VRegA_11x();
1578           const RegType& reg_type = work_line_->GetRegisterType(vregA);
1579           // Disallow returning uninitialized values and verify that the reference in vAA is an
1580           // instance of the "return_type"
1581           if (reg_type.IsUninitializedTypes()) {
1582             Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "returning uninitialized object '"
1583                                               << reg_type << "'";
1584           } else if (!return_type.IsAssignableFrom(reg_type)) {
1585             if (reg_type.IsUnresolvedTypes() || return_type.IsUnresolvedTypes()) {
1586               Fail(VERIFY_ERROR_NO_CLASS) << " can't resolve returned type '" << return_type
1587                   << "' or '" << reg_type << "'";
1588             } else {
1589               Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "returning '" << reg_type
1590                   << "', but expected from declaration '" << return_type << "'";
1591             }
1592           }
1593         }
1594       }
1595       break;
1596 
1597       /* could be boolean, int, float, or a null reference */
1598     case Instruction::CONST_4: {
1599       int32_t val = static_cast<int32_t>(inst->VRegB_11n() << 28) >> 28;
1600       work_line_->SetRegisterType(inst->VRegA_11n(), reg_types_.FromCat1Const(val, true));
1601       break;
1602     }
1603     case Instruction::CONST_16: {
1604       int16_t val = static_cast<int16_t>(inst->VRegB_21s());
1605       work_line_->SetRegisterType(inst->VRegA_21s(), reg_types_.FromCat1Const(val, true));
1606       break;
1607     }
1608     case Instruction::CONST:
1609       work_line_->SetRegisterType(inst->VRegA_31i(),
1610                                   reg_types_.FromCat1Const(inst->VRegB_31i(), true));
1611       break;
1612     case Instruction::CONST_HIGH16:
1613       work_line_->SetRegisterType(inst->VRegA_21h(),
1614                                   reg_types_.FromCat1Const(inst->VRegB_21h() << 16, true));
1615       break;
1616       /* could be long or double; resolved upon use */
1617     case Instruction::CONST_WIDE_16: {
1618       int64_t val = static_cast<int16_t>(inst->VRegB_21s());
1619       const RegType& lo = reg_types_.FromCat2ConstLo(static_cast<int32_t>(val), true);
1620       const RegType& hi = reg_types_.FromCat2ConstHi(static_cast<int32_t>(val >> 32), true);
1621       work_line_->SetRegisterTypeWide(inst->VRegA_21s(), lo, hi);
1622       break;
1623     }
1624     case Instruction::CONST_WIDE_32: {
1625       int64_t val = static_cast<int32_t>(inst->VRegB_31i());
1626       const RegType& lo = reg_types_.FromCat2ConstLo(static_cast<int32_t>(val), true);
1627       const RegType& hi = reg_types_.FromCat2ConstHi(static_cast<int32_t>(val >> 32), true);
1628       work_line_->SetRegisterTypeWide(inst->VRegA_31i(), lo, hi);
1629       break;
1630     }
1631     case Instruction::CONST_WIDE: {
1632       int64_t val = inst->VRegB_51l();
1633       const RegType& lo = reg_types_.FromCat2ConstLo(static_cast<int32_t>(val), true);
1634       const RegType& hi = reg_types_.FromCat2ConstHi(static_cast<int32_t>(val >> 32), true);
1635       work_line_->SetRegisterTypeWide(inst->VRegA_51l(), lo, hi);
1636       break;
1637     }
1638     case Instruction::CONST_WIDE_HIGH16: {
1639       int64_t val = static_cast<uint64_t>(inst->VRegB_21h()) << 48;
1640       const RegType& lo = reg_types_.FromCat2ConstLo(static_cast<int32_t>(val), true);
1641       const RegType& hi = reg_types_.FromCat2ConstHi(static_cast<int32_t>(val >> 32), true);
1642       work_line_->SetRegisterTypeWide(inst->VRegA_21h(), lo, hi);
1643       break;
1644     }
1645     case Instruction::CONST_STRING:
1646       work_line_->SetRegisterType(inst->VRegA_21c(), reg_types_.JavaLangString());
1647       break;
1648     case Instruction::CONST_STRING_JUMBO:
1649       work_line_->SetRegisterType(inst->VRegA_31c(), reg_types_.JavaLangString());
1650       break;
1651     case Instruction::CONST_CLASS: {
1652       // Get type from instruction if unresolved then we need an access check
1653       // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
1654       const RegType& res_type = ResolveClassAndCheckAccess(inst->VRegB_21c());
1655       // Register holds class, ie its type is class, on error it will hold Conflict.
1656       work_line_->SetRegisterType(inst->VRegA_21c(),
1657                                   res_type.IsConflict() ? res_type
1658                                                         : reg_types_.JavaLangClass(true));
1659       break;
1660     }
1661     case Instruction::MONITOR_ENTER:
1662       work_line_->PushMonitor(inst->VRegA_11x(), work_insn_idx_);
1663       break;
1664     case Instruction::MONITOR_EXIT:
1665       /*
1666        * monitor-exit instructions are odd. They can throw exceptions,
1667        * but when they do they act as if they succeeded and the PC is
1668        * pointing to the following instruction. (This behavior goes back
1669        * to the need to handle asynchronous exceptions, a now-deprecated
1670        * feature that Dalvik doesn't support.)
1671        *
1672        * In practice we don't need to worry about this. The only
1673        * exceptions that can be thrown from monitor-exit are for a
1674        * null reference and -exit without a matching -enter. If the
1675        * structured locking checks are working, the former would have
1676        * failed on the -enter instruction, and the latter is impossible.
1677        *
1678        * This is fortunate, because issue 3221411 prevents us from
1679        * chasing the "can throw" path when monitor verification is
1680        * enabled. If we can fully verify the locking we can ignore
1681        * some catch blocks (which will show up as "dead" code when
1682        * we skip them here); if we can't, then the code path could be
1683        * "live" so we still need to check it.
1684        */
1685       opcode_flags &= ~Instruction::kThrow;
1686       work_line_->PopMonitor(inst->VRegA_11x());
1687       break;
1688 
1689     case Instruction::CHECK_CAST:
1690     case Instruction::INSTANCE_OF: {
1691       /*
1692        * If this instruction succeeds, we will "downcast" register vA to the type in vB. (This
1693        * could be a "upcast" -- not expected, so we don't try to address it.)
1694        *
1695        * If it fails, an exception is thrown, which we deal with later by ignoring the update to
1696        * dec_insn.vA when branching to a handler.
1697        */
1698       const bool is_checkcast = (inst->Opcode() == Instruction::CHECK_CAST);
1699       const uint32_t type_idx = (is_checkcast) ? inst->VRegB_21c() : inst->VRegC_22c();
1700       const RegType& res_type = ResolveClassAndCheckAccess(type_idx);
1701       if (res_type.IsConflict()) {
1702         DCHECK_NE(failures_.size(), 0U);
1703         if (!is_checkcast) {
1704           work_line_->SetRegisterType(inst->VRegA_22c(), reg_types_.Boolean());
1705         }
1706         break;  // bad class
1707       }
1708       // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
1709       uint32_t orig_type_reg = (is_checkcast) ? inst->VRegA_21c() : inst->VRegB_22c();
1710       const RegType& orig_type = work_line_->GetRegisterType(orig_type_reg);
1711       if (!res_type.IsNonZeroReferenceTypes()) {
1712         if (is_checkcast) {
1713           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "check-cast on unexpected class " << res_type;
1714         } else {
1715           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "instance-of on unexpected class " << res_type;
1716         }
1717       } else if (!orig_type.IsReferenceTypes()) {
1718         if (is_checkcast) {
1719           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "check-cast on non-reference in v" << orig_type_reg;
1720         } else {
1721           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "instance-of on non-reference in v" << orig_type_reg;
1722         }
1723       } else {
1724         if (is_checkcast) {
1725           work_line_->SetRegisterType(inst->VRegA_21c(), res_type);
1726         } else {
1727           work_line_->SetRegisterType(inst->VRegA_22c(), reg_types_.Boolean());
1728         }
1729       }
1730       break;
1731     }
1732     case Instruction::ARRAY_LENGTH: {
1733       const RegType& res_type = work_line_->GetRegisterType(inst->VRegB_12x());
1734       if (res_type.IsReferenceTypes()) {
1735         if (!res_type.IsArrayTypes() && !res_type.IsZero()) {  // ie not an array or null
1736           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "array-length on non-array " << res_type;
1737         } else {
1738           work_line_->SetRegisterType(inst->VRegA_12x(), reg_types_.Integer());
1739         }
1740       }
1741       break;
1742     }
1743     case Instruction::NEW_INSTANCE: {
1744       const RegType& res_type = ResolveClassAndCheckAccess(inst->VRegB_21c());
1745       if (res_type.IsConflict()) {
1746         DCHECK_NE(failures_.size(), 0U);
1747         break;  // bad class
1748       }
1749       // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
1750       // can't create an instance of an interface or abstract class */
1751       if (!res_type.IsInstantiableTypes()) {
1752         Fail(VERIFY_ERROR_INSTANTIATION)
1753             << "new-instance on primitive, interface or abstract class" << res_type;
1754         // Soft failure so carry on to set register type.
1755       }
1756       const RegType& uninit_type = reg_types_.Uninitialized(res_type, work_insn_idx_);
1757       // Any registers holding previous allocations from this address that have not yet been
1758       // initialized must be marked invalid.
1759       work_line_->MarkUninitRefsAsInvalid(uninit_type);
1760       // add the new uninitialized reference to the register state
1761       work_line_->SetRegisterType(inst->VRegA_21c(), uninit_type);
1762       break;
1763     }
1764     case Instruction::NEW_ARRAY:
1765       VerifyNewArray(inst, false, false);
1766       break;
1767     case Instruction::FILLED_NEW_ARRAY:
1768       VerifyNewArray(inst, true, false);
1769       just_set_result = true;  // Filled new array sets result register
1770       break;
1771     case Instruction::FILLED_NEW_ARRAY_RANGE:
1772       VerifyNewArray(inst, true, true);
1773       just_set_result = true;  // Filled new array range sets result register
1774       break;
1775     case Instruction::CMPL_FLOAT:
1776     case Instruction::CMPG_FLOAT:
1777       if (!work_line_->VerifyRegisterType(inst->VRegB_23x(), reg_types_.Float())) {
1778         break;
1779       }
1780       if (!work_line_->VerifyRegisterType(inst->VRegC_23x(), reg_types_.Float())) {
1781         break;
1782       }
1783       work_line_->SetRegisterType(inst->VRegA_23x(), reg_types_.Integer());
1784       break;
1785     case Instruction::CMPL_DOUBLE:
1786     case Instruction::CMPG_DOUBLE:
1787       if (!work_line_->VerifyRegisterTypeWide(inst->VRegB_23x(), reg_types_.DoubleLo(),
1788                                               reg_types_.DoubleHi())) {
1789         break;
1790       }
1791       if (!work_line_->VerifyRegisterTypeWide(inst->VRegC_23x(), reg_types_.DoubleLo(),
1792                                               reg_types_.DoubleHi())) {
1793         break;
1794       }
1795       work_line_->SetRegisterType(inst->VRegA_23x(), reg_types_.Integer());
1796       break;
1797     case Instruction::CMP_LONG:
1798       if (!work_line_->VerifyRegisterTypeWide(inst->VRegB_23x(), reg_types_.LongLo(),
1799                                               reg_types_.LongHi())) {
1800         break;
1801       }
1802       if (!work_line_->VerifyRegisterTypeWide(inst->VRegC_23x(), reg_types_.LongLo(),
1803                                               reg_types_.LongHi())) {
1804         break;
1805       }
1806       work_line_->SetRegisterType(inst->VRegA_23x(), reg_types_.Integer());
1807       break;
1808     case Instruction::THROW: {
1809       const RegType& res_type = work_line_->GetRegisterType(inst->VRegA_11x());
1810       if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(res_type)) {
1811         Fail(res_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS : VERIFY_ERROR_BAD_CLASS_SOFT)
1812             << "thrown class " << res_type << " not instanceof Throwable";
1813       }
1814       break;
1815     }
1816     case Instruction::GOTO:
1817     case Instruction::GOTO_16:
1818     case Instruction::GOTO_32:
1819       /* no effect on or use of registers */
1820       break;
1821 
1822     case Instruction::PACKED_SWITCH:
1823     case Instruction::SPARSE_SWITCH:
1824       /* verify that vAA is an integer, or can be converted to one */
1825       work_line_->VerifyRegisterType(inst->VRegA_31t(), reg_types_.Integer());
1826       break;
1827 
1828     case Instruction::FILL_ARRAY_DATA: {
1829       /* Similar to the verification done for APUT */
1830       const RegType& array_type = work_line_->GetRegisterType(inst->VRegA_31t());
1831       /* array_type can be null if the reg type is Zero */
1832       if (!array_type.IsZero()) {
1833         if (!array_type.IsArrayTypes()) {
1834           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid fill-array-data with array type "
1835                                             << array_type;
1836         } else {
1837           const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_);
1838           DCHECK(!component_type.IsConflict());
1839           if (component_type.IsNonZeroReferenceTypes()) {
1840             Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid fill-array-data with component type "
1841                                               << component_type;
1842           } else {
1843             // Now verify if the element width in the table matches the element width declared in
1844             // the array
1845             const uint16_t* array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
1846             if (array_data[0] != Instruction::kArrayDataSignature) {
1847               Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid magic for array-data";
1848             } else {
1849               size_t elem_width = Primitive::ComponentSize(component_type.GetPrimitiveType());
1850               // Since we don't compress the data in Dex, expect to see equal width of data stored
1851               // in the table and expected from the array class.
1852               if (array_data[1] != elem_width) {
1853                 Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "array-data size mismatch (" << array_data[1]
1854                                                   << " vs " << elem_width << ")";
1855               }
1856             }
1857           }
1858         }
1859       }
1860       break;
1861     }
1862     case Instruction::IF_EQ:
1863     case Instruction::IF_NE: {
1864       const RegType& reg_type1 = work_line_->GetRegisterType(inst->VRegA_22t());
1865       const RegType& reg_type2 = work_line_->GetRegisterType(inst->VRegB_22t());
1866       bool mismatch = false;
1867       if (reg_type1.IsZero()) {  // zero then integral or reference expected
1868         mismatch = !reg_type2.IsReferenceTypes() && !reg_type2.IsIntegralTypes();
1869       } else if (reg_type1.IsReferenceTypes()) {  // both references?
1870         mismatch = !reg_type2.IsReferenceTypes();
1871       } else {  // both integral?
1872         mismatch = !reg_type1.IsIntegralTypes() || !reg_type2.IsIntegralTypes();
1873       }
1874       if (mismatch) {
1875         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "args to if-eq/if-ne (" << reg_type1 << ","
1876                                           << reg_type2 << ") must both be references or integral";
1877       }
1878       break;
1879     }
1880     case Instruction::IF_LT:
1881     case Instruction::IF_GE:
1882     case Instruction::IF_GT:
1883     case Instruction::IF_LE: {
1884       const RegType& reg_type1 = work_line_->GetRegisterType(inst->VRegA_22t());
1885       const RegType& reg_type2 = work_line_->GetRegisterType(inst->VRegB_22t());
1886       if (!reg_type1.IsIntegralTypes() || !reg_type2.IsIntegralTypes()) {
1887         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "args to 'if' (" << reg_type1 << ","
1888                                           << reg_type2 << ") must be integral";
1889       }
1890       break;
1891     }
1892     case Instruction::IF_EQZ:
1893     case Instruction::IF_NEZ: {
1894       const RegType& reg_type = work_line_->GetRegisterType(inst->VRegA_21t());
1895       if (!reg_type.IsReferenceTypes() && !reg_type.IsIntegralTypes()) {
1896         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "type " << reg_type
1897                                           << " unexpected as arg to if-eqz/if-nez";
1898       }
1899 
1900       // Find previous instruction - its existence is a precondition to peephole optimization.
1901       uint32_t instance_of_idx = 0;
1902       if (0 != work_insn_idx_) {
1903         instance_of_idx = work_insn_idx_ - 1;
1904         while (0 != instance_of_idx && !insn_flags_[instance_of_idx].IsOpcode()) {
1905           instance_of_idx--;
1906         }
1907         CHECK(insn_flags_[instance_of_idx].IsOpcode());
1908       } else {
1909         break;
1910       }
1911 
1912       const Instruction* instance_of_inst = Instruction::At(code_item_->insns_ + instance_of_idx);
1913 
1914       /* Check for peep-hole pattern of:
1915        *    ...;
1916        *    instance-of vX, vY, T;
1917        *    ifXXX vX, label ;
1918        *    ...;
1919        * label:
1920        *    ...;
1921        * and sharpen the type of vY to be type T.
1922        * Note, this pattern can't be if:
1923        *  - if there are other branches to this branch,
1924        *  - when vX == vY.
1925        */
1926       if (!CurrentInsnFlags()->IsBranchTarget() &&
1927           (Instruction::INSTANCE_OF == instance_of_inst->Opcode()) &&
1928           (inst->VRegA_21t() == instance_of_inst->VRegA_22c()) &&
1929           (instance_of_inst->VRegA_22c() != instance_of_inst->VRegB_22c())) {
1930         // Check that the we are not attempting conversion to interface types,
1931         // which is not done because of the multiple inheritance implications.
1932         // Also don't change the type if it would result in an upcast.
1933         const RegType& orig_type = work_line_->GetRegisterType(instance_of_inst->VRegB_22c());
1934         const RegType& cast_type = ResolveClassAndCheckAccess(instance_of_inst->VRegC_22c());
1935 
1936         if (!cast_type.IsUnresolvedTypes() && !orig_type.IsUnresolvedTypes() &&
1937             !cast_type.GetClass()->IsInterface() && !cast_type.IsAssignableFrom(orig_type)) {
1938           RegisterLine* update_line = new RegisterLine(code_item_->registers_size_, this);
1939           if (inst->Opcode() == Instruction::IF_EQZ) {
1940             fallthrough_line.reset(update_line);
1941           } else {
1942             branch_line.reset(update_line);
1943           }
1944           update_line->CopyFromLine(work_line_.get());
1945           update_line->SetRegisterType(instance_of_inst->VRegB_22c(), cast_type);
1946           if (!insn_flags_[instance_of_idx].IsBranchTarget() && 0 != instance_of_idx) {
1947             // See if instance-of was preceded by a move-object operation, common due to the small
1948             // register encoding space of instance-of, and propagate type information to the source
1949             // of the move-object.
1950             uint32_t move_idx = instance_of_idx - 1;
1951             while (0 != move_idx && !insn_flags_[move_idx].IsOpcode()) {
1952               move_idx--;
1953             }
1954             CHECK(insn_flags_[move_idx].IsOpcode());
1955             const Instruction* move_inst = Instruction::At(code_item_->insns_ + move_idx);
1956             switch (move_inst->Opcode()) {
1957               case Instruction::MOVE_OBJECT:
1958                 if (move_inst->VRegA_12x() == instance_of_inst->VRegB_22c()) {
1959                   update_line->SetRegisterType(move_inst->VRegB_12x(), cast_type);
1960                 }
1961                 break;
1962               case Instruction::MOVE_OBJECT_FROM16:
1963                 if (move_inst->VRegA_22x() == instance_of_inst->VRegB_22c()) {
1964                   update_line->SetRegisterType(move_inst->VRegB_22x(), cast_type);
1965                 }
1966                 break;
1967               case Instruction::MOVE_OBJECT_16:
1968                 if (move_inst->VRegA_32x() == instance_of_inst->VRegB_22c()) {
1969                   update_line->SetRegisterType(move_inst->VRegB_32x(), cast_type);
1970                 }
1971                 break;
1972               default:
1973                 break;
1974             }
1975           }
1976         }
1977       }
1978 
1979       break;
1980     }
1981     case Instruction::IF_LTZ:
1982     case Instruction::IF_GEZ:
1983     case Instruction::IF_GTZ:
1984     case Instruction::IF_LEZ: {
1985       const RegType& reg_type = work_line_->GetRegisterType(inst->VRegA_21t());
1986       if (!reg_type.IsIntegralTypes()) {
1987         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "type " << reg_type
1988                                           << " unexpected as arg to if-ltz/if-gez/if-gtz/if-lez";
1989       }
1990       break;
1991     }
1992     case Instruction::AGET_BOOLEAN:
1993       VerifyAGet(inst, reg_types_.Boolean(), true);
1994       break;
1995     case Instruction::AGET_BYTE:
1996       VerifyAGet(inst, reg_types_.Byte(), true);
1997       break;
1998     case Instruction::AGET_CHAR:
1999       VerifyAGet(inst, reg_types_.Char(), true);
2000       break;
2001     case Instruction::AGET_SHORT:
2002       VerifyAGet(inst, reg_types_.Short(), true);
2003       break;
2004     case Instruction::AGET:
2005       VerifyAGet(inst, reg_types_.Integer(), true);
2006       break;
2007     case Instruction::AGET_WIDE:
2008       VerifyAGet(inst, reg_types_.LongLo(), true);
2009       break;
2010     case Instruction::AGET_OBJECT:
2011       VerifyAGet(inst, reg_types_.JavaLangObject(false), false);
2012       break;
2013 
2014     case Instruction::APUT_BOOLEAN:
2015       VerifyAPut(inst, reg_types_.Boolean(), true);
2016       break;
2017     case Instruction::APUT_BYTE:
2018       VerifyAPut(inst, reg_types_.Byte(), true);
2019       break;
2020     case Instruction::APUT_CHAR:
2021       VerifyAPut(inst, reg_types_.Char(), true);
2022       break;
2023     case Instruction::APUT_SHORT:
2024       VerifyAPut(inst, reg_types_.Short(), true);
2025       break;
2026     case Instruction::APUT:
2027       VerifyAPut(inst, reg_types_.Integer(), true);
2028       break;
2029     case Instruction::APUT_WIDE:
2030       VerifyAPut(inst, reg_types_.LongLo(), true);
2031       break;
2032     case Instruction::APUT_OBJECT:
2033       VerifyAPut(inst, reg_types_.JavaLangObject(false), false);
2034       break;
2035 
2036     case Instruction::IGET_BOOLEAN:
2037       VerifyISGet(inst, reg_types_.Boolean(), true, false);
2038       break;
2039     case Instruction::IGET_BYTE:
2040       VerifyISGet(inst, reg_types_.Byte(), true, false);
2041       break;
2042     case Instruction::IGET_CHAR:
2043       VerifyISGet(inst, reg_types_.Char(), true, false);
2044       break;
2045     case Instruction::IGET_SHORT:
2046       VerifyISGet(inst, reg_types_.Short(), true, false);
2047       break;
2048     case Instruction::IGET:
2049       VerifyISGet(inst, reg_types_.Integer(), true, false);
2050       break;
2051     case Instruction::IGET_WIDE:
2052       VerifyISGet(inst, reg_types_.LongLo(), true, false);
2053       break;
2054     case Instruction::IGET_OBJECT:
2055       VerifyISGet(inst, reg_types_.JavaLangObject(false), false, false);
2056       break;
2057 
2058     case Instruction::IPUT_BOOLEAN:
2059       VerifyISPut(inst, reg_types_.Boolean(), true, false);
2060       break;
2061     case Instruction::IPUT_BYTE:
2062       VerifyISPut(inst, reg_types_.Byte(), true, false);
2063       break;
2064     case Instruction::IPUT_CHAR:
2065       VerifyISPut(inst, reg_types_.Char(), true, false);
2066       break;
2067     case Instruction::IPUT_SHORT:
2068       VerifyISPut(inst, reg_types_.Short(), true, false);
2069       break;
2070     case Instruction::IPUT:
2071       VerifyISPut(inst, reg_types_.Integer(), true, false);
2072       break;
2073     case Instruction::IPUT_WIDE:
2074       VerifyISPut(inst, reg_types_.LongLo(), true, false);
2075       break;
2076     case Instruction::IPUT_OBJECT:
2077       VerifyISPut(inst, reg_types_.JavaLangObject(false), false, false);
2078       break;
2079 
2080     case Instruction::SGET_BOOLEAN:
2081       VerifyISGet(inst, reg_types_.Boolean(), true, true);
2082       break;
2083     case Instruction::SGET_BYTE:
2084       VerifyISGet(inst, reg_types_.Byte(), true, true);
2085       break;
2086     case Instruction::SGET_CHAR:
2087       VerifyISGet(inst, reg_types_.Char(), true, true);
2088       break;
2089     case Instruction::SGET_SHORT:
2090       VerifyISGet(inst, reg_types_.Short(), true, true);
2091       break;
2092     case Instruction::SGET:
2093       VerifyISGet(inst, reg_types_.Integer(), true, true);
2094       break;
2095     case Instruction::SGET_WIDE:
2096       VerifyISGet(inst, reg_types_.LongLo(), true, true);
2097       break;
2098     case Instruction::SGET_OBJECT:
2099       VerifyISGet(inst, reg_types_.JavaLangObject(false), false, true);
2100       break;
2101 
2102     case Instruction::SPUT_BOOLEAN:
2103       VerifyISPut(inst, reg_types_.Boolean(), true, true);
2104       break;
2105     case Instruction::SPUT_BYTE:
2106       VerifyISPut(inst, reg_types_.Byte(), true, true);
2107       break;
2108     case Instruction::SPUT_CHAR:
2109       VerifyISPut(inst, reg_types_.Char(), true, true);
2110       break;
2111     case Instruction::SPUT_SHORT:
2112       VerifyISPut(inst, reg_types_.Short(), true, true);
2113       break;
2114     case Instruction::SPUT:
2115       VerifyISPut(inst, reg_types_.Integer(), true, true);
2116       break;
2117     case Instruction::SPUT_WIDE:
2118       VerifyISPut(inst, reg_types_.LongLo(), true, true);
2119       break;
2120     case Instruction::SPUT_OBJECT:
2121       VerifyISPut(inst, reg_types_.JavaLangObject(false), false, true);
2122       break;
2123 
2124     case Instruction::INVOKE_VIRTUAL:
2125     case Instruction::INVOKE_VIRTUAL_RANGE:
2126     case Instruction::INVOKE_SUPER:
2127     case Instruction::INVOKE_SUPER_RANGE: {
2128       bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE ||
2129                        inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
2130       bool is_super =  (inst->Opcode() == Instruction::INVOKE_SUPER ||
2131                         inst->Opcode() == Instruction::INVOKE_SUPER_RANGE);
2132       mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_VIRTUAL,
2133                                                                    is_range, is_super);
2134       const char* descriptor;
2135       if (called_method == NULL) {
2136         uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
2137         const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
2138         uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
2139         descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
2140       } else {
2141         descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
2142       }
2143       const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
2144       if (!return_type.IsLowHalf()) {
2145         work_line_->SetResultRegisterType(return_type);
2146       } else {
2147         work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
2148       }
2149       just_set_result = true;
2150       break;
2151     }
2152     case Instruction::INVOKE_DIRECT:
2153     case Instruction::INVOKE_DIRECT_RANGE: {
2154       bool is_range = (inst->Opcode() == Instruction::INVOKE_DIRECT_RANGE);
2155       mirror::ArtMethod* called_method = VerifyInvocationArgs(inst, METHOD_DIRECT,
2156                                                                    is_range, false);
2157       const char* return_type_descriptor;
2158       bool is_constructor;
2159       if (called_method == NULL) {
2160         uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
2161         const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
2162         is_constructor = StringPiece(dex_file_->GetMethodName(method_id)) == "<init>";
2163         uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
2164         return_type_descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
2165       } else {
2166         is_constructor = called_method->IsConstructor();
2167         return_type_descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
2168       }
2169       if (is_constructor) {
2170         /*
2171          * Some additional checks when calling a constructor. We know from the invocation arg check
2172          * that the "this" argument is an instance of called_method->klass. Now we further restrict
2173          * that to require that called_method->klass is the same as this->klass or this->super,
2174          * allowing the latter only if the "this" argument is the same as the "this" argument to
2175          * this method (which implies that we're in a constructor ourselves).
2176          */
2177         const RegType& this_type = work_line_->GetInvocationThis(inst, is_range);
2178         if (this_type.IsConflict())  // failure.
2179           break;
2180 
2181         /* no null refs allowed (?) */
2182         if (this_type.IsZero()) {
2183           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unable to initialize null ref";
2184           break;
2185         }
2186 
2187         /* must be in same class or in superclass */
2188         // const RegType& this_super_klass = this_type.GetSuperClass(&reg_types_);
2189         // TODO: re-enable constructor type verification
2190         // if (this_super_klass.IsConflict()) {
2191           // Unknown super class, fail so we re-check at runtime.
2192           // Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "super class unknown for '" << this_type << "'";
2193           // break;
2194         // }
2195 
2196         /* arg must be an uninitialized reference */
2197         if (!this_type.IsUninitializedTypes()) {
2198           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Expected initialization on uninitialized reference "
2199               << this_type;
2200           break;
2201         }
2202 
2203         /*
2204          * Replace the uninitialized reference with an initialized one. We need to do this for all
2205          * registers that have the same object instance in them, not just the "this" register.
2206          */
2207         work_line_->MarkRefsAsInitialized(this_type);
2208       }
2209       const RegType& return_type = reg_types_.FromDescriptor(class_loader_, return_type_descriptor,
2210                                                              false);
2211       if (!return_type.IsLowHalf()) {
2212         work_line_->SetResultRegisterType(return_type);
2213       } else {
2214         work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
2215       }
2216       just_set_result = true;
2217       break;
2218     }
2219     case Instruction::INVOKE_STATIC:
2220     case Instruction::INVOKE_STATIC_RANGE: {
2221         bool is_range = (inst->Opcode() == Instruction::INVOKE_STATIC_RANGE);
2222         mirror::ArtMethod* called_method = VerifyInvocationArgs(inst,
2223                                                                      METHOD_STATIC,
2224                                                                      is_range,
2225                                                                      false);
2226         const char* descriptor;
2227         if (called_method == NULL) {
2228           uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
2229           const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
2230           uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
2231           descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
2232         } else {
2233           descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
2234         }
2235         const RegType& return_type =  reg_types_.FromDescriptor(class_loader_, descriptor, false);
2236         if (!return_type.IsLowHalf()) {
2237           work_line_->SetResultRegisterType(return_type);
2238         } else {
2239           work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
2240         }
2241         just_set_result = true;
2242       }
2243       break;
2244     case Instruction::INVOKE_INTERFACE:
2245     case Instruction::INVOKE_INTERFACE_RANGE: {
2246       bool is_range =  (inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE);
2247       mirror::ArtMethod* abs_method = VerifyInvocationArgs(inst,
2248                                                                 METHOD_INTERFACE,
2249                                                                 is_range,
2250                                                                 false);
2251       if (abs_method != NULL) {
2252         mirror::Class* called_interface = abs_method->GetDeclaringClass();
2253         if (!called_interface->IsInterface() && !called_interface->IsObjectClass()) {
2254           Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected interface class in invoke-interface '"
2255               << PrettyMethod(abs_method) << "'";
2256           break;
2257         }
2258       }
2259       /* Get the type of the "this" arg, which should either be a sub-interface of called
2260        * interface or Object (see comments in RegType::JoinClass).
2261        */
2262       const RegType& this_type = work_line_->GetInvocationThis(inst, is_range);
2263       if (this_type.IsZero()) {
2264         /* null pointer always passes (and always fails at runtime) */
2265       } else {
2266         if (this_type.IsUninitializedTypes()) {
2267           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interface call on uninitialized object "
2268               << this_type;
2269           break;
2270         }
2271         // In the past we have tried to assert that "called_interface" is assignable
2272         // from "this_type.GetClass()", however, as we do an imprecise Join
2273         // (RegType::JoinClass) we don't have full information on what interfaces are
2274         // implemented by "this_type". For example, two classes may implement the same
2275         // interfaces and have a common parent that doesn't implement the interface. The
2276         // join will set "this_type" to the parent class and a test that this implements
2277         // the interface will incorrectly fail.
2278       }
2279       /*
2280        * We don't have an object instance, so we can't find the concrete method. However, all of
2281        * the type information is in the abstract method, so we're good.
2282        */
2283       const char* descriptor;
2284       if (abs_method == NULL) {
2285         uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
2286         const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
2287         uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
2288         descriptor =  dex_file_->StringByTypeIdx(return_type_idx);
2289       } else {
2290         descriptor = MethodHelper(abs_method).GetReturnTypeDescriptor();
2291       }
2292       const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
2293       if (!return_type.IsLowHalf()) {
2294         work_line_->SetResultRegisterType(return_type);
2295       } else {
2296         work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
2297       }
2298       just_set_result = true;
2299       break;
2300     }
2301     case Instruction::NEG_INT:
2302     case Instruction::NOT_INT:
2303       work_line_->CheckUnaryOp(inst, reg_types_.Integer(), reg_types_.Integer());
2304       break;
2305     case Instruction::NEG_LONG:
2306     case Instruction::NOT_LONG:
2307       work_line_->CheckUnaryOpWide(inst, reg_types_.LongLo(), reg_types_.LongHi(),
2308                                    reg_types_.LongLo(), reg_types_.LongHi());
2309       break;
2310     case Instruction::NEG_FLOAT:
2311       work_line_->CheckUnaryOp(inst, reg_types_.Float(), reg_types_.Float());
2312       break;
2313     case Instruction::NEG_DOUBLE:
2314       work_line_->CheckUnaryOpWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(),
2315                                    reg_types_.DoubleLo(), reg_types_.DoubleHi());
2316       break;
2317     case Instruction::INT_TO_LONG:
2318       work_line_->CheckUnaryOpToWide(inst, reg_types_.LongLo(), reg_types_.LongHi(),
2319                                      reg_types_.Integer());
2320       break;
2321     case Instruction::INT_TO_FLOAT:
2322       work_line_->CheckUnaryOp(inst, reg_types_.Float(), reg_types_.Integer());
2323       break;
2324     case Instruction::INT_TO_DOUBLE:
2325       work_line_->CheckUnaryOpToWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(),
2326                                      reg_types_.Integer());
2327       break;
2328     case Instruction::LONG_TO_INT:
2329       work_line_->CheckUnaryOpFromWide(inst, reg_types_.Integer(),
2330                                        reg_types_.LongLo(), reg_types_.LongHi());
2331       break;
2332     case Instruction::LONG_TO_FLOAT:
2333       work_line_->CheckUnaryOpFromWide(inst, reg_types_.Float(),
2334                                        reg_types_.LongLo(), reg_types_.LongHi());
2335       break;
2336     case Instruction::LONG_TO_DOUBLE:
2337       work_line_->CheckUnaryOpWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(),
2338                                    reg_types_.LongLo(), reg_types_.LongHi());
2339       break;
2340     case Instruction::FLOAT_TO_INT:
2341       work_line_->CheckUnaryOp(inst, reg_types_.Integer(), reg_types_.Float());
2342       break;
2343     case Instruction::FLOAT_TO_LONG:
2344       work_line_->CheckUnaryOpToWide(inst, reg_types_.LongLo(), reg_types_.LongHi(),
2345                                      reg_types_.Float());
2346       break;
2347     case Instruction::FLOAT_TO_DOUBLE:
2348       work_line_->CheckUnaryOpToWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(),
2349                                      reg_types_.Float());
2350       break;
2351     case Instruction::DOUBLE_TO_INT:
2352       work_line_->CheckUnaryOpFromWide(inst, reg_types_.Integer(),
2353                                        reg_types_.DoubleLo(), reg_types_.DoubleHi());
2354       break;
2355     case Instruction::DOUBLE_TO_LONG:
2356       work_line_->CheckUnaryOpWide(inst, reg_types_.LongLo(), reg_types_.LongHi(),
2357                                    reg_types_.DoubleLo(), reg_types_.DoubleHi());
2358       break;
2359     case Instruction::DOUBLE_TO_FLOAT:
2360       work_line_->CheckUnaryOpFromWide(inst, reg_types_.Float(),
2361                                        reg_types_.DoubleLo(), reg_types_.DoubleHi());
2362       break;
2363     case Instruction::INT_TO_BYTE:
2364       work_line_->CheckUnaryOp(inst, reg_types_.Byte(), reg_types_.Integer());
2365       break;
2366     case Instruction::INT_TO_CHAR:
2367       work_line_->CheckUnaryOp(inst, reg_types_.Char(), reg_types_.Integer());
2368       break;
2369     case Instruction::INT_TO_SHORT:
2370       work_line_->CheckUnaryOp(inst, reg_types_.Short(), reg_types_.Integer());
2371       break;
2372 
2373     case Instruction::ADD_INT:
2374     case Instruction::SUB_INT:
2375     case Instruction::MUL_INT:
2376     case Instruction::REM_INT:
2377     case Instruction::DIV_INT:
2378     case Instruction::SHL_INT:
2379     case Instruction::SHR_INT:
2380     case Instruction::USHR_INT:
2381       work_line_->CheckBinaryOp(inst, reg_types_.Integer(), reg_types_.Integer(),
2382                                 reg_types_.Integer(), false);
2383       break;
2384     case Instruction::AND_INT:
2385     case Instruction::OR_INT:
2386     case Instruction::XOR_INT:
2387       work_line_->CheckBinaryOp(inst, reg_types_.Integer(), reg_types_.Integer(),
2388                                 reg_types_.Integer(), true);
2389       break;
2390     case Instruction::ADD_LONG:
2391     case Instruction::SUB_LONG:
2392     case Instruction::MUL_LONG:
2393     case Instruction::DIV_LONG:
2394     case Instruction::REM_LONG:
2395     case Instruction::AND_LONG:
2396     case Instruction::OR_LONG:
2397     case Instruction::XOR_LONG:
2398       work_line_->CheckBinaryOpWide(inst, reg_types_.LongLo(), reg_types_.LongHi(),
2399                                     reg_types_.LongLo(), reg_types_.LongHi(),
2400                                     reg_types_.LongLo(), reg_types_.LongHi());
2401       break;
2402     case Instruction::SHL_LONG:
2403     case Instruction::SHR_LONG:
2404     case Instruction::USHR_LONG:
2405       /* shift distance is Int, making these different from other binary operations */
2406       work_line_->CheckBinaryOpWideShift(inst, reg_types_.LongLo(), reg_types_.LongHi(),
2407                                          reg_types_.Integer());
2408       break;
2409     case Instruction::ADD_FLOAT:
2410     case Instruction::SUB_FLOAT:
2411     case Instruction::MUL_FLOAT:
2412     case Instruction::DIV_FLOAT:
2413     case Instruction::REM_FLOAT:
2414       work_line_->CheckBinaryOp(inst,
2415                                 reg_types_.Float(),
2416                                 reg_types_.Float(),
2417                                 reg_types_.Float(),
2418                                 false);
2419       break;
2420     case Instruction::ADD_DOUBLE:
2421     case Instruction::SUB_DOUBLE:
2422     case Instruction::MUL_DOUBLE:
2423     case Instruction::DIV_DOUBLE:
2424     case Instruction::REM_DOUBLE:
2425       work_line_->CheckBinaryOpWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(),
2426                                     reg_types_.DoubleLo(), reg_types_.DoubleHi(),
2427                                     reg_types_.DoubleLo(), reg_types_.DoubleHi());
2428       break;
2429     case Instruction::ADD_INT_2ADDR:
2430     case Instruction::SUB_INT_2ADDR:
2431     case Instruction::MUL_INT_2ADDR:
2432     case Instruction::REM_INT_2ADDR:
2433     case Instruction::SHL_INT_2ADDR:
2434     case Instruction::SHR_INT_2ADDR:
2435     case Instruction::USHR_INT_2ADDR:
2436       work_line_->CheckBinaryOp2addr(inst,
2437                                      reg_types_.Integer(),
2438                                      reg_types_.Integer(),
2439                                      reg_types_.Integer(),
2440                                      false);
2441       break;
2442     case Instruction::AND_INT_2ADDR:
2443     case Instruction::OR_INT_2ADDR:
2444     case Instruction::XOR_INT_2ADDR:
2445       work_line_->CheckBinaryOp2addr(inst,
2446                                      reg_types_.Integer(),
2447                                      reg_types_.Integer(),
2448                                      reg_types_.Integer(),
2449                                      true);
2450       break;
2451     case Instruction::DIV_INT_2ADDR:
2452       work_line_->CheckBinaryOp2addr(inst,
2453                                      reg_types_.Integer(),
2454                                      reg_types_.Integer(),
2455                                      reg_types_.Integer(),
2456                                      false);
2457       break;
2458     case Instruction::ADD_LONG_2ADDR:
2459     case Instruction::SUB_LONG_2ADDR:
2460     case Instruction::MUL_LONG_2ADDR:
2461     case Instruction::DIV_LONG_2ADDR:
2462     case Instruction::REM_LONG_2ADDR:
2463     case Instruction::AND_LONG_2ADDR:
2464     case Instruction::OR_LONG_2ADDR:
2465     case Instruction::XOR_LONG_2ADDR:
2466       work_line_->CheckBinaryOp2addrWide(inst, reg_types_.LongLo(), reg_types_.LongHi(),
2467                                          reg_types_.LongLo(), reg_types_.LongHi(),
2468                                          reg_types_.LongLo(), reg_types_.LongHi());
2469       break;
2470     case Instruction::SHL_LONG_2ADDR:
2471     case Instruction::SHR_LONG_2ADDR:
2472     case Instruction::USHR_LONG_2ADDR:
2473       work_line_->CheckBinaryOp2addrWideShift(inst, reg_types_.LongLo(), reg_types_.LongHi(),
2474                                               reg_types_.Integer());
2475       break;
2476     case Instruction::ADD_FLOAT_2ADDR:
2477     case Instruction::SUB_FLOAT_2ADDR:
2478     case Instruction::MUL_FLOAT_2ADDR:
2479     case Instruction::DIV_FLOAT_2ADDR:
2480     case Instruction::REM_FLOAT_2ADDR:
2481       work_line_->CheckBinaryOp2addr(inst,
2482                                      reg_types_.Float(),
2483                                      reg_types_.Float(),
2484                                      reg_types_.Float(),
2485                                      false);
2486       break;
2487     case Instruction::ADD_DOUBLE_2ADDR:
2488     case Instruction::SUB_DOUBLE_2ADDR:
2489     case Instruction::MUL_DOUBLE_2ADDR:
2490     case Instruction::DIV_DOUBLE_2ADDR:
2491     case Instruction::REM_DOUBLE_2ADDR:
2492       work_line_->CheckBinaryOp2addrWide(inst, reg_types_.DoubleLo(), reg_types_.DoubleHi(),
2493                                          reg_types_.DoubleLo(),  reg_types_.DoubleHi(),
2494                                          reg_types_.DoubleLo(), reg_types_.DoubleHi());
2495       break;
2496     case Instruction::ADD_INT_LIT16:
2497     case Instruction::RSUB_INT:
2498     case Instruction::MUL_INT_LIT16:
2499     case Instruction::DIV_INT_LIT16:
2500     case Instruction::REM_INT_LIT16:
2501       work_line_->CheckLiteralOp(inst, reg_types_.Integer(), reg_types_.Integer(), false, true);
2502       break;
2503     case Instruction::AND_INT_LIT16:
2504     case Instruction::OR_INT_LIT16:
2505     case Instruction::XOR_INT_LIT16:
2506       work_line_->CheckLiteralOp(inst, reg_types_.Integer(), reg_types_.Integer(), true, true);
2507       break;
2508     case Instruction::ADD_INT_LIT8:
2509     case Instruction::RSUB_INT_LIT8:
2510     case Instruction::MUL_INT_LIT8:
2511     case Instruction::DIV_INT_LIT8:
2512     case Instruction::REM_INT_LIT8:
2513     case Instruction::SHL_INT_LIT8:
2514     case Instruction::SHR_INT_LIT8:
2515     case Instruction::USHR_INT_LIT8:
2516       work_line_->CheckLiteralOp(inst, reg_types_.Integer(), reg_types_.Integer(), false, false);
2517       break;
2518     case Instruction::AND_INT_LIT8:
2519     case Instruction::OR_INT_LIT8:
2520     case Instruction::XOR_INT_LIT8:
2521       work_line_->CheckLiteralOp(inst, reg_types_.Integer(), reg_types_.Integer(), true, false);
2522       break;
2523 
2524     // Special instructions.
2525     case Instruction::RETURN_VOID_BARRIER:
2526       DCHECK(Runtime::Current()->IsStarted()) << PrettyMethod(dex_method_idx_, *dex_file_);
2527       if (!IsConstructor() || IsStatic()) {
2528           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void-barrier not expected";
2529       }
2530       break;
2531     // Note: the following instructions encode offsets derived from class linking.
2532     // As such they use Class*/Field*/AbstractMethod* as these offsets only have
2533     // meaning if the class linking and resolution were successful.
2534     case Instruction::IGET_QUICK:
2535       VerifyIGetQuick(inst, reg_types_.Integer(), true);
2536       break;
2537     case Instruction::IGET_WIDE_QUICK:
2538       VerifyIGetQuick(inst, reg_types_.LongLo(), true);
2539       break;
2540     case Instruction::IGET_OBJECT_QUICK:
2541       VerifyIGetQuick(inst, reg_types_.JavaLangObject(false), false);
2542       break;
2543     case Instruction::IPUT_QUICK:
2544       VerifyIPutQuick(inst, reg_types_.Integer(), true);
2545       break;
2546     case Instruction::IPUT_WIDE_QUICK:
2547       VerifyIPutQuick(inst, reg_types_.LongLo(), true);
2548       break;
2549     case Instruction::IPUT_OBJECT_QUICK:
2550       VerifyIPutQuick(inst, reg_types_.JavaLangObject(false), false);
2551       break;
2552     case Instruction::INVOKE_VIRTUAL_QUICK:
2553     case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
2554       bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
2555       mirror::ArtMethod* called_method = VerifyInvokeVirtualQuickArgs(inst, is_range);
2556       if (called_method != NULL) {
2557         const char* descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
2558         const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
2559         if (!return_type.IsLowHalf()) {
2560           work_line_->SetResultRegisterType(return_type);
2561         } else {
2562           work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(&reg_types_));
2563         }
2564         just_set_result = true;
2565       }
2566       break;
2567     }
2568 
2569     /* These should never appear during verification. */
2570     case Instruction::UNUSED_3E:
2571     case Instruction::UNUSED_3F:
2572     case Instruction::UNUSED_40:
2573     case Instruction::UNUSED_41:
2574     case Instruction::UNUSED_42:
2575     case Instruction::UNUSED_43:
2576     case Instruction::UNUSED_79:
2577     case Instruction::UNUSED_7A:
2578     case Instruction::UNUSED_EB:
2579     case Instruction::UNUSED_EC:
2580     case Instruction::UNUSED_ED:
2581     case Instruction::UNUSED_EE:
2582     case Instruction::UNUSED_EF:
2583     case Instruction::UNUSED_F0:
2584     case Instruction::UNUSED_F1:
2585     case Instruction::UNUSED_F2:
2586     case Instruction::UNUSED_F3:
2587     case Instruction::UNUSED_F4:
2588     case Instruction::UNUSED_F5:
2589     case Instruction::UNUSED_F6:
2590     case Instruction::UNUSED_F7:
2591     case Instruction::UNUSED_F8:
2592     case Instruction::UNUSED_F9:
2593     case Instruction::UNUSED_FA:
2594     case Instruction::UNUSED_FB:
2595     case Instruction::UNUSED_FC:
2596     case Instruction::UNUSED_FD:
2597     case Instruction::UNUSED_FE:
2598     case Instruction::UNUSED_FF:
2599       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Unexpected opcode " << inst->DumpString(dex_file_);
2600       break;
2601 
2602     /*
2603      * DO NOT add a "default" clause here. Without it the compiler will
2604      * complain if an instruction is missing (which is desirable).
2605      */
2606   }  // end - switch (dec_insn.opcode)
2607 
2608   if (have_pending_hard_failure_) {
2609     if (Runtime::Current()->IsCompiler()) {
2610       /* When compiling, check that the last failure is a hard failure */
2611       CHECK_EQ(failures_[failures_.size() - 1], VERIFY_ERROR_BAD_CLASS_HARD);
2612     }
2613     /* immediate failure, reject class */
2614     info_messages_ << "Rejecting opcode " << inst->DumpString(dex_file_);
2615     return false;
2616   } else if (have_pending_runtime_throw_failure_) {
2617     /* checking interpreter will throw, mark following code as unreachable */
2618     opcode_flags = Instruction::kThrow;
2619   }
2620   /*
2621    * If we didn't just set the result register, clear it out. This ensures that you can only use
2622    * "move-result" immediately after the result is set. (We could check this statically, but it's
2623    * not expensive and it makes our debugging output cleaner.)
2624    */
2625   if (!just_set_result) {
2626     work_line_->SetResultTypeToUnknown();
2627   }
2628 
2629 
2630 
2631   /*
2632    * Handle "branch". Tag the branch target.
2633    *
2634    * NOTE: instructions like Instruction::EQZ provide information about the
2635    * state of the register when the branch is taken or not taken. For example,
2636    * somebody could get a reference field, check it for zero, and if the
2637    * branch is taken immediately store that register in a boolean field
2638    * since the value is known to be zero. We do not currently account for
2639    * that, and will reject the code.
2640    *
2641    * TODO: avoid re-fetching the branch target
2642    */
2643   if ((opcode_flags & Instruction::kBranch) != 0) {
2644     bool isConditional, selfOkay;
2645     if (!GetBranchOffset(work_insn_idx_, &branch_target, &isConditional, &selfOkay)) {
2646       /* should never happen after static verification */
2647       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "bad branch";
2648       return false;
2649     }
2650     DCHECK_EQ(isConditional, (opcode_flags & Instruction::kContinue) != 0);
2651     if (!CheckNotMoveException(code_item_->insns_, work_insn_idx_ + branch_target)) {
2652       return false;
2653     }
2654     /* update branch target, set "changed" if appropriate */
2655     if (NULL != branch_line.get()) {
2656       if (!UpdateRegisters(work_insn_idx_ + branch_target, branch_line.get())) {
2657         return false;
2658       }
2659     } else {
2660       if (!UpdateRegisters(work_insn_idx_ + branch_target, work_line_.get())) {
2661         return false;
2662       }
2663     }
2664   }
2665 
2666   /*
2667    * Handle "switch". Tag all possible branch targets.
2668    *
2669    * We've already verified that the table is structurally sound, so we
2670    * just need to walk through and tag the targets.
2671    */
2672   if ((opcode_flags & Instruction::kSwitch) != 0) {
2673     int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
2674     const uint16_t* switch_insns = insns + offset_to_switch;
2675     int switch_count = switch_insns[1];
2676     int offset_to_targets, targ;
2677 
2678     if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
2679       /* 0 = sig, 1 = count, 2/3 = first key */
2680       offset_to_targets = 4;
2681     } else {
2682       /* 0 = sig, 1 = count, 2..count * 2 = keys */
2683       DCHECK((*insns & 0xff) == Instruction::SPARSE_SWITCH);
2684       offset_to_targets = 2 + 2 * switch_count;
2685     }
2686 
2687     /* verify each switch target */
2688     for (targ = 0; targ < switch_count; targ++) {
2689       int offset;
2690       uint32_t abs_offset;
2691 
2692       /* offsets are 32-bit, and only partly endian-swapped */
2693       offset = switch_insns[offset_to_targets + targ * 2] |
2694          (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
2695       abs_offset = work_insn_idx_ + offset;
2696       DCHECK_LT(abs_offset, code_item_->insns_size_in_code_units_);
2697       if (!CheckNotMoveException(code_item_->insns_, abs_offset)) {
2698         return false;
2699       }
2700       if (!UpdateRegisters(abs_offset, work_line_.get()))
2701         return false;
2702     }
2703   }
2704 
2705   /*
2706    * Handle instructions that can throw and that are sitting in a "try" block. (If they're not in a
2707    * "try" block when they throw, control transfers out of the method.)
2708    */
2709   if ((opcode_flags & Instruction::kThrow) != 0 && insn_flags_[work_insn_idx_].IsInTry()) {
2710     bool within_catch_all = false;
2711     CatchHandlerIterator iterator(*code_item_, work_insn_idx_);
2712 
2713     for (; iterator.HasNext(); iterator.Next()) {
2714       if (iterator.GetHandlerTypeIndex() == DexFile::kDexNoIndex16) {
2715         within_catch_all = true;
2716       }
2717       /*
2718        * Merge registers into the "catch" block. We want to use the "savedRegs" rather than
2719        * "work_regs", because at runtime the exception will be thrown before the instruction
2720        * modifies any registers.
2721        */
2722       if (!UpdateRegisters(iterator.GetHandlerAddress(), saved_line_.get())) {
2723         return false;
2724       }
2725     }
2726 
2727     /*
2728      * If the monitor stack depth is nonzero, there must be a "catch all" handler for this
2729      * instruction. This does apply to monitor-exit because of async exception handling.
2730      */
2731     if (work_line_->MonitorStackDepth() > 0 && !within_catch_all) {
2732       /*
2733        * The state in work_line reflects the post-execution state. If the current instruction is a
2734        * monitor-enter and the monitor stack was empty, we don't need a catch-all (if it throws,
2735        * it will do so before grabbing the lock).
2736        */
2737       if (inst->Opcode() != Instruction::MONITOR_ENTER || work_line_->MonitorStackDepth() != 1) {
2738         Fail(VERIFY_ERROR_BAD_CLASS_HARD)
2739             << "expected to be within a catch-all for an instruction where a monitor is held";
2740         return false;
2741       }
2742     }
2743   }
2744 
2745   /* Handle "continue". Tag the next consecutive instruction.
2746    *  Note: Keep the code handling "continue" case below the "branch" and "switch" cases,
2747    *        because it changes work_line_ when performing peephole optimization
2748    *        and this change should not be used in those cases.
2749    */
2750   if ((opcode_flags & Instruction::kContinue) != 0) {
2751     uint32_t next_insn_idx = work_insn_idx_ + CurrentInsnFlags()->GetLengthInCodeUnits();
2752     if (next_insn_idx >= code_item_->insns_size_in_code_units_) {
2753       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Execution can walk off end of code area";
2754       return false;
2755     }
2756     // The only way to get to a move-exception instruction is to get thrown there. Make sure the
2757     // next instruction isn't one.
2758     if (!CheckNotMoveException(code_item_->insns_, next_insn_idx)) {
2759       return false;
2760     }
2761     if (NULL != fallthrough_line.get()) {
2762       // Make workline consistent with fallthrough computed from peephole optimization.
2763       work_line_->CopyFromLine(fallthrough_line.get());
2764     }
2765     if (insn_flags_[next_insn_idx].IsReturn()) {
2766       // For returns we only care about the operand to the return, all other registers are dead.
2767       const Instruction* ret_inst = Instruction::At(code_item_->insns_ + next_insn_idx);
2768       Instruction::Code opcode = ret_inst->Opcode();
2769       if ((opcode == Instruction::RETURN_VOID) || (opcode == Instruction::RETURN_VOID_BARRIER)) {
2770         work_line_->MarkAllRegistersAsConflicts();
2771       } else {
2772         if (opcode == Instruction::RETURN_WIDE) {
2773           work_line_->MarkAllRegistersAsConflictsExceptWide(ret_inst->VRegA_11x());
2774         } else {
2775           work_line_->MarkAllRegistersAsConflictsExcept(ret_inst->VRegA_11x());
2776         }
2777       }
2778     }
2779     RegisterLine* next_line = reg_table_.GetLine(next_insn_idx);
2780     if (next_line != NULL) {
2781       // Merge registers into what we have for the next instruction,
2782       // and set the "changed" flag if needed.
2783       if (!UpdateRegisters(next_insn_idx, work_line_.get())) {
2784         return false;
2785       }
2786     } else {
2787       /*
2788        * We're not recording register data for the next instruction, so we don't know what the
2789        * prior state was. We have to assume that something has changed and re-evaluate it.
2790        */
2791       insn_flags_[next_insn_idx].SetChanged();
2792     }
2793   }
2794 
2795   /* If we're returning from the method, make sure monitor stack is empty. */
2796   if ((opcode_flags & Instruction::kReturn) != 0) {
2797     if (!work_line_->VerifyMonitorStackEmpty()) {
2798       return false;
2799     }
2800   }
2801 
2802   /*
2803    * Update start_guess. Advance to the next instruction of that's
2804    * possible, otherwise use the branch target if one was found. If
2805    * neither of those exists we're in a return or throw; leave start_guess
2806    * alone and let the caller sort it out.
2807    */
2808   if ((opcode_flags & Instruction::kContinue) != 0) {
2809     *start_guess = work_insn_idx_ + insn_flags_[work_insn_idx_].GetLengthInCodeUnits();
2810   } else if ((opcode_flags & Instruction::kBranch) != 0) {
2811     /* we're still okay if branch_target is zero */
2812     *start_guess = work_insn_idx_ + branch_target;
2813   }
2814 
2815   DCHECK_LT(*start_guess, code_item_->insns_size_in_code_units_);
2816   DCHECK(insn_flags_[*start_guess].IsOpcode());
2817 
2818   return true;
2819 }  // NOLINT(readability/fn_size)
2820 
ResolveClassAndCheckAccess(uint32_t class_idx)2821 const RegType& MethodVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
2822   const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
2823   const RegType& referrer = GetDeclaringClass();
2824   mirror::Class* klass = dex_cache_->GetResolvedType(class_idx);
2825   const RegType& result =
2826       klass != NULL ? reg_types_.FromClass(descriptor, klass,
2827                                            klass->CannotBeAssignedFromOtherTypes())
2828                     : reg_types_.FromDescriptor(class_loader_, descriptor, false);
2829   if (result.IsConflict()) {
2830     Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "accessing broken descriptor '" << descriptor
2831         << "' in " << referrer;
2832     return result;
2833   }
2834   if (klass == NULL && !result.IsUnresolvedTypes()) {
2835     dex_cache_->SetResolvedType(class_idx, result.GetClass());
2836   }
2837   // Check if access is allowed. Unresolved types use xxxWithAccessCheck to
2838   // check at runtime if access is allowed and so pass here. If result is
2839   // primitive, skip the access check.
2840   if (result.IsNonZeroReferenceTypes() && !result.IsUnresolvedTypes() &&
2841       !referrer.IsUnresolvedTypes() && !referrer.CanAccess(result)) {
2842     Fail(VERIFY_ERROR_ACCESS_CLASS) << "illegal class access: '"
2843                                     << referrer << "' -> '" << result << "'";
2844   }
2845   return result;
2846 }
2847 
GetCaughtExceptionType()2848 const RegType& MethodVerifier::GetCaughtExceptionType() {
2849   const RegType* common_super = NULL;
2850   if (code_item_->tries_size_ != 0) {
2851     const byte* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
2852     uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
2853     for (uint32_t i = 0; i < handlers_size; i++) {
2854       CatchHandlerIterator iterator(handlers_ptr);
2855       for (; iterator.HasNext(); iterator.Next()) {
2856         if (iterator.GetHandlerAddress() == (uint32_t) work_insn_idx_) {
2857           if (iterator.GetHandlerTypeIndex() == DexFile::kDexNoIndex16) {
2858             common_super = &reg_types_.JavaLangThrowable(false);
2859           } else {
2860             const RegType& exception = ResolveClassAndCheckAccess(iterator.GetHandlerTypeIndex());
2861             if (common_super == NULL) {
2862               // Unconditionally assign for the first handler. We don't assert this is a Throwable
2863               // as that is caught at runtime
2864               common_super = &exception;
2865             } else if (!reg_types_.JavaLangThrowable(false).IsAssignableFrom(exception)) {
2866               if (exception.IsUnresolvedTypes()) {
2867                 // We don't know enough about the type. Fail here and let runtime handle it.
2868                 Fail(VERIFY_ERROR_NO_CLASS) << "unresolved exception class " << exception;
2869                 return exception;
2870               } else {
2871                 Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "unexpected non-exception class " << exception;
2872                 return reg_types_.Conflict();
2873               }
2874             } else if (common_super->Equals(exception)) {
2875               // odd case, but nothing to do
2876             } else {
2877               common_super = &common_super->Merge(exception, &reg_types_);
2878               CHECK(reg_types_.JavaLangThrowable(false).IsAssignableFrom(*common_super));
2879             }
2880           }
2881         }
2882       }
2883       handlers_ptr = iterator.EndDataPointer();
2884     }
2885   }
2886   if (common_super == NULL) {
2887     /* no catch blocks, or no catches with classes we can find */
2888     Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "unable to find exception handler";
2889     return reg_types_.Conflict();
2890   }
2891   return *common_super;
2892 }
2893 
ResolveMethodAndCheckAccess(uint32_t dex_method_idx,MethodType method_type)2894 mirror::ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(uint32_t dex_method_idx,
2895                                                                     MethodType method_type) {
2896   const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx);
2897   const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_);
2898   if (klass_type.IsConflict()) {
2899     std::string append(" in attempt to access method ");
2900     append += dex_file_->GetMethodName(method_id);
2901     AppendToLastFailMessage(append);
2902     return NULL;
2903   }
2904   if (klass_type.IsUnresolvedTypes()) {
2905     return NULL;  // Can't resolve Class so no more to do here
2906   }
2907   mirror::Class* klass = klass_type.GetClass();
2908   const RegType& referrer = GetDeclaringClass();
2909   mirror::ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx);
2910   if (res_method == NULL) {
2911     const char* name = dex_file_->GetMethodName(method_id);
2912     std::string signature(dex_file_->CreateMethodSignature(method_id.proto_idx_, NULL));
2913 
2914     if (method_type == METHOD_DIRECT || method_type == METHOD_STATIC) {
2915       res_method = klass->FindDirectMethod(name, signature);
2916     } else if (method_type == METHOD_INTERFACE) {
2917       res_method = klass->FindInterfaceMethod(name, signature);
2918     } else {
2919       res_method = klass->FindVirtualMethod(name, signature);
2920     }
2921     if (res_method != NULL) {
2922       dex_cache_->SetResolvedMethod(dex_method_idx, res_method);
2923     } else {
2924       // If a virtual or interface method wasn't found with the expected type, look in
2925       // the direct methods. This can happen when the wrong invoke type is used or when
2926       // a class has changed, and will be flagged as an error in later checks.
2927       if (method_type == METHOD_INTERFACE || method_type == METHOD_VIRTUAL) {
2928         res_method = klass->FindDirectMethod(name, signature);
2929       }
2930       if (res_method == NULL) {
2931         Fail(VERIFY_ERROR_NO_METHOD) << "couldn't find method "
2932                                      << PrettyDescriptor(klass) << "." << name
2933                                      << " " << signature;
2934         return NULL;
2935       }
2936     }
2937   }
2938   // Make sure calls to constructors are "direct". There are additional restrictions but we don't
2939   // enforce them here.
2940   if (res_method->IsConstructor() && method_type != METHOD_DIRECT) {
2941     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "rejecting non-direct call to constructor "
2942                                       << PrettyMethod(res_method);
2943     return NULL;
2944   }
2945   // Disallow any calls to class initializers.
2946   if (MethodHelper(res_method).IsClassInitializer()) {
2947     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "rejecting call to class initializer "
2948                                       << PrettyMethod(res_method);
2949     return NULL;
2950   }
2951   // Check if access is allowed.
2952   if (!referrer.CanAccessMember(res_method->GetDeclaringClass(), res_method->GetAccessFlags())) {
2953     Fail(VERIFY_ERROR_ACCESS_METHOD) << "illegal method access (call " << PrettyMethod(res_method)
2954                                      << " from " << referrer << ")";
2955     return res_method;
2956   }
2957   // Check that invoke-virtual and invoke-super are not used on private methods of the same class.
2958   if (res_method->IsPrivate() && method_type == METHOD_VIRTUAL) {
2959     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invoke-super/virtual can't be used on private method "
2960                                       << PrettyMethod(res_method);
2961     return NULL;
2962   }
2963   // Check that interface methods match interface classes.
2964   if (klass->IsInterface() && method_type != METHOD_INTERFACE) {
2965     Fail(VERIFY_ERROR_CLASS_CHANGE) << "non-interface method " << PrettyMethod(res_method)
2966                                     << " is in an interface class " << PrettyClass(klass);
2967     return NULL;
2968   } else if (!klass->IsInterface() && method_type == METHOD_INTERFACE) {
2969     Fail(VERIFY_ERROR_CLASS_CHANGE) << "interface method " << PrettyMethod(res_method)
2970                                     << " is in a non-interface class " << PrettyClass(klass);
2971     return NULL;
2972   }
2973   // See if the method type implied by the invoke instruction matches the access flags for the
2974   // target method.
2975   if ((method_type == METHOD_DIRECT && !res_method->IsDirect()) ||
2976       (method_type == METHOD_STATIC && !res_method->IsStatic()) ||
2977       ((method_type == METHOD_VIRTUAL || method_type == METHOD_INTERFACE) && res_method->IsDirect())
2978       ) {
2979     Fail(VERIFY_ERROR_CLASS_CHANGE) << "invoke type (" << method_type << ") does not match method "
2980                                        " type of " << PrettyMethod(res_method);
2981     return NULL;
2982   }
2983   return res_method;
2984 }
2985 
VerifyInvocationArgs(const Instruction * inst,MethodType method_type,bool is_range,bool is_super)2986 mirror::ArtMethod* MethodVerifier::VerifyInvocationArgs(const Instruction* inst,
2987                                                              MethodType method_type,
2988                                                              bool is_range,
2989                                                              bool is_super) {
2990   // Resolve the method. This could be an abstract or concrete method depending on what sort of call
2991   // we're making.
2992   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
2993   mirror::ArtMethod* res_method = ResolveMethodAndCheckAccess(method_idx, method_type);
2994   if (res_method == NULL) {  // error or class is unresolved
2995     return NULL;
2996   }
2997 
2998   // If we're using invoke-super(method), make sure that the executing method's class' superclass
2999   // has a vtable entry for the target method.
3000   if (is_super) {
3001     DCHECK(method_type == METHOD_VIRTUAL);
3002     const RegType& super = GetDeclaringClass().GetSuperClass(&reg_types_);
3003     if (super.IsUnresolvedTypes()) {
3004       Fail(VERIFY_ERROR_NO_METHOD) << "unknown super class in invoke-super from "
3005                                    << PrettyMethod(dex_method_idx_, *dex_file_)
3006                                    << " to super " << PrettyMethod(res_method);
3007       return NULL;
3008     }
3009     mirror::Class* super_klass = super.GetClass();
3010     if (res_method->GetMethodIndex() >= super_klass->GetVTable()->GetLength()) {
3011       MethodHelper mh(res_method);
3012       Fail(VERIFY_ERROR_NO_METHOD) << "invalid invoke-super from "
3013                                    << PrettyMethod(dex_method_idx_, *dex_file_)
3014                                    << " to super " << super
3015                                    << "." << mh.GetName()
3016                                    << mh.GetSignature();
3017       return NULL;
3018     }
3019   }
3020   // We use vAA as our expected arg count, rather than res_method->insSize, because we need to
3021   // match the call to the signature. Also, we might be calling through an abstract method
3022   // definition (which doesn't have register count values).
3023   const size_t expected_args = (is_range) ? inst->VRegA_3rc() : inst->VRegA_35c();
3024   /* caught by static verifier */
3025   DCHECK(is_range || expected_args <= 5);
3026   if (expected_args > code_item_->outs_size_) {
3027     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid argument count (" << expected_args
3028         << ") exceeds outsSize (" << code_item_->outs_size_ << ")";
3029     return NULL;
3030   }
3031 
3032   /*
3033    * Check the "this" argument, which must be an instance of the class that declared the method.
3034    * For an interface class, we don't do the full interface merge (see JoinClass), so we can't do a
3035    * rigorous check here (which is okay since we have to do it at runtime).
3036    */
3037   size_t actual_args = 0;
3038   if (!res_method->IsStatic()) {
3039     const RegType& actual_arg_type = work_line_->GetInvocationThis(inst, is_range);
3040     if (actual_arg_type.IsConflict()) {  // GetInvocationThis failed.
3041       return NULL;
3042     }
3043     if (actual_arg_type.IsUninitializedReference() && !res_method->IsConstructor()) {
3044       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "'this' arg must be initialized";
3045       return NULL;
3046     }
3047     if (method_type != METHOD_INTERFACE && !actual_arg_type.IsZero()) {
3048       mirror::Class* klass = res_method->GetDeclaringClass();
3049       const RegType& res_method_class =
3050           reg_types_.FromClass(ClassHelper(klass).GetDescriptor(), klass,
3051                                klass->CannotBeAssignedFromOtherTypes());
3052       if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
3053         Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS:
3054             VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
3055             << "' not instance of '" << res_method_class << "'";
3056         return NULL;
3057       }
3058     }
3059     actual_args++;
3060   }
3061   /*
3062    * Process the target method's signature. This signature may or may not
3063    * have been verified, so we can't assume it's properly formed.
3064    */
3065   MethodHelper mh(res_method);
3066   const DexFile::TypeList* params = mh.GetParameterTypeList();
3067   size_t params_size = params == NULL ? 0 : params->Size();
3068   uint32_t arg[5];
3069   if (!is_range) {
3070     inst->GetArgs(arg);
3071   }
3072   for (size_t param_index = 0; param_index < params_size; param_index++) {
3073     if (actual_args >= expected_args) {
3074       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invalid call to '" << PrettyMethod(res_method)
3075           << "'. Expected " << expected_args << " arguments, processing argument " << actual_args
3076           << " (where longs/doubles count twice).";
3077       return NULL;
3078     }
3079     const char* descriptor =
3080         mh.GetTypeDescriptorFromTypeIdx(params->GetTypeItem(param_index).type_idx_);
3081     if (descriptor == NULL) {
3082       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation of " << PrettyMethod(res_method)
3083           << " missing signature component";
3084       return NULL;
3085     }
3086     const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
3087     uint32_t get_reg = is_range ? inst->VRegC_3rc() + actual_args : arg[actual_args];
3088     if (reg_type.IsIntegralTypes()) {
3089       const RegType& src_type = work_line_->GetRegisterType(get_reg);
3090       if (!src_type.IsIntegralTypes()) {
3091         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "register v" << get_reg << " has type " << src_type
3092                                           << " but expected " << reg_type;
3093         return res_method;
3094       }
3095     } else if (!work_line_->VerifyRegisterType(get_reg, reg_type)) {
3096       return res_method;
3097     }
3098     actual_args = reg_type.IsLongOrDoubleTypes() ? actual_args + 2 : actual_args + 1;
3099   }
3100   if (actual_args != expected_args) {
3101     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation of " << PrettyMethod(res_method)
3102         << " expected " << expected_args << " arguments, found " << actual_args;
3103     return NULL;
3104   } else {
3105     return res_method;
3106   }
3107 }
3108 
GetQuickInvokedMethod(const Instruction * inst,RegisterLine * reg_line,bool is_range)3109 mirror::ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst,
3110                                                               RegisterLine* reg_line,
3111                                                               bool is_range) {
3112   DCHECK(inst->Opcode() == Instruction::INVOKE_VIRTUAL_QUICK ||
3113          inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
3114   const RegType& actual_arg_type = reg_line->GetInvocationThis(inst, is_range);
3115   if (actual_arg_type.IsConflict()) {  // GetInvocationThis failed.
3116     return NULL;
3117   }
3118   mirror::Class* this_class = NULL;
3119   if (!actual_arg_type.IsUnresolvedTypes()) {
3120     this_class = actual_arg_type.GetClass();
3121   } else {
3122     const std::string& descriptor(actual_arg_type.GetDescriptor());
3123     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3124     this_class = class_linker->FindClass(descriptor.c_str(), class_loader_);
3125     if (this_class == NULL) {
3126       Thread::Current()->ClearException();
3127       // Look for a system class
3128       this_class = class_linker->FindClass(descriptor.c_str(), NULL);
3129     }
3130   }
3131   if (this_class == NULL) {
3132     return NULL;
3133   }
3134   mirror::ObjectArray<mirror::ArtMethod>* vtable = this_class->GetVTable();
3135   CHECK(vtable != NULL);
3136   uint16_t vtable_index = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
3137   CHECK(vtable_index < vtable->GetLength());
3138   mirror::ArtMethod* res_method = vtable->Get(vtable_index);
3139   CHECK(!Thread::Current()->IsExceptionPending());
3140   return res_method;
3141 }
3142 
VerifyInvokeVirtualQuickArgs(const Instruction * inst,bool is_range)3143 mirror::ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instruction* inst,
3144                                                                      bool is_range) {
3145   DCHECK(Runtime::Current()->IsStarted());
3146   mirror::ArtMethod* res_method = GetQuickInvokedMethod(inst, work_line_.get(),
3147                                                              is_range);
3148   if (res_method == NULL) {
3149     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer method from " << inst->Name();
3150     return NULL;
3151   }
3152   CHECK(!res_method->IsDirect() && !res_method->IsStatic());
3153 
3154   // We use vAA as our expected arg count, rather than res_method->insSize, because we need to
3155   // match the call to the signature. Also, we might be calling through an abstract method
3156   // definition (which doesn't have register count values).
3157   const RegType& actual_arg_type = work_line_->GetInvocationThis(inst, is_range);
3158   if (actual_arg_type.IsConflict()) {  // GetInvocationThis failed.
3159     return NULL;
3160   }
3161   const size_t expected_args = (is_range) ? inst->VRegA_3rc() : inst->VRegA_35c();
3162   /* caught by static verifier */
3163   DCHECK(is_range || expected_args <= 5);
3164   if (expected_args > code_item_->outs_size_) {
3165     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid argument count (" << expected_args
3166         << ") exceeds outsSize (" << code_item_->outs_size_ << ")";
3167     return NULL;
3168   }
3169 
3170   /*
3171    * Check the "this" argument, which must be an instance of the class that declared the method.
3172    * For an interface class, we don't do the full interface merge (see JoinClass), so we can't do a
3173    * rigorous check here (which is okay since we have to do it at runtime).
3174    */
3175   if (actual_arg_type.IsUninitializedReference() && !res_method->IsConstructor()) {
3176     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "'this' arg must be initialized";
3177     return NULL;
3178   }
3179   if (!actual_arg_type.IsZero()) {
3180     mirror::Class* klass = res_method->GetDeclaringClass();
3181     const RegType& res_method_class =
3182         reg_types_.FromClass(ClassHelper(klass).GetDescriptor(), klass,
3183                              klass->CannotBeAssignedFromOtherTypes());
3184     if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
3185       Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :
3186           VERIFY_ERROR_BAD_CLASS_SOFT) << "'this' argument '" << actual_arg_type
3187           << "' not instance of '" << res_method_class << "'";
3188       return NULL;
3189     }
3190   }
3191   /*
3192    * Process the target method's signature. This signature may or may not
3193    * have been verified, so we can't assume it's properly formed.
3194    */
3195   MethodHelper mh(res_method);
3196   const DexFile::TypeList* params = mh.GetParameterTypeList();
3197   size_t params_size = params == NULL ? 0 : params->Size();
3198   uint32_t arg[5];
3199   if (!is_range) {
3200     inst->GetArgs(arg);
3201   }
3202   size_t actual_args = 1;
3203   for (size_t param_index = 0; param_index < params_size; param_index++) {
3204     if (actual_args >= expected_args) {
3205       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invalid call to '" << PrettyMethod(res_method)
3206                                         << "'. Expected " << expected_args
3207                                          << " arguments, processing argument " << actual_args
3208                                         << " (where longs/doubles count twice).";
3209       return NULL;
3210     }
3211     const char* descriptor =
3212         mh.GetTypeDescriptorFromTypeIdx(params->GetTypeItem(param_index).type_idx_);
3213     if (descriptor == NULL) {
3214       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation of " << PrettyMethod(res_method)
3215                                         << " missing signature component";
3216       return NULL;
3217     }
3218     const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
3219     uint32_t get_reg = is_range ? inst->VRegC_3rc() + actual_args : arg[actual_args];
3220     if (!work_line_->VerifyRegisterType(get_reg, reg_type)) {
3221       return res_method;
3222     }
3223     actual_args = reg_type.IsLongOrDoubleTypes() ? actual_args + 2 : actual_args + 1;
3224   }
3225   if (actual_args != expected_args) {
3226     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Rejecting invocation of " << PrettyMethod(res_method)
3227               << " expected " << expected_args << " arguments, found " << actual_args;
3228     return NULL;
3229   } else {
3230     return res_method;
3231   }
3232 }
3233 
VerifyNewArray(const Instruction * inst,bool is_filled,bool is_range)3234 void MethodVerifier::VerifyNewArray(const Instruction* inst, bool is_filled, bool is_range) {
3235   uint32_t type_idx;
3236   if (!is_filled) {
3237     DCHECK_EQ(inst->Opcode(), Instruction::NEW_ARRAY);
3238     type_idx = inst->VRegC_22c();
3239   } else if (!is_range) {
3240     DCHECK_EQ(inst->Opcode(), Instruction::FILLED_NEW_ARRAY);
3241     type_idx = inst->VRegB_35c();
3242   } else {
3243     DCHECK_EQ(inst->Opcode(), Instruction::FILLED_NEW_ARRAY_RANGE);
3244     type_idx = inst->VRegB_3rc();
3245   }
3246   const RegType& res_type = ResolveClassAndCheckAccess(type_idx);
3247   if (res_type.IsConflict()) {  // bad class
3248     DCHECK_NE(failures_.size(), 0U);
3249   } else {
3250     // TODO: check Compiler::CanAccessTypeWithoutChecks returns false when res_type is unresolved
3251     if (!res_type.IsArrayTypes()) {
3252       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "new-array on non-array class " << res_type;
3253     } else if (!is_filled) {
3254       /* make sure "size" register is valid type */
3255       work_line_->VerifyRegisterType(inst->VRegB_22c(), reg_types_.Integer());
3256       /* set register type to array class */
3257       const RegType& precise_type = reg_types_.FromUninitialized(res_type);
3258       work_line_->SetRegisterType(inst->VRegA_22c(), precise_type);
3259     } else {
3260       // Verify each register. If "arg_count" is bad, VerifyRegisterType() will run off the end of
3261       // the list and fail. It's legal, if silly, for arg_count to be zero.
3262       const RegType& expected_type = reg_types_.GetComponentType(res_type, class_loader_);
3263       uint32_t arg_count = (is_range) ? inst->VRegA_3rc() : inst->VRegA_35c();
3264       uint32_t arg[5];
3265       if (!is_range) {
3266         inst->GetArgs(arg);
3267       }
3268       for (size_t ui = 0; ui < arg_count; ui++) {
3269         uint32_t get_reg = is_range ? inst->VRegC_3rc() + ui : arg[ui];
3270         if (!work_line_->VerifyRegisterType(get_reg, expected_type)) {
3271           work_line_->SetResultRegisterType(reg_types_.Conflict());
3272           return;
3273         }
3274       }
3275       // filled-array result goes into "result" register
3276       const RegType& precise_type = reg_types_.FromUninitialized(res_type);
3277       work_line_->SetResultRegisterType(precise_type);
3278     }
3279   }
3280 }
3281 
VerifyAGet(const Instruction * inst,const RegType & insn_type,bool is_primitive)3282 void MethodVerifier::VerifyAGet(const Instruction* inst,
3283                                 const RegType& insn_type, bool is_primitive) {
3284   const RegType& index_type = work_line_->GetRegisterType(inst->VRegC_23x());
3285   if (!index_type.IsArrayIndexTypes()) {
3286     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Invalid reg type for array index (" << index_type << ")";
3287   } else {
3288     const RegType& array_type = work_line_->GetRegisterType(inst->VRegB_23x());
3289     if (array_type.IsZero()) {
3290       // Null array class; this code path will fail at runtime. Infer a merge-able type from the
3291       // instruction type. TODO: have a proper notion of bottom here.
3292       if (!is_primitive || insn_type.IsCategory1Types()) {
3293         // Reference or category 1
3294         work_line_->SetRegisterType(inst->VRegA_23x(), reg_types_.Zero());
3295       } else {
3296         // Category 2
3297         work_line_->SetRegisterTypeWide(inst->VRegA_23x(), reg_types_.FromCat2ConstLo(0, false),
3298                                         reg_types_.FromCat2ConstHi(0, false));
3299       }
3300     } else if (!array_type.IsArrayTypes()) {
3301       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "not array type " << array_type << " with aget";
3302     } else {
3303       /* verify the class */
3304       const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_);
3305       if (!component_type.IsReferenceTypes() && !is_primitive) {
3306         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "primitive array type " << array_type
3307             << " source for aget-object";
3308       } else if (component_type.IsNonZeroReferenceTypes() && is_primitive) {
3309         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "reference array type " << array_type
3310             << " source for category 1 aget";
3311       } else if (is_primitive && !insn_type.Equals(component_type) &&
3312                  !((insn_type.IsInteger() && component_type.IsFloat()) ||
3313                  (insn_type.IsLong() && component_type.IsDouble()))) {
3314         Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "array type " << array_type
3315             << " incompatible with aget of type " << insn_type;
3316       } else {
3317         // Use knowledge of the field type which is stronger than the type inferred from the
3318         // instruction, which can't differentiate object types and ints from floats, longs from
3319         // doubles.
3320         if (!component_type.IsLowHalf()) {
3321           work_line_->SetRegisterType(inst->VRegA_23x(), component_type);
3322         } else {
3323           work_line_->SetRegisterTypeWide(inst->VRegA_23x(), component_type,
3324                                           component_type.HighHalf(&reg_types_));
3325         }
3326       }
3327     }
3328   }
3329 }
3330 
VerifyPrimitivePut(const RegType & target_type,const RegType & insn_type,const uint32_t vregA)3331 void MethodVerifier::VerifyPrimitivePut(const RegType& target_type, const RegType& insn_type,
3332                                         const uint32_t vregA) {
3333   // Primitive assignability rules are weaker than regular assignability rules.
3334   bool instruction_compatible;
3335   bool value_compatible;
3336   const RegType& value_type = work_line_->GetRegisterType(vregA);
3337   if (target_type.IsIntegralTypes()) {
3338     instruction_compatible = target_type.Equals(insn_type);
3339     value_compatible = value_type.IsIntegralTypes();
3340   } else if (target_type.IsFloat()) {
3341     instruction_compatible = insn_type.IsInteger();  // no put-float, so expect put-int
3342     value_compatible = value_type.IsFloatTypes();
3343   } else if (target_type.IsLong()) {
3344     instruction_compatible = insn_type.IsLong();
3345     value_compatible = value_type.IsLongTypes();
3346   } else if (target_type.IsDouble()) {
3347     instruction_compatible = insn_type.IsLong();  // no put-double, so expect put-long
3348     value_compatible = value_type.IsDoubleTypes();
3349   } else {
3350     instruction_compatible = false;  // reference with primitive store
3351     value_compatible = false;  // unused
3352   }
3353   if (!instruction_compatible) {
3354     // This is a global failure rather than a class change failure as the instructions and
3355     // the descriptors for the type should have been consistent within the same file at
3356     // compile time.
3357     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "put insn has type '" << insn_type
3358         << "' but expected type '" << target_type << "'";
3359     return;
3360   }
3361   if (!value_compatible) {
3362     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected value in v" << vregA
3363         << " of type " << value_type << " but expected " << target_type << " for put";
3364     return;
3365   }
3366 }
3367 
VerifyAPut(const Instruction * inst,const RegType & insn_type,bool is_primitive)3368 void MethodVerifier::VerifyAPut(const Instruction* inst,
3369                              const RegType& insn_type, bool is_primitive) {
3370   const RegType& index_type = work_line_->GetRegisterType(inst->VRegC_23x());
3371   if (!index_type.IsArrayIndexTypes()) {
3372     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Invalid reg type for array index (" << index_type << ")";
3373   } else {
3374     const RegType& array_type = work_line_->GetRegisterType(inst->VRegB_23x());
3375     if (array_type.IsZero()) {
3376       // Null array type; this code path will fail at runtime. Infer a merge-able type from the
3377       // instruction type.
3378     } else if (!array_type.IsArrayTypes()) {
3379       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "not array type " << array_type << " with aput";
3380     } else {
3381       const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_);
3382       const uint32_t vregA = inst->VRegA_23x();
3383       if (is_primitive) {
3384         VerifyPrimitivePut(component_type, insn_type, vregA);
3385       } else {
3386         if (!component_type.IsReferenceTypes()) {
3387           Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "primitive array type " << array_type
3388               << " source for aput-object";
3389         } else {
3390           // The instruction agrees with the type of array, confirm the value to be stored does too
3391           // Note: we use the instruction type (rather than the component type) for aput-object as
3392           // incompatible classes will be caught at runtime as an array store exception
3393           work_line_->VerifyRegisterType(vregA, insn_type);
3394         }
3395       }
3396     }
3397   }
3398 }
3399 
GetStaticField(int field_idx)3400 mirror::ArtField* MethodVerifier::GetStaticField(int field_idx) {
3401   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
3402   // Check access to class
3403   const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
3404   if (klass_type.IsConflict()) {  // bad class
3405     AppendToLastFailMessage(StringPrintf(" in attempt to access static field %d (%s) in %s",
3406                                          field_idx, dex_file_->GetFieldName(field_id),
3407                                          dex_file_->GetFieldDeclaringClassDescriptor(field_id)));
3408     return NULL;
3409   }
3410   if (klass_type.IsUnresolvedTypes()) {
3411     return NULL;  // Can't resolve Class so no more to do here, will do checking at runtime.
3412   }
3413   mirror::ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_,
3414                                                                                field_idx,
3415                                                                                dex_cache_,
3416                                                                                class_loader_);
3417   if (field == NULL) {
3418     VLOG(verifier) << "Unable to resolve static field " << field_idx << " ("
3419               << dex_file_->GetFieldName(field_id) << ") in "
3420               << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
3421     DCHECK(Thread::Current()->IsExceptionPending());
3422     Thread::Current()->ClearException();
3423     return NULL;
3424   } else if (!GetDeclaringClass().CanAccessMember(field->GetDeclaringClass(),
3425                                                   field->GetAccessFlags())) {
3426     Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot access static field " << PrettyField(field)
3427                                     << " from " << GetDeclaringClass();
3428     return NULL;
3429   } else if (!field->IsStatic()) {
3430     Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected field " << PrettyField(field) << " to be static";
3431     return NULL;
3432   } else {
3433     return field;
3434   }
3435 }
3436 
GetInstanceField(const RegType & obj_type,int field_idx)3437 mirror::ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
3438   const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
3439   // Check access to class
3440   const RegType& klass_type = ResolveClassAndCheckAccess(field_id.class_idx_);
3441   if (klass_type.IsConflict()) {
3442     AppendToLastFailMessage(StringPrintf(" in attempt to access instance field %d (%s) in %s",
3443                                          field_idx, dex_file_->GetFieldName(field_id),
3444                                          dex_file_->GetFieldDeclaringClassDescriptor(field_id)));
3445     return NULL;
3446   }
3447   if (klass_type.IsUnresolvedTypes()) {
3448     return NULL;  // Can't resolve Class so no more to do here
3449   }
3450   mirror::ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_,
3451                                                                                field_idx,
3452                                                                                dex_cache_,
3453                                                                                class_loader_);
3454   if (field == NULL) {
3455     VLOG(verifier) << "Unable to resolve instance field " << field_idx << " ("
3456               << dex_file_->GetFieldName(field_id) << ") in "
3457               << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
3458     DCHECK(Thread::Current()->IsExceptionPending());
3459     Thread::Current()->ClearException();
3460     return NULL;
3461   } else if (!GetDeclaringClass().CanAccessMember(field->GetDeclaringClass(),
3462                                                   field->GetAccessFlags())) {
3463     Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot access instance field " << PrettyField(field)
3464                                     << " from " << GetDeclaringClass();
3465     return NULL;
3466   } else if (field->IsStatic()) {
3467     Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected field " << PrettyField(field)
3468                                     << " to not be static";
3469     return NULL;
3470   } else if (obj_type.IsZero()) {
3471     // Cannot infer and check type, however, access will cause null pointer exception
3472     return field;
3473   } else {
3474     mirror::Class* klass = field->GetDeclaringClass();
3475     const RegType& field_klass =
3476         reg_types_.FromClass(dex_file_->GetFieldDeclaringClassDescriptor(field_id),
3477                              klass, klass->CannotBeAssignedFromOtherTypes());
3478     if (obj_type.IsUninitializedTypes() &&
3479         (!IsConstructor() || GetDeclaringClass().Equals(obj_type) ||
3480             !field_klass.Equals(GetDeclaringClass()))) {
3481       // Field accesses through uninitialized references are only allowable for constructors where
3482       // the field is declared in this class
3483       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "cannot access instance field " << PrettyField(field)
3484                                         << " of a not fully initialized object within the context"
3485                                         << " of " << PrettyMethod(dex_method_idx_, *dex_file_);
3486       return NULL;
3487     } else if (!field_klass.IsAssignableFrom(obj_type)) {
3488       // Trying to access C1.field1 using reference of type C2, which is neither C1 or a sub-class
3489       // of C1. For resolution to occur the declared class of the field must be compatible with
3490       // obj_type, we've discovered this wasn't so, so report the field didn't exist.
3491       Fail(VERIFY_ERROR_NO_FIELD) << "cannot access instance field " << PrettyField(field)
3492                                   << " from object of type " << obj_type;
3493       return NULL;
3494     } else {
3495       return field;
3496     }
3497   }
3498 }
3499 
VerifyISGet(const Instruction * inst,const RegType & insn_type,bool is_primitive,bool is_static)3500 void MethodVerifier::VerifyISGet(const Instruction* inst, const RegType& insn_type,
3501                                  bool is_primitive, bool is_static) {
3502   uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
3503   mirror::ArtField* field;
3504   if (is_static) {
3505     field = GetStaticField(field_idx);
3506   } else {
3507     const RegType& object_type = work_line_->GetRegisterType(inst->VRegB_22c());
3508     field = GetInstanceField(object_type, field_idx);
3509   }
3510   const char* descriptor;
3511   mirror::ClassLoader* loader;
3512   if (field != NULL) {
3513     descriptor = FieldHelper(field).GetTypeDescriptor();
3514     loader = field->GetDeclaringClass()->GetClassLoader();
3515   } else {
3516     const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
3517     descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
3518     loader = class_loader_;
3519   }
3520   const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
3521   const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c();
3522   if (is_primitive) {
3523     if (field_type.Equals(insn_type) ||
3524         (field_type.IsFloat() && insn_type.IsInteger()) ||
3525         (field_type.IsDouble() && insn_type.IsLong())) {
3526       // expected that read is of the correct primitive type or that int reads are reading
3527       // floats or long reads are reading doubles
3528     } else {
3529       // This is a global failure rather than a class change failure as the instructions and
3530       // the descriptors for the type should have been consistent within the same file at
3531       // compile time
3532       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected field " << PrettyField(field)
3533                                         << " to be of type '" << insn_type
3534                                         << "' but found type '" << field_type << "' in get";
3535       return;
3536     }
3537   } else {
3538     if (!insn_type.IsAssignableFrom(field_type)) {
3539       Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
3540                                         << " to be compatible with type '" << insn_type
3541                                         << "' but found type '" << field_type
3542                                         << "' in get-object";
3543       work_line_->SetRegisterType(vregA, reg_types_.Conflict());
3544       return;
3545     }
3546   }
3547   if (!field_type.IsLowHalf()) {
3548     work_line_->SetRegisterType(vregA, field_type);
3549   } else {
3550     work_line_->SetRegisterTypeWide(vregA, field_type, field_type.HighHalf(&reg_types_));
3551   }
3552 }
3553 
VerifyISPut(const Instruction * inst,const RegType & insn_type,bool is_primitive,bool is_static)3554 void MethodVerifier::VerifyISPut(const Instruction* inst, const RegType& insn_type,
3555                                  bool is_primitive, bool is_static) {
3556   uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
3557   mirror::ArtField* field;
3558   if (is_static) {
3559     field = GetStaticField(field_idx);
3560   } else {
3561     const RegType& object_type = work_line_->GetRegisterType(inst->VRegB_22c());
3562     field = GetInstanceField(object_type, field_idx);
3563   }
3564   const char* descriptor;
3565   mirror::ClassLoader* loader;
3566   if (field != NULL) {
3567     descriptor = FieldHelper(field).GetTypeDescriptor();
3568     loader = field->GetDeclaringClass()->GetClassLoader();
3569   } else {
3570     const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
3571     descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
3572     loader = class_loader_;
3573   }
3574   const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
3575   if (field != NULL) {
3576     if (field->IsFinal() && field->GetDeclaringClass() != GetDeclaringClass().GetClass()) {
3577       Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
3578                                       << " from other class " << GetDeclaringClass();
3579       return;
3580     }
3581   }
3582   const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c();
3583   if (is_primitive) {
3584     VerifyPrimitivePut(field_type, insn_type, vregA);
3585   } else {
3586     if (!insn_type.IsAssignableFrom(field_type)) {
3587       Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
3588                                         << " to be compatible with type '" << insn_type
3589                                         << "' but found type '" << field_type
3590                                         << "' in put-object";
3591       return;
3592     }
3593     work_line_->VerifyRegisterType(vregA, field_type);
3594   }
3595 }
3596 
3597 // Look for an instance field with this offset.
3598 // TODO: we may speed up the search if offsets are sorted by doing a quick search.
FindInstanceFieldWithOffset(const mirror::Class * klass,uint32_t field_offset)3599 static mirror::ArtField* FindInstanceFieldWithOffset(const mirror::Class* klass,
3600                                                   uint32_t field_offset)
3601     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
3602   const mirror::ObjectArray<mirror::ArtField>* instance_fields = klass->GetIFields();
3603   if (instance_fields != NULL) {
3604     for (int32_t i = 0, e = instance_fields->GetLength(); i < e; ++i) {
3605       mirror::ArtField* field = instance_fields->Get(i);
3606       if (field->GetOffset().Uint32Value() == field_offset) {
3607         return field;
3608       }
3609     }
3610   }
3611   // We did not find field in class: look into superclass.
3612   if (klass->GetSuperClass() != NULL) {
3613     return FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset);
3614   } else {
3615     return NULL;
3616   }
3617 }
3618 
3619 // Returns the access field of a quick field access (iget/iput-quick) or NULL
3620 // if it cannot be found.
GetQuickFieldAccess(const Instruction * inst,RegisterLine * reg_line)3621 mirror::ArtField* MethodVerifier::GetQuickFieldAccess(const Instruction* inst,
3622                                                    RegisterLine* reg_line) {
3623   DCHECK(inst->Opcode() == Instruction::IGET_QUICK ||
3624          inst->Opcode() == Instruction::IGET_WIDE_QUICK ||
3625          inst->Opcode() == Instruction::IGET_OBJECT_QUICK ||
3626          inst->Opcode() == Instruction::IPUT_QUICK ||
3627          inst->Opcode() == Instruction::IPUT_WIDE_QUICK ||
3628          inst->Opcode() == Instruction::IPUT_OBJECT_QUICK);
3629   const RegType& object_type = reg_line->GetRegisterType(inst->VRegB_22c());
3630   mirror::Class* object_class = NULL;
3631   if (!object_type.IsUnresolvedTypes()) {
3632     object_class = object_type.GetClass();
3633   } else {
3634     // We need to resolve the class from its descriptor.
3635     const std::string& descriptor(object_type.GetDescriptor());
3636     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3637     object_class = class_linker->FindClass(descriptor.c_str(), class_loader_);
3638     if (object_class == NULL) {
3639       Thread::Current()->ClearException();
3640       // Look for a system class
3641       object_class = class_linker->FindClass(descriptor.c_str(), NULL);
3642     }
3643   }
3644   if (object_class == NULL) {
3645     // Failed to get the Class* from reg type.
3646     LOG(WARNING) << "Failed to get Class* from " << object_type;
3647     return NULL;
3648   }
3649   uint32_t field_offset = static_cast<uint32_t>(inst->VRegC_22c());
3650   return FindInstanceFieldWithOffset(object_class, field_offset);
3651 }
3652 
VerifyIGetQuick(const Instruction * inst,const RegType & insn_type,bool is_primitive)3653 void MethodVerifier::VerifyIGetQuick(const Instruction* inst, const RegType& insn_type,
3654                                      bool is_primitive) {
3655   DCHECK(Runtime::Current()->IsStarted());
3656   mirror::ArtField* field = GetQuickFieldAccess(inst, work_line_.get());
3657   if (field == NULL) {
3658     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field from " << inst->Name();
3659     return;
3660   }
3661   const char* descriptor = FieldHelper(field).GetTypeDescriptor();
3662   mirror::ClassLoader* loader = field->GetDeclaringClass()->GetClassLoader();
3663   const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
3664   const uint32_t vregA = inst->VRegA_22c();
3665   if (is_primitive) {
3666     if (field_type.Equals(insn_type) ||
3667         (field_type.IsFloat() && insn_type.IsIntegralTypes()) ||
3668         (field_type.IsDouble() && insn_type.IsLongTypes())) {
3669       // expected that read is of the correct primitive type or that int reads are reading
3670       // floats or long reads are reading doubles
3671     } else {
3672       // This is a global failure rather than a class change failure as the instructions and
3673       // the descriptors for the type should have been consistent within the same file at
3674       // compile time
3675       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected field " << PrettyField(field)
3676                                         << " to be of type '" << insn_type
3677                                         << "' but found type '" << field_type << "' in get";
3678       return;
3679     }
3680   } else {
3681     if (!insn_type.IsAssignableFrom(field_type)) {
3682       Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
3683                                         << " to be compatible with type '" << insn_type
3684                                         << "' but found type '" << field_type
3685                                         << "' in get-object";
3686       work_line_->SetRegisterType(vregA, reg_types_.Conflict());
3687       return;
3688     }
3689   }
3690   if (!field_type.IsLowHalf()) {
3691     work_line_->SetRegisterType(vregA, field_type);
3692   } else {
3693     work_line_->SetRegisterTypeWide(vregA, field_type, field_type.HighHalf(&reg_types_));
3694   }
3695 }
3696 
VerifyIPutQuick(const Instruction * inst,const RegType & insn_type,bool is_primitive)3697 void MethodVerifier::VerifyIPutQuick(const Instruction* inst, const RegType& insn_type,
3698                                      bool is_primitive) {
3699   DCHECK(Runtime::Current()->IsStarted());
3700   mirror::ArtField* field = GetQuickFieldAccess(inst, work_line_.get());
3701   if (field == NULL) {
3702     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot infer field from " << inst->Name();
3703     return;
3704   }
3705   const char* descriptor = FieldHelper(field).GetTypeDescriptor();
3706   mirror::ClassLoader* loader = field->GetDeclaringClass()->GetClassLoader();
3707   const RegType& field_type = reg_types_.FromDescriptor(loader, descriptor, false);
3708   if (field != NULL) {
3709     if (field->IsFinal() && field->GetDeclaringClass() != GetDeclaringClass().GetClass()) {
3710       Fail(VERIFY_ERROR_ACCESS_FIELD) << "cannot modify final field " << PrettyField(field)
3711                                       << " from other class " << GetDeclaringClass();
3712       return;
3713     }
3714   }
3715   const uint32_t vregA = inst->VRegA_22c();
3716   if (is_primitive) {
3717     // Primitive field assignability rules are weaker than regular assignability rules
3718     bool instruction_compatible;
3719     bool value_compatible;
3720     const RegType& value_type = work_line_->GetRegisterType(vregA);
3721     if (field_type.IsIntegralTypes()) {
3722       instruction_compatible = insn_type.IsIntegralTypes();
3723       value_compatible = value_type.IsIntegralTypes();
3724     } else if (field_type.IsFloat()) {
3725       instruction_compatible = insn_type.IsInteger();  // no [is]put-float, so expect [is]put-int
3726       value_compatible = value_type.IsFloatTypes();
3727     } else if (field_type.IsLong()) {
3728       instruction_compatible = insn_type.IsLong();
3729       value_compatible = value_type.IsLongTypes();
3730     } else if (field_type.IsDouble()) {
3731       instruction_compatible = insn_type.IsLong();  // no [is]put-double, so expect [is]put-long
3732       value_compatible = value_type.IsDoubleTypes();
3733     } else {
3734       instruction_compatible = false;  // reference field with primitive store
3735       value_compatible = false;  // unused
3736     }
3737     if (!instruction_compatible) {
3738       // This is a global failure rather than a class change failure as the instructions and
3739       // the descriptors for the type should have been consistent within the same file at
3740       // compile time
3741       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "expected field " << PrettyField(field)
3742                                         << " to be of type '" << insn_type
3743                                         << "' but found type '" << field_type
3744                                         << "' in put";
3745       return;
3746     }
3747     if (!value_compatible) {
3748       Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "unexpected value in v" << vregA
3749           << " of type " << value_type
3750           << " but expected " << field_type
3751           << " for store to " << PrettyField(field) << " in put";
3752       return;
3753     }
3754   } else {
3755     if (!insn_type.IsAssignableFrom(field_type)) {
3756       Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "expected field " << PrettyField(field)
3757                                         << " to be compatible with type '" << insn_type
3758                                         << "' but found type '" << field_type
3759                                         << "' in put-object";
3760       return;
3761     }
3762     work_line_->VerifyRegisterType(vregA, field_type);
3763   }
3764 }
3765 
CheckNotMoveException(const uint16_t * insns,int insn_idx)3766 bool MethodVerifier::CheckNotMoveException(const uint16_t* insns, int insn_idx) {
3767   if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
3768     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid use of move-exception";
3769     return false;
3770   }
3771   return true;
3772 }
3773 
UpdateRegisters(uint32_t next_insn,const RegisterLine * merge_line)3774 bool MethodVerifier::UpdateRegisters(uint32_t next_insn, const RegisterLine* merge_line) {
3775   bool changed = true;
3776   RegisterLine* target_line = reg_table_.GetLine(next_insn);
3777   if (!insn_flags_[next_insn].IsVisitedOrChanged()) {
3778     /*
3779      * We haven't processed this instruction before, and we haven't touched the registers here, so
3780      * there's nothing to "merge". Copy the registers over and mark it as changed. (This is the
3781      * only way a register can transition out of "unknown", so this is not just an optimization.)
3782      */
3783     if (!insn_flags_[next_insn].IsReturn()) {
3784       target_line->CopyFromLine(merge_line);
3785     } else {
3786       // Verify that the monitor stack is empty on return.
3787       if (!merge_line->VerifyMonitorStackEmpty()) {
3788         return false;
3789       }
3790       // For returns we only care about the operand to the return, all other registers are dead.
3791       // Initialize them as conflicts so they don't add to GC and deoptimization information.
3792       const Instruction* ret_inst = Instruction::At(code_item_->insns_ + next_insn);
3793       Instruction::Code opcode = ret_inst->Opcode();
3794       if ((opcode == Instruction::RETURN_VOID) || (opcode == Instruction::RETURN_VOID_BARRIER)) {
3795         target_line->MarkAllRegistersAsConflicts();
3796       } else {
3797         target_line->CopyFromLine(merge_line);
3798         if (opcode == Instruction::RETURN_WIDE) {
3799           target_line->MarkAllRegistersAsConflictsExceptWide(ret_inst->VRegA_11x());
3800         } else {
3801           target_line->MarkAllRegistersAsConflictsExcept(ret_inst->VRegA_11x());
3802         }
3803       }
3804     }
3805   } else {
3806     UniquePtr<RegisterLine> copy(gDebugVerify ?
3807                                  new RegisterLine(target_line->NumRegs(), this) :
3808                                  NULL);
3809     if (gDebugVerify) {
3810       copy->CopyFromLine(target_line);
3811     }
3812     changed = target_line->MergeRegisters(merge_line);
3813     if (have_pending_hard_failure_) {
3814       return false;
3815     }
3816     if (gDebugVerify && changed) {
3817       LogVerifyInfo() << "Merging at [" << reinterpret_cast<void*>(work_insn_idx_) << "]"
3818                       << " to [" << reinterpret_cast<void*>(next_insn) << "]: " << "\n"
3819                       << *copy.get() << "  MERGE\n"
3820                       << *merge_line << "  ==\n"
3821                       << *target_line << "\n";
3822     }
3823   }
3824   if (changed) {
3825     insn_flags_[next_insn].SetChanged();
3826   }
3827   return true;
3828 }
3829 
CurrentInsnFlags()3830 InstructionFlags* MethodVerifier::CurrentInsnFlags() {
3831   return &insn_flags_[work_insn_idx_];
3832 }
3833 
GetMethodReturnType()3834 const RegType& MethodVerifier::GetMethodReturnType() {
3835   const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
3836   const DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id);
3837   uint16_t return_type_idx = proto_id.return_type_idx_;
3838   const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(return_type_idx));
3839   return reg_types_.FromDescriptor(class_loader_, descriptor, false);
3840 }
3841 
GetDeclaringClass()3842 const RegType& MethodVerifier::GetDeclaringClass() {
3843   if (declaring_class_ == NULL) {
3844     const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_);
3845     const char* descriptor
3846         = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_));
3847     if (mirror_method_ != NULL) {
3848       mirror::Class* klass = mirror_method_->GetDeclaringClass();
3849       declaring_class_ = &reg_types_.FromClass(descriptor, klass,
3850                                                klass->CannotBeAssignedFromOtherTypes());
3851     } else {
3852       declaring_class_ = &reg_types_.FromDescriptor(class_loader_, descriptor, false);
3853     }
3854   }
3855   return *declaring_class_;
3856 }
3857 
ComputeGcMapSizes(size_t * gc_points,size_t * ref_bitmap_bits,size_t * log2_max_gc_pc)3858 void MethodVerifier::ComputeGcMapSizes(size_t* gc_points, size_t* ref_bitmap_bits,
3859                                        size_t* log2_max_gc_pc) {
3860   size_t local_gc_points = 0;
3861   size_t max_insn = 0;
3862   size_t max_ref_reg = -1;
3863   for (size_t i = 0; i < code_item_->insns_size_in_code_units_; i++) {
3864     if (insn_flags_[i].IsCompileTimeInfoPoint()) {
3865       local_gc_points++;
3866       max_insn = i;
3867       RegisterLine* line = reg_table_.GetLine(i);
3868       max_ref_reg = line->GetMaxNonZeroReferenceReg(max_ref_reg);
3869     }
3870   }
3871   *gc_points = local_gc_points;
3872   *ref_bitmap_bits = max_ref_reg + 1;  // if max register is 0 we need 1 bit to encode (ie +1)
3873   size_t i = 0;
3874   while ((1U << i) <= max_insn) {
3875     i++;
3876   }
3877   *log2_max_gc_pc = i;
3878 }
3879 
GenerateSafeCastSet()3880 MethodVerifier::MethodSafeCastSet* MethodVerifier::GenerateSafeCastSet() {
3881   /*
3882    * Walks over the method code and adds any cast instructions in which
3883    * the type cast is implicit to a set, which is used in the code generation
3884    * to elide these casts.
3885    */
3886   if (!failure_messages_.empty()) {
3887     return NULL;
3888   }
3889   UniquePtr<MethodSafeCastSet> mscs;
3890   const Instruction* inst = Instruction::At(code_item_->insns_);
3891   const Instruction* end = Instruction::At(code_item_->insns_ +
3892                                            code_item_->insns_size_in_code_units_);
3893 
3894   for (; inst < end; inst = inst->Next()) {
3895     if (Instruction::CHECK_CAST != inst->Opcode()) {
3896       continue;
3897     }
3898     uint32_t dex_pc = inst->GetDexPc(code_item_->insns_);
3899     RegisterLine* line = reg_table_.GetLine(dex_pc);
3900     const RegType& reg_type(line->GetRegisterType(inst->VRegA_21c()));
3901     const RegType& cast_type = ResolveClassAndCheckAccess(inst->VRegB_21c());
3902     if (cast_type.IsStrictlyAssignableFrom(reg_type)) {
3903       if (mscs.get() == NULL) {
3904         mscs.reset(new MethodSafeCastSet());
3905       }
3906       mscs->insert(dex_pc);
3907     }
3908   }
3909   return mscs.release();
3910 }
3911 
GenerateDevirtMap()3912 MethodVerifier::PcToConcreteMethodMap* MethodVerifier::GenerateDevirtMap() {
3913   // It is risky to rely on reg_types for sharpening in cases of soft
3914   // verification, we might end up sharpening to a wrong implementation. Just abort.
3915   if (!failure_messages_.empty()) {
3916     return NULL;
3917   }
3918 
3919   UniquePtr<PcToConcreteMethodMap> pc_to_concrete_method_map;
3920   const uint16_t* insns = code_item_->insns_;
3921   const Instruction* inst = Instruction::At(insns);
3922   const Instruction* end = Instruction::At(insns + code_item_->insns_size_in_code_units_);
3923 
3924   for (; inst < end; inst = inst->Next()) {
3925     bool is_virtual   = (inst->Opcode() == Instruction::INVOKE_VIRTUAL) ||
3926         (inst->Opcode() ==  Instruction::INVOKE_VIRTUAL_RANGE);
3927     bool is_interface = (inst->Opcode() == Instruction::INVOKE_INTERFACE) ||
3928         (inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE);
3929 
3930     if (!is_interface && !is_virtual) {
3931       continue;
3932     }
3933     // Get reg type for register holding the reference to the object that will be dispatched upon.
3934     uint32_t dex_pc = inst->GetDexPc(insns);
3935     RegisterLine* line = reg_table_.GetLine(dex_pc);
3936     bool is_range = (inst->Opcode() ==  Instruction::INVOKE_VIRTUAL_RANGE) ||
3937         (inst->Opcode() ==  Instruction::INVOKE_INTERFACE_RANGE);
3938     const RegType&
3939         reg_type(line->GetRegisterType(is_range ? inst->VRegC_3rc() : inst->VRegC_35c()));
3940 
3941     if (!reg_type.HasClass()) {
3942       // We will compute devirtualization information only when we know the Class of the reg type.
3943       continue;
3944     }
3945     mirror::Class* reg_class = reg_type.GetClass();
3946     if (reg_class->IsInterface()) {
3947       // We can't devirtualize when the known type of the register is an interface.
3948       continue;
3949     }
3950     if (reg_class->IsAbstract() && !reg_class->IsArrayClass()) {
3951       // We can't devirtualize abstract classes except on arrays of abstract classes.
3952       continue;
3953     }
3954     mirror::ArtMethod* abstract_method =
3955         dex_cache_->GetResolvedMethod(is_range ? inst->VRegB_3rc() : inst->VRegB_35c());
3956     if (abstract_method == NULL) {
3957       // If the method is not found in the cache this means that it was never found
3958       // by ResolveMethodAndCheckAccess() called when verifying invoke_*.
3959       continue;
3960     }
3961     // Find the concrete method.
3962     mirror::ArtMethod* concrete_method = NULL;
3963     if (is_interface) {
3964       concrete_method = reg_type.GetClass()->FindVirtualMethodForInterface(abstract_method);
3965     }
3966     if (is_virtual) {
3967       concrete_method = reg_type.GetClass()->FindVirtualMethodForVirtual(abstract_method);
3968     }
3969     if (concrete_method == NULL || concrete_method->IsAbstract()) {
3970       // In cases where concrete_method is not found, or is abstract, continue to the next invoke.
3971       continue;
3972     }
3973     if (reg_type.IsPreciseReference() || concrete_method->IsFinal() ||
3974         concrete_method->GetDeclaringClass()->IsFinal()) {
3975       // If we knew exactly the class being dispatched upon, or if the target method cannot be
3976       // overridden record the target to be used in the compiler driver.
3977       if (pc_to_concrete_method_map.get() == NULL) {
3978         pc_to_concrete_method_map.reset(new PcToConcreteMethodMap());
3979       }
3980       MethodReference concrete_ref(
3981           concrete_method->GetDeclaringClass()->GetDexCache()->GetDexFile(),
3982           concrete_method->GetDexMethodIndex());
3983       pc_to_concrete_method_map->Put(dex_pc, concrete_ref);
3984     }
3985   }
3986   return pc_to_concrete_method_map.release();
3987 }
3988 
GenerateGcMap()3989 const std::vector<uint8_t>* MethodVerifier::GenerateGcMap() {
3990   size_t num_entries, ref_bitmap_bits, pc_bits;
3991   ComputeGcMapSizes(&num_entries, &ref_bitmap_bits, &pc_bits);
3992   // There's a single byte to encode the size of each bitmap
3993   if (ref_bitmap_bits >= (8 /* bits per byte */ * 8192 /* 13-bit size */ )) {
3994     // TODO: either a better GC map format or per method failures
3995     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot encode GC map for method with "
3996        << ref_bitmap_bits << " registers";
3997     return NULL;
3998   }
3999   size_t ref_bitmap_bytes = (ref_bitmap_bits + 7) / 8;
4000   // There are 2 bytes to encode the number of entries
4001   if (num_entries >= 65536) {
4002     // TODO: either a better GC map format or per method failures
4003     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot encode GC map for method with "
4004        << num_entries << " entries";
4005     return NULL;
4006   }
4007   size_t pc_bytes;
4008   RegisterMapFormat format;
4009   if (pc_bits <= 8) {
4010     format = kRegMapFormatCompact8;
4011     pc_bytes = 1;
4012   } else if (pc_bits <= 16) {
4013     format = kRegMapFormatCompact16;
4014     pc_bytes = 2;
4015   } else {
4016     // TODO: either a better GC map format or per method failures
4017     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot encode GC map for method with "
4018        << (1 << pc_bits) << " instructions (number is rounded up to nearest power of 2)";
4019     return NULL;
4020   }
4021   size_t table_size = ((pc_bytes + ref_bitmap_bytes) * num_entries) + 4;
4022   std::vector<uint8_t>* table = new std::vector<uint8_t>;
4023   if (table == NULL) {
4024     Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "Failed to encode GC map (size=" << table_size << ")";
4025     return NULL;
4026   }
4027   table->reserve(table_size);
4028   // Write table header
4029   table->push_back(format | ((ref_bitmap_bytes >> DexPcToReferenceMap::kRegMapFormatShift) &
4030                              ~DexPcToReferenceMap::kRegMapFormatMask));
4031   table->push_back(ref_bitmap_bytes & 0xFF);
4032   table->push_back(num_entries & 0xFF);
4033   table->push_back((num_entries >> 8) & 0xFF);
4034   // Write table data
4035   for (size_t i = 0; i < code_item_->insns_size_in_code_units_; i++) {
4036     if (insn_flags_[i].IsCompileTimeInfoPoint()) {
4037       table->push_back(i & 0xFF);
4038       if (pc_bytes == 2) {
4039         table->push_back((i >> 8) & 0xFF);
4040       }
4041       RegisterLine* line = reg_table_.GetLine(i);
4042       line->WriteReferenceBitMap(*table, ref_bitmap_bytes);
4043     }
4044   }
4045   DCHECK_EQ(table->size(), table_size);
4046   return table;
4047 }
4048 
VerifyGcMap(const std::vector<uint8_t> & data)4049 void MethodVerifier::VerifyGcMap(const std::vector<uint8_t>& data) {
4050   // Check that for every GC point there is a map entry, there aren't entries for non-GC points,
4051   // that the table data is well formed and all references are marked (or not) in the bitmap
4052   DexPcToReferenceMap map(&data[0], data.size());
4053   size_t map_index = 0;
4054   for (size_t i = 0; i < code_item_->insns_size_in_code_units_; i++) {
4055     const uint8_t* reg_bitmap = map.FindBitMap(i, false);
4056     if (insn_flags_[i].IsCompileTimeInfoPoint()) {
4057       CHECK_LT(map_index, map.NumEntries());
4058       CHECK_EQ(map.GetDexPc(map_index), i);
4059       CHECK_EQ(map.GetBitMap(map_index), reg_bitmap);
4060       map_index++;
4061       RegisterLine* line = reg_table_.GetLine(i);
4062       for (size_t j = 0; j < code_item_->registers_size_; j++) {
4063         if (line->GetRegisterType(j).IsNonZeroReferenceTypes()) {
4064           CHECK_LT(j / 8, map.RegWidth());
4065           CHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 1);
4066         } else if ((j / 8) < map.RegWidth()) {
4067           CHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 0);
4068         } else {
4069           // If a register doesn't contain a reference then the bitmap may be shorter than the line
4070         }
4071       }
4072     } else {
4073       CHECK(reg_bitmap == NULL);
4074     }
4075   }
4076 }
4077 
SetDexGcMap(MethodReference ref,const std::vector<uint8_t> & gc_map)4078 void MethodVerifier::SetDexGcMap(MethodReference ref, const std::vector<uint8_t>& gc_map) {
4079   DCHECK(Runtime::Current()->IsCompiler());
4080   {
4081     WriterMutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
4082     DexGcMapTable::iterator it = dex_gc_maps_->find(ref);
4083     if (it != dex_gc_maps_->end()) {
4084       delete it->second;
4085       dex_gc_maps_->erase(it);
4086     }
4087     dex_gc_maps_->Put(ref, &gc_map);
4088   }
4089   DCHECK(GetDexGcMap(ref) != NULL);
4090 }
4091 
4092 
SetSafeCastMap(MethodReference ref,const MethodSafeCastSet * cast_set)4093 void  MethodVerifier::SetSafeCastMap(MethodReference ref, const MethodSafeCastSet* cast_set) {
4094   DCHECK(Runtime::Current()->IsCompiler());
4095   WriterMutexLock mu(Thread::Current(), *safecast_map_lock_);
4096   SafeCastMap::iterator it = safecast_map_->find(ref);
4097   if (it != safecast_map_->end()) {
4098     delete it->second;
4099     safecast_map_->erase(it);
4100   }
4101   safecast_map_->Put(ref, cast_set);
4102   DCHECK(safecast_map_->find(ref) != safecast_map_->end());
4103 }
4104 
IsSafeCast(MethodReference ref,uint32_t pc)4105 bool MethodVerifier::IsSafeCast(MethodReference ref, uint32_t pc) {
4106   DCHECK(Runtime::Current()->IsCompiler());
4107   ReaderMutexLock mu(Thread::Current(), *safecast_map_lock_);
4108   SafeCastMap::const_iterator it = safecast_map_->find(ref);
4109   if (it == safecast_map_->end()) {
4110     return false;
4111   }
4112 
4113   // Look up the cast address in the set of safe casts
4114   MethodVerifier::MethodSafeCastSet::const_iterator cast_it = it->second->find(pc);
4115   return cast_it != it->second->end();
4116 }
4117 
GetDexGcMap(MethodReference ref)4118 const std::vector<uint8_t>* MethodVerifier::GetDexGcMap(MethodReference ref) {
4119   DCHECK(Runtime::Current()->IsCompiler());
4120   ReaderMutexLock mu(Thread::Current(), *dex_gc_maps_lock_);
4121   DexGcMapTable::const_iterator it = dex_gc_maps_->find(ref);
4122   CHECK(it != dex_gc_maps_->end())
4123     << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file);
4124   CHECK(it->second != NULL);
4125   return it->second;
4126 }
4127 
SetDevirtMap(MethodReference ref,const PcToConcreteMethodMap * devirt_map)4128 void  MethodVerifier::SetDevirtMap(MethodReference ref,
4129                                    const PcToConcreteMethodMap* devirt_map) {
4130   DCHECK(Runtime::Current()->IsCompiler());
4131   WriterMutexLock mu(Thread::Current(), *devirt_maps_lock_);
4132   DevirtualizationMapTable::iterator it = devirt_maps_->find(ref);
4133   if (it != devirt_maps_->end()) {
4134     delete it->second;
4135     devirt_maps_->erase(it);
4136   }
4137 
4138   devirt_maps_->Put(ref, devirt_map);
4139   DCHECK(devirt_maps_->find(ref) != devirt_maps_->end());
4140 }
4141 
GetDevirtMap(const MethodReference & ref,uint32_t dex_pc)4142 const MethodReference* MethodVerifier::GetDevirtMap(const MethodReference& ref,
4143                                                                     uint32_t dex_pc) {
4144   DCHECK(Runtime::Current()->IsCompiler());
4145   ReaderMutexLock mu(Thread::Current(), *devirt_maps_lock_);
4146   DevirtualizationMapTable::const_iterator it = devirt_maps_->find(ref);
4147   if (it == devirt_maps_->end()) {
4148     return NULL;
4149   }
4150 
4151   // Look up the PC in the map, get the concrete method to execute and return its reference.
4152   MethodVerifier::PcToConcreteMethodMap::const_iterator pc_to_concrete_method
4153       = it->second->find(dex_pc);
4154   if (pc_to_concrete_method != it->second->end()) {
4155     return &(pc_to_concrete_method->second);
4156   } else {
4157     return NULL;
4158   }
4159 }
4160 
DescribeVRegs(uint32_t dex_pc)4161 std::vector<int32_t> MethodVerifier::DescribeVRegs(uint32_t dex_pc) {
4162   RegisterLine* line = reg_table_.GetLine(dex_pc);
4163   std::vector<int32_t> result;
4164   for (size_t i = 0; i < line->NumRegs(); ++i) {
4165     const RegType& type = line->GetRegisterType(i);
4166     if (type.IsConstant()) {
4167       result.push_back(type.IsPreciseConstant() ? kConstant : kImpreciseConstant);
4168       result.push_back(type.ConstantValue());
4169     } else if (type.IsConstantLo()) {
4170       result.push_back(type.IsPreciseConstantLo() ? kConstant : kImpreciseConstant);
4171       result.push_back(type.ConstantValueLo());
4172     } else if (type.IsConstantHi()) {
4173       result.push_back(type.IsPreciseConstantHi() ? kConstant : kImpreciseConstant);
4174       result.push_back(type.ConstantValueHi());
4175     } else if (type.IsIntegralTypes()) {
4176       result.push_back(kIntVReg);
4177       result.push_back(0);
4178     } else if (type.IsFloat()) {
4179       result.push_back(kFloatVReg);
4180       result.push_back(0);
4181     } else if (type.IsLong()) {
4182       result.push_back(kLongLoVReg);
4183       result.push_back(0);
4184       result.push_back(kLongHiVReg);
4185       result.push_back(0);
4186       ++i;
4187     } else if (type.IsDouble()) {
4188       result.push_back(kDoubleLoVReg);
4189       result.push_back(0);
4190       result.push_back(kDoubleHiVReg);
4191       result.push_back(0);
4192       ++i;
4193     } else if (type.IsUndefined() || type.IsConflict() || type.IsHighHalf()) {
4194       result.push_back(kUndefined);
4195       result.push_back(0);
4196     } else {
4197       CHECK(type.IsNonZeroReferenceTypes());
4198       result.push_back(kReferenceVReg);
4199       result.push_back(0);
4200     }
4201   }
4202   return result;
4203 }
4204 
IsCandidateForCompilation(MethodReference & method_ref,const uint32_t access_flags)4205 bool MethodVerifier::IsCandidateForCompilation(MethodReference& method_ref,
4206                                                const uint32_t access_flags) {
4207 #ifdef ART_SEA_IR_MODE
4208     bool use_sea = Runtime::Current()->IsSeaIRMode();
4209     use_sea = use_sea && (std::string::npos != PrettyMethod(
4210                           method_ref.dex_method_index, *(method_ref.dex_file)).find("fibonacci"));
4211     if (use_sea) return true;
4212 #endif
4213   // Don't compile class initializers, ever.
4214   if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) {
4215     return false;
4216   }
4217   return (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly);
4218 }
4219 
4220 ReaderWriterMutex* MethodVerifier::dex_gc_maps_lock_ = NULL;
4221 MethodVerifier::DexGcMapTable* MethodVerifier::dex_gc_maps_ = NULL;
4222 
4223 ReaderWriterMutex* MethodVerifier::safecast_map_lock_ = NULL;
4224 MethodVerifier::SafeCastMap* MethodVerifier::safecast_map_ = NULL;
4225 
4226 ReaderWriterMutex* MethodVerifier::devirt_maps_lock_ = NULL;
4227 MethodVerifier::DevirtualizationMapTable* MethodVerifier::devirt_maps_ = NULL;
4228 
4229 ReaderWriterMutex* MethodVerifier::rejected_classes_lock_ = NULL;
4230 MethodVerifier::RejectedClassesTable* MethodVerifier::rejected_classes_ = NULL;
4231 
Init()4232 void MethodVerifier::Init() {
4233   if (Runtime::Current()->IsCompiler()) {
4234     dex_gc_maps_lock_ = new ReaderWriterMutex("verifier GC maps lock");
4235     Thread* self = Thread::Current();
4236     {
4237       WriterMutexLock mu(self, *dex_gc_maps_lock_);
4238       dex_gc_maps_ = new MethodVerifier::DexGcMapTable;
4239     }
4240 
4241     safecast_map_lock_ = new ReaderWriterMutex("verifier Cast Elision lock");
4242     {
4243       WriterMutexLock mu(self, *safecast_map_lock_);
4244       safecast_map_ = new MethodVerifier::SafeCastMap();
4245     }
4246 
4247     devirt_maps_lock_ = new ReaderWriterMutex("verifier Devirtualization lock");
4248 
4249     {
4250       WriterMutexLock mu(self, *devirt_maps_lock_);
4251       devirt_maps_ = new MethodVerifier::DevirtualizationMapTable();
4252     }
4253 
4254     rejected_classes_lock_ = new ReaderWriterMutex("verifier rejected classes lock");
4255     {
4256       WriterMutexLock mu(self, *rejected_classes_lock_);
4257       rejected_classes_ = new MethodVerifier::RejectedClassesTable;
4258     }
4259   }
4260   art::verifier::RegTypeCache::Init();
4261 }
4262 
Shutdown()4263 void MethodVerifier::Shutdown() {
4264   if (Runtime::Current()->IsCompiler()) {
4265     Thread* self = Thread::Current();
4266     {
4267       WriterMutexLock mu(self, *dex_gc_maps_lock_);
4268       STLDeleteValues(dex_gc_maps_);
4269       delete dex_gc_maps_;
4270       dex_gc_maps_ = NULL;
4271     }
4272     delete dex_gc_maps_lock_;
4273     dex_gc_maps_lock_ = NULL;
4274 
4275     {
4276       WriterMutexLock mu(self, *safecast_map_lock_);
4277       STLDeleteValues(safecast_map_);
4278       delete safecast_map_;
4279       safecast_map_ = NULL;
4280     }
4281     delete safecast_map_lock_;
4282     safecast_map_lock_ = NULL;
4283 
4284     {
4285       WriterMutexLock mu(self, *devirt_maps_lock_);
4286       STLDeleteValues(devirt_maps_);
4287       delete devirt_maps_;
4288       devirt_maps_ = NULL;
4289     }
4290     delete devirt_maps_lock_;
4291     devirt_maps_lock_ = NULL;
4292 
4293     {
4294       WriterMutexLock mu(self, *rejected_classes_lock_);
4295       delete rejected_classes_;
4296       rejected_classes_ = NULL;
4297     }
4298     delete rejected_classes_lock_;
4299     rejected_classes_lock_ = NULL;
4300   }
4301   verifier::RegTypeCache::ShutDown();
4302 }
4303 
AddRejectedClass(ClassReference ref)4304 void MethodVerifier::AddRejectedClass(ClassReference ref) {
4305   DCHECK(Runtime::Current()->IsCompiler());
4306   {
4307     WriterMutexLock mu(Thread::Current(), *rejected_classes_lock_);
4308     rejected_classes_->insert(ref);
4309   }
4310   CHECK(IsClassRejected(ref));
4311 }
4312 
IsClassRejected(ClassReference ref)4313 bool MethodVerifier::IsClassRejected(ClassReference ref) {
4314   DCHECK(Runtime::Current()->IsCompiler());
4315   ReaderMutexLock mu(Thread::Current(), *rejected_classes_lock_);
4316   return (rejected_classes_->find(ref) != rejected_classes_->end());
4317 }
4318 
4319 }  // namespace verifier
4320 }  // namespace art
4321