blob: d84e4cb76799974e8f70e52ab0191e8fde3560b2 [file] [log] [blame]
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "dex_verifier.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07004
Elliott Hughes1f359b02011-07-17 14:27:17 -07005#include <iostream>
6
Brian Carlstrom1f870082011-08-23 16:02:11 -07007#include "class_linker.h"
jeffhaob4df5142011-09-19 20:25:32 -07008#include "dex_cache.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -07009#include "dex_file.h"
10#include "dex_instruction.h"
11#include "dex_instruction_visitor.h"
jeffhaobdb76512011-09-07 11:43:16 -070012#include "dex_verifier.h"
Elliott Hughes1f359b02011-07-17 14:27:17 -070013#include "logging.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070014#include "runtime.h"
Elliott Hughes1f359b02011-07-17 14:27:17 -070015#include "stringpiece.h"
Carl Shapiro0e5d75d2011-07-06 18:28:37 -070016
17namespace art {
18
jeffhaobdb76512011-09-07 11:43:16 -070019#define k_ kRegTypeUnknown
20#define kU kRegTypeUninit
21#define kX kRegTypeConflict
22#define k0 kRegTypeZero
23#define k1 kRegTypeOne
24#define kZ kRegTypeBoolean
25#define ky kRegTypeConstPosByte
26#define kY kRegTypeConstByte
27#define kh kRegTypeConstPosShort
28#define kH kRegTypeConstShort
29#define kc kRegTypeConstChar
30#define ki kRegTypeConstInteger
31#define kb kRegTypePosByte
32#define kB kRegTypeByte
33#define ks kRegTypePosShort
34#define kS kRegTypeShort
35#define kC kRegTypeChar
36#define kI kRegTypeInteger
37#define kF kRegTypeFloat
38#define kN kRegTypeConstLo
39#define kn kRegTypeConstHi
40#define kJ kRegTypeLongLo
41#define kj kRegTypeLongHi
42#define kD kRegTypeDoubleLo
43#define kd kRegTypeDoubleHi
44
45const char DexVerifier::merge_table_[kRegTypeMAX][kRegTypeMAX] =
46 {
47 /* chk: _ U X 0 1 Z y Y h H c i b B s S C I F N n J j D d */
48 { /*_*/ k_,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
49 { /*U*/ kX,kU,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
50 { /*X*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX },
51 { /*0*/ kX,kX,kX,k0,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
52 { /*1*/ kX,kX,kX,kZ,k1,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
53 { /*Z*/ kX,kX,kX,kZ,kZ,kZ,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
54 { /*y*/ kX,kX,kX,ky,ky,ky,ky,kY,kh,kH,kc,ki,kb,kB,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
55 { /*Y*/ kX,kX,kX,kY,kY,kY,kY,kY,kh,kH,kc,ki,kB,kB,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
56 { /*h*/ kX,kX,kX,kh,kh,kh,kh,kh,kh,kH,kc,ki,ks,kS,ks,kS,kC,kI,kF,kX,kX,kX,kX,kX,kX },
57 { /*H*/ kX,kX,kX,kH,kH,kH,kH,kH,kH,kH,kc,ki,kS,kS,kS,kS,kI,kI,kF,kX,kX,kX,kX,kX,kX },
58 { /*c*/ kX,kX,kX,kc,kc,kc,kc,kc,kc,kc,kc,ki,kC,kI,kC,kI,kC,kI,kF,kX,kX,kX,kX,kX,kX },
59 { /*i*/ kX,kX,kX,ki,ki,ki,ki,ki,ki,ki,ki,ki,kI,kI,kI,kI,kI,kI,kF,kX,kX,kX,kX,kX,kX },
60 { /*b*/ kX,kX,kX,kb,kb,kb,kb,kB,ks,kS,kC,kI,kb,kB,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
61 { /*B*/ kX,kX,kX,kB,kB,kB,kB,kB,kS,kS,kI,kI,kB,kB,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
62 { /*s*/ kX,kX,kX,ks,ks,ks,ks,kS,ks,kS,kC,kI,ks,kS,ks,kS,kC,kI,kX,kX,kX,kX,kX,kX,kX },
63 { /*S*/ kX,kX,kX,kS,kS,kS,kS,kS,kS,kS,kI,kI,kS,kS,kS,kS,kI,kI,kX,kX,kX,kX,kX,kX,kX },
64 { /*C*/ kX,kX,kX,kC,kC,kC,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kC,kI,kX,kX,kX,kX,kX,kX,kX },
65 { /*I*/ kX,kX,kX,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kI,kX,kX,kX,kX,kX,kX,kX },
66 { /*F*/ kX,kX,kX,kF,kF,kF,kF,kF,kF,kF,kF,kF,kX,kX,kX,kX,kX,kX,kF,kX,kX,kX,kX,kX,kX },
67 { /*N*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kN,kX,kJ,kX,kD,kX },
68 { /*n*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kn,kX,kj,kX,kd },
69 { /*J*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kJ,kX,kJ,kX,kX,kX },
70 { /*j*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kj,kX,kj,kX,kX },
71 { /*D*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kD,kX,kX,kX,kD,kX },
72 { /*d*/ kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kX,kd,kX,kX,kX,kd },
73 };
74
75#undef k_
76#undef kU
77#undef kX
78#undef k0
79#undef k1
80#undef kZ
81#undef ky
82#undef kY
83#undef kh
84#undef kH
85#undef kc
86#undef ki
87#undef kb
88#undef kB
89#undef ks
90#undef kS
91#undef kC
92#undef kI
93#undef kF
94#undef kN
95#undef kn
96#undef kJ
97#undef kj
98#undef kD
99#undef kd
100
101bool DexVerifier::VerifyClass(Class* klass) {
102 if (klass->IsVerified()) {
103 return true;
104 }
105 for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
106 Method* method = klass->GetDirectMethod(i);
107 if (!VerifyMethod(method)) {
jeffhao2a8a90e2011-09-26 14:25:31 -0700108 LOG(ERROR) << "Verifier rejected class " << PrettyClass(klass);
jeffhaobdb76512011-09-07 11:43:16 -0700109 return false;
110 }
111 }
112 for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
113 Method* method = klass->GetVirtualMethod(i);
114 if (!VerifyMethod(method)) {
jeffhao2a8a90e2011-09-26 14:25:31 -0700115 LOG(ERROR) << "Verifier rejected class " << PrettyClass(klass);
jeffhaobdb76512011-09-07 11:43:16 -0700116 return false;
117 }
118 }
119 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700120}
121
jeffhaobdb76512011-09-07 11:43:16 -0700122bool DexVerifier::VerifyMethod(Method* method) {
123 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
124 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
125 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700126 const DexFile::CodeItem* code_item =
jeffhaobdb76512011-09-07 11:43:16 -0700127 dex_file.GetCodeItem(method->GetCodeItemOffset());
128
129 /*
130 * Construct the verifier state container object.
131 */
132 VerifierData vdata(method, &dex_file, code_item);
133
134 /*
135 * If there aren't any instructions, make sure that's expected, then
136 * exit successfully.
137 */
138 if (code_item == NULL) {
139 if (!method->IsNative() && !method->IsAbstract()) {
140 LOG(ERROR) << "VFY: zero-length code in concrete non-native method";
141 return false;
142 }
143 return true;
144 }
145
146 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700147 * Sanity-check the register counts. ins + locals = registers, so make
jeffhaobdb76512011-09-07 11:43:16 -0700148 * sure that ins <= registers.
149 */
150 if (code_item->ins_size_ > code_item->registers_size_) {
151 LOG(ERROR) << "VFY: bad register counts (ins=" << code_item->ins_size_
152 << " regs=" << code_item->registers_size_;
153 return false;
154 }
155
156 /*
157 * Allocate and initialize an array to hold instruction data.
158 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700159 vdata.insn_flags_.reset(new InsnFlags[code_item->insns_size_]());
jeffhaobdb76512011-09-07 11:43:16 -0700160
161 /*
162 * Run through the instructions and see if the width checks out.
163 */
164 if (!ComputeWidthsAndCountOps(&vdata)) {
165 return false;
166 }
167
168 /*
169 * Flag instructions guarded by a "try" block and check exception handlers.
170 */
171 if (!ScanTryCatchBlocks(&vdata)) {
172 return false;
173 }
174
175 /*
176 * Perform static instruction verification.
177 */
178 if (!VerifyInstructions(&vdata)) {
179 return false;
180 }
181
182 /*
183 * Perform code flow analysis.
184 */
185 if (!VerifyCodeFlow(&vdata)) {
186 return false;
187 }
188
189 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700190}
191
jeffhaobdb76512011-09-07 11:43:16 -0700192bool DexVerifier::VerifyInstructions(VerifierData* vdata) {
193 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700194 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700195 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
196 const Instruction* inst = Instruction::At(ptr);
197
198 /* Flag the start of the method as a branch target. */
199 InsnSetBranchTarget(insn_flags, 0);
200
201 uint32_t width = 0;
202 uint32_t insns_size = code_item->insns_size_;
203
204 while (width < insns_size) {
205 if (!VerifyInstruction(vdata, inst, width)) {
jeffhaod1f0fde2011-09-08 17:25:33 -0700206 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
jeffhaobdb76512011-09-07 11:43:16 -0700207 << (int) inst->Opcode() << " at 0x" << width << std::dec;
208 return false;
209 }
210
211 /* Flag instructions that are garbage collection points */
212 if (inst->IsBranch() || inst->IsSwitch() || inst->IsThrow() ||
213 inst->IsReturn()) {
214 InsnSetGcPoint(insn_flags, width);
215 }
216
217 width += inst->Size();
218 inst = inst->Next();
219 }
220 return true;
jeffhaoba5ebb92011-08-25 17:24:37 -0700221}
222
jeffhaobdb76512011-09-07 11:43:16 -0700223bool DexVerifier::VerifyInstruction(VerifierData* vdata,
224 const Instruction* inst, uint32_t code_offset) {
225 const DexFile* dex_file = vdata->dex_file_;
226 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700227 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700228 Instruction::DecodedInstruction dec_insn(inst);
229 bool result = true;
230
231 int argumentA = inst->GetVerifyTypeArgumentA();
232 int argumentB = inst->GetVerifyTypeArgumentB();
233 int argumentC = inst->GetVerifyTypeArgumentC();
234 int extra_flags = inst->GetVerifyExtraFlags();
235
236 switch (argumentA) {
237 case Instruction::kVerifyRegA:
238 result &= CheckRegisterIndex(code_item, dec_insn.vA_);
239 break;
240 case Instruction::kVerifyRegAWide:
241 result &= CheckWideRegisterIndex(code_item, dec_insn.vA_);
242 break;
243 }
244
245 switch (argumentB) {
246 case Instruction::kVerifyRegB:
247 result &= CheckRegisterIndex(code_item, dec_insn.vB_);
248 break;
249 case Instruction::kVerifyRegBField:
250 result &= CheckFieldIndex(dex_file, dec_insn.vB_);
251 break;
252 case Instruction::kVerifyRegBMethod:
253 result &= CheckMethodIndex(dex_file, dec_insn.vB_);
254 break;
255 case Instruction::kVerifyRegBNewInstance:
256 result &= CheckNewInstance(dex_file, dec_insn.vB_);
257 break;
258 case Instruction::kVerifyRegBString:
259 result &= CheckStringIndex(dex_file, dec_insn.vB_);
260 break;
261 case Instruction::kVerifyRegBType:
262 result &= CheckTypeIndex(dex_file, dec_insn.vB_);
263 break;
264 case Instruction::kVerifyRegBWide:
265 result &= CheckWideRegisterIndex(code_item, dec_insn.vB_);
266 break;
267 }
268
269 switch (argumentC) {
270 case Instruction::kVerifyRegC:
271 result &= CheckRegisterIndex(code_item, dec_insn.vC_);
272 break;
273 case Instruction::kVerifyRegCField:
274 result &= CheckFieldIndex(dex_file, dec_insn.vC_);
275 break;
276 case Instruction::kVerifyRegCNewArray:
277 result &= CheckNewArray(dex_file, dec_insn.vC_);
278 break;
279 case Instruction::kVerifyRegCType:
280 result &= CheckTypeIndex(dex_file, dec_insn.vC_);
281 break;
282 case Instruction::kVerifyRegCWide:
283 result &= CheckWideRegisterIndex(code_item, dec_insn.vC_);
284 break;
285 }
286
287 switch (extra_flags) {
288 case Instruction::kVerifyArrayData:
289 result &= CheckArrayData(code_item, code_offset);
290 break;
291 case Instruction::kVerifyBranchTarget:
292 result &= CheckBranchTarget(code_item, insn_flags, code_offset);
293 break;
294 case Instruction::kVerifySwitchTargets:
295 result &= CheckSwitchTargets(code_item, insn_flags, code_offset);
296 break;
297 case Instruction::kVerifyVarArg:
298 result &= CheckVarArgRegs(code_item, dec_insn.vA_, dec_insn.arg_);
299 break;
300 case Instruction::kVerifyVarArgRange:
301 result &= CheckVarArgRangeRegs(code_item, dec_insn.vA_, dec_insn.vC_);
302 break;
303 case Instruction::kVerifyError:
304 LOG(ERROR) << "VFY: unexpected opcode " << std::hex
305 << (int) dec_insn.opcode_ << std::dec;
306 result = false;
307 break;
308 }
309
310 return result;
jeffhaoba5ebb92011-08-25 17:24:37 -0700311}
312
jeffhaobdb76512011-09-07 11:43:16 -0700313bool DexVerifier::VerifyCodeFlow(VerifierData* vdata) {
314 Method* method = vdata->method_;
315 const DexFile::CodeItem* code_item = vdata->code_item_;
316 uint16_t registers_size = code_item->registers_size_;
317 uint32_t insns_size = code_item->insns_size_;
318 RegisterTable reg_table;
jeffhaoba5ebb92011-08-25 17:24:37 -0700319
jeffhaobdb76512011-09-07 11:43:16 -0700320 if (registers_size * insns_size > 4*1024*1024) {
321 LOG(ERROR) << "VFY: warning: method is huge (regs=" << registers_size
322 << " insns_size=" << insns_size << ")";
323 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700324
jeffhaobdb76512011-09-07 11:43:16 -0700325 /* Create and initialize register lists. */
jeffhaoa0a764a2011-09-16 10:43:38 -0700326 if (!InitRegisterTable(vdata, &reg_table, kTrackRegsGcPoints)) {
jeffhaobdb76512011-09-07 11:43:16 -0700327 return false;
328 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700329
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700330 vdata->register_lines_ = reg_table.register_lines_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700331
332 /* Allocate a map to hold the classes of uninitialized instances. */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700333 vdata->uninit_map_.reset(CreateUninitInstanceMap(vdata));
jeffhaobdb76512011-09-07 11:43:16 -0700334
335 /* Initialize register types of method arguments. */
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700336 if (!SetTypesFromSignature(vdata, reg_table.register_lines_[0].reg_types_.get())) {
jeffhao2a8a90e2011-09-26 14:25:31 -0700337 LOG(ERROR) << "VFY: bad signature in " << PrettyMethod(method);
jeffhaobdb76512011-09-07 11:43:16 -0700338 return false;
339 }
340
341 /* Perform code flow verification. */
342 if (!CodeFlowVerifyMethod(vdata, &reg_table)) {
343 return false;
344 }
345
jeffhaoa0a764a2011-09-16 10:43:38 -0700346 /* Generate a register map and add it to the method. */
347 UniquePtr<RegisterMap> map(GenerateRegisterMapV(vdata));
348 ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
349 ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map.get()));
jeffhaoe23d93c2011-09-15 14:48:43 -0700350
jeffhaoa0a764a2011-09-16 10:43:38 -0700351 memcpy(header->GetData(), map.get()->header_, sizeof(RegisterMapHeader));
352 memcpy(data->GetData(), map.get()->data_, ComputeRegisterMapSize(map.get()));
jeffhaoe23d93c2011-09-15 14:48:43 -0700353
jeffhaoa0a764a2011-09-16 10:43:38 -0700354 method->SetRegisterMapHeader(header);
355 method->SetRegisterMapData(data);
jeffhaoba5ebb92011-08-25 17:24:37 -0700356
jeffhaobdb76512011-09-07 11:43:16 -0700357 return true;
358}
359
360bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) {
361 const uint16_t* insns = vdata->code_item_->insns_;
362 uint32_t insns_size = vdata->code_item_->insns_size_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700363 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700364 const byte* ptr = reinterpret_cast<const byte*>(insns);
365 const Instruction* inst = Instruction::At(ptr);
366 size_t new_instance_count = 0;
367 size_t monitor_enter_count = 0;
368 size_t width = 0;
369
370 while (width < insns_size) {
371 Instruction::Code opcode = inst->Opcode();
372 if (opcode == Instruction::NEW_INSTANCE) {
373 new_instance_count++;
374 } else if (opcode == Instruction::MONITOR_ENTER) {
375 monitor_enter_count++;
376 }
377
378 insn_flags[width] |= inst->Size();
379 width += inst->Size();
380 inst = inst->Next();
381 }
382
383 if (width != insns_size) {
384 LOG(ERROR) << "VFY: code did not end where expected (" << width << " vs. "
385 << insns_size << ")";
386 return false;
387 }
388
389 vdata->new_instance_count_ = new_instance_count;
390 vdata->monitor_enter_count_ = monitor_enter_count;
391 return true;
392}
393
394bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) {
395 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700396 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700397 uint32_t insns_size = code_item->insns_size_;
398 uint32_t tries_size = code_item->tries_size_;
399
400 if (tries_size == 0) {
401 return true;
402 }
403
404 const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item, 0);
405
406 for (uint32_t idx = 0; idx < tries_size; idx++) {
407 const DexFile::TryItem* try_item = &tries[idx];
408 uint32_t start = try_item->start_addr_;
409 uint32_t end = start + try_item->insn_count_;
410
411 if ((start >= end) || (start >= insns_size) || (end > insns_size)) {
412 LOG(ERROR) << "VFY: bad exception entry: startAddr=" << start
413 << " endAddr=" << end << " (size=" << insns_size << ")";
414 return false;
415 }
416
417 if (InsnGetWidth(insn_flags, start) == 0) {
418 LOG(ERROR) << "VFY: 'try' block starts inside an instruction ("
419 << start << ")";
420 return false;
421 }
422
423 uint32_t addr;
424 for (addr = start; addr < end; addr += InsnGetWidth(insn_flags, addr)) {
425 InsnSetInTry(insn_flags, addr);
426 }
427 }
428
429 /* Iterate over each of the handlers to verify target addresses. */
430 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
431 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
432 for (uint32_t idx = 0; idx < handlers_size; idx++) {
433 DexFile::CatchHandlerIterator iterator(handlers_ptr);
434
435 for (; !iterator.HasNext(); iterator.Next()) {
436 uint32_t addr = iterator.Get().address_;
437 if (InsnGetWidth(insn_flags, addr) == 0) {
438 LOG(ERROR) << "VFY: exception handler starts at bad address ("
439 << addr << ")";
440 return false;
441 }
442
443 InsnSetBranchTarget(insn_flags, addr);
444 }
445
446 handlers_ptr = iterator.GetData();
447 }
448
449 return true;
450}
451
452bool DexVerifier::GetBranchOffset(const DexFile::CodeItem* code_item,
453 const InsnFlags insn_flags[], uint32_t cur_offset, int32_t* pOffset,
jeffhaoba5ebb92011-08-25 17:24:37 -0700454 bool* pConditional, bool* selfOkay) {
455 const uint16_t* insns = code_item->insns_ + cur_offset;
456
457 switch (*insns & 0xff) {
458 case Instruction::GOTO:
459 *pOffset = ((int16_t) *insns) >> 8;
460 *pConditional = false;
461 *selfOkay = false;
462 break;
463 case Instruction::GOTO_32:
464 *pOffset = insns[1] | (((uint32_t) insns[2]) << 16);
465 *pConditional = false;
466 *selfOkay = true;
467 break;
468 case Instruction::GOTO_16:
469 *pOffset = (int16_t) insns[1];
470 *pConditional = false;
471 *selfOkay = false;
472 break;
473 case Instruction::IF_EQ:
474 case Instruction::IF_NE:
475 case Instruction::IF_LT:
476 case Instruction::IF_GE:
477 case Instruction::IF_GT:
478 case Instruction::IF_LE:
479 case Instruction::IF_EQZ:
480 case Instruction::IF_NEZ:
481 case Instruction::IF_LTZ:
482 case Instruction::IF_GEZ:
483 case Instruction::IF_GTZ:
484 case Instruction::IF_LEZ:
485 *pOffset = (int16_t) insns[1];
486 *pConditional = true;
487 *selfOkay = false;
488 break;
489 default:
490 return false;
491 break;
492 }
493
494 return true;
495}
496
jeffhaobdb76512011-09-07 11:43:16 -0700497bool DexVerifier::CheckArrayData(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700498 uint32_t cur_offset) {
499 const uint32_t insn_count = code_item->insns_size_;
500 const uint16_t* insns = code_item->insns_ + cur_offset;
501 const uint16_t* array_data;
502 int32_t array_data_offset;
503
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700504 DCHECK_LT(cur_offset, insn_count);
jeffhaoba5ebb92011-08-25 17:24:37 -0700505
506 /* make sure the start of the array data table is in range */
507 array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
508 if ((int32_t) cur_offset + array_data_offset < 0 ||
509 cur_offset + array_data_offset + 2 >= insn_count)
510 {
511 LOG(ERROR) << "VFY: invalid array data start: at " << cur_offset
512 << ", data offset " << array_data_offset << ", count "
513 << insn_count;
514 return false;
515 }
516
517 /* offset to array data table is a relative branch-style offset */
518 array_data = insns + array_data_offset;
519
520 /* make sure the table is 32-bit aligned */
521 if ((((uint32_t) array_data) & 0x03) != 0) {
522 LOG(ERROR) << "VFY: unaligned array data table: at " << cur_offset
523 << ", data offset " << array_data_offset;
524 return false;
525 }
526
527 uint32_t value_width = array_data[1];
528 uint32_t value_count = *(uint32_t*) (&array_data[2]);
529 uint32_t table_size = 4 + (value_width * value_count + 1) / 2;
530
531 /* make sure the end of the switch is in range */
532 if (cur_offset + array_data_offset + table_size > insn_count) {
533 LOG(ERROR) << "VFY: invalid array data end: at " << cur_offset
534 << ", data offset " << array_data_offset << ", end "
535 << cur_offset + array_data_offset + table_size << ", count "
536 << insn_count;
537 return false;
538 }
539
540 return true;
541}
542
jeffhaobdb76512011-09-07 11:43:16 -0700543bool DexVerifier::CheckNewInstance(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700544 if (idx >= dex_file->GetHeader().type_ids_size_) {
545 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
546 << dex_file->GetHeader().type_ids_size_ << ")";
547 return false;
548 }
549
550 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
551 if (descriptor[0] != 'L') {
552 LOG(ERROR) << "VFY: can't call new-instance on type '"
553 << descriptor << "'";
554 return false;
555 }
556
557 return true;
558}
559
jeffhaobdb76512011-09-07 11:43:16 -0700560bool DexVerifier::CheckNewArray(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700561 if (idx >= dex_file->GetHeader().type_ids_size_) {
562 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
563 << dex_file->GetHeader().type_ids_size_ << ")";
564 return false;
565 }
566
567 int bracket_count = 0;
568 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
569 const char* cp = descriptor;
570 while (*cp++ == '[')
571 bracket_count++;
572
573 if (bracket_count == 0) {
574 /* The given class must be an array type. */
575 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
576 << "' (not an array)";
577 return false;
578 } else if (bracket_count > 255) {
579 /* It is illegal to create an array of more than 255 dimensions. */
580 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
581 << "' (exceeds limit)";
582 return false;
583 }
584
585 return true;
586}
587
jeffhaobdb76512011-09-07 11:43:16 -0700588bool DexVerifier::CheckTypeIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700589 if (idx >= dex_file->GetHeader().type_ids_size_) {
590 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
591 << dex_file->GetHeader().type_ids_size_ << ")";
592 return false;
593 }
594 return true;
595}
596
jeffhaobdb76512011-09-07 11:43:16 -0700597bool DexVerifier::CheckFieldIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700598 if (idx >= dex_file->GetHeader().field_ids_size_) {
599 LOG(ERROR) << "VFY: bad field index " << idx << " (max "
600 << dex_file->GetHeader().field_ids_size_ << ")";
601 return false;
602 }
603 return true;
604}
605
jeffhaobdb76512011-09-07 11:43:16 -0700606bool DexVerifier::CheckMethodIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700607 if (idx >= dex_file->GetHeader().method_ids_size_) {
608 LOG(ERROR) << "VFY: bad method index " << idx << " (max "
609 << dex_file->GetHeader().method_ids_size_ << ")";
610 return false;
611 }
612 return true;
613}
614
jeffhaobdb76512011-09-07 11:43:16 -0700615bool DexVerifier::CheckStringIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700616 if (idx >= dex_file->GetHeader().string_ids_size_) {
617 LOG(ERROR) << "VFY: bad string index " << idx << " (max "
618 << dex_file->GetHeader().string_ids_size_ << ")";
619 return false;
620 }
621 return true;
622}
623
jeffhaobdb76512011-09-07 11:43:16 -0700624bool DexVerifier::CheckRegisterIndex(const DexFile::CodeItem* code_item,
625 uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700626 if (idx >= code_item->registers_size_) {
627 LOG(ERROR) << "VFY: register index out of range (" << idx << " >= "
628 << code_item->registers_size_ << ")";
629 return false;
630 }
631 return true;
632}
633
jeffhaobdb76512011-09-07 11:43:16 -0700634bool DexVerifier::CheckWideRegisterIndex(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700635 uint32_t idx) {
636 if (idx + 1 >= code_item->registers_size_) {
637 LOG(ERROR) << "VFY: wide register index out of range (" << idx
638 << "+1 >= " << code_item->registers_size_ << ")";
639 return false;
640 }
641 return true;
642}
643
jeffhaobdb76512011-09-07 11:43:16 -0700644bool DexVerifier::CheckVarArgRegs(const DexFile::CodeItem* code_item,
645 uint32_t vA, uint32_t arg[]) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700646 uint16_t registers_size = code_item->registers_size_;
647 uint32_t idx;
648
649 if (vA > 5) {
650 LOG(ERROR) << "VFY: invalid arg count (" << vA << ") in non-range invoke)";
651 return false;
652 }
653
654 for (idx = 0; idx < vA; idx++) {
655 if (arg[idx] > registers_size) {
656 LOG(ERROR) << "VFY: invalid reg index (" << arg[idx]
657 << ") in non-range invoke (> " << registers_size << ")";
658 return false;
659 }
660 }
661
662 return true;
663}
664
jeffhaobdb76512011-09-07 11:43:16 -0700665bool DexVerifier::CheckVarArgRangeRegs(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700666 uint32_t vA, uint32_t vC) {
667 uint16_t registers_size = code_item->registers_size_;
668
669 /*
670 * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions,
671 * so there's no risk of integer overflow when adding them here.
672 */
673 if (vA + vC > registers_size) {
674 LOG(ERROR) << "VFY: invalid reg index " << vA << "+" << vC
675 << " in range invoke (> " << registers_size << ")";
676 return false;
677 }
678
679 return true;
680}
681
jeffhaobdb76512011-09-07 11:43:16 -0700682bool DexVerifier::CheckSwitchTargets(const DexFile::CodeItem* code_item,
683 InsnFlags insn_flags[], uint32_t cur_offset) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700684 const uint32_t insn_count = code_item->insns_size_;
685 const uint16_t* insns = code_item->insns_ + cur_offset;
686 const uint16_t* switch_insns;
687 uint16_t expected_signature;
688 uint32_t switch_count, table_size;
689 int32_t switch_offset, keys_offset, targets_offset;
690 int32_t offset, abs_offset;
691 uint32_t targ;
692
693 /* make sure the start of the switch is in range */
694 switch_offset = insns[1] | ((int32_t) insns[2]) << 16;
695 if ((int32_t) cur_offset + switch_offset < 0 ||
696 cur_offset + switch_offset + 2 >= insn_count) {
697 LOG(ERROR) << "VFY: invalid switch start: at " << cur_offset
698 << ", switch offset " << switch_offset << ", count "
699 << insn_count;
700 return false;
701 }
702
703 /* offset to switch table is a relative branch-style offset */
704 switch_insns = insns + switch_offset;
705
706 /* make sure the table is 32-bit aligned */
707 if ((((uint32_t) switch_insns) & 0x03) != 0) {
708 LOG(ERROR) << "VFY: unaligned switch table: at " << cur_offset
709 << ", switch offset " << switch_offset;
710 return false;
711 }
712
713 switch_count = switch_insns[1];
714
715 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
716 /* 0=sig, 1=count, 2/3=firstKey */
717 targets_offset = 4;
718 keys_offset = -1;
719 expected_signature = Instruction::kPackedSwitchSignature;
720 } else {
721 /* 0=sig, 1=count, 2..count*2 = keys */
722 keys_offset = 2;
723 targets_offset = 2 + 2 * switch_count;
724 expected_signature = Instruction::kSparseSwitchSignature;
725 }
726 table_size = targets_offset + switch_count * 2;
727
728 if (switch_insns[0] != expected_signature) {
jeffhaobdb76512011-09-07 11:43:16 -0700729 LOG(ERROR) << "VFY: wrong signature for switch table (0x" << std::hex
730 << switch_insns[0] << ", wanted 0x" << expected_signature << ")"
731 << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700732 return false;
733 }
734
735 /* make sure the end of the switch is in range */
736 if (cur_offset + switch_offset + table_size > (uint32_t) insn_count) {
737 LOG(ERROR) << "VFY: invalid switch end: at " << cur_offset
738 << ", switch offset " << switch_offset << ", end "
739 << cur_offset + switch_offset + table_size << ", count "
740 << insn_count;
741 return false;
742 }
743
744 /* for a sparse switch, verify the keys are in ascending order */
745 if (keys_offset > 0 && switch_count > 1) {
746 int32_t last_key;
747
748 last_key = switch_insns[keys_offset] |
749 (switch_insns[keys_offset + 1] << 16);
750 for (targ = 1; targ < switch_count; targ++) {
751 int32_t key = (int32_t) switch_insns[keys_offset + targ * 2] |
752 (int32_t) (switch_insns[keys_offset + targ * 2 + 1] << 16);
753 if (key <= last_key) {
754 LOG(ERROR) << "VFY: invalid packed switch: last key=" << last_key
755 << ", this=" << key;
756 return false;
757 }
758
759 last_key = key;
760 }
761 }
762
763 /* verify each switch target */
764 for (targ = 0; targ < switch_count; targ++) {
765 offset = (int32_t) switch_insns[targets_offset + targ * 2] |
766 (int32_t) (switch_insns[targets_offset + targ * 2 + 1] << 16);
767 abs_offset = cur_offset + offset;
768
769 if (abs_offset < 0 || abs_offset >= (int32_t) insn_count ||
770 !InsnIsOpcode(insn_flags, abs_offset)) {
771 LOG(ERROR) << "VFY: invalid switch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700772 << std::hex << abs_offset << ") at " << cur_offset << std::dec
773 << "[" << targ << "]";
jeffhaoba5ebb92011-08-25 17:24:37 -0700774 return false;
775 }
jeffhaobdb76512011-09-07 11:43:16 -0700776 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700777 }
778
779 return true;
780}
781
jeffhaobdb76512011-09-07 11:43:16 -0700782bool DexVerifier::CheckBranchTarget(const DexFile::CodeItem* code_item,
783 InsnFlags insn_flags[], uint32_t cur_offset) {
784 const uint32_t insn_count = code_item->insns_size_;
jeffhaoba5ebb92011-08-25 17:24:37 -0700785 int32_t offset, abs_offset;
786 bool isConditional, selfOkay;
787
788 if (!GetBranchOffset(code_item, insn_flags, cur_offset, &offset,
789 &isConditional, &selfOkay))
790 return false;
791
792 if (!selfOkay && offset == 0) {
jeffhaobdb76512011-09-07 11:43:16 -0700793 LOG(ERROR) << "VFY: branch offset of zero not allowed at" << std::hex
794 << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700795 return false;
796 }
797
798 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700799 * Check for 32-bit overflow. This isn't strictly necessary if we can
jeffhaoba5ebb92011-08-25 17:24:37 -0700800 * depend on the VM to have identical "wrap-around" behavior, but
801 * it's unwise to depend on that.
802 */
803 if (((int64_t) cur_offset + (int64_t) offset) !=
jeffhaobdb76512011-09-07 11:43:16 -0700804 (int64_t) (cur_offset + offset)) {
805 LOG(ERROR) << "VFY: branch target overflow " << std::hex << cur_offset
806 << std::dec << " +" << offset;
jeffhaoba5ebb92011-08-25 17:24:37 -0700807 return false;
808 }
809 abs_offset = cur_offset + offset;
jeffhaobdb76512011-09-07 11:43:16 -0700810 if (abs_offset < 0 || (uint32_t) abs_offset >= insn_count ||
jeffhaoba5ebb92011-08-25 17:24:37 -0700811 !InsnIsOpcode(insn_flags, abs_offset))
812 {
813 LOG(ERROR) << "VFY: invalid branch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700814 << std::hex << abs_offset << ") at " << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700815 return false;
816 }
jeffhaobdb76512011-09-07 11:43:16 -0700817 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700818
819 return true;
820}
821
jeffhaobdb76512011-09-07 11:43:16 -0700822bool DexVerifier::InitRegisterTable(VerifierData* vdata,
823 RegisterTable* reg_table, RegisterTrackingMode track_regs_for) {
824 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700825 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700826 uint16_t registers_size = code_item->registers_size_;
827 uint32_t insns_size = code_item->insns_size_;
828 uint32_t i;
829
830 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700831 * Every address gets a RegisterLine struct. This is wasteful, but
jeffhaobdb76512011-09-07 11:43:16 -0700832 * not so much that it's worth chasing through an extra level of
833 * indirection.
834 */
835 reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700836 reg_table->register_lines_.reset(new RegisterLine[insns_size]());
jeffhaobdb76512011-09-07 11:43:16 -0700837
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700838 DCHECK_GT(insns_size, 0U);
jeffhaobdb76512011-09-07 11:43:16 -0700839
840 bool track_monitors;
841 //if (gDvm.monitorVerification) {
842 //track_monitors = (vdata->monitor_enter_count_ != 0);
843 //} else {
844 track_monitors = false;
845 //}
846
847 /*
848 * Allocate entries in the sparse register line table.
849 *
850 * There is a RegisterLine associated with every address, but not
851 * every RegisterLine has non-NULL pointers to storage for its fields.
852 */
853 for (i = 0; i < insns_size; i++) {
854 bool interesting;
855
856 switch (track_regs_for) {
857 case kTrackRegsAll:
858 interesting = InsnIsOpcode(insn_flags, i);
859 break;
860 case kTrackRegsGcPoints:
861 interesting = InsnIsGcPoint(insn_flags, i) ||
862 InsnIsBranchTarget(insn_flags, i);
863 break;
864 case kTrackRegsBranches:
865 interesting = InsnIsBranchTarget(insn_flags, i);
866 break;
867 default:
868 return false;
869 }
870
871 if (interesting) {
872 reg_table->register_lines_[i].Alloc(reg_table->insn_reg_count_plus_,
873 track_monitors);
874 }
875 }
876
877 /*
878 * Allocate space for our "temporary" register lines.
879 */
880 reg_table->work_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
881 reg_table->saved_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
882
883 return true;
884}
885
886DexVerifier::UninitInstanceMap* DexVerifier::CreateUninitInstanceMap(
887 VerifierData* vdata) {
888 Method* method = vdata->method_;
889 const DexFile::CodeItem* code_item = vdata->code_item_;
890 size_t new_instance_count = vdata->new_instance_count_;
891
892 if (IsInitMethod(method)) {
893 new_instance_count++;
894 }
895
896 /*
897 * Allocate the header and map as a single unit.
898 *
899 * TODO: consider having a static instance so we can avoid allocations.
900 * I don't think the verifier is guaranteed to be single-threaded when
901 * running in the VM (rather than dexopt), so that must be taken into
902 * account.
903 */
904 UninitInstanceMap* uninit_map = new UninitInstanceMap(new_instance_count);
905
906 size_t idx = 0;
907 if (IsInitMethod(method)) {
908 uninit_map->map_[idx++].addr_ = kUninitThisArgAddr;
909 }
910
911 /*
912 * Run through and find the new-instance instructions.
913 */
914 uint32_t addr = 0;
915 uint32_t insns_size = code_item->insns_size_;
916 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
jeffhaoba5ebb92011-08-25 17:24:37 -0700917 const Instruction* inst = Instruction::At(ptr);
jeffhaobdb76512011-09-07 11:43:16 -0700918 while (addr < insns_size) {
919 Instruction::Code opcode = inst->Opcode();
920 if (opcode == Instruction::NEW_INSTANCE) {
921 uninit_map->map_[idx++].addr_ = addr;
922 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700923
jeffhaobdb76512011-09-07 11:43:16 -0700924 addr += inst->Size();
jeffhaoba5ebb92011-08-25 17:24:37 -0700925 inst = inst->Next();
926 }
927
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700928 CHECK_EQ(idx, new_instance_count);
jeffhaobdb76512011-09-07 11:43:16 -0700929 return uninit_map;
930}
931
932bool DexVerifier::IsInitMethod(const Method* method) {
933 return (method->GetName()->Equals("<init>"));
934}
935
936Class* DexVerifier::LookupClassByDescriptor(const Method* method,
937 const char* descriptor, VerifyError* failure) {
938 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700939 * The compiler occasionally puts references to nonexistent classes in
940 * signatures. For example, if you have a non-static inner class with no
941 * constructor, the compiler provides a private <init> for you.
942 * Constructing the class requires <init>(parent), but the outer class can't
943 * call that because the method is private. So the compiler generates a
944 * package-scope <init>(parent,bogus) method that just calls the regular
945 * <init> (the "bogus" part being necessary to distinguish the signature of
946 * the synthetic method). Treating the bogus class as an instance of
947 * java.lang.Object allows the verifier to process the class successfully.
jeffhaobdb76512011-09-07 11:43:16 -0700948 */
949 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
950 const ClassLoader* class_loader =
951 method->GetDeclaringClass()->GetClassLoader();
952 Class* klass = class_linker->FindClass(descriptor, class_loader);
953
954 if (klass == NULL) {
955 Thread::Current()->ClearException();
956 if (strchr(descriptor, '$') != NULL) {
957 LOG(INFO) << "VFY: unable to find class referenced in signature ("
958 << descriptor << ")";
959 } else {
960 LOG(ERROR) << "VFY: unable to find class referenced in signature ("
961 << descriptor << ")";
962 }
963
964 /* Check if the descriptor is an array. */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700965 if (descriptor[0] == '[' && descriptor[1] != '\0') {
jeffhaobdb76512011-09-07 11:43:16 -0700966 /*
967 * There should never be a problem loading primitive arrays.
968 */
969 if (descriptor[1] != 'L' && descriptor[1] != '[') {
970 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor
971 << "'";
972 *failure = VERIFY_ERROR_GENERIC;
973 }
974
975 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700976 * Try to continue with base array type. This will let us pass basic
977 * stuff (e.g. get array len) that wouldn't fly with an Object. This
978 * is NOT correct if the missing type is a primitive array, but we
979 * should never have a problem loading those. (I'm not convinced this
980 * is correct or even useful. Just use Object here?)
jeffhaobdb76512011-09-07 11:43:16 -0700981 */
982 klass = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
983 } else if (descriptor[0] == 'L') {
984 /*
985 * We are looking at a non-array reference descriptor;
986 * try to continue with base reference type.
987 */
988 klass = class_linker->FindSystemClass("Ljava/lang/Object;");
989 } else {
990 /* We are looking at a primitive type. */
991 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor << "'";
992 *failure = VERIFY_ERROR_GENERIC;
993 }
994
995 if (klass == NULL) {
996 *failure = VERIFY_ERROR_GENERIC;
997 }
998 }
999
1000 if (klass->IsPrimitive()) {
1001 LOG(ERROR) << "VFY: invalid use of primitive type '" << descriptor << "'";
1002 *failure = VERIFY_ERROR_GENERIC;
1003 klass = NULL;
1004 }
1005
1006 return klass;
1007}
1008
1009Class* DexVerifier::LookupSignatureClass(const Method* method, std::string sig,
1010 VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001011 DCHECK_EQ(sig[0], 'L');
jeffhaobdb76512011-09-07 11:43:16 -07001012 size_t end = sig.find(';');
1013
1014 if (end == std::string::npos) {
1015 LOG(ERROR) << "VFY: bad signature component '" << sig << "' (missing ';')";
1016 *failure = VERIFY_ERROR_GENERIC;
1017 return NULL;
1018 }
1019
1020 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1021 failure);
1022}
1023
1024Class* DexVerifier::LookupSignatureArrayClass(const Method* method,
1025 std::string sig, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001026 DCHECK_EQ(sig[0], '[');
jeffhaobdb76512011-09-07 11:43:16 -07001027 size_t end = 0;
1028
1029 while (sig[end] == '[')
1030 end++;
1031
1032 if (sig[end] == 'L') {
1033 end = sig.find(';');
1034 if (end == std::string::npos) {
1035 LOG(ERROR) << "VFY: bad signature component '" << sig
1036 << "' (missing ';')";
1037 *failure = VERIFY_ERROR_GENERIC;
1038 return NULL;
1039 }
1040 }
1041
1042 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1043 failure);
1044}
1045
1046bool DexVerifier::SetTypesFromSignature(VerifierData* vdata, RegType* reg_types)
1047{
1048 Method* method = vdata->method_;
1049 const DexFile* dex_file = vdata->dex_file_;
1050 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001051 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001052
1053 int arg_start = code_item->registers_size_ - code_item->ins_size_;
1054 int expected_args = code_item->ins_size_; /* long/double count as two */
1055 int actual_args = 0;
1056
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001057 DCHECK_GE(arg_start, 0); /* should have been verified earlier */
jeffhaobdb76512011-09-07 11:43:16 -07001058
1059 /*
1060 * Include the "this" pointer.
1061 */
1062 if (!method->IsStatic()) {
1063 /*
1064 * If this is a constructor for a class other than java.lang.Object,
jeffhaod1f0fde2011-09-08 17:25:33 -07001065 * mark the first ("this") argument as uninitialized. This restricts
jeffhaobdb76512011-09-07 11:43:16 -07001066 * field access until the superclass constructor is called.
1067 */
1068 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1069 Class* klass_object = class_linker->FindSystemClass("Ljava/lang/Object;");
1070 if (IsInitMethod(method) && method->GetDeclaringClass() != klass_object) {
1071 int idx = SetUninitInstance(uninit_map, kUninitThisArgAddr,
1072 method->GetDeclaringClass());
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001073 DCHECK_EQ(idx, 0);
jeffhaobdb76512011-09-07 11:43:16 -07001074 reg_types[arg_start + actual_args] = RegTypeFromUninitIndex(idx);
1075 } else {
1076 reg_types[arg_start + actual_args] =
1077 RegTypeFromClass(method->GetDeclaringClass());
1078 }
1079 actual_args++;
1080 }
1081
1082 const DexFile::ProtoId& proto_id =
1083 dex_file->GetProtoId(method->GetProtoIdx());
1084 DexFile::ParameterIterator iterator(*dex_file, proto_id);
1085 VerifyError failure = VERIFY_ERROR_NONE;
1086
1087 for (; iterator.HasNext(); iterator.Next()) {
1088 const char* descriptor = iterator.GetDescriptor();
1089
1090 if (descriptor == NULL) {
1091 break;
1092 }
1093
1094 if (actual_args >= expected_args) {
1095 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
1096 << descriptor << ")";
1097 return false;
1098 }
1099
1100 switch (*descriptor) {
1101 case 'L':
1102 case '[':
1103 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001104 * We assume that reference arguments are initialized. The only way
1105 * it could be otherwise (assuming the caller was verified) is if
1106 * the current method is <init>, but in that case it's effectively
1107 * considered initialized the instant we reach here (in the sense
1108 * that we can return without doing anything or call virtual methods).
jeffhaobdb76512011-09-07 11:43:16 -07001109 */
1110 {
1111 Class* klass =
1112 LookupClassByDescriptor(method, descriptor, &failure);
1113 if (failure != VERIFY_ERROR_NONE)
1114 return false;
1115 reg_types[arg_start + actual_args] = RegTypeFromClass(klass);
1116 }
1117 actual_args++;
1118 break;
1119 case 'Z':
1120 reg_types[arg_start + actual_args] = kRegTypeBoolean;
1121 actual_args++;
1122 break;
1123 case 'C':
1124 reg_types[arg_start + actual_args] = kRegTypeChar;
1125 actual_args++;
1126 break;
1127 case 'B':
1128 reg_types[arg_start + actual_args] = kRegTypeByte;
1129 actual_args++;
1130 break;
1131 case 'I':
1132 reg_types[arg_start + actual_args] = kRegTypeInteger;
1133 actual_args++;
1134 break;
1135 case 'S':
1136 reg_types[arg_start + actual_args] = kRegTypeShort;
1137 actual_args++;
1138 break;
1139 case 'F':
1140 reg_types[arg_start + actual_args] = kRegTypeFloat;
1141 actual_args++;
1142 break;
1143 case 'D':
1144 reg_types[arg_start + actual_args] = kRegTypeDoubleLo;
1145 reg_types[arg_start + actual_args +1] = kRegTypeDoubleHi;
1146 actual_args += 2;
1147 break;
1148 case 'J':
1149 reg_types[arg_start + actual_args] = kRegTypeLongLo;
1150 reg_types[arg_start + actual_args +1] = kRegTypeLongHi;
1151 actual_args += 2;
1152 break;
1153 default:
1154 LOG(ERROR) << "VFY: unexpected signature type char '" << descriptor
1155 << "'";
1156 return false;
1157 }
1158 }
1159
1160 if (actual_args != expected_args) {
1161 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
1162 << actual_args;
jeffhaoba5ebb92011-08-25 17:24:37 -07001163 return false;
1164 }
1165
jeffhaobdb76512011-09-07 11:43:16 -07001166 const char* descriptor = dex_file->GetReturnTypeDescriptor(proto_id);
1167
1168 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001169 * Validate return type. We don't do the type lookup; just want to make
1170 * sure that it has the right format. Only major difference from the
jeffhaobdb76512011-09-07 11:43:16 -07001171 * method argument format is that 'V' is supported.
1172 */
1173 switch (*descriptor) {
1174 case 'I':
1175 case 'C':
1176 case 'S':
1177 case 'B':
1178 case 'Z':
1179 case 'V':
1180 case 'F':
1181 case 'D':
1182 case 'J':
1183 if (*(descriptor + 1) != '\0')
1184 return false;
1185 break;
1186 case '[':
1187 /* single/multi, object/primitive */
1188 while (*++descriptor == '[')
1189 ;
1190 if (*descriptor == 'L') {
1191 while (*++descriptor != ';' && *descriptor != '\0')
1192 ;
1193 if (*descriptor != ';')
1194 return false;
1195 } else {
1196 if (*(descriptor+1) != '\0')
1197 return false;
1198 }
1199 break;
1200 case 'L':
1201 /* could be more thorough here, but shouldn't be required */
1202 while (*++descriptor != ';' && *descriptor != '\0')
1203 ;
1204 if (*descriptor != ';')
1205 return false;
1206 break;
1207 default:
1208 return false;
1209 }
1210
jeffhaoba5ebb92011-08-25 17:24:37 -07001211 return true;
1212}
1213
jeffhaobdb76512011-09-07 11:43:16 -07001214int DexVerifier::SetUninitInstance(UninitInstanceMap* uninit_map, int addr,
1215 Class* klass) {
1216 int idx;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001217 DCHECK(klass != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07001218
jeffhaod1f0fde2011-09-08 17:25:33 -07001219 /* TODO: binary search when num_entries > 8 */
jeffhaobdb76512011-09-07 11:43:16 -07001220 for (idx = uninit_map->num_entries_ - 1; idx >= 0; idx--) {
1221 if (uninit_map->map_[idx].addr_ == addr) {
1222 if (uninit_map->map_[idx].klass_ != NULL &&
1223 uninit_map->map_[idx].klass_ != klass) {
1224 LOG(ERROR) << "VFY: addr " << addr << " already set to "
1225 << (int) uninit_map->map_[idx].klass_ << ", not setting to "
1226 << (int) klass;
1227 return -1; // already set to something else??
1228 }
1229 uninit_map->map_[idx].klass_ = klass;
1230 return idx;
1231 }
1232 }
1233
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001234 LOG(FATAL) << "VFY: addr " << addr << " not found in uninit map";
jeffhaobdb76512011-09-07 11:43:16 -07001235 return -1;
1236}
1237
1238bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata,
1239 RegisterTable* reg_table) {
1240 const Method* method = vdata->method_;
1241 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001242 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001243 const uint16_t* insns = code_item->insns_;
jeffhaoba5ebb92011-08-25 17:24:37 -07001244 uint32_t insns_size = code_item->insns_size_;
jeffhaobdb76512011-09-07 11:43:16 -07001245 size_t insn_idx, start_guess;
jeffhaoba5ebb92011-08-25 17:24:37 -07001246
jeffhaobdb76512011-09-07 11:43:16 -07001247 /* Begin by marking the first instruction as "changed". */
1248 InsnSetChanged(insn_flags, 0, true);
jeffhaoba5ebb92011-08-25 17:24:37 -07001249
jeffhaobdb76512011-09-07 11:43:16 -07001250 start_guess = 0;
jeffhaoba5ebb92011-08-25 17:24:37 -07001251
jeffhaobdb76512011-09-07 11:43:16 -07001252 /* Continue until no instructions are marked "changed". */
1253 while (true) {
1254 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001255 * Find the first marked one. Use "start_guess" as a way to find
jeffhaobdb76512011-09-07 11:43:16 -07001256 * one quickly.
1257 */
1258 for (insn_idx = start_guess; insn_idx < insns_size; insn_idx++) {
1259 if (InsnIsChanged(insn_flags, insn_idx))
1260 break;
1261 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001262
jeffhaobdb76512011-09-07 11:43:16 -07001263 if (insn_idx == insns_size) {
1264 if (start_guess != 0) {
1265 /* try again, starting from the top */
1266 start_guess = 0;
1267 continue;
1268 } else {
1269 /* all flags are clear */
1270 break;
1271 }
1272 }
1273
1274 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001275 * We carry the working set of registers from instruction to instruction.
1276 * If this address can be the target of a branch (or throw) instruction,
1277 * or if we're skipping around chasing "changed" flags, we need to load
1278 * the set of registers from the table.
jeffhaobdb76512011-09-07 11:43:16 -07001279 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001280 * Because we always prefer to continue on to the next instruction, we
1281 * should never have a situation where we have a stray "changed" flag set
1282 * on an instruction that isn't a branch target.
jeffhaobdb76512011-09-07 11:43:16 -07001283 */
1284 if (InsnIsBranchTarget(insn_flags, insn_idx)) {
1285 RegisterLine* work_line = &reg_table->work_line_;
1286 CopyLineFromTable(work_line, reg_table, insn_idx);
1287 } else {
1288#ifndef NDEBUG
1289 /*
1290 * Sanity check: retrieve the stored register line (assuming
1291 * a full table) and make sure it actually matches.
1292 */
1293 RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001294 if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table,
jeffhaobdb76512011-09-07 11:43:16 -07001295 insn_idx, &reg_table->work_line_) != 0) {
jeffhao2a8a90e2011-09-26 14:25:31 -07001296 LOG(ERROR) << "HUH? work_line diverged in " << PrettyMethod(method);
jeffhaobdb76512011-09-07 11:43:16 -07001297 }
1298#endif
1299 }
1300
1301 if (!CodeFlowVerifyInstruction(vdata, reg_table, insn_idx, &start_guess)) {
jeffhao2a8a90e2011-09-26 14:25:31 -07001302 LOG(ERROR) << "VFY: failure to verify " << PrettyMethod(method);
jeffhaoba5ebb92011-08-25 17:24:37 -07001303 return false;
1304 }
1305
jeffhaobdb76512011-09-07 11:43:16 -07001306 /* Clear "changed" and mark as visited. */
1307 InsnSetVisited(insn_flags, insn_idx, true);
1308 InsnSetChanged(insn_flags, insn_idx, false);
1309 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001310
jeffhaobdb76512011-09-07 11:43:16 -07001311 if (DEAD_CODE_SCAN && ((method->GetAccessFlags() & kAccWritable) == 0)) {
1312 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001313 * Scan for dead code. There's nothing "evil" about dead code
jeffhaobdb76512011-09-07 11:43:16 -07001314 * (besides the wasted space), but it indicates a flaw somewhere
1315 * down the line, possibly in the verifier.
1316 *
1317 * If we've substituted "always throw" instructions into the stream,
1318 * we are almost certainly going to have some dead code.
1319 */
1320 int dead_start = -1;
1321 for (insn_idx = 0; insn_idx < insns_size;
1322 insn_idx += InsnGetWidth(insn_flags, insn_idx)) {
1323 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001324 * Switch-statement data doesn't get "visited" by scanner. It
jeffhaobdb76512011-09-07 11:43:16 -07001325 * may or may not be preceded by a padding NOP (for alignment).
1326 */
1327 if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
1328 insns[insn_idx] == Instruction::kSparseSwitchSignature ||
1329 insns[insn_idx] == Instruction::kArrayDataSignature ||
1330 (insns[insn_idx] == Instruction::NOP &&
1331 (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
1332 insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
1333 insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
1334 InsnSetVisited(insn_flags, insn_idx, true);
1335 }
1336
1337 if (!InsnIsVisited(insn_flags, insn_idx)) {
1338 if (dead_start < 0)
1339 dead_start = insn_idx;
1340 } else if (dead_start >= 0) {
jeffhaobdb76512011-09-07 11:43:16 -07001341 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
jeffhao2a8a90e2011-09-26 14:25:31 -07001342 << insn_idx - 1 << std::dec << " in " << PrettyMethod(method);
jeffhaobdb76512011-09-07 11:43:16 -07001343 dead_start = -1;
1344 }
1345 }
1346 if (dead_start >= 0) {
jeffhaobdb76512011-09-07 11:43:16 -07001347 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
jeffhao2a8a90e2011-09-26 14:25:31 -07001348 << insn_idx - 1 << std::dec << " in " << PrettyMethod(method);
jeffhaoba5ebb92011-08-25 17:24:37 -07001349 }
1350 }
1351
jeffhaobdb76512011-09-07 11:43:16 -07001352 return true;
1353}
1354
1355bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata,
1356 RegisterTable* reg_table, uint32_t insn_idx, size_t* start_guess) {
1357 const Method* method = vdata->method_;
1358 Class* klass = method->GetDeclaringClass();
1359 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001360 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001361 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001362 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001363 const uint16_t* insns = code_item->insns_ + insn_idx;
1364 uint32_t insns_size = code_item->insns_size_;
1365 uint32_t registers_size = code_item->registers_size_;
1366
1367#ifdef VERIFIER_STATS
1368 if (InsnIsVisited(insn_flags, insn_idx)) {
1369 gDvm.verifierStats.instrsReexamined++;
1370 } else {
1371 gDvm.verifierStats.instrsExamined++;
1372 }
1373#endif
1374
1375 /*
1376 * Once we finish decoding the instruction, we need to figure out where
jeffhaod1f0fde2011-09-08 17:25:33 -07001377 * we can go from here. There are three possible ways to transfer
jeffhaobdb76512011-09-07 11:43:16 -07001378 * control to another statement:
1379 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001380 * (1) Continue to the next instruction. Applies to all but
jeffhaobdb76512011-09-07 11:43:16 -07001381 * unconditional branches, method returns, and exception throws.
jeffhaod1f0fde2011-09-08 17:25:33 -07001382 * (2) Branch to one or more possible locations. Applies to branches
jeffhaobdb76512011-09-07 11:43:16 -07001383 * and switch statements.
jeffhaod1f0fde2011-09-08 17:25:33 -07001384 * (3) Exception handlers. Applies to any instruction that can
jeffhaobdb76512011-09-07 11:43:16 -07001385 * throw an exception that is handled by an encompassing "try"
1386 * block.
1387 *
1388 * We can also return, in which case there is no successor instruction
1389 * from this point.
1390 *
1391 * The behavior can be determined from the OpcodeFlags.
1392 */
1393 RegisterLine* work_line = &reg_table->work_line_;
1394 const DexFile* dex_file = vdata->dex_file_;
1395 const byte* ptr = reinterpret_cast<const byte*>(insns);
1396 const Instruction* inst = Instruction::At(ptr);
1397 Instruction::DecodedInstruction dec_insn(inst);
1398 int opcode_flag = inst->Flag();
1399
1400 Class* res_class;
1401 int32_t branch_target = 0;
1402 RegType tmp_type;
1403 bool just_set_result = false;
1404 VerifyError failure = VERIFY_ERROR_NONE;
1405
1406 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001407 * Make a copy of the previous register state. If the instruction
jeffhaobdb76512011-09-07 11:43:16 -07001408 * can throw an exception, we will copy/merge this into the "catch"
1409 * address rather than work_line, because we don't want the result
1410 * from the "successful" code path (e.g. a check-cast that "improves"
1411 * a type) to be visible to the exception handler.
1412 */
1413 if ((opcode_flag & Instruction::kThrow) != 0 &&
1414 InsnIsInTry(insn_flags, insn_idx)) {
1415 CopyRegisterLine(&reg_table->saved_line_, work_line,
1416 reg_table->insn_reg_count_plus_);
1417 } else {
1418#ifndef NDEBUG
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001419 memset(reg_table->saved_line_.reg_types_.get(), 0xdd,
jeffhaobdb76512011-09-07 11:43:16 -07001420 reg_table->insn_reg_count_plus_ * sizeof(RegType));
1421#endif
1422 }
1423
1424 switch (dec_insn.opcode_) {
1425 case Instruction::NOP:
1426 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001427 * A "pure" NOP has no effect on anything. Data tables start with
jeffhaobdb76512011-09-07 11:43:16 -07001428 * a signature that looks like a NOP; if we see one of these in
1429 * the course of executing code then we have a problem.
1430 */
1431 if (dec_insn.vA_ != 0) {
1432 LOG(ERROR) << "VFY: encountered data table in instruction stream";
1433 failure = VERIFY_ERROR_GENERIC;
1434 }
1435 break;
1436
1437 case Instruction::MOVE:
1438 case Instruction::MOVE_FROM16:
1439 case Instruction::MOVE_16:
1440 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategory1nr,
1441 &failure);
1442 break;
1443 case Instruction::MOVE_WIDE:
1444 case Instruction::MOVE_WIDE_FROM16:
1445 case Instruction::MOVE_WIDE_16:
1446 CopyRegister2(work_line, dec_insn.vA_, dec_insn.vB_, &failure);
1447 break;
1448 case Instruction::MOVE_OBJECT:
1449 case Instruction::MOVE_OBJECT_FROM16:
1450 case Instruction::MOVE_OBJECT_16:
1451 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategoryRef,
1452 &failure);
1453 break;
1454
1455 /*
1456 * The move-result instructions copy data out of a "pseudo-register"
jeffhaod1f0fde2011-09-08 17:25:33 -07001457 * with the results from the last method invocation. In practice we
jeffhaobdb76512011-09-07 11:43:16 -07001458 * might want to hold the result in an actual CPU register, so the
1459 * Dalvik spec requires that these only appear immediately after an
1460 * invoke or filled-new-array.
1461 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001462 * These calls invalidate the "result" register. (This is now
jeffhaobdb76512011-09-07 11:43:16 -07001463 * redundant with the reset done below, but it can make the debug info
1464 * easier to read in some cases.)
1465 */
1466 case Instruction::MOVE_RESULT:
1467 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1468 kTypeCategory1nr, &failure);
1469 break;
1470 case Instruction::MOVE_RESULT_WIDE:
1471 CopyResultRegister2(work_line, registers_size, dec_insn.vA_, &failure);
1472 break;
1473 case Instruction::MOVE_RESULT_OBJECT:
1474 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1475 kTypeCategoryRef, &failure);
1476 break;
1477
1478 case Instruction::MOVE_EXCEPTION:
1479 /*
1480 * This statement can only appear as the first instruction in an
1481 * exception handler (though not all exception handlers need to
jeffhaod1f0fde2011-09-08 17:25:33 -07001482 * have one of these). We verify that as part of extracting the
jeffhaobdb76512011-09-07 11:43:16 -07001483 * exception type from the catch block list.
1484 *
1485 * "res_class" will hold the closest common superclass of all
1486 * exceptions that can be handled here.
1487 */
1488 res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
1489 if (res_class == NULL) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001490 DCHECK(failure != VERIFY_ERROR_NONE);
jeffhaobdb76512011-09-07 11:43:16 -07001491 } else {
1492 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1493 }
1494 break;
1495
1496 case Instruction::RETURN_VOID:
1497 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1498 failure = VERIFY_ERROR_GENERIC;
1499 } else if (GetMethodReturnType(dex_file, method) != kRegTypeUnknown) {
1500 LOG(ERROR) << "VFY: return-void not expected";
1501 failure = VERIFY_ERROR_GENERIC;
1502 }
1503 break;
1504 case Instruction::RETURN:
1505 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1506 failure = VERIFY_ERROR_GENERIC;
1507 } else {
1508 /* check the method signature */
1509 RegType return_type = GetMethodReturnType(dex_file, method);
1510 CheckTypeCategory(return_type, kTypeCategory1nr, &failure);
1511 if (failure != VERIFY_ERROR_NONE)
1512 LOG(ERROR) << "VFY: return-1nr not expected";
1513
1514 /*
1515 * compiler may generate synthetic functions that write byte
1516 * values into boolean fields. Also, it may use integer values
1517 * for boolean, byte, short, and character return types.
1518 */
1519 RegType src_type = GetRegisterType(work_line, dec_insn.vA_);
1520 if ((return_type == kRegTypeBoolean && src_type == kRegTypeByte) ||
1521 ((return_type == kRegTypeBoolean || return_type == kRegTypeByte ||
1522 return_type == kRegTypeShort || return_type == kRegTypeChar) &&
1523 src_type == kRegTypeInteger))
1524 return_type = src_type;
1525
1526 /* check the register contents */
1527 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1528 if (failure != VERIFY_ERROR_NONE) {
1529 LOG(ERROR) << "VFY: return-1nr on invalid register v" << dec_insn.vA_;
1530 }
1531 }
1532 break;
1533 case Instruction::RETURN_WIDE:
1534 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1535 failure = VERIFY_ERROR_GENERIC;
1536 } else {
1537 RegType return_type;
1538
1539 /* check the method signature */
1540 return_type = GetMethodReturnType(dex_file, method);
1541 CheckTypeCategory(return_type, kTypeCategory2, &failure);
1542 if (failure != VERIFY_ERROR_NONE)
1543 LOG(ERROR) << "VFY: return-wide not expected";
1544
1545 /* check the register contents */
1546 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1547 if (failure != VERIFY_ERROR_NONE) {
1548 LOG(ERROR) << "VFY: return-wide on invalid register pair v"
1549 << dec_insn.vA_;
1550 }
1551 }
1552 break;
1553 case Instruction::RETURN_OBJECT:
1554 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1555 failure = VERIFY_ERROR_GENERIC;
1556 } else {
1557 RegType return_type = GetMethodReturnType(dex_file, method);
1558 CheckTypeCategory(return_type, kTypeCategoryRef, &failure);
1559 if (failure != VERIFY_ERROR_NONE) {
1560 LOG(ERROR) << "VFY: return-object not expected";
1561 break;
1562 }
1563
1564 /* return_type is the *expected* return type, not register value */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001565 DCHECK(return_type != kRegTypeZero);
1566 DCHECK(!RegTypeIsUninitReference(return_type));
jeffhaobdb76512011-09-07 11:43:16 -07001567
1568 /*
1569 * Verify that the reference in vAA is an instance of the type
jeffhaod1f0fde2011-09-08 17:25:33 -07001570 * in "return_type". The Zero type is allowed here. If the
jeffhaobdb76512011-09-07 11:43:16 -07001571 * method is declared to return an interface, then any
1572 * initialized reference is acceptable.
1573 *
1574 * Note GetClassFromRegister fails if the register holds an
1575 * uninitialized reference, so we do not allow them to be
1576 * returned.
1577 */
1578 Class* decl_class = RegTypeInitializedReferenceToClass(return_type);
1579 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1580 if (failure != VERIFY_ERROR_NONE)
1581 break;
1582 if (res_class != NULL) {
1583 if (!decl_class->IsInterface() &&
jeffhaobdb76512011-09-07 11:43:16 -07001584 !decl_class->IsAssignableFrom(res_class)) {
1585 LOG(ERROR) << "VFY: returning " << std::hex
1586 << res_class->GetDescriptor()->ToModifiedUtf8()
1587 << " (cl=0x" << (int) res_class->GetClassLoader()
1588 << "), declared "
1589 << decl_class->GetDescriptor()->ToModifiedUtf8()
1590 << " (cl=0x" << (int) decl_class->GetClassLoader()
1591 << ")" << std::dec;
1592 failure = VERIFY_ERROR_GENERIC;
1593 break;
1594 }
1595 }
1596 }
1597 break;
1598
1599 case Instruction::CONST_4:
1600 case Instruction::CONST_16:
1601 case Instruction::CONST:
1602 /* could be boolean, int, float, or a null reference */
1603 SetRegisterType(work_line, dec_insn.vA_,
1604 DetermineCat1Const((int32_t) dec_insn.vB_));
1605 break;
1606 case Instruction::CONST_HIGH16:
1607 /* could be boolean, int, float, or a null reference */
1608 SetRegisterType(work_line, dec_insn.vA_,
1609 DetermineCat1Const((int32_t) dec_insn.vB_ << 16));
1610 break;
1611 case Instruction::CONST_WIDE_16:
1612 case Instruction::CONST_WIDE_32:
1613 case Instruction::CONST_WIDE:
1614 case Instruction::CONST_WIDE_HIGH16:
1615 /* could be long or double; resolved upon use */
1616 SetRegisterType(work_line, dec_insn.vA_, kRegTypeConstLo);
1617 break;
1618 case Instruction::CONST_STRING:
1619 case Instruction::CONST_STRING_JUMBO:
1620 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1621 class_linker->FindSystemClass("Ljava/lang/String;")));
1622 break;
1623 case Instruction::CONST_CLASS:
1624 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001625 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001626 if (res_class == NULL) {
1627 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1628 LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
1629 << " (" << bad_class_desc << ") in "
1630 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001631 DCHECK(failure != VERIFY_ERROR_GENERIC);
1632 } else {
1633 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1634 class_linker->FindSystemClass("Ljava/lang/Class;")));
jeffhaobdb76512011-09-07 11:43:16 -07001635 }
1636 break;
1637
1638 case Instruction::MONITOR_ENTER:
1639 HandleMonitorEnter(work_line, dec_insn.vA_, insn_idx, &failure);
1640 break;
1641 case Instruction::MONITOR_EXIT:
1642 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001643 * monitor-exit instructions are odd. They can throw exceptions,
jeffhaobdb76512011-09-07 11:43:16 -07001644 * but when they do they act as if they succeeded and the PC is
jeffhaod1f0fde2011-09-08 17:25:33 -07001645 * pointing to the following instruction. (This behavior goes back
jeffhaobdb76512011-09-07 11:43:16 -07001646 * to the need to handle asynchronous exceptions, a now-deprecated
1647 * feature that Dalvik doesn't support.)
1648 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001649 * In practice we don't need to worry about this. The only
jeffhaobdb76512011-09-07 11:43:16 -07001650 * exceptions that can be thrown from monitor-exit are for a
jeffhaod1f0fde2011-09-08 17:25:33 -07001651 * null reference and -exit without a matching -enter. If the
jeffhaobdb76512011-09-07 11:43:16 -07001652 * structured locking checks are working, the former would have
1653 * failed on the -enter instruction, and the latter is impossible.
1654 *
1655 * This is fortunate, because issue 3221411 prevents us from
1656 * chasing the "can throw" path when monitor verification is
jeffhaod1f0fde2011-09-08 17:25:33 -07001657 * enabled. If we can fully verify the locking we can ignore
jeffhaobdb76512011-09-07 11:43:16 -07001658 * some catch blocks (which will show up as "dead" code when
1659 * we skip them here); if we can't, then the code path could be
1660 * "live" so we still need to check it.
1661 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001662 if (work_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07001663 opcode_flag &= ~Instruction::kThrow;
1664 HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
1665 break;
1666
1667 case Instruction::CHECK_CAST:
1668 /*
1669 * If this instruction succeeds, we will promote register vA to
jeffhaod1f0fde2011-09-08 17:25:33 -07001670 * the type in vB. (This could be a demotion -- not expected, so
jeffhaobdb76512011-09-07 11:43:16 -07001671 * we don't try to address it.)
1672 *
1673 * If it fails, an exception is thrown, which we deal with later
1674 * by ignoring the update to dec_insn.vA_ when branching to a handler.
1675 */
jeffhao98eacac2011-09-14 16:11:53 -07001676 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001677 if (res_class == NULL) {
1678 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1679 LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
1680 << " (" << bad_class_desc << ") in "
1681 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001682 DCHECK(failure != VERIFY_ERROR_GENERIC);
1683 } else {
1684 RegType orig_type = GetRegisterType(work_line, dec_insn.vA_);
1685 if (!RegTypeIsReference(orig_type)) {
1686 LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
1687 failure = VERIFY_ERROR_GENERIC;
jeffhaobdb76512011-09-07 11:43:16 -07001688 break;
1689 }
jeffhao2a8a90e2011-09-26 14:25:31 -07001690 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
jeffhaobdb76512011-09-07 11:43:16 -07001691 }
1692 break;
1693 case Instruction::INSTANCE_OF:
1694 /* make sure we're checking a reference type */
1695 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1696 if (!RegTypeIsReference(tmp_type)) {
1697 LOG(ERROR) << "VFY: vB not a reference (" << tmp_type << ")";
1698 failure = VERIFY_ERROR_GENERIC;
1699 break;
1700 }
1701
1702 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001703 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001704 if (res_class == NULL) {
1705 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1706 LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
1707 << " (" << bad_class_desc << ") in "
1708 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001709 DCHECK(failure != VERIFY_ERROR_GENERIC);
1710 } else {
1711 /* result is boolean */
1712 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
jeffhaobdb76512011-09-07 11:43:16 -07001713 }
1714 break;
1715
1716 case Instruction::ARRAY_LENGTH:
1717 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
1718 if (failure != VERIFY_ERROR_NONE)
1719 break;
1720 if (res_class != NULL && !res_class->IsArrayClass()) {
1721 LOG(ERROR) << "VFY: array-length on non-array";
1722 failure = VERIFY_ERROR_GENERIC;
1723 break;
1724 }
1725 SetRegisterType(work_line, dec_insn.vA_, kRegTypeInteger);
1726 break;
1727
1728 case Instruction::NEW_INSTANCE:
jeffhao2a8a90e2011-09-26 14:25:31 -07001729 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
1730 if (res_class == NULL) {
1731 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1732 LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
1733 << " (" << bad_class_desc << ") in "
1734 << klass->GetDescriptor()->ToModifiedUtf8();
1735 DCHECK(failure != VERIFY_ERROR_GENERIC);
1736 } else {
jeffhaobdb76512011-09-07 11:43:16 -07001737 RegType uninit_type;
1738
1739 /* can't create an instance of an interface or abstract class */
1740 if (res_class->IsAbstract() || res_class->IsInterface()) {
1741 LOG(ERROR) << "VFY: new-instance on interface or abstract class"
1742 << res_class->GetDescriptor()->ToModifiedUtf8();
1743 failure = VERIFY_ERROR_INSTANTIATION;
1744 break;
1745 }
1746
1747 /* add resolved class to uninit map if not already there */
1748 int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001749 DCHECK_GE(uidx, 0);
jeffhaobdb76512011-09-07 11:43:16 -07001750 uninit_type = RegTypeFromUninitIndex(uidx);
1751
1752 /*
1753 * Any registers holding previous allocations from this address
1754 * that have not yet been initialized must be marked invalid.
1755 */
1756 MarkUninitRefsAsInvalid(work_line, registers_size, uninit_map,
1757 uninit_type);
1758
1759 /* add the new uninitialized reference to the register ste */
1760 SetRegisterType(work_line, dec_insn.vA_, uninit_type);
1761 }
jeffhao2a8a90e2011-09-26 14:25:31 -07001762 break;
jeffhaobdb76512011-09-07 11:43:16 -07001763 case Instruction::NEW_ARRAY:
jeffhao98eacac2011-09-14 16:11:53 -07001764 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001765 if (res_class == NULL) {
1766 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1767 LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
1768 << " (" << bad_class_desc << ") in "
1769 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001770 DCHECK(failure != VERIFY_ERROR_GENERIC);
1771 } else if (!res_class->IsArrayClass()) {
jeffhaobdb76512011-09-07 11:43:16 -07001772 LOG(ERROR) << "VFY: new-array on non-array class";
1773 failure = VERIFY_ERROR_GENERIC;
1774 } else {
1775 /* make sure "size" register is valid type */
1776 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeInteger, &failure);
1777 /* set register type to array class */
1778 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1779 }
1780 break;
1781 case Instruction::FILLED_NEW_ARRAY:
1782 case Instruction::FILLED_NEW_ARRAY_RANGE:
jeffhao98eacac2011-09-14 16:11:53 -07001783 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001784 if (res_class == NULL) {
1785 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1786 LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
1787 << " (" << bad_class_desc << ") in "
1788 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001789 DCHECK(failure != VERIFY_ERROR_GENERIC);
1790 } else if (!res_class->IsArrayClass()) {
jeffhaobdb76512011-09-07 11:43:16 -07001791 LOG(ERROR) << "VFY: filled-new-array on non-array class";
1792 failure = VERIFY_ERROR_GENERIC;
1793 } else {
jeffhaoe0cfb6f2011-09-22 16:42:56 -07001794 bool is_range = (dec_insn.opcode_ == Instruction::FILLED_NEW_ARRAY_RANGE);
jeffhaobdb76512011-09-07 11:43:16 -07001795
1796 /* check the arguments to the instruction */
1797 VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
1798 is_range, &failure);
1799 /* filled-array result goes into "result" register */
1800 SetResultRegisterType(work_line, registers_size,
1801 RegTypeFromClass(res_class));
1802 just_set_result = true;
1803 }
1804 break;
1805
1806 case Instruction::CMPL_FLOAT:
1807 case Instruction::CMPG_FLOAT:
1808 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeFloat, &failure);
1809 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeFloat, &failure);
1810 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1811 break;
1812 case Instruction::CMPL_DOUBLE:
1813 case Instruction::CMPG_DOUBLE:
1814 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeDoubleLo, &failure);
1815 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeDoubleLo, &failure);
1816 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1817 break;
1818 case Instruction::CMP_LONG:
1819 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeLongLo, &failure);
1820 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeLongLo, &failure);
1821 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1822 break;
1823
1824 case Instruction::THROW:
1825 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1826 if (failure == VERIFY_ERROR_NONE && res_class != NULL) {
1827 Class* throwable_class =
1828 class_linker->FindSystemClass("Ljava/lang/Throwable;");
1829 if (!throwable_class->IsAssignableFrom(res_class)) {
1830 LOG(ERROR) << "VFY: thrown class "
1831 << res_class->GetDescriptor()->ToModifiedUtf8()
1832 << " not instanceof Throwable",
1833 failure = VERIFY_ERROR_GENERIC;
1834 }
1835 }
1836 break;
1837
1838 case Instruction::GOTO:
1839 case Instruction::GOTO_16:
1840 case Instruction::GOTO_32:
1841 /* no effect on or use of registers */
1842 break;
1843
1844 case Instruction::PACKED_SWITCH:
1845 case Instruction::SPARSE_SWITCH:
1846 /* verify that vAA is an integer, or can be converted to one */
1847 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeInteger, &failure);
1848 break;
1849
1850 case Instruction::FILL_ARRAY_DATA:
1851 {
1852 RegType value_type;
1853 const uint16_t *array_data;
1854 uint16_t elem_width;
1855
1856 /* Similar to the verification done for APUT */
1857 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1858 if (failure != VERIFY_ERROR_NONE)
1859 break;
1860
1861 /* res_class can be null if the reg type is Zero */
1862 if (res_class == NULL)
1863 break;
1864
1865 Class::PrimitiveType prim_type =
1866 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001867 if (!res_class->IsArrayClass() ||
jeffhaobdb76512011-09-07 11:43:16 -07001868 prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
1869 LOG(ERROR) << "VFY: invalid fill-array-data on " <<
1870 res_class->GetDescriptor()->ToModifiedUtf8();
1871 failure = VERIFY_ERROR_GENERIC;
1872 break;
1873 }
1874
1875 value_type = PrimitiveTypeToRegType(prim_type);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001876 DCHECK(value_type != kRegTypeUnknown);
jeffhaobdb76512011-09-07 11:43:16 -07001877
1878 /*
1879 * Now verify if the element width in the table matches the element
1880 * width declared in the array
1881 */
1882 array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
1883 if (array_data[0] != Instruction::kArrayDataSignature) {
1884 LOG(ERROR) << "VFY: invalid magic for array-data";
1885 failure = VERIFY_ERROR_GENERIC;
1886 break;
1887 }
1888
1889 switch (prim_type) {
1890 case Class::kPrimBoolean:
1891 case Class::kPrimByte:
1892 elem_width = 1;
1893 break;
1894 case Class::kPrimChar:
1895 case Class::kPrimShort:
1896 elem_width = 2;
1897 break;
1898 case Class::kPrimFloat:
1899 case Class::kPrimInt:
1900 elem_width = 4;
1901 break;
1902 case Class::kPrimDouble:
1903 case Class::kPrimLong:
1904 elem_width = 8;
1905 break;
1906 default:
1907 elem_width = 0;
1908 break;
1909 }
1910
1911 /*
1912 * Since we don't compress the data in Dex, expect to see equal
1913 * width of data stored in the table and expected from the array
1914 * class.
1915 */
1916 if (array_data[1] != elem_width) {
1917 LOG(ERROR) << "VFY: array-data size mismatch (" << array_data[1]
1918 << " vs " << elem_width << ")";
1919 failure = VERIFY_ERROR_GENERIC;
1920 }
1921 }
1922 break;
1923
1924 case Instruction::IF_EQ:
1925 case Instruction::IF_NE:
1926 {
1927 RegType type1, type2;
1928
1929 type1 = GetRegisterType(work_line, dec_insn.vA_);
1930 type2 = GetRegisterType(work_line, dec_insn.vB_);
1931
1932 /* both references? */
1933 if (RegTypeIsReference(type1) && RegTypeIsReference(type2))
1934 break;
1935
1936 /* both category-1nr? */
1937 CheckTypeCategory(type1, kTypeCategory1nr, &failure);
1938 CheckTypeCategory(type2, kTypeCategory1nr, &failure);
1939 if (failure != VERIFY_ERROR_NONE) {
1940 LOG(ERROR) << "VFY: args to if-eq/if-ne must both be refs or cat1";
1941 break;
1942 }
1943 }
1944 break;
1945 case Instruction::IF_LT:
1946 case Instruction::IF_GE:
1947 case Instruction::IF_GT:
1948 case Instruction::IF_LE:
1949 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1950 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1951 if (failure != VERIFY_ERROR_NONE) {
1952 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1953 break;
1954 }
1955 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1956 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1957 if (failure != VERIFY_ERROR_NONE) {
1958 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1959 break;
1960 }
1961 break;
1962 case Instruction::IF_EQZ:
1963 case Instruction::IF_NEZ:
1964 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1965 if (RegTypeIsReference(tmp_type))
1966 break;
1967 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1968 if (failure != VERIFY_ERROR_NONE)
1969 LOG(ERROR) << "VFY: expected cat-1 arg to if";
1970 break;
1971 case Instruction::IF_LTZ:
1972 case Instruction::IF_GEZ:
1973 case Instruction::IF_GTZ:
1974 case Instruction::IF_LEZ:
1975 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1976 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1977 if (failure != VERIFY_ERROR_NONE)
1978 LOG(ERROR) << "VFY: expected cat-1 arg to if";
1979 break;
1980
1981 case Instruction::AGET:
1982 tmp_type = kRegTypeConstInteger;
1983 goto aget_1nr_common;
1984 case Instruction::AGET_BOOLEAN:
1985 tmp_type = kRegTypeBoolean;
1986 goto aget_1nr_common;
1987 case Instruction::AGET_BYTE:
1988 tmp_type = kRegTypeByte;
1989 goto aget_1nr_common;
1990 case Instruction::AGET_CHAR:
1991 tmp_type = kRegTypeChar;
1992 goto aget_1nr_common;
1993 case Instruction::AGET_SHORT:
1994 tmp_type = kRegTypeShort;
1995 goto aget_1nr_common;
1996aget_1nr_common:
1997 {
1998 RegType src_type, index_type;
1999
2000 index_type = GetRegisterType(work_line, dec_insn.vC_);
2001 CheckArrayIndexType(method, index_type, &failure);
2002 if (failure != VERIFY_ERROR_NONE)
2003 break;
2004
2005 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2006 if (failure != VERIFY_ERROR_NONE)
2007 break;
2008 if (res_class != NULL) {
2009 /* verify the class */
2010 Class::PrimitiveType prim_type =
2011 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002012 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002013 LOG(ERROR) << "VFY: invalid aget-1nr target "
2014 << res_class->GetDescriptor()->ToModifiedUtf8();
2015 failure = VERIFY_ERROR_GENERIC;
2016 break;
2017 }
2018
2019 /* make sure array type matches instruction */
2020 src_type = PrimitiveTypeToRegType(prim_type);
2021
2022 /* differentiate between float and int */
2023 if (src_type == kRegTypeFloat || src_type == kRegTypeInteger)
2024 tmp_type = src_type;
2025
2026 if (tmp_type != src_type) {
2027 LOG(ERROR) << "VFY: invalid aget-1nr, array type=" << src_type
2028 << " with inst type=" << tmp_type << " (on "
2029 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2030 failure = VERIFY_ERROR_GENERIC;
2031 break;
2032 }
2033
2034 }
2035 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2036 }
2037 break;
2038
2039 case Instruction::AGET_WIDE:
2040 {
2041 RegType dst_type, index_type;
2042
2043 index_type = GetRegisterType(work_line, dec_insn.vC_);
2044 CheckArrayIndexType(method, index_type, &failure);
2045 if (failure != VERIFY_ERROR_NONE)
2046 break;
2047
2048 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2049 if (failure != VERIFY_ERROR_NONE)
2050 break;
2051 if (res_class != NULL) {
2052 /* verify the class */
2053 Class::PrimitiveType prim_type =
2054 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002055 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002056 LOG(ERROR) << "VFY: invalid aget-wide target "
2057 << res_class->GetDescriptor()->ToModifiedUtf8();
2058 failure = VERIFY_ERROR_GENERIC;
2059 break;
2060 }
2061
2062 /* try to refine "dst_type" */
2063 switch (prim_type) {
2064 case Class::kPrimLong:
2065 dst_type = kRegTypeLongLo;
2066 break;
2067 case Class::kPrimDouble:
2068 dst_type = kRegTypeDoubleLo;
2069 break;
2070 default:
2071 LOG(ERROR) << "VFY: invalid aget-wide on "
2072 << res_class->GetDescriptor()->ToModifiedUtf8();
2073 dst_type = kRegTypeUnknown;
2074 failure = VERIFY_ERROR_GENERIC;
2075 break;
2076 }
2077 } else {
2078 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002079 * Null array ref; this code path will fail at runtime. We
jeffhaobdb76512011-09-07 11:43:16 -07002080 * know this is either long or double, so label it const.
2081 */
2082 dst_type = kRegTypeConstLo;
2083 }
2084 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2085 }
2086 break;
2087
2088 case Instruction::AGET_OBJECT:
2089 {
2090 RegType dst_type, index_type;
2091
2092 index_type = GetRegisterType(work_line, dec_insn.vC_);
2093 CheckArrayIndexType(method, index_type, &failure);
2094 if (failure != VERIFY_ERROR_NONE)
2095 break;
2096
2097 /* get the class of the array we're pulling an object from */
2098 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2099 if (failure != VERIFY_ERROR_NONE)
2100 break;
2101 if (res_class != NULL) {
2102 Class* element_class;
2103
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002104 DCHECK(res_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002105 if (!res_class->IsArrayClass()) {
2106 LOG(ERROR) << "VFY: aget-object on non-array class";
2107 failure = VERIFY_ERROR_GENERIC;
2108 break;
2109 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002110 DCHECK(res_class->GetComponentType() != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002111
2112 /*
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002113 * Find the element class.
jeffhaobdb76512011-09-07 11:43:16 -07002114 */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002115 element_class = res_class->GetComponentType();
2116 if (element_class->IsPrimitive()) {
jeffhaobdb76512011-09-07 11:43:16 -07002117 LOG(ERROR) << "VFY: aget-object on non-ref array class ("
2118 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2119 failure = VERIFY_ERROR_GENERIC;
2120 break;
2121 }
2122
2123 dst_type = RegTypeFromClass(element_class);
2124 } else {
2125 /*
2126 * The array reference is NULL, so the current code path will
jeffhaod1f0fde2011-09-08 17:25:33 -07002127 * throw an exception. For proper merging with later code
jeffhaobdb76512011-09-07 11:43:16 -07002128 * paths, and correct handling of "if-eqz" tests on the
2129 * result of the array get, we want to treat this as a null
2130 * reference.
2131 */
2132 dst_type = kRegTypeZero;
2133 }
2134 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2135 }
2136 break;
2137 case Instruction::APUT:
2138 tmp_type = kRegTypeInteger;
2139 goto aput_1nr_common;
2140 case Instruction::APUT_BOOLEAN:
2141 tmp_type = kRegTypeBoolean;
2142 goto aput_1nr_common;
2143 case Instruction::APUT_BYTE:
2144 tmp_type = kRegTypeByte;
2145 goto aput_1nr_common;
2146 case Instruction::APUT_CHAR:
2147 tmp_type = kRegTypeChar;
2148 goto aput_1nr_common;
2149 case Instruction::APUT_SHORT:
2150 tmp_type = kRegTypeShort;
2151 goto aput_1nr_common;
2152aput_1nr_common:
2153 {
2154 RegType src_type, dst_type, index_type;
2155
2156 index_type = GetRegisterType(work_line, dec_insn.vC_);
2157 CheckArrayIndexType(method, index_type, &failure);
2158 if (failure != VERIFY_ERROR_NONE)
2159 break;
2160
2161 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2162 if (failure != VERIFY_ERROR_NONE)
2163 break;
2164
2165 /* res_class can be null if the reg type is Zero */
2166 if (res_class == NULL)
2167 break;
2168
2169 Class::PrimitiveType prim_type =
2170 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002171 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002172 LOG(ERROR) << "VFY: invalid aput-1nr on "
2173 << res_class->GetDescriptor()->ToModifiedUtf8();
2174 failure = VERIFY_ERROR_GENERIC;
2175 break;
2176 }
2177
2178 /* verify that instruction matches array */
2179 dst_type = PrimitiveTypeToRegType(prim_type);
2180
2181 /* correct if float */
2182 if (dst_type == kRegTypeFloat)
2183 tmp_type = kRegTypeFloat;
2184
2185 /* make sure the source register has the correct type */
2186 src_type = GetRegisterType(work_line, dec_insn.vA_);
2187 if (!CanConvertTo1nr(src_type, tmp_type)) {
2188 LOG(ERROR) << "VFY: invalid reg type " << src_type
2189 << " on aput instr (need " << tmp_type << ")";
2190 failure = VERIFY_ERROR_GENERIC;
2191 break;
2192 }
2193
2194 VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);
2195
2196 if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
2197 tmp_type != dst_type) {
2198 LOG(ERROR) << "VFY: invalid aput-1nr on "
2199 << res_class->GetDescriptor()->ToModifiedUtf8()
2200 << " (inst=" << tmp_type << " dst=" << dst_type << ")";
2201 failure = VERIFY_ERROR_GENERIC;
2202 break;
2203 }
2204 }
2205 break;
2206 case Instruction::APUT_WIDE:
2207 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2208 CheckArrayIndexType(method, tmp_type, &failure);
2209 if (failure != VERIFY_ERROR_NONE)
2210 break;
2211
2212 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2213 if (failure != VERIFY_ERROR_NONE)
2214 break;
2215 if (res_class != NULL) {
2216 Class::PrimitiveType prim_type =
2217 res_class->GetComponentType()->GetPrimitiveType();
2218 /* verify the class and try to refine "dst_type" */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002219 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot)
jeffhaobdb76512011-09-07 11:43:16 -07002220 {
2221 LOG(ERROR) << "VFY: invalid aput-wide on "
2222 << res_class->GetDescriptor()->ToModifiedUtf8();
2223 failure = VERIFY_ERROR_GENERIC;
2224 break;
2225 }
2226
2227 switch (prim_type) {
2228 case Class::kPrimLong:
2229 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
2230 &failure);
2231 break;
2232 case Class::kPrimDouble:
2233 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2234 &failure);
2235 break;
2236 default:
2237 LOG(ERROR) << "VFY: invalid aput-wide on "
2238 << res_class->GetDescriptor()->ToModifiedUtf8();
2239 failure = VERIFY_ERROR_GENERIC;
2240 break;
2241 }
2242 }
2243 break;
2244 case Instruction::APUT_OBJECT:
2245 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2246 CheckArrayIndexType(method, tmp_type, &failure);
2247 if (failure != VERIFY_ERROR_NONE)
2248 break;
2249
2250 /* get the ref we're storing; Zero is okay, Uninit is not */
2251 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
2252 if (failure != VERIFY_ERROR_NONE)
2253 break;
2254 if (res_class != NULL) {
2255 Class* array_class;
2256 Class* element_class;
2257
2258 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002259 * Get the array class. If the array ref is null, we won't
jeffhaobdb76512011-09-07 11:43:16 -07002260 * have type information (and we'll crash at runtime with a
2261 * null pointer exception).
2262 */
2263 array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2264
2265 if (array_class != NULL) {
2266 /* see if the array holds a compatible type */
2267 if (!array_class->IsArrayClass()) {
2268 LOG(ERROR) << "VFY: invalid aput-object on "
2269 << array_class->GetDescriptor()->ToModifiedUtf8();
2270 failure = VERIFY_ERROR_GENERIC;
2271 break;
2272 }
2273
2274 /*
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002275 * Find the element class.
jeffhaobdb76512011-09-07 11:43:16 -07002276 *
2277 * All we want to check here is that the element type is a
jeffhaod1f0fde2011-09-08 17:25:33 -07002278 * reference class. We *don't* check instanceof here, because
jeffhaobdb76512011-09-07 11:43:16 -07002279 * you can still put a String into a String[] after the latter
2280 * has been cast to an Object[].
2281 */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002282 element_class = array_class->GetComponentType();
2283 if (element_class->IsPrimitive()) {
jeffhaobdb76512011-09-07 11:43:16 -07002284 LOG(ERROR) << "VFY: invalid aput-object of "
2285 << res_class->GetDescriptor()->ToModifiedUtf8()
2286 << " into "
2287 << array_class->GetDescriptor()->ToModifiedUtf8();
2288 failure = VERIFY_ERROR_GENERIC;
2289 break;
2290 }
2291 }
2292 }
2293 break;
2294
2295 case Instruction::IGET:
2296 tmp_type = kRegTypeInteger;
2297 goto iget_1nr_common;
2298 case Instruction::IGET_BOOLEAN:
2299 tmp_type = kRegTypeBoolean;
2300 goto iget_1nr_common;
2301 case Instruction::IGET_BYTE:
2302 tmp_type = kRegTypeByte;
2303 goto iget_1nr_common;
2304 case Instruction::IGET_CHAR:
2305 tmp_type = kRegTypeChar;
2306 goto iget_1nr_common;
2307 case Instruction::IGET_SHORT:
2308 tmp_type = kRegTypeShort;
2309 goto iget_1nr_common;
2310iget_1nr_common:
2311 {
2312 Field* inst_field;
2313 RegType obj_type, field_type;
2314
2315 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2316 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2317 if (failure != VERIFY_ERROR_NONE)
2318 break;
2319
2320 /* make sure the field's type is compatible with expectation */
jeffhao2a8a90e2011-09-26 14:25:31 -07002321 field_type = PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
jeffhaobdb76512011-09-07 11:43:16 -07002322
2323 /* correct if float */
2324 if (field_type == kRegTypeFloat)
2325 tmp_type = kRegTypeFloat;
2326
2327 if (field_type == kRegTypeUnknown || tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002328 LOG(ERROR) << "VFY: invalid iget-1nr of " << PrettyField(inst_field)
jeffhaobdb76512011-09-07 11:43:16 -07002329 << " (inst=" << tmp_type << " field=" << field_type << ")";
2330 failure = VERIFY_ERROR_GENERIC;
2331 break;
2332 }
2333
2334 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2335 }
2336 break;
2337 case Instruction::IGET_WIDE:
2338 {
jeffhaobdb76512011-09-07 11:43:16 -07002339 Field* inst_field;
2340 RegType obj_type;
2341
2342 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2343 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002344 if (failure != VERIFY_ERROR_NONE)
2345 break;
2346 /* check the type, which should be prim */
2347 switch (inst_field->GetType()->GetPrimitiveType()) {
2348 case Class::kPrimDouble:
jeffhao2a8a90e2011-09-26 14:25:31 -07002349 SetRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo);
jeffhaobdb76512011-09-07 11:43:16 -07002350 break;
2351 case Class::kPrimLong:
jeffhao2a8a90e2011-09-26 14:25:31 -07002352 SetRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo);
jeffhaobdb76512011-09-07 11:43:16 -07002353 break;
2354 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002355 LOG(ERROR) << "VFY: invalid iget-wide of " << PrettyField(inst_field);
jeffhaobdb76512011-09-07 11:43:16 -07002356 failure = VERIFY_ERROR_GENERIC;
2357 break;
2358 }
jeffhaobdb76512011-09-07 11:43:16 -07002359 }
2360 break;
2361 case Instruction::IGET_OBJECT:
2362 {
2363 Class* field_class;
2364 Field* inst_field;
2365 RegType obj_type;
2366
2367 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2368 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2369 if (failure != VERIFY_ERROR_NONE)
2370 break;
2371 field_class = inst_field->GetType();
2372 if (field_class == NULL) {
2373 /* class not found or primitive type */
2374 LOG(ERROR) << "VFY: unable to recover field class from "
2375 << inst_field->GetName()->ToModifiedUtf8();
2376 failure = VERIFY_ERROR_GENERIC;
2377 break;
2378 }
jeffhao2a8a90e2011-09-26 14:25:31 -07002379 DCHECK(!field_class->IsPrimitive()) << PrettyClass(field_class);
2380 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
jeffhaobdb76512011-09-07 11:43:16 -07002381 }
2382 break;
2383 case Instruction::IPUT:
2384 tmp_type = kRegTypeInteger;
2385 goto iput_1nr_common;
2386 case Instruction::IPUT_BOOLEAN:
2387 tmp_type = kRegTypeBoolean;
2388 goto iput_1nr_common;
2389 case Instruction::IPUT_BYTE:
2390 tmp_type = kRegTypeByte;
2391 goto iput_1nr_common;
2392 case Instruction::IPUT_CHAR:
2393 tmp_type = kRegTypeChar;
2394 goto iput_1nr_common;
2395 case Instruction::IPUT_SHORT:
2396 tmp_type = kRegTypeShort;
2397 goto iput_1nr_common;
2398iput_1nr_common:
2399 {
2400 RegType src_type, field_type, obj_type;
2401 Field* inst_field;
2402
2403 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2404 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2405 if (failure != VERIFY_ERROR_NONE)
2406 break;
2407 CheckFinalFieldAccess(method, inst_field, &failure);
2408 if (failure != VERIFY_ERROR_NONE)
2409 break;
2410
2411 /* get type of field we're storing into */
jeffhao2a8a90e2011-09-26 14:25:31 -07002412 field_type = PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
jeffhaobdb76512011-09-07 11:43:16 -07002413 src_type = GetRegisterType(work_line, dec_insn.vA_);
2414
2415 /* correct if float */
2416 if (field_type == kRegTypeFloat)
2417 tmp_type = kRegTypeFloat;
2418
2419 /*
2420 * compiler can generate synthetic functions that write byte values
2421 * into boolean fields.
2422 */
2423 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2424 tmp_type = kRegTypeByte;
2425 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2426 field_type = kRegTypeByte;
2427
2428 /* make sure the source register has the correct type */
2429 if (!CanConvertTo1nr(src_type, tmp_type)) {
2430 LOG(ERROR) << "VFY: invalid reg type " << src_type
2431 << " on iput instr (need " << tmp_type << ")",
2432 failure = VERIFY_ERROR_GENERIC;
2433 break;
2434 }
2435
2436 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2437
2438 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2439 tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002440 LOG(ERROR) << "VFY: invalid iput-1nr of " << PrettyField(inst_field)
jeffhaobdb76512011-09-07 11:43:16 -07002441 << " (inst=" << tmp_type << " field=" << field_type << ")";
2442 failure = VERIFY_ERROR_GENERIC;
2443 break;
2444 }
2445 }
2446 break;
2447 case Instruction::IPUT_WIDE:
jeffhao2a8a90e2011-09-26 14:25:31 -07002448 {
2449 Field* inst_field;
2450 RegType obj_type;
jeffhaobdb76512011-09-07 11:43:16 -07002451
jeffhao2a8a90e2011-09-26 14:25:31 -07002452 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2453 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2454 if (failure != VERIFY_ERROR_NONE)
2455 break;
2456 CheckFinalFieldAccess(method, inst_field, &failure);
2457 if (failure != VERIFY_ERROR_NONE)
2458 break;
jeffhaobdb76512011-09-07 11:43:16 -07002459
jeffhao2a8a90e2011-09-26 14:25:31 -07002460 /* check the type, which should be prim */
2461 switch (inst_field->GetType()->GetPrimitiveType()) {
2462 case Class::kPrimDouble:
2463 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2464 &failure);
2465 break;
2466 case Class::kPrimLong:
2467 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2468 break;
2469 default:
2470 LOG(ERROR) << "VFY: invalid iput-wide of " << PrettyField(inst_field);
2471 failure = VERIFY_ERROR_GENERIC;
2472 break;
jeffhaobdb76512011-09-07 11:43:16 -07002473 }
jeffhao2a8a90e2011-09-26 14:25:31 -07002474 break;
2475 }
jeffhaobdb76512011-09-07 11:43:16 -07002476 case Instruction::IPUT_OBJECT:
2477 {
2478 Class* field_class;
2479 Class* value_class;
2480 Field* inst_field;
2481 RegType obj_type, value_type;
2482
2483 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2484 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2485 if (failure != VERIFY_ERROR_NONE)
2486 break;
Brian Carlstrom65ca0772011-09-24 16:03:08 -07002487 DCHECK(inst_field != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002488 CheckFinalFieldAccess(method, inst_field, &failure);
2489 if (failure != VERIFY_ERROR_NONE)
2490 break;
2491
2492 field_class = inst_field->GetType();
2493 if (field_class == NULL) {
2494 LOG(ERROR) << "VFY: unable to recover field class from '"
2495 << inst_field->GetName()->ToModifiedUtf8() << "'";
2496 failure = VERIFY_ERROR_GENERIC;
2497 break;
2498 }
2499
2500 value_type = GetRegisterType(work_line, dec_insn.vA_);
2501 if (!RegTypeIsReference(value_type)) {
2502 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2503 << " into ref field '"
2504 << inst_field->GetName()->ToModifiedUtf8() << "' ("
2505 << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
2506 failure = VERIFY_ERROR_GENERIC;
2507 break;
2508 }
2509 if (value_type != kRegTypeZero) {
2510 value_class = RegTypeInitializedReferenceToClass(value_type);
2511 if (value_class == NULL) {
2512 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2513 << " into ref field";
2514 failure = VERIFY_ERROR_GENERIC;
2515 break;
2516 }
2517 /* allow if field is any interface or field is base class */
2518 if (!field_class->IsInterface() &&
2519 !field_class->IsAssignableFrom(value_class)) {
jeffhaobdb76512011-09-07 11:43:16 -07002520 LOG(ERROR) << "VFY: storing type '"
2521 << value_class->GetDescriptor()->ToModifiedUtf8()
2522 << "' into field type '"
2523 << field_class->GetDescriptor()->ToModifiedUtf8()
jeffhao2a8a90e2011-09-26 14:25:31 -07002524 << "' (" << PrettyField(inst_field) << ")";
jeffhaobdb76512011-09-07 11:43:16 -07002525 failure = VERIFY_ERROR_GENERIC;
2526 break;
2527 }
2528 }
2529 }
2530 break;
2531
2532 case Instruction::SGET:
2533 tmp_type = kRegTypeInteger;
2534 goto sget_1nr_common;
2535 case Instruction::SGET_BOOLEAN:
2536 tmp_type = kRegTypeBoolean;
2537 goto sget_1nr_common;
2538 case Instruction::SGET_BYTE:
2539 tmp_type = kRegTypeByte;
2540 goto sget_1nr_common;
2541 case Instruction::SGET_CHAR:
2542 tmp_type = kRegTypeChar;
2543 goto sget_1nr_common;
2544 case Instruction::SGET_SHORT:
2545 tmp_type = kRegTypeShort;
2546 goto sget_1nr_common;
2547sget_1nr_common:
2548 {
2549 Field* static_field;
2550 RegType field_type;
2551
2552 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2553 if (failure != VERIFY_ERROR_NONE)
2554 break;
2555
2556 /*
2557 * Make sure the field's type is compatible with expectation.
2558 * We can get ourselves into trouble if we mix & match loads
2559 * and stores with different widths, so rather than just checking
2560 * "CanConvertTo1nr" we require that the field types have equal
2561 * widths.
2562 */
2563 field_type =
2564 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2565
2566 /* correct if float */
2567 if (field_type == kRegTypeFloat)
2568 tmp_type = kRegTypeFloat;
2569
2570 if (tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002571 LOG(ERROR) << "VFY: invalid sget-1nr of " << PrettyField(static_field)
jeffhaobdb76512011-09-07 11:43:16 -07002572 << " (inst=" << tmp_type << " actual=" << field_type
2573 << ")";
2574 failure = VERIFY_ERROR_GENERIC;
2575 break;
2576 }
2577
2578 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2579 }
2580 break;
2581 case Instruction::SGET_WIDE:
2582 {
jeffhao2a8a90e2011-09-26 14:25:31 -07002583 Field* static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002584 if (failure != VERIFY_ERROR_NONE)
2585 break;
2586 /* check the type, which should be prim */
2587 switch (static_field->GetType()->GetPrimitiveType()) {
2588 case Class::kPrimDouble:
jeffhao2a8a90e2011-09-26 14:25:31 -07002589 SetRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo);
jeffhaobdb76512011-09-07 11:43:16 -07002590 break;
2591 case Class::kPrimLong:
jeffhao2a8a90e2011-09-26 14:25:31 -07002592 SetRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo);
jeffhaobdb76512011-09-07 11:43:16 -07002593 break;
2594 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002595 LOG(ERROR) << "VFY: invalid sget-wide of " << PrettyField(static_field);
jeffhaobdb76512011-09-07 11:43:16 -07002596 failure = VERIFY_ERROR_GENERIC;
2597 break;
2598 }
jeffhaobdb76512011-09-07 11:43:16 -07002599 }
2600 break;
2601 case Instruction::SGET_OBJECT:
2602 {
jeffhao2a8a90e2011-09-26 14:25:31 -07002603 Field* static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002604 if (failure != VERIFY_ERROR_NONE)
2605 break;
jeffhao2a8a90e2011-09-26 14:25:31 -07002606 Class* field_class = static_field->GetType();
jeffhaobdb76512011-09-07 11:43:16 -07002607 if (field_class == NULL) {
2608 LOG(ERROR) << "VFY: unable to recover field class from '"
2609 << static_field->GetName()->ToModifiedUtf8() << "'";
2610 failure = VERIFY_ERROR_GENERIC;
2611 break;
2612 }
2613 if (field_class->IsPrimitive()) {
2614 LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
2615 failure = VERIFY_ERROR_GENERIC;
2616 break;
2617 }
2618 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
2619 }
2620 break;
2621 case Instruction::SPUT:
2622 tmp_type = kRegTypeInteger;
2623 goto sput_1nr_common;
2624 case Instruction::SPUT_BOOLEAN:
2625 tmp_type = kRegTypeBoolean;
2626 goto sput_1nr_common;
2627 case Instruction::SPUT_BYTE:
2628 tmp_type = kRegTypeByte;
2629 goto sput_1nr_common;
2630 case Instruction::SPUT_CHAR:
2631 tmp_type = kRegTypeChar;
2632 goto sput_1nr_common;
2633 case Instruction::SPUT_SHORT:
2634 tmp_type = kRegTypeShort;
2635 goto sput_1nr_common;
2636sput_1nr_common:
2637 {
2638 RegType src_type, field_type;
2639 Field* static_field;
2640
2641 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2642 if (failure != VERIFY_ERROR_NONE)
2643 break;
2644 CheckFinalFieldAccess(method, static_field, &failure);
2645 if (failure != VERIFY_ERROR_NONE)
2646 break;
2647
2648 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002649 * Get type of field we're storing into. We know that the
jeffhaobdb76512011-09-07 11:43:16 -07002650 * contents of the register match the instruction, but we also
2651 * need to ensure that the instruction matches the field type.
2652 * Using e.g. sput-short to write into a 32-bit integer field
2653 * can lead to trouble if we do 16-bit writes.
2654 */
2655 field_type =
2656 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2657 src_type = GetRegisterType(work_line, dec_insn.vA_);
2658
2659 /* correct if float */
2660 if (field_type == kRegTypeFloat)
2661 tmp_type = kRegTypeFloat;
2662
2663 /*
2664 * compiler can generate synthetic functions that write byte values
2665 * into boolean fields.
2666 */
2667 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2668 tmp_type = kRegTypeByte;
2669 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2670 field_type = kRegTypeByte;
2671
2672 /* make sure the source register has the correct type */
2673 if (!CanConvertTo1nr(src_type, tmp_type)) {
2674 LOG(ERROR) << "VFY: invalid reg type " << src_type
2675 << " on sput instr (need " << tmp_type << ")";
2676 failure = VERIFY_ERROR_GENERIC;
2677 break;
2678 }
2679
2680 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2681
2682 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2683 tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002684 LOG(ERROR) << "VFY: invalid sput-1nr of " << PrettyField(static_field)
jeffhaobdb76512011-09-07 11:43:16 -07002685 << " (inst=" << tmp_type << " actual=" << field_type
2686 << ")";
2687 failure = VERIFY_ERROR_GENERIC;
2688 break;
2689 }
2690 }
2691 break;
2692 case Instruction::SPUT_WIDE:
2693 Field* static_field;
2694
2695 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2696 if (failure != VERIFY_ERROR_NONE)
2697 break;
2698 CheckFinalFieldAccess(method, static_field, &failure);
2699 if (failure != VERIFY_ERROR_NONE)
2700 break;
2701
2702 /* check the type, which should be prim */
2703 switch (static_field->GetType()->GetPrimitiveType()) {
2704 case Class::kPrimDouble:
2705 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2706 &failure);
2707 break;
2708 case Class::kPrimLong:
2709 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2710 break;
2711 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002712 LOG(ERROR) << "VFY: invalid sput-wide of " << PrettyField(static_field);
jeffhaobdb76512011-09-07 11:43:16 -07002713 failure = VERIFY_ERROR_GENERIC;
2714 break;
2715 }
2716 break;
2717 case Instruction::SPUT_OBJECT:
2718 {
2719 Class* field_class;
2720 Class* value_class;
2721 Field* static_field;
2722 RegType value_type;
2723
2724 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2725 if (failure != VERIFY_ERROR_NONE)
2726 break;
2727 CheckFinalFieldAccess(method, static_field, &failure);
2728 if (failure != VERIFY_ERROR_NONE)
2729 break;
2730
2731 field_class = static_field->GetType();
2732 if (field_class == NULL) {
2733 LOG(ERROR) << "VFY: unable to recover field class from '"
2734 << static_field->GetName()->ToModifiedUtf8() << "'";
2735 failure = VERIFY_ERROR_GENERIC;
2736 break;
2737 }
2738
2739 value_type = GetRegisterType(work_line, dec_insn.vA_);
2740 if (!RegTypeIsReference(value_type)) {
2741 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2742 << " into ref field '"
2743 << static_field->GetName()->ToModifiedUtf8() << "' ("
2744 << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
2745 failure = VERIFY_ERROR_GENERIC;
2746 break;
2747 }
2748 if (value_type != kRegTypeZero) {
2749 value_class = RegTypeInitializedReferenceToClass(value_type);
2750 if (value_class == NULL) {
2751 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2752 << " into ref field";
2753 failure = VERIFY_ERROR_GENERIC;
2754 break;
2755 }
2756 /* allow if field is any interface or field is base class */
2757 if (!field_class->IsInterface() &&
2758 !field_class->IsAssignableFrom(value_class)) {
jeffhaobdb76512011-09-07 11:43:16 -07002759 LOG(ERROR) << "VFY: storing type '"
2760 << value_class->GetDescriptor()->ToModifiedUtf8()
2761 << "' into field type '"
2762 << field_class->GetDescriptor()->ToModifiedUtf8()
jeffhao2a8a90e2011-09-26 14:25:31 -07002763 << "' (" << PrettyField(static_field) << ")";
jeffhaobdb76512011-09-07 11:43:16 -07002764 failure = VERIFY_ERROR_GENERIC;
2765 break;
2766 }
2767 }
2768 }
2769 break;
2770
2771 case Instruction::INVOKE_VIRTUAL:
2772 case Instruction::INVOKE_VIRTUAL_RANGE:
2773 case Instruction::INVOKE_SUPER:
2774 case Instruction::INVOKE_SUPER_RANGE:
2775 {
2776 Method* called_method;
2777 RegType return_type;
2778 bool is_range;
2779 bool is_super;
2780
2781 is_range = (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
2782 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2783 is_super = (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
2784 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2785
2786 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2787 &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
2788 if (failure != VERIFY_ERROR_NONE)
2789 break;
2790 return_type = GetMethodReturnType(dex_file, called_method);
2791 SetResultRegisterType(work_line, registers_size, return_type);
2792 just_set_result = true;
2793 }
2794 break;
2795 case Instruction::INVOKE_DIRECT:
2796 case Instruction::INVOKE_DIRECT_RANGE:
2797 {
2798 RegType return_type;
2799 Method* called_method;
2800 bool is_range;
2801
2802 is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
2803 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2804 &dec_insn, METHOD_DIRECT, is_range, false, &failure);
2805 if (failure != VERIFY_ERROR_NONE)
2806 break;
2807
2808 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002809 * Some additional checks when calling <init>. We know from
jeffhaobdb76512011-09-07 11:43:16 -07002810 * the invocation arg check that the "this" argument is an
jeffhaod1f0fde2011-09-08 17:25:33 -07002811 * instance of called_method->klass. Now we further restrict
jeffhaobdb76512011-09-07 11:43:16 -07002812 * that to require that called_method->klass is the same as
2813 * this->klass or this->super, allowing the latter only if
2814 * the "this" argument is the same as the "this" argument to
2815 * this method (which implies that we're in <init> ourselves).
2816 */
2817 if (IsInitMethod(called_method)) {
2818 RegType this_type;
2819 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2820 if (failure != VERIFY_ERROR_NONE)
2821 break;
2822
2823 /* no null refs allowed (?) */
2824 if (this_type == kRegTypeZero) {
2825 LOG(ERROR) << "VFY: unable to initialize null ref";
2826 failure = VERIFY_ERROR_GENERIC;
2827 break;
2828 }
2829
2830 Class* this_class;
2831
2832 this_class = RegTypeReferenceToClass(this_type, uninit_map);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002833 DCHECK(this_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002834
2835 /* must be in same class or in superclass */
2836 if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
2837 {
2838 if (this_class != method->GetDeclaringClass()) {
2839 LOG(ERROR) << "VFY: invoke-direct <init> on super only "
2840 << "allowed for 'this' in <init>";
2841 failure = VERIFY_ERROR_GENERIC;
2842 break;
2843 }
2844 } else if (called_method->GetDeclaringClass() != this_class) {
2845 LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
2846 << "class or super";
2847 failure = VERIFY_ERROR_GENERIC;
2848 break;
2849 }
2850
2851 /* arg must be an uninitialized reference */
2852 if (!RegTypeIsUninitReference(this_type)) {
2853 LOG(ERROR) << "VFY: can only initialize the uninitialized";
2854 failure = VERIFY_ERROR_GENERIC;
2855 break;
2856 }
2857
2858 /*
2859 * Replace the uninitialized reference with an initialized
jeffhaod1f0fde2011-09-08 17:25:33 -07002860 * one, and clear the entry in the uninit map. We need to
jeffhaobdb76512011-09-07 11:43:16 -07002861 * do this for all registers that have the same object
2862 * instance in them, not just the "this" register.
2863 */
2864 MarkRefsAsInitialized(work_line, registers_size, uninit_map,
2865 this_type, &failure);
2866 if (failure != VERIFY_ERROR_NONE)
2867 break;
jeffhao2a8a90e2011-09-26 14:25:31 -07002868 }
jeffhaobdb76512011-09-07 11:43:16 -07002869 return_type = GetMethodReturnType(dex_file, called_method);
2870 SetResultRegisterType(work_line, registers_size, return_type);
2871 just_set_result = true;
2872 }
2873 break;
2874 case Instruction::INVOKE_STATIC:
2875 case Instruction::INVOKE_STATIC_RANGE:
2876 {
2877 RegType return_type;
2878 Method* called_method;
2879 bool is_range;
2880
2881 is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
2882 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2883 &dec_insn, METHOD_STATIC, is_range, false, &failure);
2884 if (failure != VERIFY_ERROR_NONE)
2885 break;
2886
2887 return_type = GetMethodReturnType(dex_file, called_method);
2888 SetResultRegisterType(work_line, registers_size, return_type);
2889 just_set_result = true;
2890 }
2891 break;
2892 case Instruction::INVOKE_INTERFACE:
2893 case Instruction::INVOKE_INTERFACE_RANGE:
2894 {
2895 RegType /*this_type,*/ return_type;
2896 Method* abs_method;
2897 bool is_range;
2898
2899 is_range = (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
2900 abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2901 &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
2902 if (failure != VERIFY_ERROR_NONE)
2903 break;
2904
2905#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
2906 /*
2907 * Get the type of the "this" arg, which should always be an
jeffhaod1f0fde2011-09-08 17:25:33 -07002908 * interface class. Because we don't do a full merge on
jeffhaobdb76512011-09-07 11:43:16 -07002909 * interface classes, this might have reduced to Object.
2910 */
2911 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2912 if (failure != VERIFY_ERROR_NONE)
2913 break;
2914
2915 if (this_type == kRegTypeZero) {
2916 /* null pointer always passes (and always fails at runtime) */
2917 } else {
2918 Class* this_class;
2919
2920 this_class = RegTypeInitializedReferenceToClass(this_type);
2921 if (this_class == NULL) {
2922 LOG(ERROR) << "VFY: interface call on uninitialized";
2923 failure = VERIFY_ERROR_GENERIC;
2924 break;
2925 }
2926
2927 /*
2928 * Either "this_class" needs to be the interface class that
2929 * defined abs_method, or abs_method's class needs to be one
jeffhaod1f0fde2011-09-08 17:25:33 -07002930 * of the interfaces implemented by "this_class". (Or, if
jeffhaobdb76512011-09-07 11:43:16 -07002931 * we couldn't complete the merge, this will be Object.)
2932 */
2933 if (this_class != abs_method->GetDeclaringClass() &&
2934 this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
2935 !this_class->Implements(abs_method->GetDeclaringClass())) {
2936 LOG(ERROR) << "VFY: unable to match abs_method '"
2937 << abs_method->GetName()->ToModifiedUtf8() << "' with "
2938 << this_class->GetDescriptor()->ToModifiedUtf8()
2939 << " interfaces";
2940 failure = VERIFY_ERROR_GENERIC;
2941 break;
2942 }
2943 }
2944#endif
2945
2946 /*
2947 * We don't have an object instance, so we can't find the
jeffhaod1f0fde2011-09-08 17:25:33 -07002948 * concrete method. However, all of the type information is
jeffhaobdb76512011-09-07 11:43:16 -07002949 * in the abstract method, so we're good.
2950 */
2951 return_type = GetMethodReturnType(dex_file, abs_method);
2952 SetResultRegisterType(work_line, registers_size, return_type);
2953 just_set_result = true;
2954 }
2955 break;
2956
2957 case Instruction::NEG_INT:
2958 case Instruction::NOT_INT:
2959 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
2960 &failure);
2961 break;
2962 case Instruction::NEG_LONG:
2963 case Instruction::NOT_LONG:
2964 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
2965 break;
2966 case Instruction::NEG_FLOAT:
2967 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
2968 break;
2969 case Instruction::NEG_DOUBLE:
2970 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
2971 &failure);
2972 break;
2973 case Instruction::INT_TO_LONG:
2974 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
2975 &failure);
2976 break;
2977 case Instruction::INT_TO_FLOAT:
2978 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
2979 break;
2980 case Instruction::INT_TO_DOUBLE:
2981 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
2982 &failure);
2983 break;
2984 case Instruction::LONG_TO_INT:
2985 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
2986 &failure);
2987 break;
2988 case Instruction::LONG_TO_FLOAT:
2989 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
2990 break;
2991 case Instruction::LONG_TO_DOUBLE:
2992 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
2993 &failure);
2994 break;
2995 case Instruction::FLOAT_TO_INT:
2996 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
2997 break;
2998 case Instruction::FLOAT_TO_LONG:
2999 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
3000 break;
3001 case Instruction::FLOAT_TO_DOUBLE:
3002 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
3003 &failure);
3004 break;
3005 case Instruction::DOUBLE_TO_INT:
3006 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
3007 &failure);
3008 break;
3009 case Instruction::DOUBLE_TO_LONG:
3010 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
3011 &failure);
3012 break;
3013 case Instruction::DOUBLE_TO_FLOAT:
3014 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
3015 &failure);
3016 break;
3017 case Instruction::INT_TO_BYTE:
3018 CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
3019 break;
3020 case Instruction::INT_TO_CHAR:
3021 CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
3022 break;
3023 case Instruction::INT_TO_SHORT:
3024 CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
3025 break;
3026
3027 case Instruction::ADD_INT:
3028 case Instruction::SUB_INT:
3029 case Instruction::MUL_INT:
3030 case Instruction::REM_INT:
3031 case Instruction::DIV_INT:
3032 case Instruction::SHL_INT:
3033 case Instruction::SHR_INT:
3034 case Instruction::USHR_INT:
3035 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3036 kRegTypeInteger, false, &failure);
3037 break;
3038 case Instruction::AND_INT:
3039 case Instruction::OR_INT:
3040 case Instruction::XOR_INT:
3041 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3042 kRegTypeInteger, true, &failure);
3043 break;
3044 case Instruction::ADD_LONG:
3045 case Instruction::SUB_LONG:
3046 case Instruction::MUL_LONG:
3047 case Instruction::DIV_LONG:
3048 case Instruction::REM_LONG:
3049 case Instruction::AND_LONG:
3050 case Instruction::OR_LONG:
3051 case Instruction::XOR_LONG:
3052 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3053 kRegTypeLongLo, false, &failure);
3054 break;
3055 case Instruction::SHL_LONG:
3056 case Instruction::SHR_LONG:
3057 case Instruction::USHR_LONG:
3058 /* shift distance is Int, making these different from other binops */
3059 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3060 kRegTypeInteger, false, &failure);
3061 break;
3062 case Instruction::ADD_FLOAT:
3063 case Instruction::SUB_FLOAT:
3064 case Instruction::MUL_FLOAT:
3065 case Instruction::DIV_FLOAT:
3066 case Instruction::REM_FLOAT:
3067 CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3068 kRegTypeFloat, false, &failure);
3069 break;
3070 case Instruction::ADD_DOUBLE:
3071 case Instruction::SUB_DOUBLE:
3072 case Instruction::MUL_DOUBLE:
3073 case Instruction::DIV_DOUBLE:
3074 case Instruction::REM_DOUBLE:
3075 CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3076 kRegTypeDoubleLo, false, &failure);
3077 break;
3078 case Instruction::ADD_INT_2ADDR:
3079 case Instruction::SUB_INT_2ADDR:
3080 case Instruction::MUL_INT_2ADDR:
3081 case Instruction::REM_INT_2ADDR:
3082 case Instruction::SHL_INT_2ADDR:
3083 case Instruction::SHR_INT_2ADDR:
3084 case Instruction::USHR_INT_2ADDR:
3085 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3086 kRegTypeInteger, false, &failure);
3087 break;
3088 case Instruction::AND_INT_2ADDR:
3089 case Instruction::OR_INT_2ADDR:
3090 case Instruction::XOR_INT_2ADDR:
3091 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3092 kRegTypeInteger, true, &failure);
3093 break;
3094 case Instruction::DIV_INT_2ADDR:
3095 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3096 kRegTypeInteger, false, &failure);
3097 break;
3098 case Instruction::ADD_LONG_2ADDR:
3099 case Instruction::SUB_LONG_2ADDR:
3100 case Instruction::MUL_LONG_2ADDR:
3101 case Instruction::DIV_LONG_2ADDR:
3102 case Instruction::REM_LONG_2ADDR:
3103 case Instruction::AND_LONG_2ADDR:
3104 case Instruction::OR_LONG_2ADDR:
3105 case Instruction::XOR_LONG_2ADDR:
3106 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3107 kRegTypeLongLo, false, &failure);
3108 break;
3109 case Instruction::SHL_LONG_2ADDR:
3110 case Instruction::SHR_LONG_2ADDR:
3111 case Instruction::USHR_LONG_2ADDR:
3112 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3113 kRegTypeInteger, false, &failure);
3114 break;
3115 case Instruction::ADD_FLOAT_2ADDR:
3116 case Instruction::SUB_FLOAT_2ADDR:
3117 case Instruction::MUL_FLOAT_2ADDR:
3118 case Instruction::DIV_FLOAT_2ADDR:
3119 case Instruction::REM_FLOAT_2ADDR:
3120 CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3121 kRegTypeFloat, false, &failure);
3122 break;
3123 case Instruction::ADD_DOUBLE_2ADDR:
3124 case Instruction::SUB_DOUBLE_2ADDR:
3125 case Instruction::MUL_DOUBLE_2ADDR:
3126 case Instruction::DIV_DOUBLE_2ADDR:
3127 case Instruction::REM_DOUBLE_2ADDR:
3128 CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3129 kRegTypeDoubleLo, false, &failure);
3130 break;
3131 case Instruction::ADD_INT_LIT16:
3132 case Instruction::RSUB_INT:
3133 case Instruction::MUL_INT_LIT16:
3134 case Instruction::DIV_INT_LIT16:
3135 case Instruction::REM_INT_LIT16:
3136 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3137 &failure);
3138 break;
3139 case Instruction::AND_INT_LIT16:
3140 case Instruction::OR_INT_LIT16:
3141 case Instruction::XOR_INT_LIT16:
3142 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3143 &failure);
3144 break;
3145 case Instruction::ADD_INT_LIT8:
3146 case Instruction::RSUB_INT_LIT8:
3147 case Instruction::MUL_INT_LIT8:
3148 case Instruction::DIV_INT_LIT8:
3149 case Instruction::REM_INT_LIT8:
3150 case Instruction::SHL_INT_LIT8:
3151 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3152 &failure);
3153 break;
3154 case Instruction::SHR_INT_LIT8:
3155 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
jeffhaob4df5142011-09-19 20:25:32 -07003156 false);
jeffhaobdb76512011-09-07 11:43:16 -07003157 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3158 &failure);
3159 break;
3160 case Instruction::USHR_INT_LIT8:
3161 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
jeffhaob4df5142011-09-19 20:25:32 -07003162 true);
jeffhaobdb76512011-09-07 11:43:16 -07003163 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3164 &failure);
3165 break;
3166 case Instruction::AND_INT_LIT8:
3167 case Instruction::OR_INT_LIT8:
3168 case Instruction::XOR_INT_LIT8:
3169 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3170 &failure);
3171 break;
3172
3173 /*
3174 * This falls into the general category of "optimized" instructions,
jeffhaod1f0fde2011-09-08 17:25:33 -07003175 * which don't generally appear during verification. Because it's
jeffhaobdb76512011-09-07 11:43:16 -07003176 * inserted in the course of verification, we can expect to see it here.
3177 */
jeffhaob4df5142011-09-19 20:25:32 -07003178 case Instruction::THROW_VERIFICATION_ERROR:
jeffhaobdb76512011-09-07 11:43:16 -07003179 break;
3180
3181 /*
3182 * Verifying "quickened" instructions is tricky, because we have
jeffhaod1f0fde2011-09-08 17:25:33 -07003183 * discarded the original field/method information. The byte offsets
jeffhaobdb76512011-09-07 11:43:16 -07003184 * and vtable indices only have meaning in the context of an object
3185 * instance.
3186 *
3187 * If a piece of code declares a local reference variable, assigns
3188 * null to it, and then issues a virtual method call on it, we
jeffhaod1f0fde2011-09-08 17:25:33 -07003189 * cannot evaluate the method call during verification. This situation
jeffhaobdb76512011-09-07 11:43:16 -07003190 * isn't hard to handle, since we know the call will always result in an
jeffhaod1f0fde2011-09-08 17:25:33 -07003191 * NPE, and the arguments and return value don't matter. Any code that
jeffhaobdb76512011-09-07 11:43:16 -07003192 * depends on the result of the method call is inaccessible, so the
3193 * fact that we can't fully verify anything that comes after the bad
3194 * call is not a problem.
3195 *
3196 * We must also consider the case of multiple code paths, only some of
jeffhaod1f0fde2011-09-08 17:25:33 -07003197 * which involve a null reference. We can completely verify the method
jeffhaobdb76512011-09-07 11:43:16 -07003198 * if we sidestep the results of executing with a null reference.
3199 * For example, if on the first pass through the code we try to do a
3200 * virtual method invocation through a null ref, we have to skip the
3201 * method checks and have the method return a "wildcard" type (which
jeffhaod1f0fde2011-09-08 17:25:33 -07003202 * merges with anything to become that other thing). The move-result
jeffhaobdb76512011-09-07 11:43:16 -07003203 * will tell us if it's a reference, single-word numeric, or double-word
jeffhaod1f0fde2011-09-08 17:25:33 -07003204 * value. We continue to perform the verification, and at the end of
jeffhaobdb76512011-09-07 11:43:16 -07003205 * the function any invocations that were never fully exercised are
3206 * marked as null-only.
3207 *
jeffhaod1f0fde2011-09-08 17:25:33 -07003208 * We would do something similar for the field accesses. The field's
jeffhaobdb76512011-09-07 11:43:16 -07003209 * type, once known, can be used to recover the width of short integers.
3210 * If the object reference was null, the field-get returns the "wildcard"
3211 * type, which is acceptable for any operation.
3212 */
3213 case Instruction::UNUSED_EE:
3214 case Instruction::UNUSED_EF:
3215 case Instruction::UNUSED_F2:
3216 case Instruction::UNUSED_F3:
3217 case Instruction::UNUSED_F4:
3218 case Instruction::UNUSED_F5:
3219 case Instruction::UNUSED_F6:
3220 case Instruction::UNUSED_F7:
3221 case Instruction::UNUSED_F8:
3222 case Instruction::UNUSED_F9:
3223 case Instruction::UNUSED_FA:
3224 case Instruction::UNUSED_FB:
3225 //case Instruction::EXECUTE_INLINE:
3226 //case Instruction::EXECUTE_INLINE_RANGE:
3227 //case Instruction::IGET_QUICK:
3228 //case Instruction::IGET_WIDE_QUICK:
3229 //case Instruction::IGET_OBJECT_QUICK:
3230 //case Instruction::IPUT_QUICK:
3231 //case Instruction::IPUT_WIDE_QUICK:
3232 //case Instruction::IPUT_OBJECT_QUICK:
3233 //case Instruction::INVOKE_VIRTUAL_QUICK:
3234 //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
3235 //case Instruction::INVOKE_SUPER_QUICK:
3236 //case Instruction::INVOKE_SUPER_QUICK_RANGE:
3237 /* fall through to failure */
3238
3239 /*
3240 * These instructions are equivalent (from the verifier's point of view)
jeffhaod1f0fde2011-09-08 17:25:33 -07003241 * to the original form. The change was made for correctness rather
jeffhaobdb76512011-09-07 11:43:16 -07003242 * than improved performance (except for invoke-object-init, which
jeffhaod1f0fde2011-09-08 17:25:33 -07003243 * provides both). The substitution takes place after verification
jeffhaobdb76512011-09-07 11:43:16 -07003244 * completes, though, so we don't expect to see them here.
3245 */
3246 case Instruction::UNUSED_F0:
3247 case Instruction::UNUSED_F1:
3248 case Instruction::UNUSED_E3:
3249 case Instruction::UNUSED_E8:
3250 case Instruction::UNUSED_E7:
3251 case Instruction::UNUSED_E4:
3252 case Instruction::UNUSED_E9:
3253 case Instruction::UNUSED_FC:
3254 case Instruction::UNUSED_E5:
3255 case Instruction::UNUSED_EA:
3256 case Instruction::UNUSED_FD:
3257 case Instruction::UNUSED_E6:
3258 case Instruction::UNUSED_EB:
3259 case Instruction::UNUSED_FE:
3260 //case Instruction::INVOKE_OBJECT_INIT_RANGE:
3261 //case Instruction::RETURN_VOID_BARRIER:
3262 //case Instruction::IGET_VOLATILE:
3263 //case Instruction::IGET_WIDE_VOLATILE:
3264 //case Instruction::IGET_OBJECT_VOLATILE:
3265 //case Instruction::IPUT_VOLATILE:
3266 //case Instruction::IPUT_WIDE_VOLATILE:
3267 //case Instruction::IPUT_OBJECT_VOLATILE:
3268 //case Instruction::SGET_VOLATILE:
3269 //case Instruction::SGET_WIDE_VOLATILE:
3270 //case Instruction::SGET_OBJECT_VOLATILE:
3271 //case Instruction::SPUT_VOLATILE:
3272 //case Instruction::SPUT_WIDE_VOLATILE:
3273 //case Instruction::SPUT_OBJECT_VOLATILE:
3274 /* fall through to failure */
3275
3276 /* These should never appear during verification. */
3277 case Instruction::UNUSED_3E:
3278 case Instruction::UNUSED_3F:
3279 case Instruction::UNUSED_40:
3280 case Instruction::UNUSED_41:
3281 case Instruction::UNUSED_42:
3282 case Instruction::UNUSED_43:
3283 case Instruction::UNUSED_73:
3284 case Instruction::UNUSED_79:
3285 case Instruction::UNUSED_7A:
3286 case Instruction::UNUSED_EC:
3287 case Instruction::UNUSED_FF:
3288 //case Instruction::BREAKPOINT:
3289 //case Instruction::DISPATCH_FF:
3290 failure = VERIFY_ERROR_GENERIC;
3291 break;
3292
3293 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003294 * DO NOT add a "default" clause here. Without it the compiler will
jeffhaobdb76512011-09-07 11:43:16 -07003295 * complain if an instruction is missing (which is desirable).
3296 */
3297 }
3298
3299 if (failure != VERIFY_ERROR_NONE) {
jeffhaobdb76512011-09-07 11:43:16 -07003300 if (failure == VERIFY_ERROR_GENERIC) {
3301 /* immediate failure, reject class */
3302 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3303 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3304 return false;
3305 } else {
3306 /* replace opcode and continue on */
3307 LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
3308 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
jeffhaob4df5142011-09-19 20:25:32 -07003309 if (!ReplaceFailingInstruction(code_item, insn_idx, failure)) {
jeffhaobdb76512011-09-07 11:43:16 -07003310 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3311 << (int) dec_insn.opcode_ << " at 0x" << insn_idx
3312 << std::dec;
3313 return false;
3314 }
3315 /* IMPORTANT: method->insns may have been changed */
3316 insns = code_item->insns_ + insn_idx;
3317
3318 /* continue on as if we just handled a throw-verification-error */
3319 failure = VERIFY_ERROR_NONE;
3320 opcode_flag = Instruction::kThrow;
3321 }
3322 }
3323
3324 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003325 * If we didn't just set the result register, clear it out. This
jeffhaobdb76512011-09-07 11:43:16 -07003326 * ensures that you can only use "move-result" immediately after the
jeffhaod1f0fde2011-09-08 17:25:33 -07003327 * result is set. (We could check this statically, but it's not
jeffhaobdb76512011-09-07 11:43:16 -07003328 * expensive and it makes our debugging output cleaner.)
3329 */
3330 if (!just_set_result) {
3331 int reg = RESULT_REGISTER(registers_size);
3332 SetRegisterType(work_line, reg, kRegTypeUnknown);
3333 SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
3334 }
3335
jeffhaoa0a764a2011-09-16 10:43:38 -07003336 /* Handle "continue". Tag the next consecutive instruction. */
jeffhaobdb76512011-09-07 11:43:16 -07003337 if ((opcode_flag & Instruction::kContinue) != 0) {
3338 size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
3339 if (insn_idx + insn_width >= insns_size) {
3340 LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
3341 << std::hex << insn_idx << std::dec << ")";
3342 return false;
3343 }
3344
3345 /*
3346 * The only way to get to a move-exception instruction is to get
jeffhaod1f0fde2011-09-08 17:25:33 -07003347 * thrown there. Make sure the next instruction isn't one.
jeffhaobdb76512011-09-07 11:43:16 -07003348 */
3349 if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
3350 return false;
3351
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003352 if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003353 /*
3354 * Merge registers into what we have for the next instruction,
3355 * and set the "changed" flag if needed.
3356 */
3357 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
3358 work_line))
3359 return false;
3360 } else {
3361 /*
3362 * We're not recording register data for the next instruction,
jeffhaod1f0fde2011-09-08 17:25:33 -07003363 * so we don't know what the prior state was. We have to
jeffhaobdb76512011-09-07 11:43:16 -07003364 * assume that something has changed and re-evaluate it.
3365 */
3366 InsnSetChanged(insn_flags, insn_idx + insn_width, true);
3367 }
3368 }
3369
3370 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003371 * Handle "branch". Tag the branch target.
jeffhaobdb76512011-09-07 11:43:16 -07003372 *
3373 * NOTE: instructions like Instruction::EQZ provide information about the
jeffhaod1f0fde2011-09-08 17:25:33 -07003374 * state of the register when the branch is taken or not taken. For example,
jeffhaobdb76512011-09-07 11:43:16 -07003375 * somebody could get a reference field, check it for zero, and if the
3376 * branch is taken immediately store that register in a boolean field
jeffhaod1f0fde2011-09-08 17:25:33 -07003377 * since the value is known to be zero. We do not currently account for
jeffhaobdb76512011-09-07 11:43:16 -07003378 * that, and will reject the code.
3379 *
3380 * TODO: avoid re-fetching the branch target
3381 */
3382 if ((opcode_flag & Instruction::kBranch) != 0) {
3383 bool isConditional, selfOkay;
3384
3385 if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
3386 &isConditional, &selfOkay)) {
3387 /* should never happen after static verification */
3388 LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
3389 return false;
3390 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003391 DCHECK_EQ(isConditional, (opcode_flag & Instruction::kContinue) != 0);
jeffhaobdb76512011-09-07 11:43:16 -07003392
3393 if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
3394 return false;
3395
3396 /* update branch target, set "changed" if appropriate */
3397 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
3398 work_line))
3399 return false;
3400 }
3401
3402 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003403 * Handle "switch". Tag all possible branch targets.
jeffhaobdb76512011-09-07 11:43:16 -07003404 *
3405 * We've already verified that the table is structurally sound, so we
3406 * just need to walk through and tag the targets.
3407 */
3408 if ((opcode_flag & Instruction::kSwitch) != 0) {
3409 int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
3410 const uint16_t* switch_insns = insns + offset_to_switch;
3411 int switch_count = switch_insns[1];
3412 int offset_to_targets, targ;
3413
3414 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
3415 /* 0 = sig, 1 = count, 2/3 = first key */
3416 offset_to_targets = 4;
3417 } else {
3418 /* 0 = sig, 1 = count, 2..count * 2 = keys */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003419 DCHECK((*insns & 0xff) == Instruction::SPARSE_SWITCH);
jeffhaobdb76512011-09-07 11:43:16 -07003420 offset_to_targets = 2 + 2 * switch_count;
3421 }
3422
3423 /* verify each switch target */
3424 for (targ = 0; targ < switch_count; targ++) {
3425 int offset;
3426 uint32_t abs_offset;
3427
3428 /* offsets are 32-bit, and only partly endian-swapped */
3429 offset = switch_insns[offset_to_targets + targ * 2] |
3430 (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
3431 abs_offset = insn_idx + offset;
3432
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003433 DCHECK_LT(abs_offset, insns_size);
jeffhaobdb76512011-09-07 11:43:16 -07003434
3435 if (!CheckMoveException(code_item->insns_, abs_offset))
3436 return false;
3437
3438 if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
3439 return false;
3440 }
3441 }
3442
3443 /*
3444 * Handle instructions that can throw and that are sitting in a
jeffhaod1f0fde2011-09-08 17:25:33 -07003445 * "try" block. (If they're not in a "try" block when they throw,
jeffhaobdb76512011-09-07 11:43:16 -07003446 * control transfers out of the method.)
3447 */
3448 if ((opcode_flag & Instruction::kThrow) != 0 &&
3449 InsnIsInTry(insn_flags, insn_idx)) {
3450 bool has_catch_all = false;
3451 DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
3452 *code_item, insn_idx);
3453
3454 for (; !iterator.HasNext(); iterator.Next()) {
3455 if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
3456 has_catch_all = true;
3457
3458 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003459 * Merge registers into the "catch" block. We want to use the
3460 * "savedRegs" rather than "work_regs", because at runtime the
3461 * exception will be thrown before the instruction modifies any
3462 * registers.
jeffhaobdb76512011-09-07 11:43:16 -07003463 */
3464 if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
3465 &reg_table->saved_line_))
3466 return false;
3467 }
3468
3469 /*
3470 * If the monitor stack depth is nonzero, there must be a "catch all"
jeffhaod1f0fde2011-09-08 17:25:33 -07003471 * handler for this instruction. This does apply to monitor-exit
jeffhaobdb76512011-09-07 11:43:16 -07003472 * because of async exception handling.
3473 */
3474 if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
3475 /*
3476 * The state in work_line reflects the post-execution state.
3477 * If the current instruction is a monitor-enter and the monitor
3478 * stack was empty, we don't need a catch-all (if it throws,
3479 * it will do so before grabbing the lock).
3480 */
3481 if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
3482 work_line->monitor_stack_top_ == 1))
3483 {
3484 LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
3485 << insn_idx << std::dec;
3486 return false;
3487 }
3488 }
3489 }
3490
jeffhaod1f0fde2011-09-08 17:25:33 -07003491 /* If we're returning from the method, make sure monitor stack is empty. */
jeffhaobdb76512011-09-07 11:43:16 -07003492 if ((opcode_flag & Instruction::kReturn) != 0 &&
3493 work_line->monitor_stack_top_ != 0) {
3494 LOG(ERROR) << "VFY: return with stack depth="
3495 << work_line->monitor_stack_top_ << " at 0x" << std::hex
3496 << insn_idx << std::dec;
3497 return false;
3498 }
3499
3500 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003501 * Update start_guess. Advance to the next instruction of that's
3502 * possible, otherwise use the branch target if one was found. If
jeffhaobdb76512011-09-07 11:43:16 -07003503 * neither of those exists we're in a return or throw; leave start_guess
3504 * alone and let the caller sort it out.
3505 */
3506 if ((opcode_flag & Instruction::kContinue) != 0) {
3507 *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
3508 } else if ((opcode_flag & Instruction::kBranch) != 0) {
3509 /* we're still okay if branch_target is zero */
3510 *start_guess = insn_idx + branch_target;
3511 }
3512
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003513 DCHECK_LT(*start_guess, insns_size);
Brian Carlstrom03c99df2011-09-18 10:52:00 -07003514 DCHECK_NE(InsnGetWidth(insn_flags, *start_guess), 0);
jeffhaobdb76512011-09-07 11:43:16 -07003515
3516 return true;
3517}
3518
3519bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
jeffhaob4df5142011-09-19 20:25:32 -07003520 int insn_idx, VerifyError failure) {
jeffhaobdb76512011-09-07 11:43:16 -07003521 const uint16_t* insns = code_item->insns_ + insn_idx;
3522 const byte* ptr = reinterpret_cast<const byte*>(insns);
3523 const Instruction* inst = Instruction::At(ptr);
3524 Instruction::Code opcode = inst->Opcode();
3525 VerifyErrorRefType ref_type;
3526
3527 /*
3528 * Generate the new instruction out of the old.
3529 *
3530 * First, make sure this is an instruction we're expecting to stomp on.
3531 */
3532 switch (opcode) {
3533 case Instruction::CONST_CLASS: // insn[1] == class ref, 2 bytes
3534 case Instruction::CHECK_CAST:
3535 case Instruction::INSTANCE_OF:
3536 case Instruction::NEW_INSTANCE:
3537 case Instruction::NEW_ARRAY:
3538 case Instruction::FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
3539 case Instruction::FILLED_NEW_ARRAY_RANGE:
3540 ref_type = VERIFY_ERROR_REF_CLASS;
3541 break;
3542
3543 case Instruction::IGET: // insn[1] == field ref, 2 bytes
3544 case Instruction::IGET_BOOLEAN:
3545 case Instruction::IGET_BYTE:
3546 case Instruction::IGET_CHAR:
3547 case Instruction::IGET_SHORT:
3548 case Instruction::IGET_WIDE:
3549 case Instruction::IGET_OBJECT:
3550 case Instruction::IPUT:
3551 case Instruction::IPUT_BOOLEAN:
3552 case Instruction::IPUT_BYTE:
3553 case Instruction::IPUT_CHAR:
3554 case Instruction::IPUT_SHORT:
3555 case Instruction::IPUT_WIDE:
3556 case Instruction::IPUT_OBJECT:
3557 case Instruction::SGET:
3558 case Instruction::SGET_BOOLEAN:
3559 case Instruction::SGET_BYTE:
3560 case Instruction::SGET_CHAR:
3561 case Instruction::SGET_SHORT:
3562 case Instruction::SGET_WIDE:
3563 case Instruction::SGET_OBJECT:
3564 case Instruction::SPUT:
3565 case Instruction::SPUT_BOOLEAN:
3566 case Instruction::SPUT_BYTE:
3567 case Instruction::SPUT_CHAR:
3568 case Instruction::SPUT_SHORT:
3569 case Instruction::SPUT_WIDE:
3570 case Instruction::SPUT_OBJECT:
3571 ref_type = VERIFY_ERROR_REF_FIELD;
3572 break;
3573
3574 case Instruction::INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3575 case Instruction::INVOKE_VIRTUAL_RANGE:
3576 case Instruction::INVOKE_SUPER:
3577 case Instruction::INVOKE_SUPER_RANGE:
3578 case Instruction::INVOKE_DIRECT:
3579 case Instruction::INVOKE_DIRECT_RANGE:
3580 case Instruction::INVOKE_STATIC:
3581 case Instruction::INVOKE_STATIC_RANGE:
3582 case Instruction::INVOKE_INTERFACE:
3583 case Instruction::INVOKE_INTERFACE_RANGE:
3584 ref_type = VERIFY_ERROR_REF_METHOD;
3585 break;
3586
3587 default:
3588 /* could handle this in a generic way, but this is probably safer */
3589 LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
3590 << (int) opcode << std::dec;
3591 return false;
3592 }
3593
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003594 DCHECK(inst->IsThrow());
jeffhaobdb76512011-09-07 11:43:16 -07003595
3596 /* write a NOP over the third code unit, if necessary */
jeffhaob4df5142011-09-19 20:25:32 -07003597 int width = inst->Size();
jeffhaobdb76512011-09-07 11:43:16 -07003598 switch (width) {
3599 case 2:
3600 /* nothing to do */
3601 break;
3602 case 3:
jeffhaob4df5142011-09-19 20:25:32 -07003603 UpdateCodeUnit(insns + 2, Instruction::NOP);
jeffhaobdb76512011-09-07 11:43:16 -07003604 break;
3605 default:
3606 /* whoops */
3607 LOG(FATAL) << "ERROR: stomped a " << width
3608 << "-unit instruction with a verifier error";
3609 }
3610
3611 /* encode the opcode, with the failure code in the high byte */
jeffhaob4df5142011-09-19 20:25:32 -07003612 DCHECK(width == 2 || width == 3);
3613 uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
3614 (failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
3615 UpdateCodeUnit(insns, new_val);
jeffhaobdb76512011-09-07 11:43:16 -07003616
3617 return true;
3618}
3619
jeffhaob4df5142011-09-19 20:25:32 -07003620void DexVerifier::UpdateCodeUnit(const uint16_t* ptr, uint16_t new_val) {
3621 *(uint16_t*) ptr = new_val;
3622}
3623
jeffhaobdb76512011-09-07 11:43:16 -07003624void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
3625 uint32_t insn_idx, VerifyError* failure) {
3626 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3627 LOG(ERROR) << "VFY: monitor-enter on non-object";
3628 *failure = VERIFY_ERROR_GENERIC;
3629 return;
3630 }
3631
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003632 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003633 return;
3634 }
3635
3636 if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
3637 LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
3638 << ")";
3639 *failure = VERIFY_ERROR_GENERIC;
3640 return;
3641 }
3642
3643 /*
3644 * Push an entry on the stack, and set a bit in the register flags to
3645 * indicate that it's associated with this register.
3646 */
3647 work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
3648 work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
3649}
3650
jeffhaobdb76512011-09-07 11:43:16 -07003651void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
3652 uint32_t insn_idx, VerifyError* failure) {
3653 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3654 LOG(ERROR) << "VFY: monitor-exit on non-object";
3655 *failure = VERIFY_ERROR_GENERIC;
3656 return;
3657 }
3658
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003659 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003660 return;
3661 }
3662
3663 if (work_line->monitor_stack_top_ == 0) {
3664 LOG(ERROR) << "VFY: monitor-exit stack underflow";
3665 *failure = VERIFY_ERROR_GENERIC;
3666 return;
3667 }
3668
3669 /*
3670 * Confirm that the entry at the top of the stack is associated with
jeffhaod1f0fde2011-09-08 17:25:33 -07003671 * the register. Pop the top entry off.
jeffhaobdb76512011-09-07 11:43:16 -07003672 */
3673 work_line->monitor_stack_top_--;
3674#ifdef BUG_3215458_FIXED
3675 /*
3676 * TODO: This code can safely be enabled if know we are working on
3677 * a dex file of format version 036 or later. (That is, we'll need to
3678 * add a check for the version number.)
3679 */
3680 if ((work_line->monitor_entries_[reg_idx] &
3681 (1 << work_line->monitor_stack_top_)) == 0) {
3682 LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
3683 << " not set: addr=0x" << std::hex << insn_idx << std::dec
3684 << " (bits[" << reg_idx << "]=" << std::hex
3685 << work_line->monitor_entries_[reg_idx] << std::dec << ")";
3686 *failure = VERIFY_ERROR_GENERIC;
3687 return;
3688 }
3689#endif
3690 work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;
3691
3692 /* Clear the bit from the register flags. */
3693 work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
3694}
3695
3696Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
3697 int field_idx, VerifyError* failure) {
3698 Method* method = vdata->method_;
3699 const DexFile* dex_file = vdata->dex_file_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003700 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003701 bool must_be_local = false;
3702
3703 if (!RegTypeIsReference(obj_type)) {
3704 LOG(ERROR) << "VFY: attempt to access field in non-reference type "
3705 << obj_type;
3706 *failure = VERIFY_ERROR_GENERIC;
jeffhaob4df5142011-09-19 20:25:32 -07003707 return NULL;
jeffhaobdb76512011-09-07 11:43:16 -07003708 }
3709
jeffhaob4df5142011-09-19 20:25:32 -07003710 Field* field = ResolveFieldAndCheckAccess(dex_file, field_idx,
3711 method->GetDeclaringClass(), failure, false);
jeffhaobdb76512011-09-07 11:43:16 -07003712 if (field == NULL) {
3713 LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
jeffhao2a8a90e2011-09-26 14:25:31 -07003714 return NULL;
jeffhaobdb76512011-09-07 11:43:16 -07003715 }
3716
3717 if (obj_type == kRegTypeZero)
3718 return field;
3719
3720 /*
3721 * Access to fields in uninitialized objects is allowed if this is
3722 * the <init> method for the object and the field in question is
3723 * declared by this class.
3724 */
jeffhaob4df5142011-09-19 20:25:32 -07003725 Class* obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003726 DCHECK(obj_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07003727 if (RegTypeIsUninitReference(obj_type)) {
3728 if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
3729 LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
3730 *failure = VERIFY_ERROR_GENERIC;
3731 return field;
3732 }
3733 must_be_local = true;
3734 }
3735
jeffhaobdb76512011-09-07 11:43:16 -07003736 if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
jeffhao2a8a90e2011-09-26 14:25:31 -07003737 LOG(ERROR) << "VFY: invalid field access (field " << PrettyField(field)
3738 << ", through " << obj_class->GetDescriptor()->ToModifiedUtf8()
3739 << " ref)";
jeffhaobdb76512011-09-07 11:43:16 -07003740 *failure = VERIFY_ERROR_NO_FIELD;
3741 return field;
3742 }
3743
3744 if (must_be_local) {
3745 bool found = false;
3746 /* for uninit ref, make sure it's defined by this class, not super */
3747 for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
3748 found |= (field == obj_class->GetInstanceField(i));
3749 }
3750 if (!found) {
3751 LOG(ERROR) << "VFY: invalid constructor field access (field "
3752 << field->GetName()->ToModifiedUtf8() << " in "
3753 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
3754 *failure = VERIFY_ERROR_GENERIC;
3755 return field;
3756 }
3757 }
3758
3759 return field;
3760}
3761
3762Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
3763 VerifyError* failure) {
3764 Method* method = vdata->method_;
3765 const DexFile* dex_file = vdata->dex_file_;
jeffhaob4df5142011-09-19 20:25:32 -07003766 Field* field = ResolveFieldAndCheckAccess(dex_file, field_idx,
3767 method->GetDeclaringClass(), failure, true);
jeffhaobdb76512011-09-07 11:43:16 -07003768 if (field == NULL) {
jeffhaob4df5142011-09-19 20:25:32 -07003769 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
3770 LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
3771 << dex_file->GetFieldName(field_id) << ") in "
3772 << dex_file->GetFieldClassDescriptor(field_id);
3773 *failure = VERIFY_ERROR_NO_FIELD;
jeffhaobdb76512011-09-07 11:43:16 -07003774 }
3775
3776 return field;
3777}
3778
3779Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
3780 VerifyError* failure) {
3781 const DexFile* dex_file = vdata->dex_file_;
3782 const DexFile::CodeItem* code_item = vdata->code_item_;
3783 Method* method = vdata->method_;
3784 Class* common_super = NULL;
3785 uint32_t handlers_size;
jeffhaoba5ebb92011-08-25 17:24:37 -07003786 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
jeffhao2a8a90e2011-09-26 14:25:31 -07003787 VerifyError local_failure;
jeffhaobdb76512011-09-07 11:43:16 -07003788
3789 if (code_item->tries_size_ != 0) {
3790 handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
3791 } else {
3792 handlers_size = 0;
3793 }
3794
3795 for (uint32_t i = 0; i < handlers_size; i++) {
jeffhaoba5ebb92011-08-25 17:24:37 -07003796 DexFile::CatchHandlerIterator iterator(handlers_ptr);
3797
3798 for (; !iterator.HasNext(); iterator.Next()) {
jeffhaobdb76512011-09-07 11:43:16 -07003799 DexFile::CatchHandlerItem handler = iterator.Get();
3800 if (handler.address_ == (uint32_t) insn_idx) {
3801 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3802 Class* klass;
jeffhaoba5ebb92011-08-25 17:24:37 -07003803
jeffhaobdb76512011-09-07 11:43:16 -07003804 if (handler.type_idx_ == DexFile::kDexNoIndex) {
3805 klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
3806 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003807 klass = ResolveClassAndCheckAccess(dex_file, handler.type_idx_,
jeffhao2a8a90e2011-09-26 14:25:31 -07003808 method->GetDeclaringClass(), &local_failure);
jeffhaobdb76512011-09-07 11:43:16 -07003809 }
3810
3811 if (klass == NULL) {
3812 LOG(ERROR) << "VFY: unable to resolve exception class "
3813 << handler.type_idx_ << " ("
3814 << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
jeffhaod1f0fde2011-09-08 17:25:33 -07003815 /* TODO: do we want to keep going? If we don't fail this we run
3816 * the risk of having a non-Throwable introduced at runtime.
3817 * However, that won't pass an instanceof test, so is essentially
3818 * harmless.
jeffhaobdb76512011-09-07 11:43:16 -07003819 */
3820 } else {
3821 if (common_super == NULL)
3822 common_super = klass;
3823 else
3824 common_super = FindCommonSuperclass(klass, common_super);
3825 }
3826 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003827 }
3828
3829 handlers_ptr = iterator.GetData();
3830 }
3831
jeffhaobdb76512011-09-07 11:43:16 -07003832 if (common_super == NULL) {
3833 /* no catch blocks, or no catches with classes we can find */
3834 LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
3835 << insn_idx << std::dec;
3836 *failure = VERIFY_ERROR_GENERIC;
3837 }
3838
3839 return common_super;
jeffhaoba5ebb92011-08-25 17:24:37 -07003840}
3841
jeffhaobdb76512011-09-07 11:43:16 -07003842DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
3843 const Method* method) {
3844 Class* klass = method->GetReturnType();
3845 if (klass->IsPrimitive())
3846 return PrimitiveTypeToRegType(klass->GetPrimitiveType());
3847 else
3848 return RegTypeFromClass(klass);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003849}
3850
jeffhaobdb76512011-09-07 11:43:16 -07003851Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
3852 uint32_t vsrc, VerifyError* failure) {
3853 /* get the element type of the array held in vsrc */
3854 RegType type = GetRegisterType(register_line, vsrc);
jeffhaoba5ebb92011-08-25 17:24:37 -07003855
jeffhaobdb76512011-09-07 11:43:16 -07003856 /* if "always zero", we allow it to fail at runtime */
3857 if (type == kRegTypeZero)
3858 return NULL;
3859
3860 if (!RegTypeIsReference(type)) {
3861 LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
3862 << " (type=" << type << ")",
3863 *failure = VERIFY_ERROR_GENERIC;
3864 return NULL;
3865 }
3866 if (RegTypeIsUninitReference(type)) {
3867 LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
3868 *failure = VERIFY_ERROR_GENERIC;
3869 return NULL;
jeffhaoba5ebb92011-08-25 17:24:37 -07003870 }
3871
jeffhaobdb76512011-09-07 11:43:16 -07003872 return RegTypeInitializedReferenceToClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003873}
3874
jeffhaobdb76512011-09-07 11:43:16 -07003875DexVerifier::RegType DexVerifier::GetInvocationThis(
3876 const RegisterLine* register_line,
3877 const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
3878 if (dec_insn->vA_ < 1) {
3879 LOG(ERROR) << "VFY: invoke lacks 'this'";
3880 *failure = VERIFY_ERROR_GENERIC;
3881 return kRegTypeUnknown;
jeffhaoba5ebb92011-08-25 17:24:37 -07003882 }
jeffhaobdb76512011-09-07 11:43:16 -07003883
3884 /* get the element type of the array held in vsrc */
3885 RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
3886 if (!RegTypeIsReference(this_type)) {
3887 LOG(ERROR) << "VFY: tried to get class from non-ref register v"
3888 << dec_insn->vC_ << " (type=" << this_type << ")";
3889 *failure = VERIFY_ERROR_GENERIC;
3890 return kRegTypeUnknown;
3891 }
3892
3893 return this_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003894}
3895
jeffhaobdb76512011-09-07 11:43:16 -07003896void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
3897 RegType new_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003898 RegType* insn_regs = register_line->reg_types_.get();
jeffhaoba5ebb92011-08-25 17:24:37 -07003899
jeffhaobdb76512011-09-07 11:43:16 -07003900 switch (new_type) {
3901 case kRegTypeUnknown:
3902 case kRegTypeBoolean:
3903 case kRegTypeOne:
3904 case kRegTypeConstByte:
3905 case kRegTypeConstPosByte:
3906 case kRegTypeConstShort:
3907 case kRegTypeConstPosShort:
3908 case kRegTypeConstChar:
3909 case kRegTypeConstInteger:
3910 case kRegTypeByte:
3911 case kRegTypePosByte:
3912 case kRegTypeShort:
3913 case kRegTypePosShort:
3914 case kRegTypeChar:
3915 case kRegTypeInteger:
3916 case kRegTypeFloat:
3917 case kRegTypeZero:
3918 case kRegTypeUninit:
3919 insn_regs[vdst] = new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003920 break;
jeffhaobdb76512011-09-07 11:43:16 -07003921 case kRegTypeConstLo:
3922 case kRegTypeLongLo:
3923 case kRegTypeDoubleLo:
3924 insn_regs[vdst] = new_type;
3925 insn_regs[vdst + 1] = new_type + 1;
3926 break;
3927 case kRegTypeConstHi:
3928 case kRegTypeLongHi:
3929 case kRegTypeDoubleHi:
3930 /* should never set these explicitly */
3931 LOG(FATAL) << "BUG: explicit set of high register type";
3932 break;
3933
3934 default:
3935 /* can't switch for ref types, so we check explicitly */
3936 if (RegTypeIsReference(new_type)) {
3937 insn_regs[vdst] = new_type;
3938
3939 /*
3940 * In most circumstances we won't see a reference to a primitive
3941 * class here (e.g. "D"), since that would mean the object in the
jeffhaod1f0fde2011-09-08 17:25:33 -07003942 * register is actually a primitive type. It can happen as the
jeffhaobdb76512011-09-07 11:43:16 -07003943 * result of an assumed-successful check-cast instruction in
jeffhaod1f0fde2011-09-08 17:25:33 -07003944 * which the second argument refers to a primitive class. (In
jeffhaobdb76512011-09-07 11:43:16 -07003945 * practice, such an instruction will always throw an exception.)
3946 *
3947 * This is not an issue for instructions like const-class, where
3948 * the object in the register is a java.lang.Class instance.
3949 */
3950 break;
3951 }
3952 /* bad type - fall through */
3953
3954 case kRegTypeConflict: // should only be set during a merge
3955 LOG(FATAL) << "BUG: set register to unknown type " << new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003956 break;
3957 }
3958
jeffhaobdb76512011-09-07 11:43:16 -07003959 /*
3960 * Clear the monitor entry bits for this register.
3961 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003962 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07003963 register_line->monitor_entries_[vdst] = 0;
3964}
3965
3966void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
3967 RegType check_type, VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003968 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003969 RegType src_type = insn_regs[vsrc];
3970
3971 switch (check_type) {
3972 case kRegTypeFloat:
3973 case kRegTypeBoolean:
3974 case kRegTypePosByte:
3975 case kRegTypeByte:
3976 case kRegTypePosShort:
3977 case kRegTypeShort:
3978 case kRegTypeChar:
3979 case kRegTypeInteger:
3980 if (!CanConvertTo1nr(src_type, check_type)) {
3981 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
3982 << ", wanted " << check_type;
3983 *failure = VERIFY_ERROR_GENERIC;
3984 }
3985 /* Update type if result is float */
3986 if (check_type == kRegTypeFloat) {
3987 SetRegisterType(register_line, vsrc, check_type);
3988 } else {
3989 /* Update const type to actual type after use */
3990 SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
3991 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003992 break;
jeffhaobdb76512011-09-07 11:43:16 -07003993 case kRegTypeLongLo:
3994 case kRegTypeDoubleLo:
3995 if (insn_regs[vsrc + 1] != src_type + 1) {
3996 LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
3997 << " values " << insn_regs[vsrc] << ","
3998 << insn_regs[vsrc + 1];
3999 *failure = VERIFY_ERROR_GENERIC;
4000 } else if (!CanConvertTo2(src_type, check_type)) {
4001 LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
4002 << ", wanted " << check_type;
4003 *failure = VERIFY_ERROR_GENERIC;
4004 }
4005 /* Update type if source is from const */
4006 if (src_type == kRegTypeConstLo) {
4007 SetRegisterType(register_line, vsrc, check_type);
4008 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004009 break;
jeffhaobdb76512011-09-07 11:43:16 -07004010 case kRegTypeConstLo:
4011 case kRegTypeConstHi:
4012 case kRegTypeLongHi:
4013 case kRegTypeDoubleHi:
4014 case kRegTypeZero:
4015 case kRegTypeOne:
4016 case kRegTypeUnknown:
4017 case kRegTypeConflict:
4018 /* should never be checking for these explicitly */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004019 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004020 *failure = VERIFY_ERROR_GENERIC;
4021 return;
4022 case kRegTypeUninit:
4023 default:
4024 /* make sure check_type is initialized reference */
4025 if (!RegTypeIsReference(check_type)) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004026 LOG(FATAL) << "VFY: unexpected check type " << check_type;
jeffhaobdb76512011-09-07 11:43:16 -07004027 *failure = VERIFY_ERROR_GENERIC;
4028 break;
4029 }
4030 if (RegTypeIsUninitReference(check_type)) {
4031 LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
4032 *failure = VERIFY_ERROR_GENERIC;
4033 break;
4034 }
4035 /* make sure src_type is initialized reference or always-NULL */
4036 if (!RegTypeIsReference(src_type)) {
4037 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4038 << ", wanted ref";
4039 *failure = VERIFY_ERROR_GENERIC;
4040 break;
4041 }
4042 if (RegTypeIsUninitReference(src_type)) {
4043 LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
4044 *failure = VERIFY_ERROR_GENERIC;
4045 break;
4046 }
4047 /* if the register isn't Zero, make sure it's an instance of check */
4048 if (src_type != kRegTypeZero) {
4049 Class* src_class = RegTypeInitializedReferenceToClass(src_type);
4050 Class* check_class = RegTypeInitializedReferenceToClass(check_type);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004051 DCHECK(src_class != NULL);
4052 DCHECK(check_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004053
jeffhaoe0cfb6f2011-09-22 16:42:56 -07004054 if (check_class->IsInterface()) {
4055 /*
4056 * All objects implement all interfaces as far as the verifier is
4057 * concerned. The runtime has to sort it out. See coments above
4058 * FindCommonSuperclass.
4059 */
4060 } else {
4061 if (!check_class->IsAssignableFrom(src_class)) {
4062 LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
4063 << " is not instance of "
4064 << check_class->GetDescriptor()->ToModifiedUtf8();
4065 *failure = VERIFY_ERROR_GENERIC;
4066 }
jeffhaobdb76512011-09-07 11:43:16 -07004067 }
4068 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004069 break;
4070 }
jeffhaobdb76512011-09-07 11:43:16 -07004071}
jeffhaoba5ebb92011-08-25 17:24:37 -07004072
jeffhaobdb76512011-09-07 11:43:16 -07004073void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
4074 const int insn_reg_count, RegType new_type) {
4075 SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
4076}
4077
4078void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
4079 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
4080 VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004081 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004082 Class* klass = GetUninitInstance(uninit_map,
4083 RegTypeToUninitIndex(uninit_type));
4084
4085 if (klass == NULL) {
4086 LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
4087 << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
4088 << ")";
4089 *failure = VERIFY_ERROR_GENERIC;
4090 return;
jeffhaoba5ebb92011-08-25 17:24:37 -07004091 }
4092
jeffhaobdb76512011-09-07 11:43:16 -07004093 RegType init_type = RegTypeFromClass(klass);
4094 int changed = 0;
4095 for (int i = 0; i < insn_reg_count; i++) {
4096 if (insn_regs[i] == uninit_type) {
4097 insn_regs[i] = init_type;
4098 changed++;
4099 }
4100 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004101 DCHECK_GT(changed, 0);
jeffhaobdb76512011-09-07 11:43:16 -07004102
4103 return;
4104}
4105
4106void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
4107 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004108 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004109
4110 for (int i = 0; i < insn_reg_count; i++) {
4111 if (insn_regs[i] == uninit_type) {
4112 insn_regs[i] = kRegTypeConflict;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004113 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004114 register_line->monitor_entries_[i] = 0;
4115 }
4116 }
4117}
4118
4119void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
4120 uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004121 DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
jeffhaobdb76512011-09-07 11:43:16 -07004122 RegType type = GetRegisterType(register_line, vsrc);
4123 CheckTypeCategory(type, cat, failure);
4124 if (*failure != VERIFY_ERROR_NONE) {
4125 LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
4126 << " cat=" << (int) cat;
4127 } else {
4128 SetRegisterType(register_line, vdst, type);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004129 if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07004130 register_line->monitor_entries_[vdst] =
4131 register_line->monitor_entries_[vsrc];
4132 }
4133 }
4134}
4135
4136void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
4137 uint32_t vsrc, VerifyError* failure) {
4138 RegType type_l = GetRegisterType(register_line, vsrc);
4139 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4140
4141 CheckTypeCategory(type_l, kTypeCategory2, failure);
4142 CheckWidePair(type_l, type_h, failure);
4143 if (*failure != VERIFY_ERROR_NONE) {
4144 LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
4145 << "/" << type_h;
4146 } else {
4147 SetRegisterType(register_line, vdst, type_l);
4148 }
4149}
4150
4151void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
4152 const int insn_reg_count, uint32_t vdst, TypeCategory cat,
4153 VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004154 DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
jeffhaobdb76512011-09-07 11:43:16 -07004155
4156 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4157 RegType type = GetRegisterType(register_line, vsrc);
4158 CheckTypeCategory(type, cat, failure);
4159 if (*failure != VERIFY_ERROR_NONE) {
4160 LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
4161 << (int) cat << " type=" << type;
4162 } else {
4163 SetRegisterType(register_line, vdst, type);
4164 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4165 }
4166}
4167
4168/*
jeffhaod1f0fde2011-09-08 17:25:33 -07004169 * Implement "move-result-wide". Copy the category-2 value from the result
jeffhaobdb76512011-09-07 11:43:16 -07004170 * register to another register, and reset the result register.
4171 */
4172void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
4173 const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004174 DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
jeffhaobdb76512011-09-07 11:43:16 -07004175
4176 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4177 RegType type_l = GetRegisterType(register_line, vsrc);
4178 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4179 CheckTypeCategory(type_l, kTypeCategory2, failure);
4180 CheckWidePair(type_l, type_h, failure);
4181 if (*failure != VERIFY_ERROR_NONE) {
4182 LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
4183 << type_l << "/" << type_h;
4184 } else {
4185 SetRegisterType(register_line, vdst, type_l);
4186 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4187 SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
4188 }
4189}
4190
4191int DexVerifier::GetClassDepth(Class* klass) {
4192 int depth = 0;
4193 while (klass->GetSuperClass() != NULL) {
4194 klass = klass->GetSuperClass();
4195 depth++;
4196 }
4197 return depth;
4198}
4199
4200Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
4201 int depth1, depth2;
4202
4203 depth1 = GetClassDepth(c1);
4204 depth2 = GetClassDepth(c2);
4205
4206 /* pull the deepest one up */
4207 if (depth1 > depth2) {
4208 while (depth1 > depth2) {
4209 c1 = c1->GetSuperClass();
4210 depth1--;
4211 }
4212 } else {
4213 while (depth2 > depth1) {
4214 c2 = c2->GetSuperClass();
4215 depth2--;
4216 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004217 }
4218
jeffhaobdb76512011-09-07 11:43:16 -07004219 /* walk up in lock-step */
4220 while (c1 != c2) {
4221 c1 = c1->GetSuperClass();
4222 c2 = c2->GetSuperClass();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004223 DCHECK(c1 != NULL);
4224 DCHECK(c2 != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004225 }
4226
4227 return c1;
4228}
4229
4230Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004231 DCHECK(c1->IsArrayClass());
4232 DCHECK(c2->IsArrayClass());
4233 Class* e1 = c1->GetComponentType();
4234 Class* e2 = c2->GetComponentType();
4235 if (e1->IsPrimitive() || e2->IsPrimitive()) {
4236 return c1->GetSuperClass(); // == java.lang.Object
jeffhaobdb76512011-09-07 11:43:16 -07004237 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004238 Class* common_elem = FindCommonSuperclass(c1->GetComponentType(), c2->GetComponentType());
4239 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4240 const ClassLoader* class_loader = c1->GetClassLoader();
4241 std::string descriptor = "[" + common_elem->GetDescriptor()->ToModifiedUtf8();
4242 Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
4243 DCHECK(array_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004244 return array_class;
4245}
4246
4247Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004248 DCHECK(!c1->IsPrimitive()) << PrettyClass(c1);
4249 DCHECK(!c2->IsPrimitive()) << PrettyClass(c2);
jeffhaobdb76512011-09-07 11:43:16 -07004250
4251 if (c1 == c2)
4252 return c1;
4253
jeffhao5dbddee2011-09-07 16:38:26 -07004254 if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
jeffhaobdb76512011-09-07 11:43:16 -07004255 return c1;
4256 }
jeffhao5dbddee2011-09-07 16:38:26 -07004257 if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
jeffhaobdb76512011-09-07 11:43:16 -07004258 return c2;
4259 }
4260 if (c1->IsArrayClass() && c2->IsArrayClass()) {
4261 return FindCommonArraySuperclass(c1, c2);
4262 }
4263
4264 return DigForSuperclass(c1, c2);
4265}
4266
jeffhao98eacac2011-09-14 16:11:53 -07004267Class* DexVerifier::ResolveClassAndCheckAccess(const DexFile* dex_file,
jeffhaob4df5142011-09-19 20:25:32 -07004268 uint32_t class_idx, const Class* referrer, VerifyError* failure) {
jeffhao98eacac2011-09-14 16:11:53 -07004269 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4270 Class* res_class = class_linker->ResolveType(*dex_file, class_idx, referrer);
4271
4272 if (res_class == NULL) {
buzbeec0ecd652011-09-25 18:11:54 -07004273 Thread::Current()->ClearException();
jeffhaoe0cfb6f2011-09-22 16:42:56 -07004274 LOG(ERROR) << "VFY: can't find class with index 0x" << std::hex << class_idx << std::dec;
jeffhao2a8a90e2011-09-26 14:25:31 -07004275 *failure = VERIFY_ERROR_NO_CLASS;
jeffhao98eacac2011-09-14 16:11:53 -07004276 return NULL;
4277 }
4278
4279 /* Check if access is allowed. */
4280 if (!referrer->CanAccess(res_class)) {
4281 LOG(ERROR) << "VFY: illegal class access: "
4282 << referrer->GetDescriptor()->ToModifiedUtf8() << " -> "
4283 << res_class->GetDescriptor()->ToModifiedUtf8();
4284 *failure = VERIFY_ERROR_ACCESS_CLASS;
4285 return NULL;
4286 }
4287
4288 return res_class;
4289}
4290
jeffhaob4df5142011-09-19 20:25:32 -07004291Method* DexVerifier::ResolveMethodAndCheckAccess(const DexFile* dex_file,
4292 uint32_t method_idx, const Class* referrer, VerifyError* failure,
4293 bool is_direct) {
4294 DexCache* dex_cache = referrer->GetDexCache();
4295 Method* res_method = dex_cache->GetResolvedMethod(method_idx);
4296
4297 if (res_method == NULL) {
4298 const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
4299 Class* klass = ResolveClassAndCheckAccess(dex_file, method_id.class_idx_, referrer, failure);
4300 if (klass == NULL) {
4301 DCHECK(*failure != VERIFY_ERROR_NONE);
4302 return NULL;
4303 }
4304
4305 const char* name = dex_file->dexStringById(method_id.name_idx_);
4306 std::string signature(dex_file->CreateMethodDescriptor(method_id.proto_idx_, NULL));
4307 if (is_direct) {
4308 res_method = klass->FindDirectMethod(name, signature);
4309 } else if (klass->IsInterface()) {
4310 res_method = klass->FindInterfaceMethod(name, signature);
4311 } else {
4312 res_method = klass->FindVirtualMethod(name, signature);
4313 }
4314 if (res_method != NULL) {
4315 dex_cache->SetResolvedMethod(method_idx, res_method);
4316 } else {
4317 LOG(ERROR) << "VFY: couldn't find method "
4318 << klass->GetDescriptor()->ToModifiedUtf8() << "." << name
4319 << " " << signature;
4320 *failure = VERIFY_ERROR_NO_METHOD;
4321 return NULL;
4322 }
4323 }
4324
4325 /* Check if access is allowed. */
jeffhao4a801a42011-09-23 13:53:40 -07004326 if (!referrer->CanAccessMember(res_method->GetDeclaringClass(), res_method->GetAccessFlags())) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004327 LOG(ERROR) << "VFY: illegal method access (call " << PrettyMethod(res_method)
4328 << " from " << referrer->GetDescriptor()->ToModifiedUtf8() << ")";
jeffhaob4df5142011-09-19 20:25:32 -07004329 *failure = VERIFY_ERROR_ACCESS_METHOD;
4330 return NULL;
4331 }
4332
4333 return res_method;
4334}
4335
4336Field* DexVerifier::ResolveFieldAndCheckAccess(const DexFile* dex_file,
4337 uint32_t field_idx, const Class* referrer, VerifyError* failure,
4338 bool is_static) {
4339 DexCache* dex_cache = referrer->GetDexCache();
4340 Field* res_field = dex_cache->GetResolvedField(field_idx);
4341
4342 if (res_field == NULL) {
4343 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
4344 Class* klass = ResolveClassAndCheckAccess(dex_file, field_id.class_idx_, referrer, failure);
4345 if (klass == NULL) {
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004346 DCHECK(*failure != VERIFY_ERROR_NONE) << PrettyClass(referrer);
jeffhaob4df5142011-09-19 20:25:32 -07004347 return NULL;
4348 }
4349
4350 Class* field_type = ResolveClassAndCheckAccess(dex_file, field_id.type_idx_, referrer, failure);
4351 if (field_type == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004352 DCHECK(*failure != VERIFY_ERROR_NONE) << PrettyClass(referrer) << " " << PrettyClass(klass);
jeffhaob4df5142011-09-19 20:25:32 -07004353 return NULL;
4354 }
4355
4356 const char* name = dex_file->dexStringById(field_id.name_idx_);
4357 if (is_static) {
4358 res_field = klass->FindStaticField(name, field_type);
4359 } else {
4360 res_field = klass->FindInstanceField(name, field_type);
4361 }
4362 if (res_field != NULL) {
Elliott Hughes4a2b4172011-09-20 17:08:25 -07004363 dex_cache->SetResolvedField(field_idx, res_field);
jeffhaob4df5142011-09-19 20:25:32 -07004364 } else {
4365 LOG(ERROR) << "VFY: couldn't find field "
4366 << klass->GetDescriptor()->ToModifiedUtf8() << "." << name;
4367 *failure = VERIFY_ERROR_NO_FIELD;
4368 return NULL;
4369 }
4370 }
4371
4372 /* Check if access is allowed. */
jeffhao4a801a42011-09-23 13:53:40 -07004373 if (!referrer->CanAccessMember(res_field->GetDeclaringClass(), res_field->GetAccessFlags())) {
jeffhaob4df5142011-09-19 20:25:32 -07004374 LOG(ERROR) << "VFY: access denied from "
4375 << referrer->GetDescriptor()->ToModifiedUtf8() << " to field "
jeffhao2a8a90e2011-09-26 14:25:31 -07004376 << PrettyField(res_field);
jeffhaob4df5142011-09-19 20:25:32 -07004377 *failure = VERIFY_ERROR_ACCESS_FIELD;
4378 return NULL;
4379 }
4380
4381 return res_field;
4382}
4383
jeffhaobdb76512011-09-07 11:43:16 -07004384DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
4385 bool* changed) {
4386 RegType result;
4387
jeffhao98eacac2011-09-14 16:11:53 -07004388 /* Check for trivial case so we don't have to hit memory. */
jeffhaobdb76512011-09-07 11:43:16 -07004389 if (type1 == type2)
4390 return type1;
4391
4392 /*
4393 * Use the table if we can, and reject any attempts to merge something
4394 * from the table with a reference type.
4395 *
4396 * Uninitialized references are composed of the enum ORed with an
jeffhaod1f0fde2011-09-08 17:25:33 -07004397 * index value. The uninitialized table entry at index zero *will*
4398 * show up as a simple kRegTypeUninit value. Since this cannot be
jeffhaobdb76512011-09-07 11:43:16 -07004399 * merged with anything but itself, the rules do the right thing.
4400 */
4401 if (type1 < kRegTypeMAX) {
4402 if (type2 < kRegTypeMAX) {
4403 result = merge_table_[type1][type2];
4404 } else {
4405 /* simple + reference == conflict, usually */
4406 if (type1 == kRegTypeZero)
4407 result = type2;
4408 else
4409 result = kRegTypeConflict;
4410 }
4411 } else {
4412 if (type2 < kRegTypeMAX) {
4413 /* reference + simple == conflict, usually */
4414 if (type2 == kRegTypeZero)
4415 result = type1;
4416 else
4417 result = kRegTypeConflict;
4418 } else {
4419 /* merging two references */
4420 if (RegTypeIsUninitReference(type1) ||
4421 RegTypeIsUninitReference(type2))
4422 {
4423 /* can't merge uninit with anything but self */
4424 result = kRegTypeConflict;
4425 } else {
4426 Class* klass1 = RegTypeInitializedReferenceToClass(type1);
4427 Class* klass2 = RegTypeInitializedReferenceToClass(type2);
4428 Class* merged_class = FindCommonSuperclass(klass1, klass2);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004429 DCHECK(merged_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004430 result = RegTypeFromClass(merged_class);
4431 }
4432 }
4433 }
4434
4435 if (result != type1)
4436 *changed = true;
jeffhaoba5ebb92011-08-25 17:24:37 -07004437 return result;
jeffhaobdb76512011-09-07 11:43:16 -07004438}
4439
4440DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
4441 MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
4442 MonitorEntries result = ents1 & ents2;
4443 if (result != ents1)
4444 *changed = true;
4445 return result;
4446}
4447
4448bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
4449 RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
4450 const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004451 DCHECK(work_line != NULL);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004452 const RegType* work_regs = work_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004453
4454 if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
4455 /*
4456 * We haven't processed this instruction before, and we haven't
jeffhaod1f0fde2011-09-08 17:25:33 -07004457 * touched the registers here, so there's nothing to "merge". Copy
4458 * the registers over and mark it as changed. (This is the only
jeffhaobdb76512011-09-07 11:43:16 -07004459 * way a register can transition out of "unknown", so this is not
4460 * just an optimization.)
4461 */
4462 CopyLineToTable(reg_table, next_insn, work_line);
4463 InsnSetChanged(insn_flags, next_insn, true);
4464 } else {
4465 /* Merge registers, set Changed only if different */
4466 RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004467 RegType* target_regs = target_line->reg_types_.get();
4468 MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
4469 MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004470 bool changed = false;
4471 unsigned int idx;
4472
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004473 DCHECK(target_regs != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004474 if (target_mon_ents != NULL) {
4475 /* Monitor stacks must be identical. */
4476 if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
4477 LOG(ERROR) << "VFY: mismatched stack depth "
4478 << target_line->monitor_stack_top_ << " vs. "
4479 << work_line->monitor_stack_top_ << " at 0x"
4480 << std::hex << next_insn << std::dec;
4481 return false;
4482 }
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004483 if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
jeffhaobdb76512011-09-07 11:43:16 -07004484 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
4485 LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
4486 << next_insn << std::dec;
4487 return false;
4488 }
4489 }
4490
4491 for (idx = 0; idx < insn_reg_count_plus; idx++) {
4492 target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);
4493
4494 if (target_mon_ents != NULL) {
4495 target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
4496 work_mon_ents[idx], &changed);
4497 }
4498 }
4499
4500 if (changed) {
4501 InsnSetChanged(insn_flags, next_insn, true);
4502 }
4503 }
4504
4505 return true;
4506}
4507
4508bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
4509 static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
4510 [kRegType1nrEND - kRegType1nrSTART + 1] =
4511 {
4512 /* chk: 0 1 Z y Y h H c i b B s S C I F */
4513 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4514 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4515 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
4516 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4517 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
4518 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
4519 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
4520 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
4521 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
4522 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
4523 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
4524 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
4525 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
4526 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
4527 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
4528 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
4529 };
4530
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004531 DCHECK(check_type >= kRegType1nrSTART);
4532 DCHECK(check_type <= kRegType1nrEND);
jeffhaobdb76512011-09-07 11:43:16 -07004533
4534 if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
4535 return (bool) conv_tab[src_type - kRegType1nrSTART]
4536 [check_type - kRegType1nrSTART];
4537
4538 return false;
4539}
4540
4541bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
4542 return ((src_type == kRegTypeConstLo || src_type == check_type) &&
4543 (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
4544}
4545
4546DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
4547 Class::PrimitiveType prim_type) {
4548 switch (prim_type) {
4549 case Class::kPrimBoolean: return kRegTypeBoolean;
4550 case Class::kPrimByte: return kRegTypeByte;
4551 case Class::kPrimShort: return kRegTypeShort;
4552 case Class::kPrimChar: return kRegTypeChar;
4553 case Class::kPrimInt: return kRegTypeInteger;
4554 case Class::kPrimLong: return kRegTypeLongLo;
4555 case Class::kPrimFloat: return kRegTypeFloat;
4556 case Class::kPrimDouble: return kRegTypeDoubleLo;
4557 case Class::kPrimVoid:
4558 default: {
4559 return kRegTypeUnknown;
4560 }
4561 }
4562}
4563
4564DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
4565 switch (const_type) {
4566 case kRegTypeConstPosByte: return kRegTypePosByte;
4567 case kRegTypeConstByte: return kRegTypeByte;
4568 case kRegTypeConstPosShort: return kRegTypePosShort;
4569 case kRegTypeConstShort: return kRegTypeShort;
4570 case kRegTypeConstChar: return kRegTypeChar;
4571 case kRegTypeConstInteger: return kRegTypeInteger;
4572 default: {
4573 return const_type;
4574 }
4575 }
4576}
4577
4578char DexVerifier::DetermineCat1Const(int32_t value) {
4579 if (value < -32768)
4580 return kRegTypeConstInteger;
4581 else if (value < -128)
4582 return kRegTypeConstShort;
4583 else if (value < 0)
4584 return kRegTypeConstByte;
4585 else if (value == 0)
4586 return kRegTypeZero;
4587 else if (value == 1)
4588 return kRegTypeOne;
4589 else if (value < 128)
4590 return kRegTypeConstPosByte;
4591 else if (value < 32768)
4592 return kRegTypeConstPosShort;
4593 else if (value < 65536)
4594 return kRegTypeConstChar;
4595 else
4596 return kRegTypeConstInteger;
4597}
4598
4599void DexVerifier::CheckFinalFieldAccess(const Method* method,
4600 const Field* field, VerifyError* failure) {
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004601 DCHECK(field != NULL);
4602 if (!field->IsFinal()) {
jeffhaobdb76512011-09-07 11:43:16 -07004603 return;
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004604 }
jeffhaobdb76512011-09-07 11:43:16 -07004605
4606 /* make sure we're in the same class */
4607 if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004608 LOG(ERROR) << "VFY: can't modify final field " << PrettyField(field);
jeffhaobdb76512011-09-07 11:43:16 -07004609 *failure = VERIFY_ERROR_ACCESS_FIELD;
4610 return;
4611 }
4612}
4613
4614void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
4615 VerifyError* failure) {
4616 if (*failure == VERIFY_ERROR_NONE) {
4617 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004618 * The 1nr types are interchangeable at this level. We could
jeffhaobdb76512011-09-07 11:43:16 -07004619 * do something special if we can definitively identify it as a
4620 * float, but there's no real value in doing so.
4621 */
4622 CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
4623 if (*failure != VERIFY_ERROR_NONE) {
4624 LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
4625 }
4626 }
4627}
4628
4629bool DexVerifier::CheckConstructorReturn(const Method* method,
4630 const RegisterLine* register_line, const int insn_reg_count) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004631 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004632
4633 if (!IsInitMethod(method))
4634 return true;
4635
4636 RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);
4637
4638 for (int i = 0; i < insn_reg_count; i++) {
4639 if (insn_regs[i] == uninit_this) {
4640 LOG(ERROR) << "VFY: <init> returning without calling superclass init";
4641 return false;
4642 }
4643 }
4644 return true;
4645}
4646
4647bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
4648 if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
4649 LOG(ERROR) << "VFY: invalid use of move-exception";
4650 return false;
4651 }
4652 return true;
4653}
4654
4655void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
4656 VerifyError* failure) {
4657 switch (cat) {
4658 case kTypeCategory1nr:
4659 switch (type) {
4660 case kRegTypeZero:
4661 case kRegTypeOne:
4662 case kRegTypeBoolean:
4663 case kRegTypeConstPosByte:
4664 case kRegTypeConstByte:
4665 case kRegTypeConstPosShort:
4666 case kRegTypeConstShort:
4667 case kRegTypeConstChar:
4668 case kRegTypeConstInteger:
4669 case kRegTypePosByte:
4670 case kRegTypeByte:
4671 case kRegTypePosShort:
4672 case kRegTypeShort:
4673 case kRegTypeChar:
4674 case kRegTypeInteger:
4675 case kRegTypeFloat:
4676 break;
4677 default:
4678 *failure = VERIFY_ERROR_GENERIC;
4679 break;
4680 }
4681 break;
4682 case kTypeCategory2:
4683 switch (type) {
4684 case kRegTypeConstLo:
4685 case kRegTypeLongLo:
4686 case kRegTypeDoubleLo:
4687 break;
4688 default:
4689 *failure = VERIFY_ERROR_GENERIC;
4690 break;
4691 }
4692 break;
4693 case kTypeCategoryRef:
4694 if (type != kRegTypeZero && !RegTypeIsReference(type))
4695 *failure = VERIFY_ERROR_GENERIC;
4696 break;
4697 default:
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004698 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004699 *failure = VERIFY_ERROR_GENERIC;
4700 break;
4701 }
4702}
4703
4704void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
4705 VerifyError* failure) {
4706 if ((type_h != type_l + 1))
4707 *failure = VERIFY_ERROR_GENERIC;
4708}
4709
4710void DexVerifier::CheckUnop(RegisterLine* register_line,
4711 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4712 RegType src_type, VerifyError* failure) {
4713 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4714 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4715}
4716
4717bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
4718 uint32_t reg2) {
4719 RegType type1, type2;
4720
4721 type1 = GetRegisterType(register_line, reg1);
4722 type2 = GetRegisterType(register_line, reg2);
4723
4724 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
4725 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
4726 return true;
4727 }
4728 return false;
4729}
4730
4731void DexVerifier::CheckLitop(RegisterLine* register_line,
4732 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4733 RegType src_type, bool check_boolean_op, VerifyError* failure) {
4734 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4735
4736 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004737 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004738
4739 /* check vB with the call, then check the constant manually */
4740 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
4741 && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
4742 dst_type = kRegTypeBoolean;
4743 }
4744 }
4745
4746 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4747}
4748
4749void DexVerifier::CheckBinop(RegisterLine* register_line,
4750 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4751 RegType src_type1, RegType src_type2, bool check_boolean_op,
4752 VerifyError* failure) {
4753 VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
4754 VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
4755
4756 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004757 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004758 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
4759 dst_type = kRegTypeBoolean;
4760 }
4761
4762 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4763}
4764
4765void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
4766 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4767 RegType src_type1, RegType src_type2, bool check_boolean_op,
4768 VerifyError* failure) {
4769 VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
4770 VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
4771
4772 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004773 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004774 if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
4775 dst_type = kRegTypeBoolean;
4776 }
4777
4778 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4779}
4780
4781DexVerifier::RegType DexVerifier::AdjustForRightShift(
4782 RegisterLine* register_line, int reg, unsigned int shift_count,
jeffhaob4df5142011-09-19 20:25:32 -07004783 bool is_unsigned_shift) {
jeffhaobdb76512011-09-07 11:43:16 -07004784 RegType src_type = GetRegisterType(register_line, reg);
4785 RegType new_type;
4786
4787 /* convert const derived types to their actual types */
4788 src_type = ConstTypeToRegType(src_type);
4789
4790 /* no-op */
4791 if (shift_count == 0)
4792 return src_type;
4793
4794 /* safe defaults */
4795 if (is_unsigned_shift)
4796 new_type = kRegTypeInteger;
4797 else
4798 new_type = src_type;
4799
4800 if (shift_count >= 32) {
4801 LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
4802 /* fail? */
4803 return new_type;
4804 }
4805
4806 switch (src_type) {
4807 case kRegTypeInteger: /* 32-bit signed value */
4808 if (is_unsigned_shift) {
4809 if (shift_count > 24)
4810 new_type = kRegTypePosByte;
4811 else if (shift_count >= 16)
4812 new_type = kRegTypeChar;
4813 } else {
4814 if (shift_count >= 24)
4815 new_type = kRegTypeByte;
4816 else if (shift_count >= 16)
4817 new_type = kRegTypeShort;
4818 }
4819 break;
4820 case kRegTypeShort: /* 16-bit signed value */
4821 if (is_unsigned_shift) {
4822 /* default (kRegTypeInteger) is correct */
4823 } else {
4824 if (shift_count >= 8)
4825 new_type = kRegTypeByte;
4826 }
4827 break;
4828 case kRegTypePosShort: /* 15-bit unsigned value */
4829 if (shift_count >= 8)
4830 new_type = kRegTypePosByte;
4831 break;
4832 case kRegTypeChar: /* 16-bit unsigned value */
4833 if (shift_count > 8)
4834 new_type = kRegTypePosByte;
4835 break;
4836 case kRegTypeByte: /* 8-bit signed value */
4837 /* defaults (u=kRegTypeInteger / s=src_type) are correct */
4838 break;
4839 case kRegTypePosByte: /* 7-bit unsigned value */
4840 /* always use new_type=src_type */
4841 new_type = src_type;
4842 break;
4843 case kRegTypeZero: /* 1-bit unsigned value */
4844 case kRegTypeOne:
4845 case kRegTypeBoolean:
4846 /* unnecessary? */
4847 new_type = kRegTypeZero;
4848 break;
4849 default:
4850 /* long, double, references; shouldn't be here! */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004851 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004852 break;
4853 }
4854
4855 return new_type;
4856}
4857
4858void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
4859 RegisterLine* register_line,
4860 const Instruction::DecodedInstruction* dec_insn, Class* res_class,
4861 bool is_range, VerifyError* failure) {
4862 uint32_t arg_count = dec_insn->vA_;
4863 RegType expected_type;
4864 Class::PrimitiveType elem_type;
4865 unsigned int ui;
4866
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004867 DCHECK(res_class->IsArrayClass()) << PrettyClass(res_class);
jeffhaobdb76512011-09-07 11:43:16 -07004868 elem_type = res_class->GetComponentType()->GetPrimitiveType();
4869 if (elem_type == Class::kPrimNot) {
4870 expected_type = RegTypeFromClass(res_class->GetComponentType());
4871 } else {
4872 expected_type = PrimitiveTypeToRegType(elem_type);
4873 }
4874
4875 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004876 * Verify each register. If "arg_count" is bad, VerifyRegisterType()
4877 * will run off the end of the list and fail. It's legal, if silly,
jeffhaobdb76512011-09-07 11:43:16 -07004878 * for arg_count to be zero.
4879 */
4880 for (ui = 0; ui < arg_count; ui++) {
4881 uint32_t get_reg;
4882
4883 if (is_range)
4884 get_reg = dec_insn->vC_ + ui;
4885 else
4886 get_reg = dec_insn->arg_[ui];
4887
4888 VerifyRegisterType(register_line, get_reg, expected_type, failure);
4889 if (*failure != VERIFY_ERROR_NONE) {
4890 LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
4891 << ") not valid";
4892 return;
4893 }
4894 }
4895}
4896
4897bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
4898 Method* res_method) {
4899 switch (method_type) {
4900 case METHOD_DIRECT:
4901 return res_method->IsDirect();
4902 case METHOD_STATIC:
4903 return res_method->IsStatic();
4904 case METHOD_VIRTUAL:
4905 case METHOD_INTERFACE:
4906 return !res_method->IsDirect();
4907 default:
4908 return false;
4909 }
4910}
4911
4912Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
4913 RegisterLine* register_line, const int insn_reg_count,
4914 const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
4915 bool is_range, bool is_super, VerifyError* failure) {
4916 Method* method = vdata->method_;
4917 const DexFile* dex_file = vdata->dex_file_;
4918 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004919 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004920
4921 Method* res_method;
4922 std::string sig;
4923 size_t sig_offset;
4924 int expected_args;
4925 int actual_args;
4926
4927 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004928 * Resolve the method. This could be an abstract or concrete method
jeffhaobdb76512011-09-07 11:43:16 -07004929 * depending on what sort of call we're making.
4930 */
jeffhaob4df5142011-09-19 20:25:32 -07004931 res_method = ResolveMethodAndCheckAccess(dex_file, dec_insn->vB_, method->GetDeclaringClass(),
4932 failure, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
jeffhaobdb76512011-09-07 11:43:16 -07004933
jeffhaobdb76512011-09-07 11:43:16 -07004934 if (res_method == NULL) {
jeffhao98eacac2011-09-14 16:11:53 -07004935 const DexFile::MethodId& method_id = dex_file->GetMethodId(dec_insn->vB_);
4936 const char* method_name = dex_file->GetMethodName(method_id);
Brian Carlstromaded5f72011-10-07 17:15:04 -07004937 std::string method_signature = dex_file->GetMethodSignature(method_id);
jeffhao98eacac2011-09-14 16:11:53 -07004938 const char* class_descriptor = dex_file->GetMethodClassDescriptor(method_id);
4939
4940 LOG(ERROR) << "VFY: unable to resolve method " << dec_insn->vB_ << ": "
Brian Carlstromaded5f72011-10-07 17:15:04 -07004941 << class_descriptor << "." << method_name << " " << method_signature;
jeffhaobdb76512011-09-07 11:43:16 -07004942 return NULL;
4943 }
jeffhaobdb76512011-09-07 11:43:16 -07004944
4945 /*
jeffhao2a8a90e2011-09-26 14:25:31 -07004946 * Make sure calls to "<init>" are "direct". There are additional restrictions
4947 * but we don't enfore them here.
jeffhaobdb76512011-09-07 11:43:16 -07004948 */
jeffhao2a8a90e2011-09-26 14:25:31 -07004949 if (res_method->GetName()->Equals("<init>") && method_type != METHOD_DIRECT) {
4950 LOG(ERROR) << "VFY: invalid call to " << PrettyMethod(res_method);
4951 goto bad_sig;
jeffhaobdb76512011-09-07 11:43:16 -07004952 }
4953
4954 /*
4955 * See if the method type implied by the invoke instruction matches the
4956 * access flags for the target method.
4957 */
4958 if (!IsCorrectInvokeKind(method_type, res_method)) {
4959 LOG(ERROR) << "VFY: invoke type does not match method type of "
jeffhao2a8a90e2011-09-26 14:25:31 -07004960 << PrettyMethod(res_method);
jeffhaobdb76512011-09-07 11:43:16 -07004961 *failure = VERIFY_ERROR_GENERIC;
4962 return NULL;
4963 }
4964
4965 /*
4966 * If we're using invoke-super(method), make sure that the executing
4967 * method's class' superclass has a vtable entry for the target method.
4968 */
4969 if (is_super) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004970 DCHECK(method_type == METHOD_VIRTUAL);
jeffhaobdb76512011-09-07 11:43:16 -07004971 Class* super = method->GetDeclaringClass()->GetSuperClass();
4972 if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
4973 if (super == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004974 LOG(ERROR) << "VFY: invalid invoke-super from " << PrettyMethod(method)
4975 << " to super -." << res_method->GetName()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07004976 << " " << res_method->GetSignature()->ToModifiedUtf8();
4977 } else {
jeffhao2a8a90e2011-09-26 14:25:31 -07004978 LOG(ERROR) << "VFY: invalid invoke-super from " << PrettyMethod(method)
4979 << " to super " << super->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07004980 << "." << res_method->GetName()->ToModifiedUtf8()
4981 << " " << res_method->GetSignature()->ToModifiedUtf8();
4982 }
4983 *failure = VERIFY_ERROR_NO_METHOD;
4984 return NULL;
4985 }
4986 }
4987
4988 /*
4989 * We use vAA as our expected arg count, rather than res_method->insSize,
jeffhaod1f0fde2011-09-08 17:25:33 -07004990 * because we need to match the call to the signature. Also, we might
jeffhaobdb76512011-09-07 11:43:16 -07004991 * might be calling through an abstract method definition (which doesn't
4992 * have register count values).
4993 */
4994 expected_args = dec_insn->vA_;
4995 actual_args = 0;
4996
4997 /* caught by static verifier */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004998 DCHECK(is_range || expected_args <= 5);
jeffhaobdb76512011-09-07 11:43:16 -07004999
5000 if (expected_args > code_item->outs_size_) {
5001 LOG(ERROR) << "VFY: invalid arg count (" << expected_args
5002 << ") exceeds outsSize (" << code_item->outs_size_ << ")";
5003 *failure = VERIFY_ERROR_GENERIC;
5004 return NULL;
5005 }
5006
5007 sig = res_method->GetSignature()->ToModifiedUtf8();
5008 if (sig[0] != '(') {
5009 LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
5010 goto bad_sig;
5011 }
5012
5013 /*
5014 * Check the "this" argument, which must be an instance of the class
jeffhaod1f0fde2011-09-08 17:25:33 -07005015 * that declared the method. For an interface class, we don't do the
jeffhaobdb76512011-09-07 11:43:16 -07005016 * full interface merge, so we can't do a rigorous check here (which
5017 * is okay since we have to do it at runtime).
5018 */
5019 if (!res_method->IsStatic()) {
5020 Class* actual_this_ref;
5021 RegType actual_arg_type;
5022
5023 actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
5024 if (*failure != VERIFY_ERROR_NONE)
5025 return NULL;
5026
5027 if (RegTypeIsUninitReference(actual_arg_type) &&
5028 !res_method->GetName()->Equals("<init>")) {
5029 LOG(ERROR) << "VFY: 'this' arg must be initialized";
5030 *failure = VERIFY_ERROR_GENERIC;
5031 return NULL;
5032 }
5033 if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
5034 actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
5035 if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
5036 LOG(ERROR) << "VFY: 'this' arg '"
5037 << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
5038 << "' not instance of '"
5039 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5040 << "'";
5041 *failure = VERIFY_ERROR_GENERIC;
5042 return NULL;
5043 }
5044 }
5045 actual_args++;
5046 }
5047
5048 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07005049 * Process the target method's signature. This signature may or may not
jeffhaobdb76512011-09-07 11:43:16 -07005050 * have been verified, so we can't assume it's properly formed.
5051 */
5052 for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
jeffhaobdb76512011-09-07 11:43:16 -07005053 if (sig[sig_offset] == ')')
5054 break;
5055
5056 if (actual_args >= expected_args) {
5057 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
5058 << sig.substr(sig_offset) << ")";
5059 goto bad_sig;
5060 }
5061
5062 uint32_t get_reg;
5063 if (is_range)
5064 get_reg = dec_insn->vC_ + actual_args;
5065 else
5066 get_reg = dec_insn->arg_[actual_args];
5067
5068 switch (sig[sig_offset]) {
5069 case 'L':
5070 {
5071 Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
5072 failure);
5073 if (*failure != VERIFY_ERROR_NONE)
5074 goto bad_sig;
5075 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5076 failure);
5077 if (*failure != VERIFY_ERROR_NONE) {
5078 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5079 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5080 goto bad_sig;
5081 }
5082 sig_offset += sig.substr(sig_offset).find(';');
5083 }
5084 actual_args++;
5085 break;
5086 case '[':
5087 {
5088 Class* klass = LookupSignatureArrayClass(method,
5089 sig.substr(sig_offset), failure);
5090 if (*failure != VERIFY_ERROR_NONE)
5091 goto bad_sig;
5092 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5093 failure);
5094 if (*failure != VERIFY_ERROR_NONE) {
5095 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5096 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5097 goto bad_sig;
5098 }
5099 while (sig[sig_offset] == '[')
5100 sig_offset++;
5101 if (sig[sig_offset] == 'L')
5102 sig_offset += sig.substr(sig_offset).find(';');
5103 }
5104 actual_args++;
5105 break;
5106 case 'Z':
5107 VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
5108 actual_args++;
5109 break;
5110 case 'C':
5111 VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
5112 actual_args++;
5113 break;
5114 case 'B':
5115 VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
5116 actual_args++;
5117 break;
5118 case 'I':
5119 VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
5120 actual_args++;
5121 break;
5122 case 'S':
5123 VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
5124 actual_args++;
5125 break;
5126 case 'F':
5127 VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
5128 actual_args++;
5129 break;
5130 case 'D':
5131 VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
5132 actual_args += 2;
5133 break;
5134 case 'J':
5135 VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
5136 actual_args += 2;
5137 break;
5138 default:
5139 LOG(ERROR) << "VFY: invocation target: bad signature type char '"
5140 << sig << "'";
5141 goto bad_sig;
5142 }
5143 }
5144 if (sig[sig_offset] != ')') {
5145 LOG(ERROR) << "VFY: invocation target: bad signature '"
5146 << res_method->GetSignature()->ToModifiedUtf8() << "'";
5147 goto bad_sig;
5148 }
5149
5150 if (actual_args != expected_args) {
5151 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
5152 << actual_args;
5153 goto bad_sig;
5154 }
5155
5156 return res_method;
5157
5158bad_sig:
jeffhao2a8a90e2011-09-26 14:25:31 -07005159 LOG(ERROR) << "VFY: rejecting call to " << PrettyMethod(res_method);
jeffhaobdb76512011-09-07 11:43:16 -07005160 if (*failure == VERIFY_ERROR_NONE)
5161 *failure = VERIFY_ERROR_GENERIC;
5162 return NULL;
5163}
jeffhaoba5ebb92011-08-25 17:24:37 -07005164
jeffhaod1f0fde2011-09-08 17:25:33 -07005165DexVerifier::RegisterMap* DexVerifier::GenerateRegisterMapV(VerifierData* vdata)
5166{
5167 const DexFile::CodeItem* code_item = vdata->code_item_;
5168 int i, bytes_for_addr, gc_point_count;
5169
5170 if (code_item->registers_size_ >= 2048) {
5171 LOG(ERROR) << "ERROR: register map can't handle "
5172 << code_item->registers_size_ << " registers";
5173 return NULL;
5174 }
5175 uint8_t reg_width = (code_item->registers_size_ + 7) / 8;
5176
5177 /*
5178 * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
5179 * we only need 16 bits if we actually encode an address >= 256 -- if
5180 * the method has a section at the end without GC points (e.g. array
5181 * data) we don't need to count it. The situation is unusual, and
5182 * detecting it requires scanning the entire method, so we don't bother.
5183 */
5184 RegisterMapFormat format;
5185 if (code_item->insns_size_ < 256) {
5186 format = kRegMapFormatCompact8;
5187 bytes_for_addr = 1;
5188 } else {
5189 format = kRegMapFormatCompact16;
5190 bytes_for_addr = 2;
5191 }
5192
5193 /*
5194 * Count up the number of GC point instructions.
5195 *
5196 * NOTE: this does not automatically include the first instruction,
5197 * since we don't count method entry as a GC point.
5198 */
5199 gc_point_count = 0;
5200 for (i = 0; i < (int) code_item->insns_size_; i++) {
5201 if (InsnIsGcPoint(vdata->insn_flags_.get(), i))
5202 gc_point_count++;
5203 }
5204 if (gc_point_count >= 65536) {
5205 /* We could handle this, but in practice we don't get near this. */
5206 LOG(ERROR) << "ERROR: register map can't handle " << gc_point_count
5207 << " gc points in one method";
5208 return NULL;
5209 }
5210
5211 /* Calculate size of buffer to hold the map data. */
5212 uint32_t data_size = gc_point_count * (bytes_for_addr + reg_width);
5213
5214 RegisterMap* map = new RegisterMap(format, reg_width, gc_point_count,
jeffhaoa0a764a2011-09-16 10:43:38 -07005215 data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005216
5217 /* Populate it. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005218 uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005219 for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
5220 if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005221 DCHECK(vdata->register_lines_[i].reg_types_.get() != NULL);
jeffhaod1f0fde2011-09-08 17:25:33 -07005222 if (format == kRegMapFormatCompact8) {
5223 *map_data++ = i;
5224 } else /*kRegMapFormatCompact16*/ {
5225 *map_data++ = i & 0xff;
5226 *map_data++ = i >> 8;
5227 }
5228 OutputTypeVector(vdata->register_lines_[i].reg_types_.get(),
5229 code_item->registers_size_, map_data);
5230 map_data += reg_width;
5231 }
5232 }
5233
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005234 DCHECK_EQ((uint32_t) map_data - (uint32_t) map->data_, data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005235
5236 // TODO: Remove this check when it's really running...
5237#if 1
5238 if (!VerifyMap(vdata, map)) {
5239 LOG(ERROR) << "Map failed to verify";
5240 return NULL;
5241 }
5242#endif
5243
5244 /* Try to compress the map. */
Shih-wei Liao4f894e32011-09-27 21:33:19 -07005245#if 0
jeffhaod1f0fde2011-09-08 17:25:33 -07005246 RegisterMap* compress_map = CompressMapDifferential(map);
5247 if (compress_map != NULL) {
5248 // TODO: Remove this check when it's really running...
5249#if 1
5250 /*
5251 * Expand the compressed map we just created, and compare it
5252 * to the original. Abort the VM if it doesn't match up.
5253 */
5254 UniquePtr<RegisterMap> uncompressed_map(UncompressMapDifferential(compress_map));
5255 if (uncompressed_map.get() == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07005256 LOG(ERROR) << "Map failed to uncompress - " << PrettyMethod(vdata->method_);
jeffhaod1f0fde2011-09-08 17:25:33 -07005257 delete map;
5258 delete compress_map;
5259 /* bad - compression is broken or we're out of memory */
5260 return NULL;
5261 } else {
5262 if (!CompareMaps(map, uncompressed_map.get())) {
jeffhao2a8a90e2011-09-26 14:25:31 -07005263 LOG(ERROR) << "Map comparison failed - " << PrettyMethod(vdata->method_);
jeffhaod1f0fde2011-09-08 17:25:33 -07005264 delete map;
5265 delete compress_map;
5266 /* bad - compression is broken */
5267 return NULL;
5268 }
5269 }
5270#endif
5271 delete map;
5272 map = compress_map;
5273 }
Shih-wei Liao4f894e32011-09-27 21:33:19 -07005274#endif
jeffhaod1f0fde2011-09-08 17:25:33 -07005275 return map;
5276}
5277
jeffhaoa0a764a2011-09-16 10:43:38 -07005278DexVerifier::RegisterMap* DexVerifier::GetExpandedRegisterMapHelper(
5279 Method* method, RegisterMap* map) {
5280 RegisterMap* new_map;
5281
5282 if (map == NULL)
5283 return NULL;
5284
5285 /* TODO: sanity check to ensure this isn't called w/o external locking */
5286
5287 uint8_t format = map->header_->format_;
5288 switch (format) {
5289 case kRegMapFormatCompact8:
5290 case kRegMapFormatCompact16:
5291 /* already expanded */
5292 return map;
5293 case kRegMapFormatDifferential:
5294 new_map = UncompressMapDifferential(map);
5295 break;
5296 default:
5297 LOG(ERROR) << "Unknown format " << format
5298 << " in dvmGetExpandedRegisterMap";
5299 return NULL;
5300 }
5301
5302 if (new_map == NULL) {
5303 LOG(ERROR) << "Map failed to uncompress (fmt=" << format << ") "
jeffhao2a8a90e2011-09-26 14:25:31 -07005304 << PrettyMethod(method);
jeffhaoa0a764a2011-09-16 10:43:38 -07005305 return NULL;
5306 }
5307
5308 /* Update method, and free compressed map if it was sitting on the heap. */
Ian Rogersd6b1f612011-09-27 13:38:14 -07005309 //ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
5310 //ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map));
jeffhaoa0a764a2011-09-16 10:43:38 -07005311
Ian Rogersd6b1f612011-09-27 13:38:14 -07005312 //memcpy(header->GetData(), map->header_, sizeof(RegisterMapHeader));
5313 //memcpy(data->GetData(), map->data_, ComputeRegisterMapSize(map));
jeffhaoa0a764a2011-09-16 10:43:38 -07005314
Ian Rogersd6b1f612011-09-27 13:38:14 -07005315 //method->SetRegisterMapHeader(header);
5316 //method->SetRegisterMapData(data);
jeffhaoa0a764a2011-09-16 10:43:38 -07005317
5318 delete map;
5319 return new_map;
5320}
5321
5322const uint8_t* DexVerifier::RegisterMapGetLine(const RegisterMap* map, int addr) {
5323 int addr_width, line_width;
5324 uint8_t format = map->header_->format_;
5325 uint16_t num_entries = map->header_->num_entries_;
5326
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005327 DCHECK_GT(num_entries, 0);
jeffhaoa0a764a2011-09-16 10:43:38 -07005328
5329 switch (format) {
5330 case kRegMapFormatNone:
5331 return NULL;
5332 case kRegMapFormatCompact8:
5333 addr_width = 1;
5334 break;
5335 case kRegMapFormatCompact16:
5336 addr_width = 2;
5337 break;
5338 default:
5339 LOG(ERROR) << "Unknown format " << format;
5340 return NULL;
5341 }
5342
5343 line_width = addr_width + map->header_->reg_width_;
5344
5345 /*
5346 * Find the appropriate entry. Many maps are very small, some are very large.
5347 */
5348 static const int kSearchThreshold = 8;
5349 const uint8_t* data = NULL;
5350 int line_addr;
5351
5352 if (num_entries < kSearchThreshold) {
5353 int i;
5354 data = map->data_;
5355 for (i = num_entries; i > 0; i--) {
5356 line_addr = data[0];
5357 if (addr_width > 1)
5358 line_addr |= data[1] << 8;
5359 if (line_addr == addr)
5360 return data + addr_width;
5361
5362 data += line_width;
5363 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005364 DCHECK_EQ(data, map->data_ + line_width * num_entries);
jeffhaoa0a764a2011-09-16 10:43:38 -07005365 } else {
5366 int hi, lo, mid;
5367
5368 lo = 0;
5369 hi = num_entries -1;
5370
5371 while (hi >= lo) {
5372 mid = (hi + lo) / 2;
5373 data = map->data_ + line_width * mid;
5374
5375 line_addr = data[0];
5376 if (addr_width > 1)
5377 line_addr |= data[1] << 8;
5378
5379 if (addr > line_addr) {
5380 lo = mid + 1;
5381 } else if (addr < line_addr) {
5382 hi = mid - 1;
5383 } else {
5384 return data + addr_width;
5385 }
5386 }
5387 }
5388
5389 return NULL;
5390}
5391
jeffhaod1f0fde2011-09-08 17:25:33 -07005392void DexVerifier::OutputTypeVector(const RegType* regs, int insn_reg_count,
5393 uint8_t* data) {
5394 uint8_t val = 0;
5395 int i;
5396
5397 for (i = 0; i < insn_reg_count; i++) {
5398 RegType type = *regs++;
5399 val >>= 1;
5400 if (IsReferenceType(type))
5401 val |= 0x80; /* set hi bit */
5402
5403 if ((i & 0x07) == 7)
5404 *data++ = val;
5405 }
5406 if ((i & 0x07) != 0) {
5407 /* Flush bits from last byte. */
5408 val >>= 8 - (i & 0x07);
5409 *data++ = val;
5410 }
5411}
5412
5413bool DexVerifier::VerifyMap(VerifierData* vdata, const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005414 const uint8_t* raw_map = map->data_;
5415 uint8_t format = map->header_->format_;
5416 const int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005417 int ent;
5418
jeffhaoe23d93c2011-09-15 14:48:43 -07005419 if ((vdata->code_item_->registers_size_ + 7) / 8 != map->header_->reg_width_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005420 LOG(ERROR) << "GLITCH: registersSize=" << vdata->code_item_->registers_size_
jeffhaoe23d93c2011-09-15 14:48:43 -07005421 << ", reg_width=" << map->header_->reg_width_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005422 return false;
5423 }
5424
5425 for (ent = 0; ent < num_entries; ent++) {
5426 int addr;
5427
5428 switch (format) {
5429 case kRegMapFormatCompact8:
5430 addr = *raw_map++;
5431 break;
5432 case kRegMapFormatCompact16:
5433 addr = *raw_map++;
5434 addr |= (*raw_map++) << 8;
5435 break;
5436 default:
5437 LOG(FATAL) << "GLITCH: bad format (" << format << ")";
5438 return false;
5439 }
5440
5441 const RegType* regs = vdata->register_lines_[addr].reg_types_.get();
5442 if (regs == NULL) {
5443 LOG(ERROR) << "GLITCH: addr " << addr << " has no data";
5444 return false;
5445 }
5446
5447 uint8_t val = 0;
5448 int i;
5449
5450 for (i = 0; i < vdata->code_item_->registers_size_; i++) {
5451 bool bit_is_ref, reg_is_ref;
5452
5453 val >>= 1;
5454 if ((i & 0x07) == 0) {
5455 /* Load next byte of data. */
5456 val = *raw_map++;
5457 }
5458
5459 bit_is_ref = val & 0x01;
5460
5461 RegType type = regs[i];
5462 reg_is_ref = IsReferenceType(type);
5463
5464 if (bit_is_ref != reg_is_ref) {
5465 LOG(ERROR) << "GLITCH: addr " << addr << " reg " << i << ": bit="
5466 << bit_is_ref << " reg=" << reg_is_ref << "(" << type << ")";
5467 return false;
5468 }
5469 }
5470 /* Raw_map now points to the address field of the next entry. */
5471 }
5472
5473 return true;
5474}
5475
5476bool DexVerifier::CompareMaps(const RegisterMap* map1, const RegisterMap* map2)
5477{
5478 size_t size1, size2;
5479
5480 size1 = ComputeRegisterMapSize(map1);
5481 size2 = ComputeRegisterMapSize(map2);
5482 if (size1 != size2) {
5483 LOG(ERROR) << "CompareMaps: size mismatch (" << size1 << " vs " << size2
5484 << ")";
5485 return false;
5486 }
5487
jeffhaoe23d93c2011-09-15 14:48:43 -07005488 if (map1->header_->format_ != map2->header_->format_ ||
5489 map1->header_->reg_width_ != map2->header_->reg_width_ ||
jeffhaoa0a764a2011-09-16 10:43:38 -07005490 map1->header_->num_entries_ != map2->header_->num_entries_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005491 LOG(ERROR) << "CompareMaps: fields mismatch";
5492 }
jeffhaoe23d93c2011-09-15 14:48:43 -07005493 if (memcmp(map1->data_, map2->data_, size1) != 0) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005494 LOG(ERROR) << "CompareMaps: data mismatch";
5495 return false;
5496 }
5497
5498 return true;
5499}
5500
5501size_t DexVerifier::ComputeRegisterMapSize(const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005502 uint8_t format = map->header_->format_;
5503 uint16_t num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005504
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005505 DCHECK(map != NULL);
jeffhaod1f0fde2011-09-08 17:25:33 -07005506
5507 switch (format) {
5508 case kRegMapFormatNone:
5509 return 1;
5510 case kRegMapFormatCompact8:
jeffhaoe23d93c2011-09-15 14:48:43 -07005511 return (1 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005512 case kRegMapFormatCompact16:
jeffhaoe23d93c2011-09-15 14:48:43 -07005513 return (2 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005514 case kRegMapFormatDifferential:
5515 {
5516 /* Decoded ULEB128 length. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005517 const uint8_t* ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005518 return DecodeUnsignedLeb128(&ptr);
5519 }
5520 default:
5521 LOG(FATAL) << "Bad register map format " << format;
5522 return 0;
5523 }
5524}
5525
5526int DexVerifier::ComputeBitDiff(const uint8_t* bits1, const uint8_t* bits2,
5527 int byte_width, int* first_bit_changed_ptr, int* num_bits_changed_ptr,
5528 uint8_t* leb_out_buf) {
5529 int num_bits_changed = 0;
5530 int first_bit_changed = -1;
5531 int leb_size = 0;
5532 int byte_num;
5533
5534 /*
5535 * Run through the vectors, first comparing them at the byte level. This
5536 * will yield a fairly quick result if nothing has changed between them.
5537 */
5538 for (byte_num = 0; byte_num < byte_width; byte_num++) {
5539 uint8_t byte1 = *bits1++;
5540 uint8_t byte2 = *bits2++;
5541 if (byte1 != byte2) {
5542 /* Walk through the byte, identifying the changed bits. */
5543 int bit_num;
5544 for (bit_num = 0; bit_num < 8; bit_num++) {
5545 if (((byte1 >> bit_num) & 0x01) != ((byte2 >> bit_num) & 0x01)) {
5546 int bit_offset = (byte_num << 3) + bit_num;
5547
5548 if (first_bit_changed < 0)
5549 first_bit_changed = bit_offset;
5550 num_bits_changed++;
5551
5552 if (leb_out_buf == NULL) {
5553 leb_size += UnsignedLeb128Size(bit_offset);
5554 } else {
5555 uint8_t* cur_buf = leb_out_buf;
5556 leb_out_buf = WriteUnsignedLeb128(leb_out_buf, bit_offset);
5557 leb_size += leb_out_buf - cur_buf;
5558 }
5559 }
5560 }
5561 }
5562 }
5563
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005564 if (num_bits_changed > 0) {
5565 DCHECK_GE(first_bit_changed, 0);
5566 }
jeffhaod1f0fde2011-09-08 17:25:33 -07005567
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005568 if (first_bit_changed_ptr != NULL) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005569 *first_bit_changed_ptr = first_bit_changed;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005570 }
5571
5572 if (num_bits_changed_ptr != NULL) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005573 *num_bits_changed_ptr = num_bits_changed;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005574 }
jeffhaod1f0fde2011-09-08 17:25:33 -07005575
5576 return leb_size;
5577}
5578
5579DexVerifier::RegisterMap* DexVerifier::CompressMapDifferential(
5580 const RegisterMap* map) {
5581 int orig_size = ComputeRegisterMapSize(map);
5582 uint8_t* tmp_ptr;
5583 int addr_width;
5584
jeffhaoe23d93c2011-09-15 14:48:43 -07005585 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005586 switch (format) {
5587 case kRegMapFormatCompact8:
5588 addr_width = 1;
5589 break;
5590 case kRegMapFormatCompact16:
5591 addr_width = 2;
5592 break;
5593 default:
5594 LOG(ERROR) << "ERROR: can't compress map with format=" << format;
5595 return NULL;
5596 }
5597
jeffhaoe23d93c2011-09-15 14:48:43 -07005598 int reg_width = map->header_->reg_width_;
5599 int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005600
5601 if (num_entries <= 1) {
5602 return NULL;
5603 }
5604
5605 /*
5606 * We don't know how large the compressed data will be. It's possible
5607 * for it to expand and become larger than the original. The header
5608 * itself is variable-sized, so we generate everything into a temporary
5609 * buffer and then copy it to form-fitting storage once we know how big
5610 * it will be (and that it's smaller than the original).
5611 *
5612 * If we use a size that is equal to the size of the input map plus
5613 * a value longer than a single entry can possibly expand to, we need
5614 * only check for overflow at the end of each entry. The worst case
5615 * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
5616 * Addresses are 16 bits, so that's (1 + 3 + reg_width).
5617 *
5618 * The initial address offset and bit vector will take up less than
5619 * or equal to the amount of space required when uncompressed -- large
5620 * initial offsets are rejected.
5621 */
5622 UniquePtr<uint8_t[]> tmp_buf(new uint8_t[orig_size + (1 + 3 + reg_width)]);
5623
5624 tmp_ptr = tmp_buf.get();
5625
jeffhaoe23d93c2011-09-15 14:48:43 -07005626 const uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005627 const uint8_t* prev_bits;
5628 uint16_t addr, prev_addr;
5629
5630 addr = *map_data++;
5631 if (addr_width > 1)
5632 addr |= (*map_data++) << 8;
5633
5634 if (addr >= 128) {
5635 LOG(ERROR) << "Can't compress map with starting address >= 128";
5636 return NULL;
5637 }
5638
5639 /*
5640 * Start by writing the initial address and bit vector data. The high
5641 * bit of the initial address is used to indicate the required address
5642 * width (which the decoder can't otherwise determine without parsing
5643 * the compressed data).
5644 */
5645 *tmp_ptr++ = addr | (addr_width > 1 ? 0x80 : 0x00);
5646 memcpy(tmp_ptr, map_data, reg_width);
5647
5648 prev_bits = map_data;
5649 prev_addr = addr;
5650
5651 tmp_ptr += reg_width;
5652 map_data += reg_width;
5653
5654 /* Loop over all following entries. */
5655 for (int entry = 1; entry < num_entries; entry++) {
5656 int addr_diff;
5657 uint8_t key;
5658
5659 /* Pull out the address and figure out how to encode it. */
5660 addr = *map_data++;
5661 if (addr_width > 1)
5662 addr |= (*map_data++) << 8;
5663
5664 addr_diff = addr - prev_addr;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005665 DCHECK_GT(addr_diff, 0);
jeffhaod1f0fde2011-09-08 17:25:33 -07005666 if (addr_diff < 8) {
5667 /* Small difference, encode in 3 bits. */
5668 key = addr_diff -1; /* set 00000AAA */
5669 } else {
5670 /* Large difference, output escape code. */
5671 key = 0x07; /* escape code for AAA */
5672 }
5673
5674 int num_bits_changed, first_bit_changed, leb_size;
5675
5676 leb_size = ComputeBitDiff(prev_bits, map_data, reg_width,
5677 &first_bit_changed, &num_bits_changed, NULL);
5678
5679 if (num_bits_changed == 0) {
5680 /* set B to 1 and CCCC to zero to indicate no bits were changed */
5681 key |= 0x08;
5682 } else if (num_bits_changed == 1 && first_bit_changed < 16) {
5683 /* set B to 0 and CCCC to the index of the changed bit */
5684 key |= first_bit_changed << 4;
5685 } else if (num_bits_changed < 15 && leb_size < reg_width) {
5686 /* set B to 1 and CCCC to the number of bits */
5687 key |= 0x08 | (num_bits_changed << 4);
5688 } else {
5689 /* set B to 1 and CCCC to 0x0f so we store the entire vector */
5690 key |= 0x08 | 0xf0;
5691 }
5692
5693 /*
5694 * Encode output. Start with the key, follow with the address
5695 * diff (if it didn't fit in 3 bits), then the changed bit info.
5696 */
5697 *tmp_ptr++ = key;
5698 if ((key & 0x07) == 0x07)
5699 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, addr_diff);
5700
5701 if ((key & 0x08) != 0) {
5702 int bit_count = key >> 4;
5703 if (bit_count == 0) {
5704 /* nothing changed, no additional output required */
5705 } else if (bit_count == 15) {
5706 /* full vector is most compact representation */
5707 memcpy(tmp_ptr, map_data, reg_width);
5708 tmp_ptr += reg_width;
5709 } else {
5710 /* write bit indices in ULEB128 format */
5711 (void) ComputeBitDiff(prev_bits, map_data, reg_width,
5712 NULL, NULL, tmp_ptr);
5713 tmp_ptr += leb_size;
5714 }
5715 } else {
5716 /* single-bit changed, value encoded in key byte */
5717 }
5718
5719 prev_bits = map_data;
5720 prev_addr = addr;
5721 map_data += reg_width;
5722
5723 /* See if we've run past the original size. */
5724 if (tmp_ptr - tmp_buf.get() >= orig_size) {
5725 return NULL;
5726 }
5727 }
5728
5729 /*
5730 * Create a RegisterMap with the contents.
5731 *
5732 * TODO: consider using a threshold other than merely ">=". We would
5733 * get poorer compression but potentially use less native heap space.
5734 */
5735 int new_data_size = tmp_ptr - tmp_buf.get();
5736 int new_map_size = new_data_size + UnsignedLeb128Size(new_data_size);
5737
5738 if (new_map_size >= orig_size) {
5739 return NULL;
5740 }
5741
5742 RegisterMap* new_map = new RegisterMap(kRegMapFormatDifferential, reg_width,
jeffhaoa0a764a2011-09-16 10:43:38 -07005743 num_entries, new_map_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005744
jeffhaoe23d93c2011-09-15 14:48:43 -07005745 tmp_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005746 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, new_data_size);
5747 memcpy(tmp_ptr, tmp_buf.get(), new_data_size);
5748
5749 return new_map;
5750}
5751
5752DexVerifier::RegisterMap* DexVerifier::UncompressMapDifferential(
5753 const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005754 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005755 RegisterMapFormat new_format;
5756 int reg_width, num_entries, new_addr_width, new_data_size;
5757
5758 if (format != kRegMapFormatDifferential) {
5759 LOG(ERROR) << "Not differential (" << format << ")";
5760 return NULL;
5761 }
5762
jeffhaoe23d93c2011-09-15 14:48:43 -07005763 reg_width = map->header_->reg_width_;
5764 num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005765
5766 /* Get the data size; we can check this at the end. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005767 const uint8_t* src_ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005768 int expected_src_len = DecodeUnsignedLeb128(&src_ptr);
5769 const uint8_t* src_start = src_ptr;
5770
5771 /* Get the initial address and the 16-bit address flag. */
5772 int addr = *src_ptr & 0x7f;
5773 if ((*src_ptr & 0x80) == 0) {
5774 new_format = kRegMapFormatCompact8;
5775 new_addr_width = 1;
5776 } else {
5777 new_format = kRegMapFormatCompact16;
5778 new_addr_width = 2;
5779 }
5780 src_ptr++;
5781
5782 /* Now we know enough to allocate the new map. */
5783 new_data_size = (new_addr_width + reg_width) * num_entries;
5784 RegisterMap* new_map = new RegisterMap(new_format, reg_width, num_entries,
jeffhaoa0a764a2011-09-16 10:43:38 -07005785 new_data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005786
5787 /* Write the start address and initial bits to the new map. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005788 uint8_t* dst_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005789
5790 *dst_ptr++ = addr & 0xff;
5791 if (new_addr_width > 1)
5792 *dst_ptr++ = (uint8_t) (addr >> 8);
5793
5794 memcpy(dst_ptr, src_ptr, reg_width);
5795
5796 int prev_addr = addr;
5797 const uint8_t* prev_bits = dst_ptr; /* point at uncompressed data */
5798
5799 dst_ptr += reg_width;
5800 src_ptr += reg_width;
5801
5802 /* Walk through, uncompressing one line at a time. */
5803 int entry;
5804 for (entry = 1; entry < num_entries; entry++) {
5805 int addr_diff;
5806 uint8_t key;
5807
5808 key = *src_ptr++;
5809
5810 /* Get the address. */
5811 if ((key & 0x07) == 7) {
5812 /* Address diff follows in ULEB128. */
5813 addr_diff = DecodeUnsignedLeb128(&src_ptr);
5814 } else {
5815 addr_diff = (key & 0x07) +1;
5816 }
5817
5818 addr = prev_addr + addr_diff;
5819 *dst_ptr++ = addr & 0xff;
5820 if (new_addr_width > 1)
5821 *dst_ptr++ = (uint8_t) (addr >> 8);
5822
5823 /* Unpack the bits. */
5824 if ((key & 0x08) != 0) {
5825 int bit_count = (key >> 4);
5826 if (bit_count == 0) {
5827 /* No bits changed, just copy previous. */
5828 memcpy(dst_ptr, prev_bits, reg_width);
5829 } else if (bit_count == 15) {
5830 /* Full copy of bit vector is present; ignore prev_bits. */
5831 memcpy(dst_ptr, src_ptr, reg_width);
5832 src_ptr += reg_width;
5833 } else {
5834 /* Copy previous bits and modify listed indices. */
5835 memcpy(dst_ptr, prev_bits, reg_width);
5836 while (bit_count--) {
5837 int bit_index = DecodeUnsignedLeb128(&src_ptr);
5838 ToggleBit(dst_ptr, bit_index);
5839 }
5840 }
5841 } else {
5842 /* Copy previous bits and modify the specified one. */
5843 memcpy(dst_ptr, prev_bits, reg_width);
5844
5845 /* One bit, from 0-15 inclusive, was changed. */
5846 ToggleBit(dst_ptr, key >> 4);
5847 }
5848
5849 prev_addr = addr;
5850 prev_bits = dst_ptr;
5851 dst_ptr += reg_width;
5852 }
5853
jeffhaoe23d93c2011-09-15 14:48:43 -07005854 if (dst_ptr - new_map->data_ != new_data_size) {
5855 LOG(ERROR) << "ERROR: output " << dst_ptr - new_map->data_
jeffhaod1f0fde2011-09-08 17:25:33 -07005856 << " bytes, expected " << new_data_size;
5857 free(new_map);
5858 return NULL;
5859 }
5860
5861 if (src_ptr - src_start != expected_src_len) {
5862 LOG(ERROR) << "ERROR: consumed " << src_ptr - src_start
5863 << " bytes, expected " << expected_src_len;
5864 free(new_map);
5865 return NULL;
5866 }
5867
5868 return new_map;
5869}
5870
jeffhaoe0cfb6f2011-09-22 16:42:56 -07005871/* Dump the register types for the specifed address to the log file. */
5872void DexVerifier::DumpRegTypes(const VerifierData* vdata,
5873 const RegisterLine* register_line, int addr, const char* addr_name,
5874 const UninitInstanceMap* uninit_map) {
5875 const DexFile::CodeItem* code_item = vdata->code_item_;
5876 uint16_t reg_count = code_item->registers_size_;
5877 uint32_t insns_size = code_item->insns_size_;
5878 const InsnFlags* insn_flags = vdata->insn_flags_.get();
5879 const RegType* addr_regs = register_line->reg_types_.get();
5880 int full_reg_count = reg_count + kExtraRegs;
5881 bool branch_target = InsnIsBranchTarget(insn_flags, addr);
5882 int i;
5883
5884 CHECK(addr >= 0 && addr < (int) insns_size);
5885
5886 int reg_char_size = full_reg_count + (full_reg_count - 1) / 4 + 2 + 1;
5887 char reg_chars[reg_char_size + 1];
5888 memset(reg_chars, ' ', reg_char_size);
5889 reg_chars[0] = '[';
5890 if (reg_count == 0)
5891 reg_chars[1] = ']';
5892 else
5893 reg_chars[1 + (reg_count - 1) + (reg_count -1 ) / 4 + 1] = ']';
5894 reg_chars[reg_char_size] = '\0';
5895
5896 for (i = 0; i < reg_count + kExtraRegs; i++) {
5897 char tch;
5898
5899 switch (addr_regs[i]) {
5900 case kRegTypeUnknown: tch = '.'; break;
5901 case kRegTypeConflict: tch = 'X'; break;
5902 case kRegTypeZero: tch = '0'; break;
5903 case kRegTypeOne: tch = '1'; break;
5904 case kRegTypeBoolean: tch = 'Z'; break;
5905 case kRegTypeConstPosByte: tch = 'y'; break;
5906 case kRegTypeConstByte: tch = 'Y'; break;
5907 case kRegTypeConstPosShort: tch = 'h'; break;
5908 case kRegTypeConstShort: tch = 'H'; break;
5909 case kRegTypeConstChar: tch = 'c'; break;
5910 case kRegTypeConstInteger: tch = 'i'; break;
5911 case kRegTypePosByte: tch = 'b'; break;
5912 case kRegTypeByte: tch = 'B'; break;
5913 case kRegTypePosShort: tch = 's'; break;
5914 case kRegTypeShort: tch = 'S'; break;
5915 case kRegTypeChar: tch = 'C'; break;
5916 case kRegTypeInteger: tch = 'I'; break;
5917 case kRegTypeFloat: tch = 'F'; break;
5918 case kRegTypeConstLo: tch = 'N'; break;
5919 case kRegTypeConstHi: tch = 'n'; break;
5920 case kRegTypeLongLo: tch = 'J'; break;
5921 case kRegTypeLongHi: tch = 'j'; break;
5922 case kRegTypeDoubleLo: tch = 'D'; break;
5923 case kRegTypeDoubleHi: tch = 'd'; break;
5924 default:
5925 if (RegTypeIsReference(addr_regs[i])) {
5926 if (RegTypeIsUninitReference(addr_regs[i]))
5927 tch = 'U';
5928 else
5929 tch = 'L';
5930 } else {
5931 tch = '*';
5932 CHECK(false);
5933 }
5934 break;
5935 }
5936
5937 if (i < reg_count)
5938 reg_chars[1 + i + (i / 4)] = tch;
5939 else
5940 reg_chars[1 + i + (i / 4) + 2] = tch;
5941 }
5942
5943 if (addr == 0 && addr_name != NULL) {
5944 char start = branch_target ? '>' : ' ';
5945 LOG(INFO) << start << addr_name << " " << reg_chars << " mst="
5946 << register_line->monitor_stack_top_;
5947 } else {
5948 char start = branch_target ? '>' : ' ';
5949 LOG(INFO) << start << "0x" << std::hex << addr << std::dec << " "
5950 << reg_chars << " mst=" << register_line->monitor_stack_top_;
5951 }
5952
5953 for (i = 0; i < reg_count + kExtraRegs; i++) {
5954 if (RegTypeIsReference(addr_regs[i]) && addr_regs[i] != kRegTypeZero) {
5955 Class* klass = RegTypeReferenceToClass(addr_regs[i], uninit_map);
5956 if (i < reg_count) {
5957 const char* undef = RegTypeIsUninitReference(addr_regs[i]) ? "[U]" : "";
5958 LOG(INFO) << " " << i << ": 0x" << std::hex << addr_regs[i] << std::dec
5959 << " " << undef << klass->GetDescriptor()->ToModifiedUtf8();
5960 } else {
5961 const char* undef = RegTypeIsUninitReference(addr_regs[i]) ? "[U]" : "";
5962 LOG(INFO) << " RS: 0x" << std::hex << addr_regs[i] << std::dec
5963 << " " << undef << klass->GetDescriptor()->ToModifiedUtf8();
5964 }
5965 }
5966 }
5967}
5968
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07005969} // namespace art