blob: 3e41d235e94ef20055cce528578e0a6674f297e4 [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;
Elliott Hughes362f9bc2011-10-17 18:56:41 -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 }
jeffhaobdb76512011-09-07 11:43:16 -07002033 }
2034 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2035 }
2036 break;
2037
2038 case Instruction::AGET_WIDE:
2039 {
2040 RegType dst_type, index_type;
2041
2042 index_type = GetRegisterType(work_line, dec_insn.vC_);
2043 CheckArrayIndexType(method, index_type, &failure);
2044 if (failure != VERIFY_ERROR_NONE)
2045 break;
2046
2047 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2048 if (failure != VERIFY_ERROR_NONE)
2049 break;
2050 if (res_class != NULL) {
2051 /* verify the class */
2052 Class::PrimitiveType prim_type =
2053 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002054 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002055 LOG(ERROR) << "VFY: invalid aget-wide target "
2056 << res_class->GetDescriptor()->ToModifiedUtf8();
2057 failure = VERIFY_ERROR_GENERIC;
2058 break;
2059 }
2060
2061 /* try to refine "dst_type" */
2062 switch (prim_type) {
2063 case Class::kPrimLong:
2064 dst_type = kRegTypeLongLo;
2065 break;
2066 case Class::kPrimDouble:
2067 dst_type = kRegTypeDoubleLo;
2068 break;
2069 default:
2070 LOG(ERROR) << "VFY: invalid aget-wide on "
2071 << res_class->GetDescriptor()->ToModifiedUtf8();
2072 dst_type = kRegTypeUnknown;
2073 failure = VERIFY_ERROR_GENERIC;
2074 break;
2075 }
2076 } else {
2077 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002078 * Null array ref; this code path will fail at runtime. We
jeffhaobdb76512011-09-07 11:43:16 -07002079 * know this is either long or double, so label it const.
2080 */
2081 dst_type = kRegTypeConstLo;
2082 }
2083 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2084 }
2085 break;
2086
2087 case Instruction::AGET_OBJECT:
2088 {
2089 RegType dst_type, index_type;
2090
2091 index_type = GetRegisterType(work_line, dec_insn.vC_);
2092 CheckArrayIndexType(method, index_type, &failure);
2093 if (failure != VERIFY_ERROR_NONE)
2094 break;
2095
2096 /* get the class of the array we're pulling an object from */
2097 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2098 if (failure != VERIFY_ERROR_NONE)
2099 break;
2100 if (res_class != NULL) {
2101 Class* element_class;
2102
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002103 DCHECK(res_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002104 if (!res_class->IsArrayClass()) {
2105 LOG(ERROR) << "VFY: aget-object on non-array class";
2106 failure = VERIFY_ERROR_GENERIC;
2107 break;
2108 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002109 DCHECK(res_class->GetComponentType() != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002110
2111 /*
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002112 * Find the element class.
jeffhaobdb76512011-09-07 11:43:16 -07002113 */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002114 element_class = res_class->GetComponentType();
2115 if (element_class->IsPrimitive()) {
jeffhaobdb76512011-09-07 11:43:16 -07002116 LOG(ERROR) << "VFY: aget-object on non-ref array class ("
2117 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2118 failure = VERIFY_ERROR_GENERIC;
2119 break;
2120 }
2121
2122 dst_type = RegTypeFromClass(element_class);
2123 } else {
2124 /*
2125 * The array reference is NULL, so the current code path will
jeffhaod1f0fde2011-09-08 17:25:33 -07002126 * throw an exception. For proper merging with later code
jeffhaobdb76512011-09-07 11:43:16 -07002127 * paths, and correct handling of "if-eqz" tests on the
2128 * result of the array get, we want to treat this as a null
2129 * reference.
2130 */
2131 dst_type = kRegTypeZero;
2132 }
2133 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2134 }
2135 break;
2136 case Instruction::APUT:
2137 tmp_type = kRegTypeInteger;
2138 goto aput_1nr_common;
2139 case Instruction::APUT_BOOLEAN:
2140 tmp_type = kRegTypeBoolean;
2141 goto aput_1nr_common;
2142 case Instruction::APUT_BYTE:
2143 tmp_type = kRegTypeByte;
2144 goto aput_1nr_common;
2145 case Instruction::APUT_CHAR:
2146 tmp_type = kRegTypeChar;
2147 goto aput_1nr_common;
2148 case Instruction::APUT_SHORT:
2149 tmp_type = kRegTypeShort;
2150 goto aput_1nr_common;
2151aput_1nr_common:
2152 {
2153 RegType src_type, dst_type, index_type;
2154
2155 index_type = GetRegisterType(work_line, dec_insn.vC_);
2156 CheckArrayIndexType(method, index_type, &failure);
2157 if (failure != VERIFY_ERROR_NONE)
2158 break;
2159
2160 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2161 if (failure != VERIFY_ERROR_NONE)
2162 break;
2163
2164 /* res_class can be null if the reg type is Zero */
2165 if (res_class == NULL)
2166 break;
2167
2168 Class::PrimitiveType prim_type =
2169 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002170 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002171 LOG(ERROR) << "VFY: invalid aput-1nr on "
2172 << res_class->GetDescriptor()->ToModifiedUtf8();
2173 failure = VERIFY_ERROR_GENERIC;
2174 break;
2175 }
2176
2177 /* verify that instruction matches array */
2178 dst_type = PrimitiveTypeToRegType(prim_type);
2179
2180 /* correct if float */
2181 if (dst_type == kRegTypeFloat)
2182 tmp_type = kRegTypeFloat;
2183
2184 /* make sure the source register has the correct type */
2185 src_type = GetRegisterType(work_line, dec_insn.vA_);
2186 if (!CanConvertTo1nr(src_type, tmp_type)) {
2187 LOG(ERROR) << "VFY: invalid reg type " << src_type
2188 << " on aput instr (need " << tmp_type << ")";
2189 failure = VERIFY_ERROR_GENERIC;
2190 break;
2191 }
2192
2193 VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);
2194
2195 if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
2196 tmp_type != dst_type) {
2197 LOG(ERROR) << "VFY: invalid aput-1nr on "
2198 << res_class->GetDescriptor()->ToModifiedUtf8()
2199 << " (inst=" << tmp_type << " dst=" << dst_type << ")";
2200 failure = VERIFY_ERROR_GENERIC;
2201 break;
2202 }
2203 }
2204 break;
2205 case Instruction::APUT_WIDE:
2206 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2207 CheckArrayIndexType(method, tmp_type, &failure);
2208 if (failure != VERIFY_ERROR_NONE)
2209 break;
2210
2211 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2212 if (failure != VERIFY_ERROR_NONE)
2213 break;
2214 if (res_class != NULL) {
2215 Class::PrimitiveType prim_type =
2216 res_class->GetComponentType()->GetPrimitiveType();
2217 /* verify the class and try to refine "dst_type" */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002218 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot)
jeffhaobdb76512011-09-07 11:43:16 -07002219 {
2220 LOG(ERROR) << "VFY: invalid aput-wide on "
2221 << res_class->GetDescriptor()->ToModifiedUtf8();
2222 failure = VERIFY_ERROR_GENERIC;
2223 break;
2224 }
2225
2226 switch (prim_type) {
2227 case Class::kPrimLong:
2228 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
2229 &failure);
2230 break;
2231 case Class::kPrimDouble:
2232 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2233 &failure);
2234 break;
2235 default:
2236 LOG(ERROR) << "VFY: invalid aput-wide on "
2237 << res_class->GetDescriptor()->ToModifiedUtf8();
2238 failure = VERIFY_ERROR_GENERIC;
2239 break;
2240 }
2241 }
2242 break;
2243 case Instruction::APUT_OBJECT:
2244 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2245 CheckArrayIndexType(method, tmp_type, &failure);
2246 if (failure != VERIFY_ERROR_NONE)
2247 break;
2248
2249 /* get the ref we're storing; Zero is okay, Uninit is not */
2250 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
2251 if (failure != VERIFY_ERROR_NONE)
2252 break;
2253 if (res_class != NULL) {
2254 Class* array_class;
2255 Class* element_class;
2256
2257 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002258 * Get the array class. If the array ref is null, we won't
jeffhaobdb76512011-09-07 11:43:16 -07002259 * have type information (and we'll crash at runtime with a
2260 * null pointer exception).
2261 */
2262 array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2263
2264 if (array_class != NULL) {
2265 /* see if the array holds a compatible type */
2266 if (!array_class->IsArrayClass()) {
2267 LOG(ERROR) << "VFY: invalid aput-object on "
2268 << array_class->GetDescriptor()->ToModifiedUtf8();
2269 failure = VERIFY_ERROR_GENERIC;
2270 break;
2271 }
2272
2273 /*
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002274 * Find the element class.
jeffhaobdb76512011-09-07 11:43:16 -07002275 *
2276 * All we want to check here is that the element type is a
jeffhaod1f0fde2011-09-08 17:25:33 -07002277 * reference class. We *don't* check instanceof here, because
jeffhaobdb76512011-09-07 11:43:16 -07002278 * you can still put a String into a String[] after the latter
2279 * has been cast to an Object[].
2280 */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002281 element_class = array_class->GetComponentType();
2282 if (element_class->IsPrimitive()) {
jeffhaobdb76512011-09-07 11:43:16 -07002283 LOG(ERROR) << "VFY: invalid aput-object of "
2284 << res_class->GetDescriptor()->ToModifiedUtf8()
2285 << " into "
2286 << array_class->GetDescriptor()->ToModifiedUtf8();
2287 failure = VERIFY_ERROR_GENERIC;
2288 break;
2289 }
2290 }
2291 }
2292 break;
2293
2294 case Instruction::IGET:
2295 tmp_type = kRegTypeInteger;
2296 goto iget_1nr_common;
2297 case Instruction::IGET_BOOLEAN:
2298 tmp_type = kRegTypeBoolean;
2299 goto iget_1nr_common;
2300 case Instruction::IGET_BYTE:
2301 tmp_type = kRegTypeByte;
2302 goto iget_1nr_common;
2303 case Instruction::IGET_CHAR:
2304 tmp_type = kRegTypeChar;
2305 goto iget_1nr_common;
2306 case Instruction::IGET_SHORT:
2307 tmp_type = kRegTypeShort;
2308 goto iget_1nr_common;
2309iget_1nr_common:
2310 {
2311 Field* inst_field;
2312 RegType obj_type, field_type;
2313
2314 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2315 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2316 if (failure != VERIFY_ERROR_NONE)
2317 break;
2318
2319 /* make sure the field's type is compatible with expectation */
jeffhao2a8a90e2011-09-26 14:25:31 -07002320 field_type = PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
jeffhaobdb76512011-09-07 11:43:16 -07002321
2322 /* correct if float */
2323 if (field_type == kRegTypeFloat)
2324 tmp_type = kRegTypeFloat;
2325
2326 if (field_type == kRegTypeUnknown || tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002327 LOG(ERROR) << "VFY: invalid iget-1nr of " << PrettyField(inst_field)
jeffhaobdb76512011-09-07 11:43:16 -07002328 << " (inst=" << tmp_type << " field=" << field_type << ")";
2329 failure = VERIFY_ERROR_GENERIC;
2330 break;
2331 }
2332
2333 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2334 }
2335 break;
2336 case Instruction::IGET_WIDE:
2337 {
jeffhaobdb76512011-09-07 11:43:16 -07002338 Field* inst_field;
2339 RegType obj_type;
2340
2341 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2342 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002343 if (failure != VERIFY_ERROR_NONE)
2344 break;
2345 /* check the type, which should be prim */
2346 switch (inst_field->GetType()->GetPrimitiveType()) {
2347 case Class::kPrimDouble:
jeffhao2a8a90e2011-09-26 14:25:31 -07002348 SetRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo);
jeffhaobdb76512011-09-07 11:43:16 -07002349 break;
2350 case Class::kPrimLong:
jeffhao2a8a90e2011-09-26 14:25:31 -07002351 SetRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo);
jeffhaobdb76512011-09-07 11:43:16 -07002352 break;
2353 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002354 LOG(ERROR) << "VFY: invalid iget-wide of " << PrettyField(inst_field);
jeffhaobdb76512011-09-07 11:43:16 -07002355 failure = VERIFY_ERROR_GENERIC;
2356 break;
2357 }
jeffhaobdb76512011-09-07 11:43:16 -07002358 }
2359 break;
2360 case Instruction::IGET_OBJECT:
2361 {
2362 Class* field_class;
2363 Field* inst_field;
2364 RegType obj_type;
2365
2366 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2367 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2368 if (failure != VERIFY_ERROR_NONE)
2369 break;
2370 field_class = inst_field->GetType();
2371 if (field_class == NULL) {
2372 /* class not found or primitive type */
2373 LOG(ERROR) << "VFY: unable to recover field class from "
2374 << inst_field->GetName()->ToModifiedUtf8();
2375 failure = VERIFY_ERROR_GENERIC;
2376 break;
2377 }
jeffhao2a8a90e2011-09-26 14:25:31 -07002378 DCHECK(!field_class->IsPrimitive()) << PrettyClass(field_class);
2379 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
jeffhaobdb76512011-09-07 11:43:16 -07002380 }
2381 break;
2382 case Instruction::IPUT:
2383 tmp_type = kRegTypeInteger;
2384 goto iput_1nr_common;
2385 case Instruction::IPUT_BOOLEAN:
2386 tmp_type = kRegTypeBoolean;
2387 goto iput_1nr_common;
2388 case Instruction::IPUT_BYTE:
2389 tmp_type = kRegTypeByte;
2390 goto iput_1nr_common;
2391 case Instruction::IPUT_CHAR:
2392 tmp_type = kRegTypeChar;
2393 goto iput_1nr_common;
2394 case Instruction::IPUT_SHORT:
2395 tmp_type = kRegTypeShort;
2396 goto iput_1nr_common;
2397iput_1nr_common:
2398 {
2399 RegType src_type, field_type, obj_type;
2400 Field* inst_field;
2401
2402 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2403 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2404 if (failure != VERIFY_ERROR_NONE)
2405 break;
2406 CheckFinalFieldAccess(method, inst_field, &failure);
2407 if (failure != VERIFY_ERROR_NONE)
2408 break;
2409
2410 /* get type of field we're storing into */
jeffhao2a8a90e2011-09-26 14:25:31 -07002411 field_type = PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
jeffhaobdb76512011-09-07 11:43:16 -07002412 src_type = GetRegisterType(work_line, dec_insn.vA_);
2413
2414 /* correct if float */
2415 if (field_type == kRegTypeFloat)
2416 tmp_type = kRegTypeFloat;
2417
2418 /*
2419 * compiler can generate synthetic functions that write byte values
2420 * into boolean fields.
2421 */
2422 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2423 tmp_type = kRegTypeByte;
2424 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2425 field_type = kRegTypeByte;
2426
2427 /* make sure the source register has the correct type */
2428 if (!CanConvertTo1nr(src_type, tmp_type)) {
2429 LOG(ERROR) << "VFY: invalid reg type " << src_type
2430 << " on iput instr (need " << tmp_type << ")",
2431 failure = VERIFY_ERROR_GENERIC;
2432 break;
2433 }
2434
2435 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2436
2437 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2438 tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002439 LOG(ERROR) << "VFY: invalid iput-1nr of " << PrettyField(inst_field)
jeffhaobdb76512011-09-07 11:43:16 -07002440 << " (inst=" << tmp_type << " field=" << field_type << ")";
2441 failure = VERIFY_ERROR_GENERIC;
2442 break;
2443 }
2444 }
2445 break;
2446 case Instruction::IPUT_WIDE:
jeffhao2a8a90e2011-09-26 14:25:31 -07002447 {
2448 Field* inst_field;
2449 RegType obj_type;
jeffhaobdb76512011-09-07 11:43:16 -07002450
jeffhao2a8a90e2011-09-26 14:25:31 -07002451 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2452 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2453 if (failure != VERIFY_ERROR_NONE)
2454 break;
2455 CheckFinalFieldAccess(method, inst_field, &failure);
2456 if (failure != VERIFY_ERROR_NONE)
2457 break;
jeffhaobdb76512011-09-07 11:43:16 -07002458
jeffhao2a8a90e2011-09-26 14:25:31 -07002459 /* check the type, which should be prim */
2460 switch (inst_field->GetType()->GetPrimitiveType()) {
2461 case Class::kPrimDouble:
2462 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2463 &failure);
2464 break;
2465 case Class::kPrimLong:
2466 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2467 break;
2468 default:
2469 LOG(ERROR) << "VFY: invalid iput-wide of " << PrettyField(inst_field);
2470 failure = VERIFY_ERROR_GENERIC;
2471 break;
jeffhaobdb76512011-09-07 11:43:16 -07002472 }
jeffhao2a8a90e2011-09-26 14:25:31 -07002473 break;
2474 }
jeffhaobdb76512011-09-07 11:43:16 -07002475 case Instruction::IPUT_OBJECT:
2476 {
2477 Class* field_class;
2478 Class* value_class;
2479 Field* inst_field;
2480 RegType obj_type, value_type;
2481
2482 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2483 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2484 if (failure != VERIFY_ERROR_NONE)
2485 break;
Brian Carlstrom65ca0772011-09-24 16:03:08 -07002486 DCHECK(inst_field != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002487 CheckFinalFieldAccess(method, inst_field, &failure);
2488 if (failure != VERIFY_ERROR_NONE)
2489 break;
2490
2491 field_class = inst_field->GetType();
2492 if (field_class == NULL) {
2493 LOG(ERROR) << "VFY: unable to recover field class from '"
2494 << inst_field->GetName()->ToModifiedUtf8() << "'";
2495 failure = VERIFY_ERROR_GENERIC;
2496 break;
2497 }
2498
2499 value_type = GetRegisterType(work_line, dec_insn.vA_);
2500 if (!RegTypeIsReference(value_type)) {
2501 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2502 << " into ref field '"
2503 << inst_field->GetName()->ToModifiedUtf8() << "' ("
2504 << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
2505 failure = VERIFY_ERROR_GENERIC;
2506 break;
2507 }
2508 if (value_type != kRegTypeZero) {
2509 value_class = RegTypeInitializedReferenceToClass(value_type);
2510 if (value_class == NULL) {
2511 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2512 << " into ref field";
2513 failure = VERIFY_ERROR_GENERIC;
2514 break;
2515 }
2516 /* allow if field is any interface or field is base class */
2517 if (!field_class->IsInterface() &&
2518 !field_class->IsAssignableFrom(value_class)) {
jeffhaobdb76512011-09-07 11:43:16 -07002519 LOG(ERROR) << "VFY: storing type '"
2520 << value_class->GetDescriptor()->ToModifiedUtf8()
2521 << "' into field type '"
2522 << field_class->GetDescriptor()->ToModifiedUtf8()
jeffhao2a8a90e2011-09-26 14:25:31 -07002523 << "' (" << PrettyField(inst_field) << ")";
jeffhaobdb76512011-09-07 11:43:16 -07002524 failure = VERIFY_ERROR_GENERIC;
2525 break;
2526 }
2527 }
2528 }
2529 break;
2530
2531 case Instruction::SGET:
2532 tmp_type = kRegTypeInteger;
2533 goto sget_1nr_common;
2534 case Instruction::SGET_BOOLEAN:
2535 tmp_type = kRegTypeBoolean;
2536 goto sget_1nr_common;
2537 case Instruction::SGET_BYTE:
2538 tmp_type = kRegTypeByte;
2539 goto sget_1nr_common;
2540 case Instruction::SGET_CHAR:
2541 tmp_type = kRegTypeChar;
2542 goto sget_1nr_common;
2543 case Instruction::SGET_SHORT:
2544 tmp_type = kRegTypeShort;
2545 goto sget_1nr_common;
2546sget_1nr_common:
2547 {
2548 Field* static_field;
2549 RegType field_type;
2550
2551 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2552 if (failure != VERIFY_ERROR_NONE)
2553 break;
2554
2555 /*
2556 * Make sure the field's type is compatible with expectation.
2557 * We can get ourselves into trouble if we mix & match loads
2558 * and stores with different widths, so rather than just checking
2559 * "CanConvertTo1nr" we require that the field types have equal
2560 * widths.
2561 */
2562 field_type =
2563 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2564
2565 /* correct if float */
2566 if (field_type == kRegTypeFloat)
2567 tmp_type = kRegTypeFloat;
2568
2569 if (tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002570 LOG(ERROR) << "VFY: invalid sget-1nr of " << PrettyField(static_field)
jeffhaobdb76512011-09-07 11:43:16 -07002571 << " (inst=" << tmp_type << " actual=" << field_type
2572 << ")";
2573 failure = VERIFY_ERROR_GENERIC;
2574 break;
2575 }
2576
2577 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2578 }
2579 break;
2580 case Instruction::SGET_WIDE:
2581 {
jeffhao2a8a90e2011-09-26 14:25:31 -07002582 Field* static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002583 if (failure != VERIFY_ERROR_NONE)
2584 break;
2585 /* check the type, which should be prim */
2586 switch (static_field->GetType()->GetPrimitiveType()) {
2587 case Class::kPrimDouble:
jeffhao2a8a90e2011-09-26 14:25:31 -07002588 SetRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo);
jeffhaobdb76512011-09-07 11:43:16 -07002589 break;
2590 case Class::kPrimLong:
jeffhao2a8a90e2011-09-26 14:25:31 -07002591 SetRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo);
jeffhaobdb76512011-09-07 11:43:16 -07002592 break;
2593 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002594 LOG(ERROR) << "VFY: invalid sget-wide of " << PrettyField(static_field);
jeffhaobdb76512011-09-07 11:43:16 -07002595 failure = VERIFY_ERROR_GENERIC;
2596 break;
2597 }
jeffhaobdb76512011-09-07 11:43:16 -07002598 }
2599 break;
2600 case Instruction::SGET_OBJECT:
2601 {
jeffhao2a8a90e2011-09-26 14:25:31 -07002602 Field* static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002603 if (failure != VERIFY_ERROR_NONE)
2604 break;
jeffhao2a8a90e2011-09-26 14:25:31 -07002605 Class* field_class = static_field->GetType();
jeffhaobdb76512011-09-07 11:43:16 -07002606 if (field_class == NULL) {
2607 LOG(ERROR) << "VFY: unable to recover field class from '"
2608 << static_field->GetName()->ToModifiedUtf8() << "'";
2609 failure = VERIFY_ERROR_GENERIC;
2610 break;
2611 }
2612 if (field_class->IsPrimitive()) {
2613 LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
2614 failure = VERIFY_ERROR_GENERIC;
2615 break;
2616 }
2617 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
2618 }
2619 break;
2620 case Instruction::SPUT:
2621 tmp_type = kRegTypeInteger;
2622 goto sput_1nr_common;
2623 case Instruction::SPUT_BOOLEAN:
2624 tmp_type = kRegTypeBoolean;
2625 goto sput_1nr_common;
2626 case Instruction::SPUT_BYTE:
2627 tmp_type = kRegTypeByte;
2628 goto sput_1nr_common;
2629 case Instruction::SPUT_CHAR:
2630 tmp_type = kRegTypeChar;
2631 goto sput_1nr_common;
2632 case Instruction::SPUT_SHORT:
2633 tmp_type = kRegTypeShort;
2634 goto sput_1nr_common;
2635sput_1nr_common:
2636 {
2637 RegType src_type, field_type;
2638 Field* static_field;
2639
2640 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2641 if (failure != VERIFY_ERROR_NONE)
2642 break;
2643 CheckFinalFieldAccess(method, static_field, &failure);
2644 if (failure != VERIFY_ERROR_NONE)
2645 break;
2646
2647 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002648 * Get type of field we're storing into. We know that the
jeffhaobdb76512011-09-07 11:43:16 -07002649 * contents of the register match the instruction, but we also
2650 * need to ensure that the instruction matches the field type.
2651 * Using e.g. sput-short to write into a 32-bit integer field
2652 * can lead to trouble if we do 16-bit writes.
2653 */
2654 field_type =
2655 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2656 src_type = GetRegisterType(work_line, dec_insn.vA_);
2657
2658 /* correct if float */
2659 if (field_type == kRegTypeFloat)
2660 tmp_type = kRegTypeFloat;
2661
2662 /*
2663 * compiler can generate synthetic functions that write byte values
2664 * into boolean fields.
2665 */
2666 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2667 tmp_type = kRegTypeByte;
2668 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2669 field_type = kRegTypeByte;
2670
2671 /* make sure the source register has the correct type */
2672 if (!CanConvertTo1nr(src_type, tmp_type)) {
2673 LOG(ERROR) << "VFY: invalid reg type " << src_type
2674 << " on sput instr (need " << tmp_type << ")";
2675 failure = VERIFY_ERROR_GENERIC;
2676 break;
2677 }
2678
2679 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2680
2681 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2682 tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002683 LOG(ERROR) << "VFY: invalid sput-1nr of " << PrettyField(static_field)
jeffhaobdb76512011-09-07 11:43:16 -07002684 << " (inst=" << tmp_type << " actual=" << field_type
2685 << ")";
2686 failure = VERIFY_ERROR_GENERIC;
2687 break;
2688 }
2689 }
2690 break;
2691 case Instruction::SPUT_WIDE:
2692 Field* static_field;
2693
2694 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2695 if (failure != VERIFY_ERROR_NONE)
2696 break;
2697 CheckFinalFieldAccess(method, static_field, &failure);
2698 if (failure != VERIFY_ERROR_NONE)
2699 break;
2700
2701 /* check the type, which should be prim */
2702 switch (static_field->GetType()->GetPrimitiveType()) {
2703 case Class::kPrimDouble:
2704 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2705 &failure);
2706 break;
2707 case Class::kPrimLong:
2708 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2709 break;
2710 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002711 LOG(ERROR) << "VFY: invalid sput-wide of " << PrettyField(static_field);
jeffhaobdb76512011-09-07 11:43:16 -07002712 failure = VERIFY_ERROR_GENERIC;
2713 break;
2714 }
2715 break;
2716 case Instruction::SPUT_OBJECT:
2717 {
2718 Class* field_class;
2719 Class* value_class;
2720 Field* static_field;
2721 RegType value_type;
2722
2723 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2724 if (failure != VERIFY_ERROR_NONE)
2725 break;
2726 CheckFinalFieldAccess(method, static_field, &failure);
2727 if (failure != VERIFY_ERROR_NONE)
2728 break;
2729
2730 field_class = static_field->GetType();
2731 if (field_class == NULL) {
2732 LOG(ERROR) << "VFY: unable to recover field class from '"
2733 << static_field->GetName()->ToModifiedUtf8() << "'";
2734 failure = VERIFY_ERROR_GENERIC;
2735 break;
2736 }
2737
2738 value_type = GetRegisterType(work_line, dec_insn.vA_);
2739 if (!RegTypeIsReference(value_type)) {
2740 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2741 << " into ref field '"
2742 << static_field->GetName()->ToModifiedUtf8() << "' ("
2743 << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
2744 failure = VERIFY_ERROR_GENERIC;
2745 break;
2746 }
2747 if (value_type != kRegTypeZero) {
2748 value_class = RegTypeInitializedReferenceToClass(value_type);
2749 if (value_class == NULL) {
2750 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2751 << " into ref field";
2752 failure = VERIFY_ERROR_GENERIC;
2753 break;
2754 }
2755 /* allow if field is any interface or field is base class */
2756 if (!field_class->IsInterface() &&
2757 !field_class->IsAssignableFrom(value_class)) {
jeffhaobdb76512011-09-07 11:43:16 -07002758 LOG(ERROR) << "VFY: storing type '"
2759 << value_class->GetDescriptor()->ToModifiedUtf8()
2760 << "' into field type '"
2761 << field_class->GetDescriptor()->ToModifiedUtf8()
jeffhao2a8a90e2011-09-26 14:25:31 -07002762 << "' (" << PrettyField(static_field) << ")";
jeffhaobdb76512011-09-07 11:43:16 -07002763 failure = VERIFY_ERROR_GENERIC;
2764 break;
2765 }
2766 }
2767 }
2768 break;
2769
2770 case Instruction::INVOKE_VIRTUAL:
2771 case Instruction::INVOKE_VIRTUAL_RANGE:
2772 case Instruction::INVOKE_SUPER:
2773 case Instruction::INVOKE_SUPER_RANGE:
2774 {
2775 Method* called_method;
2776 RegType return_type;
2777 bool is_range;
2778 bool is_super;
2779
2780 is_range = (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
2781 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2782 is_super = (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
2783 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2784
2785 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2786 &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
2787 if (failure != VERIFY_ERROR_NONE)
2788 break;
2789 return_type = GetMethodReturnType(dex_file, called_method);
2790 SetResultRegisterType(work_line, registers_size, return_type);
2791 just_set_result = true;
2792 }
2793 break;
2794 case Instruction::INVOKE_DIRECT:
2795 case Instruction::INVOKE_DIRECT_RANGE:
2796 {
2797 RegType return_type;
2798 Method* called_method;
2799 bool is_range;
2800
2801 is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
2802 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2803 &dec_insn, METHOD_DIRECT, is_range, false, &failure);
2804 if (failure != VERIFY_ERROR_NONE)
2805 break;
2806
2807 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002808 * Some additional checks when calling <init>. We know from
jeffhaobdb76512011-09-07 11:43:16 -07002809 * the invocation arg check that the "this" argument is an
jeffhaod1f0fde2011-09-08 17:25:33 -07002810 * instance of called_method->klass. Now we further restrict
jeffhaobdb76512011-09-07 11:43:16 -07002811 * that to require that called_method->klass is the same as
2812 * this->klass or this->super, allowing the latter only if
2813 * the "this" argument is the same as the "this" argument to
2814 * this method (which implies that we're in <init> ourselves).
2815 */
2816 if (IsInitMethod(called_method)) {
2817 RegType this_type;
2818 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2819 if (failure != VERIFY_ERROR_NONE)
2820 break;
2821
2822 /* no null refs allowed (?) */
2823 if (this_type == kRegTypeZero) {
2824 LOG(ERROR) << "VFY: unable to initialize null ref";
2825 failure = VERIFY_ERROR_GENERIC;
2826 break;
2827 }
2828
2829 Class* this_class;
2830
2831 this_class = RegTypeReferenceToClass(this_type, uninit_map);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002832 DCHECK(this_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002833
2834 /* must be in same class or in superclass */
2835 if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
2836 {
2837 if (this_class != method->GetDeclaringClass()) {
2838 LOG(ERROR) << "VFY: invoke-direct <init> on super only "
2839 << "allowed for 'this' in <init>";
2840 failure = VERIFY_ERROR_GENERIC;
2841 break;
2842 }
2843 } else if (called_method->GetDeclaringClass() != this_class) {
2844 LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
2845 << "class or super";
2846 failure = VERIFY_ERROR_GENERIC;
2847 break;
2848 }
2849
2850 /* arg must be an uninitialized reference */
2851 if (!RegTypeIsUninitReference(this_type)) {
2852 LOG(ERROR) << "VFY: can only initialize the uninitialized";
2853 failure = VERIFY_ERROR_GENERIC;
2854 break;
2855 }
2856
2857 /*
2858 * Replace the uninitialized reference with an initialized
jeffhaod1f0fde2011-09-08 17:25:33 -07002859 * one, and clear the entry in the uninit map. We need to
jeffhaobdb76512011-09-07 11:43:16 -07002860 * do this for all registers that have the same object
2861 * instance in them, not just the "this" register.
2862 */
2863 MarkRefsAsInitialized(work_line, registers_size, uninit_map,
2864 this_type, &failure);
2865 if (failure != VERIFY_ERROR_NONE)
2866 break;
jeffhao2a8a90e2011-09-26 14:25:31 -07002867 }
jeffhaobdb76512011-09-07 11:43:16 -07002868 return_type = GetMethodReturnType(dex_file, called_method);
2869 SetResultRegisterType(work_line, registers_size, return_type);
2870 just_set_result = true;
2871 }
2872 break;
2873 case Instruction::INVOKE_STATIC:
2874 case Instruction::INVOKE_STATIC_RANGE:
2875 {
2876 RegType return_type;
2877 Method* called_method;
2878 bool is_range;
2879
2880 is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
2881 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2882 &dec_insn, METHOD_STATIC, is_range, false, &failure);
2883 if (failure != VERIFY_ERROR_NONE)
2884 break;
2885
2886 return_type = GetMethodReturnType(dex_file, called_method);
2887 SetResultRegisterType(work_line, registers_size, return_type);
2888 just_set_result = true;
2889 }
2890 break;
2891 case Instruction::INVOKE_INTERFACE:
2892 case Instruction::INVOKE_INTERFACE_RANGE:
2893 {
2894 RegType /*this_type,*/ return_type;
2895 Method* abs_method;
2896 bool is_range;
2897
2898 is_range = (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
2899 abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2900 &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
2901 if (failure != VERIFY_ERROR_NONE)
2902 break;
2903
2904#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
2905 /*
2906 * Get the type of the "this" arg, which should always be an
jeffhaod1f0fde2011-09-08 17:25:33 -07002907 * interface class. Because we don't do a full merge on
jeffhaobdb76512011-09-07 11:43:16 -07002908 * interface classes, this might have reduced to Object.
2909 */
2910 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2911 if (failure != VERIFY_ERROR_NONE)
2912 break;
2913
2914 if (this_type == kRegTypeZero) {
2915 /* null pointer always passes (and always fails at runtime) */
2916 } else {
2917 Class* this_class;
2918
2919 this_class = RegTypeInitializedReferenceToClass(this_type);
2920 if (this_class == NULL) {
2921 LOG(ERROR) << "VFY: interface call on uninitialized";
2922 failure = VERIFY_ERROR_GENERIC;
2923 break;
2924 }
2925
2926 /*
2927 * Either "this_class" needs to be the interface class that
2928 * defined abs_method, or abs_method's class needs to be one
jeffhaod1f0fde2011-09-08 17:25:33 -07002929 * of the interfaces implemented by "this_class". (Or, if
jeffhaobdb76512011-09-07 11:43:16 -07002930 * we couldn't complete the merge, this will be Object.)
2931 */
2932 if (this_class != abs_method->GetDeclaringClass() &&
2933 this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
2934 !this_class->Implements(abs_method->GetDeclaringClass())) {
2935 LOG(ERROR) << "VFY: unable to match abs_method '"
2936 << abs_method->GetName()->ToModifiedUtf8() << "' with "
2937 << this_class->GetDescriptor()->ToModifiedUtf8()
2938 << " interfaces";
2939 failure = VERIFY_ERROR_GENERIC;
2940 break;
2941 }
2942 }
2943#endif
2944
2945 /*
2946 * We don't have an object instance, so we can't find the
jeffhaod1f0fde2011-09-08 17:25:33 -07002947 * concrete method. However, all of the type information is
jeffhaobdb76512011-09-07 11:43:16 -07002948 * in the abstract method, so we're good.
2949 */
2950 return_type = GetMethodReturnType(dex_file, abs_method);
2951 SetResultRegisterType(work_line, registers_size, return_type);
2952 just_set_result = true;
2953 }
2954 break;
2955
2956 case Instruction::NEG_INT:
2957 case Instruction::NOT_INT:
2958 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
2959 &failure);
2960 break;
2961 case Instruction::NEG_LONG:
2962 case Instruction::NOT_LONG:
2963 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
2964 break;
2965 case Instruction::NEG_FLOAT:
2966 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
2967 break;
2968 case Instruction::NEG_DOUBLE:
2969 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
2970 &failure);
2971 break;
2972 case Instruction::INT_TO_LONG:
2973 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
2974 &failure);
2975 break;
2976 case Instruction::INT_TO_FLOAT:
2977 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
2978 break;
2979 case Instruction::INT_TO_DOUBLE:
2980 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
2981 &failure);
2982 break;
2983 case Instruction::LONG_TO_INT:
2984 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
2985 &failure);
2986 break;
2987 case Instruction::LONG_TO_FLOAT:
2988 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
2989 break;
2990 case Instruction::LONG_TO_DOUBLE:
2991 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
2992 &failure);
2993 break;
2994 case Instruction::FLOAT_TO_INT:
2995 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
2996 break;
2997 case Instruction::FLOAT_TO_LONG:
2998 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
2999 break;
3000 case Instruction::FLOAT_TO_DOUBLE:
3001 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
3002 &failure);
3003 break;
3004 case Instruction::DOUBLE_TO_INT:
3005 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
3006 &failure);
3007 break;
3008 case Instruction::DOUBLE_TO_LONG:
3009 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
3010 &failure);
3011 break;
3012 case Instruction::DOUBLE_TO_FLOAT:
3013 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
3014 &failure);
3015 break;
3016 case Instruction::INT_TO_BYTE:
3017 CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
3018 break;
3019 case Instruction::INT_TO_CHAR:
3020 CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
3021 break;
3022 case Instruction::INT_TO_SHORT:
3023 CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
3024 break;
3025
3026 case Instruction::ADD_INT:
3027 case Instruction::SUB_INT:
3028 case Instruction::MUL_INT:
3029 case Instruction::REM_INT:
3030 case Instruction::DIV_INT:
3031 case Instruction::SHL_INT:
3032 case Instruction::SHR_INT:
3033 case Instruction::USHR_INT:
3034 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3035 kRegTypeInteger, false, &failure);
3036 break;
3037 case Instruction::AND_INT:
3038 case Instruction::OR_INT:
3039 case Instruction::XOR_INT:
3040 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3041 kRegTypeInteger, true, &failure);
3042 break;
3043 case Instruction::ADD_LONG:
3044 case Instruction::SUB_LONG:
3045 case Instruction::MUL_LONG:
3046 case Instruction::DIV_LONG:
3047 case Instruction::REM_LONG:
3048 case Instruction::AND_LONG:
3049 case Instruction::OR_LONG:
3050 case Instruction::XOR_LONG:
3051 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3052 kRegTypeLongLo, false, &failure);
3053 break;
3054 case Instruction::SHL_LONG:
3055 case Instruction::SHR_LONG:
3056 case Instruction::USHR_LONG:
3057 /* shift distance is Int, making these different from other binops */
3058 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3059 kRegTypeInteger, false, &failure);
3060 break;
3061 case Instruction::ADD_FLOAT:
3062 case Instruction::SUB_FLOAT:
3063 case Instruction::MUL_FLOAT:
3064 case Instruction::DIV_FLOAT:
3065 case Instruction::REM_FLOAT:
3066 CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3067 kRegTypeFloat, false, &failure);
3068 break;
3069 case Instruction::ADD_DOUBLE:
3070 case Instruction::SUB_DOUBLE:
3071 case Instruction::MUL_DOUBLE:
3072 case Instruction::DIV_DOUBLE:
3073 case Instruction::REM_DOUBLE:
3074 CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3075 kRegTypeDoubleLo, false, &failure);
3076 break;
3077 case Instruction::ADD_INT_2ADDR:
3078 case Instruction::SUB_INT_2ADDR:
3079 case Instruction::MUL_INT_2ADDR:
3080 case Instruction::REM_INT_2ADDR:
3081 case Instruction::SHL_INT_2ADDR:
3082 case Instruction::SHR_INT_2ADDR:
3083 case Instruction::USHR_INT_2ADDR:
3084 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3085 kRegTypeInteger, false, &failure);
3086 break;
3087 case Instruction::AND_INT_2ADDR:
3088 case Instruction::OR_INT_2ADDR:
3089 case Instruction::XOR_INT_2ADDR:
3090 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3091 kRegTypeInteger, true, &failure);
3092 break;
3093 case Instruction::DIV_INT_2ADDR:
3094 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3095 kRegTypeInteger, false, &failure);
3096 break;
3097 case Instruction::ADD_LONG_2ADDR:
3098 case Instruction::SUB_LONG_2ADDR:
3099 case Instruction::MUL_LONG_2ADDR:
3100 case Instruction::DIV_LONG_2ADDR:
3101 case Instruction::REM_LONG_2ADDR:
3102 case Instruction::AND_LONG_2ADDR:
3103 case Instruction::OR_LONG_2ADDR:
3104 case Instruction::XOR_LONG_2ADDR:
3105 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3106 kRegTypeLongLo, false, &failure);
3107 break;
3108 case Instruction::SHL_LONG_2ADDR:
3109 case Instruction::SHR_LONG_2ADDR:
3110 case Instruction::USHR_LONG_2ADDR:
3111 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3112 kRegTypeInteger, false, &failure);
3113 break;
3114 case Instruction::ADD_FLOAT_2ADDR:
3115 case Instruction::SUB_FLOAT_2ADDR:
3116 case Instruction::MUL_FLOAT_2ADDR:
3117 case Instruction::DIV_FLOAT_2ADDR:
3118 case Instruction::REM_FLOAT_2ADDR:
3119 CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3120 kRegTypeFloat, false, &failure);
3121 break;
3122 case Instruction::ADD_DOUBLE_2ADDR:
3123 case Instruction::SUB_DOUBLE_2ADDR:
3124 case Instruction::MUL_DOUBLE_2ADDR:
3125 case Instruction::DIV_DOUBLE_2ADDR:
3126 case Instruction::REM_DOUBLE_2ADDR:
3127 CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3128 kRegTypeDoubleLo, false, &failure);
3129 break;
3130 case Instruction::ADD_INT_LIT16:
3131 case Instruction::RSUB_INT:
3132 case Instruction::MUL_INT_LIT16:
3133 case Instruction::DIV_INT_LIT16:
3134 case Instruction::REM_INT_LIT16:
3135 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3136 &failure);
3137 break;
3138 case Instruction::AND_INT_LIT16:
3139 case Instruction::OR_INT_LIT16:
3140 case Instruction::XOR_INT_LIT16:
3141 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3142 &failure);
3143 break;
3144 case Instruction::ADD_INT_LIT8:
3145 case Instruction::RSUB_INT_LIT8:
3146 case Instruction::MUL_INT_LIT8:
3147 case Instruction::DIV_INT_LIT8:
3148 case Instruction::REM_INT_LIT8:
3149 case Instruction::SHL_INT_LIT8:
3150 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3151 &failure);
3152 break;
3153 case Instruction::SHR_INT_LIT8:
3154 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
jeffhaob4df5142011-09-19 20:25:32 -07003155 false);
jeffhaobdb76512011-09-07 11:43:16 -07003156 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3157 &failure);
3158 break;
3159 case Instruction::USHR_INT_LIT8:
3160 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
jeffhaob4df5142011-09-19 20:25:32 -07003161 true);
jeffhaobdb76512011-09-07 11:43:16 -07003162 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3163 &failure);
3164 break;
3165 case Instruction::AND_INT_LIT8:
3166 case Instruction::OR_INT_LIT8:
3167 case Instruction::XOR_INT_LIT8:
3168 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3169 &failure);
3170 break;
3171
3172 /*
3173 * This falls into the general category of "optimized" instructions,
jeffhaod1f0fde2011-09-08 17:25:33 -07003174 * which don't generally appear during verification. Because it's
jeffhaobdb76512011-09-07 11:43:16 -07003175 * inserted in the course of verification, we can expect to see it here.
3176 */
jeffhaob4df5142011-09-19 20:25:32 -07003177 case Instruction::THROW_VERIFICATION_ERROR:
jeffhaobdb76512011-09-07 11:43:16 -07003178 break;
3179
3180 /*
3181 * Verifying "quickened" instructions is tricky, because we have
jeffhaod1f0fde2011-09-08 17:25:33 -07003182 * discarded the original field/method information. The byte offsets
jeffhaobdb76512011-09-07 11:43:16 -07003183 * and vtable indices only have meaning in the context of an object
3184 * instance.
3185 *
3186 * If a piece of code declares a local reference variable, assigns
3187 * null to it, and then issues a virtual method call on it, we
jeffhaod1f0fde2011-09-08 17:25:33 -07003188 * cannot evaluate the method call during verification. This situation
jeffhaobdb76512011-09-07 11:43:16 -07003189 * isn't hard to handle, since we know the call will always result in an
jeffhaod1f0fde2011-09-08 17:25:33 -07003190 * NPE, and the arguments and return value don't matter. Any code that
jeffhaobdb76512011-09-07 11:43:16 -07003191 * depends on the result of the method call is inaccessible, so the
3192 * fact that we can't fully verify anything that comes after the bad
3193 * call is not a problem.
3194 *
3195 * We must also consider the case of multiple code paths, only some of
jeffhaod1f0fde2011-09-08 17:25:33 -07003196 * which involve a null reference. We can completely verify the method
jeffhaobdb76512011-09-07 11:43:16 -07003197 * if we sidestep the results of executing with a null reference.
3198 * For example, if on the first pass through the code we try to do a
3199 * virtual method invocation through a null ref, we have to skip the
3200 * method checks and have the method return a "wildcard" type (which
jeffhaod1f0fde2011-09-08 17:25:33 -07003201 * merges with anything to become that other thing). The move-result
jeffhaobdb76512011-09-07 11:43:16 -07003202 * will tell us if it's a reference, single-word numeric, or double-word
jeffhaod1f0fde2011-09-08 17:25:33 -07003203 * value. We continue to perform the verification, and at the end of
jeffhaobdb76512011-09-07 11:43:16 -07003204 * the function any invocations that were never fully exercised are
3205 * marked as null-only.
3206 *
jeffhaod1f0fde2011-09-08 17:25:33 -07003207 * We would do something similar for the field accesses. The field's
jeffhaobdb76512011-09-07 11:43:16 -07003208 * type, once known, can be used to recover the width of short integers.
3209 * If the object reference was null, the field-get returns the "wildcard"
3210 * type, which is acceptable for any operation.
3211 */
3212 case Instruction::UNUSED_EE:
3213 case Instruction::UNUSED_EF:
3214 case Instruction::UNUSED_F2:
3215 case Instruction::UNUSED_F3:
3216 case Instruction::UNUSED_F4:
3217 case Instruction::UNUSED_F5:
3218 case Instruction::UNUSED_F6:
3219 case Instruction::UNUSED_F7:
3220 case Instruction::UNUSED_F8:
3221 case Instruction::UNUSED_F9:
3222 case Instruction::UNUSED_FA:
3223 case Instruction::UNUSED_FB:
3224 //case Instruction::EXECUTE_INLINE:
3225 //case Instruction::EXECUTE_INLINE_RANGE:
3226 //case Instruction::IGET_QUICK:
3227 //case Instruction::IGET_WIDE_QUICK:
3228 //case Instruction::IGET_OBJECT_QUICK:
3229 //case Instruction::IPUT_QUICK:
3230 //case Instruction::IPUT_WIDE_QUICK:
3231 //case Instruction::IPUT_OBJECT_QUICK:
3232 //case Instruction::INVOKE_VIRTUAL_QUICK:
3233 //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
3234 //case Instruction::INVOKE_SUPER_QUICK:
3235 //case Instruction::INVOKE_SUPER_QUICK_RANGE:
3236 /* fall through to failure */
3237
3238 /*
3239 * These instructions are equivalent (from the verifier's point of view)
jeffhaod1f0fde2011-09-08 17:25:33 -07003240 * to the original form. The change was made for correctness rather
jeffhaobdb76512011-09-07 11:43:16 -07003241 * than improved performance (except for invoke-object-init, which
jeffhaod1f0fde2011-09-08 17:25:33 -07003242 * provides both). The substitution takes place after verification
jeffhaobdb76512011-09-07 11:43:16 -07003243 * completes, though, so we don't expect to see them here.
3244 */
3245 case Instruction::UNUSED_F0:
3246 case Instruction::UNUSED_F1:
3247 case Instruction::UNUSED_E3:
3248 case Instruction::UNUSED_E8:
3249 case Instruction::UNUSED_E7:
3250 case Instruction::UNUSED_E4:
3251 case Instruction::UNUSED_E9:
3252 case Instruction::UNUSED_FC:
3253 case Instruction::UNUSED_E5:
3254 case Instruction::UNUSED_EA:
3255 case Instruction::UNUSED_FD:
3256 case Instruction::UNUSED_E6:
3257 case Instruction::UNUSED_EB:
3258 case Instruction::UNUSED_FE:
3259 //case Instruction::INVOKE_OBJECT_INIT_RANGE:
3260 //case Instruction::RETURN_VOID_BARRIER:
3261 //case Instruction::IGET_VOLATILE:
3262 //case Instruction::IGET_WIDE_VOLATILE:
3263 //case Instruction::IGET_OBJECT_VOLATILE:
3264 //case Instruction::IPUT_VOLATILE:
3265 //case Instruction::IPUT_WIDE_VOLATILE:
3266 //case Instruction::IPUT_OBJECT_VOLATILE:
3267 //case Instruction::SGET_VOLATILE:
3268 //case Instruction::SGET_WIDE_VOLATILE:
3269 //case Instruction::SGET_OBJECT_VOLATILE:
3270 //case Instruction::SPUT_VOLATILE:
3271 //case Instruction::SPUT_WIDE_VOLATILE:
3272 //case Instruction::SPUT_OBJECT_VOLATILE:
3273 /* fall through to failure */
3274
3275 /* These should never appear during verification. */
3276 case Instruction::UNUSED_3E:
3277 case Instruction::UNUSED_3F:
3278 case Instruction::UNUSED_40:
3279 case Instruction::UNUSED_41:
3280 case Instruction::UNUSED_42:
3281 case Instruction::UNUSED_43:
3282 case Instruction::UNUSED_73:
3283 case Instruction::UNUSED_79:
3284 case Instruction::UNUSED_7A:
3285 case Instruction::UNUSED_EC:
3286 case Instruction::UNUSED_FF:
3287 //case Instruction::BREAKPOINT:
3288 //case Instruction::DISPATCH_FF:
3289 failure = VERIFY_ERROR_GENERIC;
3290 break;
3291
3292 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003293 * DO NOT add a "default" clause here. Without it the compiler will
jeffhaobdb76512011-09-07 11:43:16 -07003294 * complain if an instruction is missing (which is desirable).
3295 */
3296 }
3297
3298 if (failure != VERIFY_ERROR_NONE) {
jeffhaobdb76512011-09-07 11:43:16 -07003299 if (failure == VERIFY_ERROR_GENERIC) {
3300 /* immediate failure, reject class */
3301 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3302 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3303 return false;
3304 } else {
3305 /* replace opcode and continue on */
3306 LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
3307 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
jeffhaob4df5142011-09-19 20:25:32 -07003308 if (!ReplaceFailingInstruction(code_item, insn_idx, failure)) {
jeffhaobdb76512011-09-07 11:43:16 -07003309 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3310 << (int) dec_insn.opcode_ << " at 0x" << insn_idx
3311 << std::dec;
3312 return false;
3313 }
3314 /* IMPORTANT: method->insns may have been changed */
3315 insns = code_item->insns_ + insn_idx;
3316
3317 /* continue on as if we just handled a throw-verification-error */
3318 failure = VERIFY_ERROR_NONE;
3319 opcode_flag = Instruction::kThrow;
3320 }
3321 }
3322
3323 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003324 * If we didn't just set the result register, clear it out. This
jeffhaobdb76512011-09-07 11:43:16 -07003325 * ensures that you can only use "move-result" immediately after the
jeffhaod1f0fde2011-09-08 17:25:33 -07003326 * result is set. (We could check this statically, but it's not
jeffhaobdb76512011-09-07 11:43:16 -07003327 * expensive and it makes our debugging output cleaner.)
3328 */
3329 if (!just_set_result) {
3330 int reg = RESULT_REGISTER(registers_size);
3331 SetRegisterType(work_line, reg, kRegTypeUnknown);
3332 SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
3333 }
3334
jeffhaoa0a764a2011-09-16 10:43:38 -07003335 /* Handle "continue". Tag the next consecutive instruction. */
jeffhaobdb76512011-09-07 11:43:16 -07003336 if ((opcode_flag & Instruction::kContinue) != 0) {
3337 size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
3338 if (insn_idx + insn_width >= insns_size) {
3339 LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
3340 << std::hex << insn_idx << std::dec << ")";
3341 return false;
3342 }
3343
3344 /*
3345 * The only way to get to a move-exception instruction is to get
jeffhaod1f0fde2011-09-08 17:25:33 -07003346 * thrown there. Make sure the next instruction isn't one.
jeffhaobdb76512011-09-07 11:43:16 -07003347 */
3348 if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
3349 return false;
3350
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003351 if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003352 /*
3353 * Merge registers into what we have for the next instruction,
3354 * and set the "changed" flag if needed.
3355 */
3356 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
3357 work_line))
3358 return false;
3359 } else {
3360 /*
3361 * We're not recording register data for the next instruction,
jeffhaod1f0fde2011-09-08 17:25:33 -07003362 * so we don't know what the prior state was. We have to
jeffhaobdb76512011-09-07 11:43:16 -07003363 * assume that something has changed and re-evaluate it.
3364 */
3365 InsnSetChanged(insn_flags, insn_idx + insn_width, true);
3366 }
3367 }
3368
3369 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003370 * Handle "branch". Tag the branch target.
jeffhaobdb76512011-09-07 11:43:16 -07003371 *
3372 * NOTE: instructions like Instruction::EQZ provide information about the
jeffhaod1f0fde2011-09-08 17:25:33 -07003373 * state of the register when the branch is taken or not taken. For example,
jeffhaobdb76512011-09-07 11:43:16 -07003374 * somebody could get a reference field, check it for zero, and if the
3375 * branch is taken immediately store that register in a boolean field
jeffhaod1f0fde2011-09-08 17:25:33 -07003376 * since the value is known to be zero. We do not currently account for
jeffhaobdb76512011-09-07 11:43:16 -07003377 * that, and will reject the code.
3378 *
3379 * TODO: avoid re-fetching the branch target
3380 */
3381 if ((opcode_flag & Instruction::kBranch) != 0) {
3382 bool isConditional, selfOkay;
3383
3384 if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
3385 &isConditional, &selfOkay)) {
3386 /* should never happen after static verification */
3387 LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
3388 return false;
3389 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003390 DCHECK_EQ(isConditional, (opcode_flag & Instruction::kContinue) != 0);
jeffhaobdb76512011-09-07 11:43:16 -07003391
3392 if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
3393 return false;
3394
3395 /* update branch target, set "changed" if appropriate */
3396 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
3397 work_line))
3398 return false;
3399 }
3400
3401 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003402 * Handle "switch". Tag all possible branch targets.
jeffhaobdb76512011-09-07 11:43:16 -07003403 *
3404 * We've already verified that the table is structurally sound, so we
3405 * just need to walk through and tag the targets.
3406 */
3407 if ((opcode_flag & Instruction::kSwitch) != 0) {
3408 int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
3409 const uint16_t* switch_insns = insns + offset_to_switch;
3410 int switch_count = switch_insns[1];
3411 int offset_to_targets, targ;
3412
3413 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
3414 /* 0 = sig, 1 = count, 2/3 = first key */
3415 offset_to_targets = 4;
3416 } else {
3417 /* 0 = sig, 1 = count, 2..count * 2 = keys */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003418 DCHECK((*insns & 0xff) == Instruction::SPARSE_SWITCH);
jeffhaobdb76512011-09-07 11:43:16 -07003419 offset_to_targets = 2 + 2 * switch_count;
3420 }
3421
3422 /* verify each switch target */
3423 for (targ = 0; targ < switch_count; targ++) {
3424 int offset;
3425 uint32_t abs_offset;
3426
3427 /* offsets are 32-bit, and only partly endian-swapped */
3428 offset = switch_insns[offset_to_targets + targ * 2] |
3429 (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
3430 abs_offset = insn_idx + offset;
3431
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003432 DCHECK_LT(abs_offset, insns_size);
jeffhaobdb76512011-09-07 11:43:16 -07003433
3434 if (!CheckMoveException(code_item->insns_, abs_offset))
3435 return false;
3436
3437 if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
3438 return false;
3439 }
3440 }
3441
3442 /*
3443 * Handle instructions that can throw and that are sitting in a
jeffhaod1f0fde2011-09-08 17:25:33 -07003444 * "try" block. (If they're not in a "try" block when they throw,
jeffhaobdb76512011-09-07 11:43:16 -07003445 * control transfers out of the method.)
3446 */
3447 if ((opcode_flag & Instruction::kThrow) != 0 &&
3448 InsnIsInTry(insn_flags, insn_idx)) {
3449 bool has_catch_all = false;
3450 DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
3451 *code_item, insn_idx);
3452
3453 for (; !iterator.HasNext(); iterator.Next()) {
3454 if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
3455 has_catch_all = true;
3456
3457 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003458 * Merge registers into the "catch" block. We want to use the
3459 * "savedRegs" rather than "work_regs", because at runtime the
3460 * exception will be thrown before the instruction modifies any
3461 * registers.
jeffhaobdb76512011-09-07 11:43:16 -07003462 */
3463 if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
3464 &reg_table->saved_line_))
3465 return false;
3466 }
3467
3468 /*
3469 * If the monitor stack depth is nonzero, there must be a "catch all"
jeffhaod1f0fde2011-09-08 17:25:33 -07003470 * handler for this instruction. This does apply to monitor-exit
jeffhaobdb76512011-09-07 11:43:16 -07003471 * because of async exception handling.
3472 */
3473 if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
3474 /*
3475 * The state in work_line reflects the post-execution state.
3476 * If the current instruction is a monitor-enter and the monitor
3477 * stack was empty, we don't need a catch-all (if it throws,
3478 * it will do so before grabbing the lock).
3479 */
3480 if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
3481 work_line->monitor_stack_top_ == 1))
3482 {
3483 LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
3484 << insn_idx << std::dec;
3485 return false;
3486 }
3487 }
3488 }
3489
jeffhaod1f0fde2011-09-08 17:25:33 -07003490 /* If we're returning from the method, make sure monitor stack is empty. */
jeffhaobdb76512011-09-07 11:43:16 -07003491 if ((opcode_flag & Instruction::kReturn) != 0 &&
3492 work_line->monitor_stack_top_ != 0) {
3493 LOG(ERROR) << "VFY: return with stack depth="
3494 << work_line->monitor_stack_top_ << " at 0x" << std::hex
3495 << insn_idx << std::dec;
3496 return false;
3497 }
3498
3499 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003500 * Update start_guess. Advance to the next instruction of that's
3501 * possible, otherwise use the branch target if one was found. If
jeffhaobdb76512011-09-07 11:43:16 -07003502 * neither of those exists we're in a return or throw; leave start_guess
3503 * alone and let the caller sort it out.
3504 */
3505 if ((opcode_flag & Instruction::kContinue) != 0) {
3506 *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
3507 } else if ((opcode_flag & Instruction::kBranch) != 0) {
3508 /* we're still okay if branch_target is zero */
3509 *start_guess = insn_idx + branch_target;
3510 }
3511
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003512 DCHECK_LT(*start_guess, insns_size);
Brian Carlstrom03c99df2011-09-18 10:52:00 -07003513 DCHECK_NE(InsnGetWidth(insn_flags, *start_guess), 0);
jeffhaobdb76512011-09-07 11:43:16 -07003514
3515 return true;
3516}
3517
3518bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
jeffhaob4df5142011-09-19 20:25:32 -07003519 int insn_idx, VerifyError failure) {
jeffhaobdb76512011-09-07 11:43:16 -07003520 const uint16_t* insns = code_item->insns_ + insn_idx;
3521 const byte* ptr = reinterpret_cast<const byte*>(insns);
3522 const Instruction* inst = Instruction::At(ptr);
3523 Instruction::Code opcode = inst->Opcode();
3524 VerifyErrorRefType ref_type;
3525
3526 /*
3527 * Generate the new instruction out of the old.
3528 *
3529 * First, make sure this is an instruction we're expecting to stomp on.
3530 */
3531 switch (opcode) {
3532 case Instruction::CONST_CLASS: // insn[1] == class ref, 2 bytes
3533 case Instruction::CHECK_CAST:
3534 case Instruction::INSTANCE_OF:
3535 case Instruction::NEW_INSTANCE:
3536 case Instruction::NEW_ARRAY:
3537 case Instruction::FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
3538 case Instruction::FILLED_NEW_ARRAY_RANGE:
3539 ref_type = VERIFY_ERROR_REF_CLASS;
3540 break;
3541
3542 case Instruction::IGET: // insn[1] == field ref, 2 bytes
3543 case Instruction::IGET_BOOLEAN:
3544 case Instruction::IGET_BYTE:
3545 case Instruction::IGET_CHAR:
3546 case Instruction::IGET_SHORT:
3547 case Instruction::IGET_WIDE:
3548 case Instruction::IGET_OBJECT:
3549 case Instruction::IPUT:
3550 case Instruction::IPUT_BOOLEAN:
3551 case Instruction::IPUT_BYTE:
3552 case Instruction::IPUT_CHAR:
3553 case Instruction::IPUT_SHORT:
3554 case Instruction::IPUT_WIDE:
3555 case Instruction::IPUT_OBJECT:
3556 case Instruction::SGET:
3557 case Instruction::SGET_BOOLEAN:
3558 case Instruction::SGET_BYTE:
3559 case Instruction::SGET_CHAR:
3560 case Instruction::SGET_SHORT:
3561 case Instruction::SGET_WIDE:
3562 case Instruction::SGET_OBJECT:
3563 case Instruction::SPUT:
3564 case Instruction::SPUT_BOOLEAN:
3565 case Instruction::SPUT_BYTE:
3566 case Instruction::SPUT_CHAR:
3567 case Instruction::SPUT_SHORT:
3568 case Instruction::SPUT_WIDE:
3569 case Instruction::SPUT_OBJECT:
3570 ref_type = VERIFY_ERROR_REF_FIELD;
3571 break;
3572
3573 case Instruction::INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3574 case Instruction::INVOKE_VIRTUAL_RANGE:
3575 case Instruction::INVOKE_SUPER:
3576 case Instruction::INVOKE_SUPER_RANGE:
3577 case Instruction::INVOKE_DIRECT:
3578 case Instruction::INVOKE_DIRECT_RANGE:
3579 case Instruction::INVOKE_STATIC:
3580 case Instruction::INVOKE_STATIC_RANGE:
3581 case Instruction::INVOKE_INTERFACE:
3582 case Instruction::INVOKE_INTERFACE_RANGE:
3583 ref_type = VERIFY_ERROR_REF_METHOD;
3584 break;
3585
3586 default:
3587 /* could handle this in a generic way, but this is probably safer */
3588 LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
3589 << (int) opcode << std::dec;
3590 return false;
3591 }
3592
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003593 DCHECK(inst->IsThrow());
jeffhaobdb76512011-09-07 11:43:16 -07003594
3595 /* write a NOP over the third code unit, if necessary */
jeffhaob4df5142011-09-19 20:25:32 -07003596 int width = inst->Size();
jeffhaobdb76512011-09-07 11:43:16 -07003597 switch (width) {
3598 case 2:
3599 /* nothing to do */
3600 break;
3601 case 3:
jeffhaob4df5142011-09-19 20:25:32 -07003602 UpdateCodeUnit(insns + 2, Instruction::NOP);
jeffhaobdb76512011-09-07 11:43:16 -07003603 break;
3604 default:
3605 /* whoops */
3606 LOG(FATAL) << "ERROR: stomped a " << width
3607 << "-unit instruction with a verifier error";
3608 }
3609
3610 /* encode the opcode, with the failure code in the high byte */
jeffhaob4df5142011-09-19 20:25:32 -07003611 DCHECK(width == 2 || width == 3);
3612 uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
3613 (failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
3614 UpdateCodeUnit(insns, new_val);
jeffhaobdb76512011-09-07 11:43:16 -07003615
3616 return true;
3617}
3618
jeffhaob4df5142011-09-19 20:25:32 -07003619void DexVerifier::UpdateCodeUnit(const uint16_t* ptr, uint16_t new_val) {
3620 *(uint16_t*) ptr = new_val;
3621}
3622
jeffhaobdb76512011-09-07 11:43:16 -07003623void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
3624 uint32_t insn_idx, VerifyError* failure) {
3625 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3626 LOG(ERROR) << "VFY: monitor-enter on non-object";
3627 *failure = VERIFY_ERROR_GENERIC;
3628 return;
3629 }
3630
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003631 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003632 return;
3633 }
3634
3635 if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
3636 LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
3637 << ")";
3638 *failure = VERIFY_ERROR_GENERIC;
3639 return;
3640 }
3641
3642 /*
3643 * Push an entry on the stack, and set a bit in the register flags to
3644 * indicate that it's associated with this register.
3645 */
3646 work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
3647 work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
3648}
3649
jeffhaobdb76512011-09-07 11:43:16 -07003650void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
3651 uint32_t insn_idx, VerifyError* failure) {
3652 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3653 LOG(ERROR) << "VFY: monitor-exit on non-object";
3654 *failure = VERIFY_ERROR_GENERIC;
3655 return;
3656 }
3657
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003658 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003659 return;
3660 }
3661
3662 if (work_line->monitor_stack_top_ == 0) {
3663 LOG(ERROR) << "VFY: monitor-exit stack underflow";
3664 *failure = VERIFY_ERROR_GENERIC;
3665 return;
3666 }
3667
3668 /*
3669 * Confirm that the entry at the top of the stack is associated with
jeffhaod1f0fde2011-09-08 17:25:33 -07003670 * the register. Pop the top entry off.
jeffhaobdb76512011-09-07 11:43:16 -07003671 */
3672 work_line->monitor_stack_top_--;
3673#ifdef BUG_3215458_FIXED
3674 /*
3675 * TODO: This code can safely be enabled if know we are working on
3676 * a dex file of format version 036 or later. (That is, we'll need to
3677 * add a check for the version number.)
3678 */
3679 if ((work_line->monitor_entries_[reg_idx] &
3680 (1 << work_line->monitor_stack_top_)) == 0) {
3681 LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
3682 << " not set: addr=0x" << std::hex << insn_idx << std::dec
3683 << " (bits[" << reg_idx << "]=" << std::hex
3684 << work_line->monitor_entries_[reg_idx] << std::dec << ")";
3685 *failure = VERIFY_ERROR_GENERIC;
3686 return;
3687 }
3688#endif
3689 work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;
3690
3691 /* Clear the bit from the register flags. */
3692 work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
3693}
3694
3695Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
3696 int field_idx, VerifyError* failure) {
3697 Method* method = vdata->method_;
3698 const DexFile* dex_file = vdata->dex_file_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003699 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003700 bool must_be_local = false;
3701
3702 if (!RegTypeIsReference(obj_type)) {
3703 LOG(ERROR) << "VFY: attempt to access field in non-reference type "
3704 << obj_type;
3705 *failure = VERIFY_ERROR_GENERIC;
jeffhaob4df5142011-09-19 20:25:32 -07003706 return NULL;
jeffhaobdb76512011-09-07 11:43:16 -07003707 }
3708
jeffhaob4df5142011-09-19 20:25:32 -07003709 Field* field = ResolveFieldAndCheckAccess(dex_file, field_idx,
3710 method->GetDeclaringClass(), failure, false);
jeffhaobdb76512011-09-07 11:43:16 -07003711 if (field == NULL) {
3712 LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
jeffhao2a8a90e2011-09-26 14:25:31 -07003713 return NULL;
jeffhaobdb76512011-09-07 11:43:16 -07003714 }
3715
3716 if (obj_type == kRegTypeZero)
3717 return field;
3718
3719 /*
3720 * Access to fields in uninitialized objects is allowed if this is
3721 * the <init> method for the object and the field in question is
3722 * declared by this class.
3723 */
jeffhaob4df5142011-09-19 20:25:32 -07003724 Class* obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003725 DCHECK(obj_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07003726 if (RegTypeIsUninitReference(obj_type)) {
3727 if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
3728 LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
3729 *failure = VERIFY_ERROR_GENERIC;
3730 return field;
3731 }
3732 must_be_local = true;
3733 }
3734
jeffhaobdb76512011-09-07 11:43:16 -07003735 if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
jeffhao2a8a90e2011-09-26 14:25:31 -07003736 LOG(ERROR) << "VFY: invalid field access (field " << PrettyField(field)
3737 << ", through " << obj_class->GetDescriptor()->ToModifiedUtf8()
3738 << " ref)";
jeffhaobdb76512011-09-07 11:43:16 -07003739 *failure = VERIFY_ERROR_NO_FIELD;
3740 return field;
3741 }
3742
3743 if (must_be_local) {
3744 bool found = false;
3745 /* for uninit ref, make sure it's defined by this class, not super */
3746 for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
3747 found |= (field == obj_class->GetInstanceField(i));
3748 }
3749 if (!found) {
3750 LOG(ERROR) << "VFY: invalid constructor field access (field "
3751 << field->GetName()->ToModifiedUtf8() << " in "
3752 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
3753 *failure = VERIFY_ERROR_GENERIC;
3754 return field;
3755 }
3756 }
3757
3758 return field;
3759}
3760
3761Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
3762 VerifyError* failure) {
3763 Method* method = vdata->method_;
3764 const DexFile* dex_file = vdata->dex_file_;
jeffhaob4df5142011-09-19 20:25:32 -07003765 Field* field = ResolveFieldAndCheckAccess(dex_file, field_idx,
3766 method->GetDeclaringClass(), failure, true);
jeffhaobdb76512011-09-07 11:43:16 -07003767 if (field == NULL) {
jeffhaob4df5142011-09-19 20:25:32 -07003768 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
3769 LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
3770 << dex_file->GetFieldName(field_id) << ") in "
3771 << dex_file->GetFieldClassDescriptor(field_id);
3772 *failure = VERIFY_ERROR_NO_FIELD;
jeffhaobdb76512011-09-07 11:43:16 -07003773 }
3774
3775 return field;
3776}
3777
3778Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
3779 VerifyError* failure) {
3780 const DexFile* dex_file = vdata->dex_file_;
3781 const DexFile::CodeItem* code_item = vdata->code_item_;
3782 Method* method = vdata->method_;
3783 Class* common_super = NULL;
3784 uint32_t handlers_size;
jeffhaoba5ebb92011-08-25 17:24:37 -07003785 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
jeffhao2a8a90e2011-09-26 14:25:31 -07003786 VerifyError local_failure;
jeffhaobdb76512011-09-07 11:43:16 -07003787
3788 if (code_item->tries_size_ != 0) {
3789 handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
3790 } else {
3791 handlers_size = 0;
3792 }
3793
3794 for (uint32_t i = 0; i < handlers_size; i++) {
jeffhaoba5ebb92011-08-25 17:24:37 -07003795 DexFile::CatchHandlerIterator iterator(handlers_ptr);
3796
3797 for (; !iterator.HasNext(); iterator.Next()) {
jeffhaobdb76512011-09-07 11:43:16 -07003798 DexFile::CatchHandlerItem handler = iterator.Get();
3799 if (handler.address_ == (uint32_t) insn_idx) {
3800 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3801 Class* klass;
jeffhaoba5ebb92011-08-25 17:24:37 -07003802
jeffhaobdb76512011-09-07 11:43:16 -07003803 if (handler.type_idx_ == DexFile::kDexNoIndex) {
3804 klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
3805 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003806 klass = ResolveClassAndCheckAccess(dex_file, handler.type_idx_,
jeffhao2a8a90e2011-09-26 14:25:31 -07003807 method->GetDeclaringClass(), &local_failure);
jeffhaobdb76512011-09-07 11:43:16 -07003808 }
3809
3810 if (klass == NULL) {
3811 LOG(ERROR) << "VFY: unable to resolve exception class "
3812 << handler.type_idx_ << " ("
3813 << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
jeffhaod1f0fde2011-09-08 17:25:33 -07003814 /* TODO: do we want to keep going? If we don't fail this we run
3815 * the risk of having a non-Throwable introduced at runtime.
3816 * However, that won't pass an instanceof test, so is essentially
3817 * harmless.
jeffhaobdb76512011-09-07 11:43:16 -07003818 */
3819 } else {
3820 if (common_super == NULL)
3821 common_super = klass;
3822 else
3823 common_super = FindCommonSuperclass(klass, common_super);
3824 }
3825 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003826 }
3827
3828 handlers_ptr = iterator.GetData();
3829 }
3830
jeffhaobdb76512011-09-07 11:43:16 -07003831 if (common_super == NULL) {
3832 /* no catch blocks, or no catches with classes we can find */
3833 LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
3834 << insn_idx << std::dec;
3835 *failure = VERIFY_ERROR_GENERIC;
3836 }
3837
3838 return common_super;
jeffhaoba5ebb92011-08-25 17:24:37 -07003839}
3840
jeffhaobdb76512011-09-07 11:43:16 -07003841DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
3842 const Method* method) {
3843 Class* klass = method->GetReturnType();
3844 if (klass->IsPrimitive())
3845 return PrimitiveTypeToRegType(klass->GetPrimitiveType());
3846 else
3847 return RegTypeFromClass(klass);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003848}
3849
jeffhaobdb76512011-09-07 11:43:16 -07003850Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
3851 uint32_t vsrc, VerifyError* failure) {
3852 /* get the element type of the array held in vsrc */
3853 RegType type = GetRegisterType(register_line, vsrc);
jeffhaoba5ebb92011-08-25 17:24:37 -07003854
jeffhaobdb76512011-09-07 11:43:16 -07003855 /* if "always zero", we allow it to fail at runtime */
3856 if (type == kRegTypeZero)
3857 return NULL;
3858
3859 if (!RegTypeIsReference(type)) {
3860 LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
3861 << " (type=" << type << ")",
3862 *failure = VERIFY_ERROR_GENERIC;
3863 return NULL;
3864 }
3865 if (RegTypeIsUninitReference(type)) {
3866 LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
3867 *failure = VERIFY_ERROR_GENERIC;
3868 return NULL;
jeffhaoba5ebb92011-08-25 17:24:37 -07003869 }
3870
jeffhaobdb76512011-09-07 11:43:16 -07003871 return RegTypeInitializedReferenceToClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003872}
3873
jeffhaobdb76512011-09-07 11:43:16 -07003874DexVerifier::RegType DexVerifier::GetInvocationThis(
3875 const RegisterLine* register_line,
3876 const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
3877 if (dec_insn->vA_ < 1) {
3878 LOG(ERROR) << "VFY: invoke lacks 'this'";
3879 *failure = VERIFY_ERROR_GENERIC;
3880 return kRegTypeUnknown;
jeffhaoba5ebb92011-08-25 17:24:37 -07003881 }
jeffhaobdb76512011-09-07 11:43:16 -07003882
3883 /* get the element type of the array held in vsrc */
3884 RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
3885 if (!RegTypeIsReference(this_type)) {
3886 LOG(ERROR) << "VFY: tried to get class from non-ref register v"
3887 << dec_insn->vC_ << " (type=" << this_type << ")";
3888 *failure = VERIFY_ERROR_GENERIC;
3889 return kRegTypeUnknown;
3890 }
3891
3892 return this_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003893}
3894
jeffhaobdb76512011-09-07 11:43:16 -07003895void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
3896 RegType new_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003897 RegType* insn_regs = register_line->reg_types_.get();
jeffhaoba5ebb92011-08-25 17:24:37 -07003898
jeffhaobdb76512011-09-07 11:43:16 -07003899 switch (new_type) {
3900 case kRegTypeUnknown:
3901 case kRegTypeBoolean:
3902 case kRegTypeOne:
3903 case kRegTypeConstByte:
3904 case kRegTypeConstPosByte:
3905 case kRegTypeConstShort:
3906 case kRegTypeConstPosShort:
3907 case kRegTypeConstChar:
3908 case kRegTypeConstInteger:
3909 case kRegTypeByte:
3910 case kRegTypePosByte:
3911 case kRegTypeShort:
3912 case kRegTypePosShort:
3913 case kRegTypeChar:
3914 case kRegTypeInteger:
3915 case kRegTypeFloat:
3916 case kRegTypeZero:
3917 case kRegTypeUninit:
3918 insn_regs[vdst] = new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003919 break;
jeffhaobdb76512011-09-07 11:43:16 -07003920 case kRegTypeConstLo:
3921 case kRegTypeLongLo:
3922 case kRegTypeDoubleLo:
3923 insn_regs[vdst] = new_type;
3924 insn_regs[vdst + 1] = new_type + 1;
3925 break;
3926 case kRegTypeConstHi:
3927 case kRegTypeLongHi:
3928 case kRegTypeDoubleHi:
3929 /* should never set these explicitly */
3930 LOG(FATAL) << "BUG: explicit set of high register type";
3931 break;
3932
3933 default:
3934 /* can't switch for ref types, so we check explicitly */
3935 if (RegTypeIsReference(new_type)) {
3936 insn_regs[vdst] = new_type;
3937
3938 /*
3939 * In most circumstances we won't see a reference to a primitive
3940 * class here (e.g. "D"), since that would mean the object in the
jeffhaod1f0fde2011-09-08 17:25:33 -07003941 * register is actually a primitive type. It can happen as the
jeffhaobdb76512011-09-07 11:43:16 -07003942 * result of an assumed-successful check-cast instruction in
jeffhaod1f0fde2011-09-08 17:25:33 -07003943 * which the second argument refers to a primitive class. (In
jeffhaobdb76512011-09-07 11:43:16 -07003944 * practice, such an instruction will always throw an exception.)
3945 *
3946 * This is not an issue for instructions like const-class, where
3947 * the object in the register is a java.lang.Class instance.
3948 */
3949 break;
3950 }
3951 /* bad type - fall through */
3952
3953 case kRegTypeConflict: // should only be set during a merge
3954 LOG(FATAL) << "BUG: set register to unknown type " << new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003955 break;
3956 }
3957
jeffhaobdb76512011-09-07 11:43:16 -07003958 /*
3959 * Clear the monitor entry bits for this register.
3960 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003961 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07003962 register_line->monitor_entries_[vdst] = 0;
3963}
3964
3965void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
3966 RegType check_type, VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003967 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003968 RegType src_type = insn_regs[vsrc];
3969
3970 switch (check_type) {
3971 case kRegTypeFloat:
3972 case kRegTypeBoolean:
3973 case kRegTypePosByte:
3974 case kRegTypeByte:
3975 case kRegTypePosShort:
3976 case kRegTypeShort:
3977 case kRegTypeChar:
3978 case kRegTypeInteger:
3979 if (!CanConvertTo1nr(src_type, check_type)) {
3980 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
3981 << ", wanted " << check_type;
3982 *failure = VERIFY_ERROR_GENERIC;
3983 }
3984 /* Update type if result is float */
3985 if (check_type == kRegTypeFloat) {
3986 SetRegisterType(register_line, vsrc, check_type);
3987 } else {
3988 /* Update const type to actual type after use */
3989 SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
3990 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003991 break;
jeffhaobdb76512011-09-07 11:43:16 -07003992 case kRegTypeLongLo:
3993 case kRegTypeDoubleLo:
3994 if (insn_regs[vsrc + 1] != src_type + 1) {
3995 LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
3996 << " values " << insn_regs[vsrc] << ","
3997 << insn_regs[vsrc + 1];
3998 *failure = VERIFY_ERROR_GENERIC;
3999 } else if (!CanConvertTo2(src_type, check_type)) {
4000 LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
4001 << ", wanted " << check_type;
4002 *failure = VERIFY_ERROR_GENERIC;
4003 }
4004 /* Update type if source is from const */
4005 if (src_type == kRegTypeConstLo) {
4006 SetRegisterType(register_line, vsrc, check_type);
4007 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004008 break;
jeffhaobdb76512011-09-07 11:43:16 -07004009 case kRegTypeConstLo:
4010 case kRegTypeConstHi:
4011 case kRegTypeLongHi:
4012 case kRegTypeDoubleHi:
4013 case kRegTypeZero:
4014 case kRegTypeOne:
4015 case kRegTypeUnknown:
4016 case kRegTypeConflict:
4017 /* should never be checking for these explicitly */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004018 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004019 *failure = VERIFY_ERROR_GENERIC;
4020 return;
4021 case kRegTypeUninit:
4022 default:
4023 /* make sure check_type is initialized reference */
4024 if (!RegTypeIsReference(check_type)) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004025 LOG(FATAL) << "VFY: unexpected check type " << check_type;
jeffhaobdb76512011-09-07 11:43:16 -07004026 *failure = VERIFY_ERROR_GENERIC;
4027 break;
4028 }
4029 if (RegTypeIsUninitReference(check_type)) {
4030 LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
4031 *failure = VERIFY_ERROR_GENERIC;
4032 break;
4033 }
4034 /* make sure src_type is initialized reference or always-NULL */
4035 if (!RegTypeIsReference(src_type)) {
4036 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4037 << ", wanted ref";
4038 *failure = VERIFY_ERROR_GENERIC;
4039 break;
4040 }
4041 if (RegTypeIsUninitReference(src_type)) {
4042 LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
4043 *failure = VERIFY_ERROR_GENERIC;
4044 break;
4045 }
4046 /* if the register isn't Zero, make sure it's an instance of check */
4047 if (src_type != kRegTypeZero) {
4048 Class* src_class = RegTypeInitializedReferenceToClass(src_type);
4049 Class* check_class = RegTypeInitializedReferenceToClass(check_type);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004050 DCHECK(src_class != NULL);
4051 DCHECK(check_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004052
jeffhaoe0cfb6f2011-09-22 16:42:56 -07004053 if (check_class->IsInterface()) {
4054 /*
4055 * All objects implement all interfaces as far as the verifier is
4056 * concerned. The runtime has to sort it out. See coments above
4057 * FindCommonSuperclass.
4058 */
4059 } else {
4060 if (!check_class->IsAssignableFrom(src_class)) {
4061 LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
4062 << " is not instance of "
4063 << check_class->GetDescriptor()->ToModifiedUtf8();
4064 *failure = VERIFY_ERROR_GENERIC;
4065 }
jeffhaobdb76512011-09-07 11:43:16 -07004066 }
4067 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004068 break;
4069 }
jeffhaobdb76512011-09-07 11:43:16 -07004070}
jeffhaoba5ebb92011-08-25 17:24:37 -07004071
jeffhaobdb76512011-09-07 11:43:16 -07004072void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
4073 const int insn_reg_count, RegType new_type) {
4074 SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
4075}
4076
4077void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
4078 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
4079 VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004080 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004081 Class* klass = GetUninitInstance(uninit_map,
4082 RegTypeToUninitIndex(uninit_type));
4083
4084 if (klass == NULL) {
4085 LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
4086 << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
4087 << ")";
4088 *failure = VERIFY_ERROR_GENERIC;
4089 return;
jeffhaoba5ebb92011-08-25 17:24:37 -07004090 }
4091
jeffhaobdb76512011-09-07 11:43:16 -07004092 RegType init_type = RegTypeFromClass(klass);
4093 int changed = 0;
4094 for (int i = 0; i < insn_reg_count; i++) {
4095 if (insn_regs[i] == uninit_type) {
4096 insn_regs[i] = init_type;
4097 changed++;
4098 }
4099 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004100 DCHECK_GT(changed, 0);
jeffhaobdb76512011-09-07 11:43:16 -07004101
4102 return;
4103}
4104
4105void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
4106 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004107 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004108
4109 for (int i = 0; i < insn_reg_count; i++) {
4110 if (insn_regs[i] == uninit_type) {
4111 insn_regs[i] = kRegTypeConflict;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004112 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004113 register_line->monitor_entries_[i] = 0;
4114 }
4115 }
4116}
4117
4118void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
4119 uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004120 DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
jeffhaobdb76512011-09-07 11:43:16 -07004121 RegType type = GetRegisterType(register_line, vsrc);
4122 CheckTypeCategory(type, cat, failure);
4123 if (*failure != VERIFY_ERROR_NONE) {
4124 LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
4125 << " cat=" << (int) cat;
4126 } else {
4127 SetRegisterType(register_line, vdst, type);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004128 if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07004129 register_line->monitor_entries_[vdst] =
4130 register_line->monitor_entries_[vsrc];
4131 }
4132 }
4133}
4134
4135void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
4136 uint32_t vsrc, VerifyError* failure) {
4137 RegType type_l = GetRegisterType(register_line, vsrc);
4138 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4139
4140 CheckTypeCategory(type_l, kTypeCategory2, failure);
4141 CheckWidePair(type_l, type_h, failure);
4142 if (*failure != VERIFY_ERROR_NONE) {
4143 LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
4144 << "/" << type_h;
4145 } else {
4146 SetRegisterType(register_line, vdst, type_l);
4147 }
4148}
4149
4150void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
4151 const int insn_reg_count, uint32_t vdst, TypeCategory cat,
4152 VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004153 DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
jeffhaobdb76512011-09-07 11:43:16 -07004154
4155 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4156 RegType type = GetRegisterType(register_line, vsrc);
4157 CheckTypeCategory(type, cat, failure);
4158 if (*failure != VERIFY_ERROR_NONE) {
4159 LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
4160 << (int) cat << " type=" << type;
4161 } else {
4162 SetRegisterType(register_line, vdst, type);
4163 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4164 }
4165}
4166
4167/*
jeffhaod1f0fde2011-09-08 17:25:33 -07004168 * Implement "move-result-wide". Copy the category-2 value from the result
jeffhaobdb76512011-09-07 11:43:16 -07004169 * register to another register, and reset the result register.
4170 */
4171void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
4172 const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004173 DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
jeffhaobdb76512011-09-07 11:43:16 -07004174
4175 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4176 RegType type_l = GetRegisterType(register_line, vsrc);
4177 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4178 CheckTypeCategory(type_l, kTypeCategory2, failure);
4179 CheckWidePair(type_l, type_h, failure);
4180 if (*failure != VERIFY_ERROR_NONE) {
4181 LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
4182 << type_l << "/" << type_h;
4183 } else {
4184 SetRegisterType(register_line, vdst, type_l);
4185 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4186 SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
4187 }
4188}
4189
4190int DexVerifier::GetClassDepth(Class* klass) {
4191 int depth = 0;
4192 while (klass->GetSuperClass() != NULL) {
4193 klass = klass->GetSuperClass();
4194 depth++;
4195 }
4196 return depth;
4197}
4198
4199Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
4200 int depth1, depth2;
4201
4202 depth1 = GetClassDepth(c1);
4203 depth2 = GetClassDepth(c2);
4204
4205 /* pull the deepest one up */
4206 if (depth1 > depth2) {
4207 while (depth1 > depth2) {
4208 c1 = c1->GetSuperClass();
4209 depth1--;
4210 }
4211 } else {
4212 while (depth2 > depth1) {
4213 c2 = c2->GetSuperClass();
4214 depth2--;
4215 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004216 }
4217
jeffhaobdb76512011-09-07 11:43:16 -07004218 /* walk up in lock-step */
4219 while (c1 != c2) {
4220 c1 = c1->GetSuperClass();
4221 c2 = c2->GetSuperClass();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004222 DCHECK(c1 != NULL);
4223 DCHECK(c2 != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004224 }
4225
4226 return c1;
4227}
4228
4229Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004230 DCHECK(c1->IsArrayClass());
4231 DCHECK(c2->IsArrayClass());
4232 Class* e1 = c1->GetComponentType();
4233 Class* e2 = c2->GetComponentType();
4234 if (e1->IsPrimitive() || e2->IsPrimitive()) {
4235 return c1->GetSuperClass(); // == java.lang.Object
jeffhaobdb76512011-09-07 11:43:16 -07004236 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004237 Class* common_elem = FindCommonSuperclass(c1->GetComponentType(), c2->GetComponentType());
4238 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4239 const ClassLoader* class_loader = c1->GetClassLoader();
4240 std::string descriptor = "[" + common_elem->GetDescriptor()->ToModifiedUtf8();
4241 Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
4242 DCHECK(array_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004243 return array_class;
4244}
4245
4246Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004247 DCHECK(!c1->IsPrimitive()) << PrettyClass(c1);
4248 DCHECK(!c2->IsPrimitive()) << PrettyClass(c2);
jeffhaobdb76512011-09-07 11:43:16 -07004249
4250 if (c1 == c2)
4251 return c1;
4252
jeffhao5dbddee2011-09-07 16:38:26 -07004253 if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
jeffhaobdb76512011-09-07 11:43:16 -07004254 return c1;
4255 }
jeffhao5dbddee2011-09-07 16:38:26 -07004256 if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
jeffhaobdb76512011-09-07 11:43:16 -07004257 return c2;
4258 }
4259 if (c1->IsArrayClass() && c2->IsArrayClass()) {
4260 return FindCommonArraySuperclass(c1, c2);
4261 }
4262
4263 return DigForSuperclass(c1, c2);
4264}
4265
jeffhao98eacac2011-09-14 16:11:53 -07004266Class* DexVerifier::ResolveClassAndCheckAccess(const DexFile* dex_file,
jeffhaob4df5142011-09-19 20:25:32 -07004267 uint32_t class_idx, const Class* referrer, VerifyError* failure) {
jeffhao98eacac2011-09-14 16:11:53 -07004268 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4269 Class* res_class = class_linker->ResolveType(*dex_file, class_idx, referrer);
4270
4271 if (res_class == NULL) {
buzbeec0ecd652011-09-25 18:11:54 -07004272 Thread::Current()->ClearException();
jeffhaoe0cfb6f2011-09-22 16:42:56 -07004273 LOG(ERROR) << "VFY: can't find class with index 0x" << std::hex << class_idx << std::dec;
jeffhao2a8a90e2011-09-26 14:25:31 -07004274 *failure = VERIFY_ERROR_NO_CLASS;
jeffhao98eacac2011-09-14 16:11:53 -07004275 return NULL;
4276 }
4277
4278 /* Check if access is allowed. */
4279 if (!referrer->CanAccess(res_class)) {
4280 LOG(ERROR) << "VFY: illegal class access: "
4281 << referrer->GetDescriptor()->ToModifiedUtf8() << " -> "
4282 << res_class->GetDescriptor()->ToModifiedUtf8();
4283 *failure = VERIFY_ERROR_ACCESS_CLASS;
4284 return NULL;
4285 }
4286
4287 return res_class;
4288}
4289
jeffhaob4df5142011-09-19 20:25:32 -07004290Method* DexVerifier::ResolveMethodAndCheckAccess(const DexFile* dex_file,
4291 uint32_t method_idx, const Class* referrer, VerifyError* failure,
4292 bool is_direct) {
4293 DexCache* dex_cache = referrer->GetDexCache();
4294 Method* res_method = dex_cache->GetResolvedMethod(method_idx);
4295
4296 if (res_method == NULL) {
4297 const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
4298 Class* klass = ResolveClassAndCheckAccess(dex_file, method_id.class_idx_, referrer, failure);
4299 if (klass == NULL) {
4300 DCHECK(*failure != VERIFY_ERROR_NONE);
4301 return NULL;
4302 }
4303
4304 const char* name = dex_file->dexStringById(method_id.name_idx_);
4305 std::string signature(dex_file->CreateMethodDescriptor(method_id.proto_idx_, NULL));
4306 if (is_direct) {
4307 res_method = klass->FindDirectMethod(name, signature);
4308 } else if (klass->IsInterface()) {
4309 res_method = klass->FindInterfaceMethod(name, signature);
4310 } else {
4311 res_method = klass->FindVirtualMethod(name, signature);
4312 }
4313 if (res_method != NULL) {
4314 dex_cache->SetResolvedMethod(method_idx, res_method);
4315 } else {
4316 LOG(ERROR) << "VFY: couldn't find method "
4317 << klass->GetDescriptor()->ToModifiedUtf8() << "." << name
4318 << " " << signature;
4319 *failure = VERIFY_ERROR_NO_METHOD;
4320 return NULL;
4321 }
4322 }
4323
4324 /* Check if access is allowed. */
jeffhao4a801a42011-09-23 13:53:40 -07004325 if (!referrer->CanAccessMember(res_method->GetDeclaringClass(), res_method->GetAccessFlags())) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004326 LOG(ERROR) << "VFY: illegal method access (call " << PrettyMethod(res_method)
4327 << " from " << referrer->GetDescriptor()->ToModifiedUtf8() << ")";
jeffhaob4df5142011-09-19 20:25:32 -07004328 *failure = VERIFY_ERROR_ACCESS_METHOD;
4329 return NULL;
4330 }
4331
4332 return res_method;
4333}
4334
4335Field* DexVerifier::ResolveFieldAndCheckAccess(const DexFile* dex_file,
4336 uint32_t field_idx, const Class* referrer, VerifyError* failure,
4337 bool is_static) {
4338 DexCache* dex_cache = referrer->GetDexCache();
4339 Field* res_field = dex_cache->GetResolvedField(field_idx);
4340
4341 if (res_field == NULL) {
4342 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
4343 Class* klass = ResolveClassAndCheckAccess(dex_file, field_id.class_idx_, referrer, failure);
4344 if (klass == NULL) {
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004345 DCHECK(*failure != VERIFY_ERROR_NONE) << PrettyClass(referrer);
jeffhaob4df5142011-09-19 20:25:32 -07004346 return NULL;
4347 }
4348
4349 Class* field_type = ResolveClassAndCheckAccess(dex_file, field_id.type_idx_, referrer, failure);
4350 if (field_type == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004351 DCHECK(*failure != VERIFY_ERROR_NONE) << PrettyClass(referrer) << " " << PrettyClass(klass);
jeffhaob4df5142011-09-19 20:25:32 -07004352 return NULL;
4353 }
4354
4355 const char* name = dex_file->dexStringById(field_id.name_idx_);
4356 if (is_static) {
4357 res_field = klass->FindStaticField(name, field_type);
4358 } else {
4359 res_field = klass->FindInstanceField(name, field_type);
4360 }
4361 if (res_field != NULL) {
Elliott Hughes4a2b4172011-09-20 17:08:25 -07004362 dex_cache->SetResolvedField(field_idx, res_field);
jeffhaob4df5142011-09-19 20:25:32 -07004363 } else {
4364 LOG(ERROR) << "VFY: couldn't find field "
4365 << klass->GetDescriptor()->ToModifiedUtf8() << "." << name;
4366 *failure = VERIFY_ERROR_NO_FIELD;
4367 return NULL;
4368 }
4369 }
4370
4371 /* Check if access is allowed. */
jeffhao4a801a42011-09-23 13:53:40 -07004372 if (!referrer->CanAccessMember(res_field->GetDeclaringClass(), res_field->GetAccessFlags())) {
jeffhaob4df5142011-09-19 20:25:32 -07004373 LOG(ERROR) << "VFY: access denied from "
4374 << referrer->GetDescriptor()->ToModifiedUtf8() << " to field "
jeffhao2a8a90e2011-09-26 14:25:31 -07004375 << PrettyField(res_field);
jeffhaob4df5142011-09-19 20:25:32 -07004376 *failure = VERIFY_ERROR_ACCESS_FIELD;
4377 return NULL;
4378 }
4379
4380 return res_field;
4381}
4382
jeffhaobdb76512011-09-07 11:43:16 -07004383DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
4384 bool* changed) {
4385 RegType result;
4386
jeffhao98eacac2011-09-14 16:11:53 -07004387 /* Check for trivial case so we don't have to hit memory. */
jeffhaobdb76512011-09-07 11:43:16 -07004388 if (type1 == type2)
4389 return type1;
4390
4391 /*
4392 * Use the table if we can, and reject any attempts to merge something
4393 * from the table with a reference type.
4394 *
4395 * Uninitialized references are composed of the enum ORed with an
jeffhaod1f0fde2011-09-08 17:25:33 -07004396 * index value. The uninitialized table entry at index zero *will*
4397 * show up as a simple kRegTypeUninit value. Since this cannot be
jeffhaobdb76512011-09-07 11:43:16 -07004398 * merged with anything but itself, the rules do the right thing.
4399 */
4400 if (type1 < kRegTypeMAX) {
4401 if (type2 < kRegTypeMAX) {
4402 result = merge_table_[type1][type2];
4403 } else {
4404 /* simple + reference == conflict, usually */
4405 if (type1 == kRegTypeZero)
4406 result = type2;
4407 else
4408 result = kRegTypeConflict;
4409 }
4410 } else {
4411 if (type2 < kRegTypeMAX) {
4412 /* reference + simple == conflict, usually */
4413 if (type2 == kRegTypeZero)
4414 result = type1;
4415 else
4416 result = kRegTypeConflict;
4417 } else {
4418 /* merging two references */
4419 if (RegTypeIsUninitReference(type1) ||
4420 RegTypeIsUninitReference(type2))
4421 {
4422 /* can't merge uninit with anything but self */
4423 result = kRegTypeConflict;
4424 } else {
4425 Class* klass1 = RegTypeInitializedReferenceToClass(type1);
4426 Class* klass2 = RegTypeInitializedReferenceToClass(type2);
4427 Class* merged_class = FindCommonSuperclass(klass1, klass2);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004428 DCHECK(merged_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004429 result = RegTypeFromClass(merged_class);
4430 }
4431 }
4432 }
4433
4434 if (result != type1)
4435 *changed = true;
jeffhaoba5ebb92011-08-25 17:24:37 -07004436 return result;
jeffhaobdb76512011-09-07 11:43:16 -07004437}
4438
4439DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
4440 MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
4441 MonitorEntries result = ents1 & ents2;
4442 if (result != ents1)
4443 *changed = true;
4444 return result;
4445}
4446
4447bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
4448 RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
4449 const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004450 DCHECK(work_line != NULL);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004451 const RegType* work_regs = work_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004452
4453 if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
4454 /*
4455 * We haven't processed this instruction before, and we haven't
jeffhaod1f0fde2011-09-08 17:25:33 -07004456 * touched the registers here, so there's nothing to "merge". Copy
4457 * the registers over and mark it as changed. (This is the only
jeffhaobdb76512011-09-07 11:43:16 -07004458 * way a register can transition out of "unknown", so this is not
4459 * just an optimization.)
4460 */
4461 CopyLineToTable(reg_table, next_insn, work_line);
4462 InsnSetChanged(insn_flags, next_insn, true);
4463 } else {
4464 /* Merge registers, set Changed only if different */
4465 RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004466 RegType* target_regs = target_line->reg_types_.get();
4467 MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
4468 MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004469 bool changed = false;
4470 unsigned int idx;
4471
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004472 DCHECK(target_regs != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004473 if (target_mon_ents != NULL) {
4474 /* Monitor stacks must be identical. */
4475 if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
4476 LOG(ERROR) << "VFY: mismatched stack depth "
4477 << target_line->monitor_stack_top_ << " vs. "
4478 << work_line->monitor_stack_top_ << " at 0x"
4479 << std::hex << next_insn << std::dec;
4480 return false;
4481 }
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004482 if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
jeffhaobdb76512011-09-07 11:43:16 -07004483 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
4484 LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
4485 << next_insn << std::dec;
4486 return false;
4487 }
4488 }
4489
4490 for (idx = 0; idx < insn_reg_count_plus; idx++) {
4491 target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);
4492
4493 if (target_mon_ents != NULL) {
4494 target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
4495 work_mon_ents[idx], &changed);
4496 }
4497 }
4498
4499 if (changed) {
4500 InsnSetChanged(insn_flags, next_insn, true);
4501 }
4502 }
4503
4504 return true;
4505}
4506
4507bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
4508 static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
4509 [kRegType1nrEND - kRegType1nrSTART + 1] =
4510 {
4511 /* chk: 0 1 Z y Y h H c i b B s S C I F */
4512 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4513 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4514 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
4515 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4516 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
4517 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
4518 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
4519 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
4520 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
4521 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
4522 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
4523 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
4524 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
4525 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
4526 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
4527 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
4528 };
4529
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004530 DCHECK(check_type >= kRegType1nrSTART);
4531 DCHECK(check_type <= kRegType1nrEND);
jeffhaobdb76512011-09-07 11:43:16 -07004532
4533 if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
4534 return (bool) conv_tab[src_type - kRegType1nrSTART]
4535 [check_type - kRegType1nrSTART];
4536
4537 return false;
4538}
4539
4540bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
4541 return ((src_type == kRegTypeConstLo || src_type == check_type) &&
4542 (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
4543}
4544
4545DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
4546 Class::PrimitiveType prim_type) {
4547 switch (prim_type) {
4548 case Class::kPrimBoolean: return kRegTypeBoolean;
4549 case Class::kPrimByte: return kRegTypeByte;
4550 case Class::kPrimShort: return kRegTypeShort;
4551 case Class::kPrimChar: return kRegTypeChar;
4552 case Class::kPrimInt: return kRegTypeInteger;
4553 case Class::kPrimLong: return kRegTypeLongLo;
4554 case Class::kPrimFloat: return kRegTypeFloat;
4555 case Class::kPrimDouble: return kRegTypeDoubleLo;
4556 case Class::kPrimVoid:
4557 default: {
4558 return kRegTypeUnknown;
4559 }
4560 }
4561}
4562
4563DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
4564 switch (const_type) {
4565 case kRegTypeConstPosByte: return kRegTypePosByte;
4566 case kRegTypeConstByte: return kRegTypeByte;
4567 case kRegTypeConstPosShort: return kRegTypePosShort;
4568 case kRegTypeConstShort: return kRegTypeShort;
4569 case kRegTypeConstChar: return kRegTypeChar;
4570 case kRegTypeConstInteger: return kRegTypeInteger;
4571 default: {
4572 return const_type;
4573 }
4574 }
4575}
4576
4577char DexVerifier::DetermineCat1Const(int32_t value) {
4578 if (value < -32768)
4579 return kRegTypeConstInteger;
4580 else if (value < -128)
4581 return kRegTypeConstShort;
4582 else if (value < 0)
4583 return kRegTypeConstByte;
4584 else if (value == 0)
4585 return kRegTypeZero;
4586 else if (value == 1)
4587 return kRegTypeOne;
4588 else if (value < 128)
4589 return kRegTypeConstPosByte;
4590 else if (value < 32768)
4591 return kRegTypeConstPosShort;
4592 else if (value < 65536)
4593 return kRegTypeConstChar;
4594 else
4595 return kRegTypeConstInteger;
4596}
4597
4598void DexVerifier::CheckFinalFieldAccess(const Method* method,
4599 const Field* field, VerifyError* failure) {
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004600 DCHECK(field != NULL);
4601 if (!field->IsFinal()) {
jeffhaobdb76512011-09-07 11:43:16 -07004602 return;
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004603 }
jeffhaobdb76512011-09-07 11:43:16 -07004604
4605 /* make sure we're in the same class */
4606 if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004607 LOG(ERROR) << "VFY: can't modify final field " << PrettyField(field);
jeffhaobdb76512011-09-07 11:43:16 -07004608 *failure = VERIFY_ERROR_ACCESS_FIELD;
4609 return;
4610 }
4611}
4612
4613void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
4614 VerifyError* failure) {
4615 if (*failure == VERIFY_ERROR_NONE) {
4616 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004617 * The 1nr types are interchangeable at this level. We could
jeffhaobdb76512011-09-07 11:43:16 -07004618 * do something special if we can definitively identify it as a
4619 * float, but there's no real value in doing so.
4620 */
4621 CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
4622 if (*failure != VERIFY_ERROR_NONE) {
4623 LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
4624 }
4625 }
4626}
4627
4628bool DexVerifier::CheckConstructorReturn(const Method* method,
4629 const RegisterLine* register_line, const int insn_reg_count) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004630 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004631
4632 if (!IsInitMethod(method))
4633 return true;
4634
4635 RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);
4636
4637 for (int i = 0; i < insn_reg_count; i++) {
4638 if (insn_regs[i] == uninit_this) {
4639 LOG(ERROR) << "VFY: <init> returning without calling superclass init";
4640 return false;
4641 }
4642 }
4643 return true;
4644}
4645
4646bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
4647 if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
4648 LOG(ERROR) << "VFY: invalid use of move-exception";
4649 return false;
4650 }
4651 return true;
4652}
4653
4654void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
4655 VerifyError* failure) {
4656 switch (cat) {
4657 case kTypeCategory1nr:
4658 switch (type) {
4659 case kRegTypeZero:
4660 case kRegTypeOne:
4661 case kRegTypeBoolean:
4662 case kRegTypeConstPosByte:
4663 case kRegTypeConstByte:
4664 case kRegTypeConstPosShort:
4665 case kRegTypeConstShort:
4666 case kRegTypeConstChar:
4667 case kRegTypeConstInteger:
4668 case kRegTypePosByte:
4669 case kRegTypeByte:
4670 case kRegTypePosShort:
4671 case kRegTypeShort:
4672 case kRegTypeChar:
4673 case kRegTypeInteger:
4674 case kRegTypeFloat:
4675 break;
4676 default:
4677 *failure = VERIFY_ERROR_GENERIC;
4678 break;
4679 }
4680 break;
4681 case kTypeCategory2:
4682 switch (type) {
4683 case kRegTypeConstLo:
4684 case kRegTypeLongLo:
4685 case kRegTypeDoubleLo:
4686 break;
4687 default:
4688 *failure = VERIFY_ERROR_GENERIC;
4689 break;
4690 }
4691 break;
4692 case kTypeCategoryRef:
4693 if (type != kRegTypeZero && !RegTypeIsReference(type))
4694 *failure = VERIFY_ERROR_GENERIC;
4695 break;
4696 default:
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004697 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004698 *failure = VERIFY_ERROR_GENERIC;
4699 break;
4700 }
4701}
4702
4703void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
4704 VerifyError* failure) {
4705 if ((type_h != type_l + 1))
4706 *failure = VERIFY_ERROR_GENERIC;
4707}
4708
4709void DexVerifier::CheckUnop(RegisterLine* register_line,
4710 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4711 RegType src_type, VerifyError* failure) {
4712 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4713 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4714}
4715
4716bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
4717 uint32_t reg2) {
4718 RegType type1, type2;
4719
4720 type1 = GetRegisterType(register_line, reg1);
4721 type2 = GetRegisterType(register_line, reg2);
4722
4723 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
4724 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
4725 return true;
4726 }
4727 return false;
4728}
4729
4730void DexVerifier::CheckLitop(RegisterLine* register_line,
4731 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4732 RegType src_type, bool check_boolean_op, VerifyError* failure) {
4733 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4734
4735 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004736 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004737
4738 /* check vB with the call, then check the constant manually */
4739 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
4740 && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
4741 dst_type = kRegTypeBoolean;
4742 }
4743 }
4744
4745 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4746}
4747
4748void DexVerifier::CheckBinop(RegisterLine* register_line,
4749 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4750 RegType src_type1, RegType src_type2, bool check_boolean_op,
4751 VerifyError* failure) {
4752 VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
4753 VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
4754
4755 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004756 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004757 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
4758 dst_type = kRegTypeBoolean;
4759 }
4760
4761 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4762}
4763
4764void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
4765 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4766 RegType src_type1, RegType src_type2, bool check_boolean_op,
4767 VerifyError* failure) {
4768 VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
4769 VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
4770
4771 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004772 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004773 if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
4774 dst_type = kRegTypeBoolean;
4775 }
4776
4777 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4778}
4779
4780DexVerifier::RegType DexVerifier::AdjustForRightShift(
4781 RegisterLine* register_line, int reg, unsigned int shift_count,
jeffhaob4df5142011-09-19 20:25:32 -07004782 bool is_unsigned_shift) {
jeffhaobdb76512011-09-07 11:43:16 -07004783 RegType src_type = GetRegisterType(register_line, reg);
4784 RegType new_type;
4785
4786 /* convert const derived types to their actual types */
4787 src_type = ConstTypeToRegType(src_type);
4788
4789 /* no-op */
4790 if (shift_count == 0)
4791 return src_type;
4792
4793 /* safe defaults */
4794 if (is_unsigned_shift)
4795 new_type = kRegTypeInteger;
4796 else
4797 new_type = src_type;
4798
4799 if (shift_count >= 32) {
4800 LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
4801 /* fail? */
4802 return new_type;
4803 }
4804
4805 switch (src_type) {
4806 case kRegTypeInteger: /* 32-bit signed value */
4807 if (is_unsigned_shift) {
4808 if (shift_count > 24)
4809 new_type = kRegTypePosByte;
4810 else if (shift_count >= 16)
4811 new_type = kRegTypeChar;
4812 } else {
4813 if (shift_count >= 24)
4814 new_type = kRegTypeByte;
4815 else if (shift_count >= 16)
4816 new_type = kRegTypeShort;
4817 }
4818 break;
4819 case kRegTypeShort: /* 16-bit signed value */
4820 if (is_unsigned_shift) {
4821 /* default (kRegTypeInteger) is correct */
4822 } else {
4823 if (shift_count >= 8)
4824 new_type = kRegTypeByte;
4825 }
4826 break;
4827 case kRegTypePosShort: /* 15-bit unsigned value */
4828 if (shift_count >= 8)
4829 new_type = kRegTypePosByte;
4830 break;
4831 case kRegTypeChar: /* 16-bit unsigned value */
4832 if (shift_count > 8)
4833 new_type = kRegTypePosByte;
4834 break;
4835 case kRegTypeByte: /* 8-bit signed value */
4836 /* defaults (u=kRegTypeInteger / s=src_type) are correct */
4837 break;
4838 case kRegTypePosByte: /* 7-bit unsigned value */
4839 /* always use new_type=src_type */
4840 new_type = src_type;
4841 break;
4842 case kRegTypeZero: /* 1-bit unsigned value */
4843 case kRegTypeOne:
4844 case kRegTypeBoolean:
4845 /* unnecessary? */
4846 new_type = kRegTypeZero;
4847 break;
4848 default:
4849 /* long, double, references; shouldn't be here! */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004850 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004851 break;
4852 }
4853
4854 return new_type;
4855}
4856
4857void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
4858 RegisterLine* register_line,
4859 const Instruction::DecodedInstruction* dec_insn, Class* res_class,
4860 bool is_range, VerifyError* failure) {
4861 uint32_t arg_count = dec_insn->vA_;
4862 RegType expected_type;
4863 Class::PrimitiveType elem_type;
4864 unsigned int ui;
4865
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004866 DCHECK(res_class->IsArrayClass()) << PrettyClass(res_class);
jeffhaobdb76512011-09-07 11:43:16 -07004867 elem_type = res_class->GetComponentType()->GetPrimitiveType();
4868 if (elem_type == Class::kPrimNot) {
4869 expected_type = RegTypeFromClass(res_class->GetComponentType());
4870 } else {
4871 expected_type = PrimitiveTypeToRegType(elem_type);
4872 }
4873
4874 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004875 * Verify each register. If "arg_count" is bad, VerifyRegisterType()
4876 * will run off the end of the list and fail. It's legal, if silly,
jeffhaobdb76512011-09-07 11:43:16 -07004877 * for arg_count to be zero.
4878 */
4879 for (ui = 0; ui < arg_count; ui++) {
4880 uint32_t get_reg;
4881
4882 if (is_range)
4883 get_reg = dec_insn->vC_ + ui;
4884 else
4885 get_reg = dec_insn->arg_[ui];
4886
4887 VerifyRegisterType(register_line, get_reg, expected_type, failure);
4888 if (*failure != VERIFY_ERROR_NONE) {
4889 LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
4890 << ") not valid";
4891 return;
4892 }
4893 }
4894}
4895
4896bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
4897 Method* res_method) {
4898 switch (method_type) {
4899 case METHOD_DIRECT:
4900 return res_method->IsDirect();
4901 case METHOD_STATIC:
4902 return res_method->IsStatic();
4903 case METHOD_VIRTUAL:
4904 case METHOD_INTERFACE:
4905 return !res_method->IsDirect();
4906 default:
4907 return false;
4908 }
4909}
4910
4911Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
4912 RegisterLine* register_line, const int insn_reg_count,
4913 const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
4914 bool is_range, bool is_super, VerifyError* failure) {
4915 Method* method = vdata->method_;
4916 const DexFile* dex_file = vdata->dex_file_;
4917 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004918 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004919
4920 Method* res_method;
4921 std::string sig;
4922 size_t sig_offset;
4923 int expected_args;
4924 int actual_args;
4925
4926 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004927 * Resolve the method. This could be an abstract or concrete method
jeffhaobdb76512011-09-07 11:43:16 -07004928 * depending on what sort of call we're making.
4929 */
jeffhaob4df5142011-09-19 20:25:32 -07004930 res_method = ResolveMethodAndCheckAccess(dex_file, dec_insn->vB_, method->GetDeclaringClass(),
4931 failure, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
jeffhaobdb76512011-09-07 11:43:16 -07004932
jeffhaobdb76512011-09-07 11:43:16 -07004933 if (res_method == NULL) {
jeffhao98eacac2011-09-14 16:11:53 -07004934 const DexFile::MethodId& method_id = dex_file->GetMethodId(dec_insn->vB_);
4935 const char* method_name = dex_file->GetMethodName(method_id);
Brian Carlstromaded5f72011-10-07 17:15:04 -07004936 std::string method_signature = dex_file->GetMethodSignature(method_id);
jeffhao98eacac2011-09-14 16:11:53 -07004937 const char* class_descriptor = dex_file->GetMethodClassDescriptor(method_id);
4938
4939 LOG(ERROR) << "VFY: unable to resolve method " << dec_insn->vB_ << ": "
Brian Carlstromaded5f72011-10-07 17:15:04 -07004940 << class_descriptor << "." << method_name << " " << method_signature;
jeffhaobdb76512011-09-07 11:43:16 -07004941 return NULL;
4942 }
jeffhaobdb76512011-09-07 11:43:16 -07004943
4944 /*
jeffhao2a8a90e2011-09-26 14:25:31 -07004945 * Make sure calls to "<init>" are "direct". There are additional restrictions
4946 * but we don't enfore them here.
jeffhaobdb76512011-09-07 11:43:16 -07004947 */
jeffhao2a8a90e2011-09-26 14:25:31 -07004948 if (res_method->GetName()->Equals("<init>") && method_type != METHOD_DIRECT) {
4949 LOG(ERROR) << "VFY: invalid call to " << PrettyMethod(res_method);
4950 goto bad_sig;
jeffhaobdb76512011-09-07 11:43:16 -07004951 }
4952
4953 /*
4954 * See if the method type implied by the invoke instruction matches the
4955 * access flags for the target method.
4956 */
4957 if (!IsCorrectInvokeKind(method_type, res_method)) {
4958 LOG(ERROR) << "VFY: invoke type does not match method type of "
jeffhao2a8a90e2011-09-26 14:25:31 -07004959 << PrettyMethod(res_method);
jeffhaobdb76512011-09-07 11:43:16 -07004960 *failure = VERIFY_ERROR_GENERIC;
4961 return NULL;
4962 }
4963
4964 /*
4965 * If we're using invoke-super(method), make sure that the executing
4966 * method's class' superclass has a vtable entry for the target method.
4967 */
4968 if (is_super) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004969 DCHECK(method_type == METHOD_VIRTUAL);
jeffhaobdb76512011-09-07 11:43:16 -07004970 Class* super = method->GetDeclaringClass()->GetSuperClass();
4971 if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
4972 if (super == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004973 LOG(ERROR) << "VFY: invalid invoke-super from " << PrettyMethod(method)
4974 << " to super -." << res_method->GetName()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07004975 << " " << res_method->GetSignature()->ToModifiedUtf8();
4976 } else {
jeffhao2a8a90e2011-09-26 14:25:31 -07004977 LOG(ERROR) << "VFY: invalid invoke-super from " << PrettyMethod(method)
4978 << " to super " << super->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07004979 << "." << res_method->GetName()->ToModifiedUtf8()
4980 << " " << res_method->GetSignature()->ToModifiedUtf8();
4981 }
4982 *failure = VERIFY_ERROR_NO_METHOD;
4983 return NULL;
4984 }
4985 }
4986
4987 /*
4988 * We use vAA as our expected arg count, rather than res_method->insSize,
jeffhaod1f0fde2011-09-08 17:25:33 -07004989 * because we need to match the call to the signature. Also, we might
jeffhaobdb76512011-09-07 11:43:16 -07004990 * might be calling through an abstract method definition (which doesn't
4991 * have register count values).
4992 */
4993 expected_args = dec_insn->vA_;
4994 actual_args = 0;
4995
4996 /* caught by static verifier */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004997 DCHECK(is_range || expected_args <= 5);
jeffhaobdb76512011-09-07 11:43:16 -07004998
4999 if (expected_args > code_item->outs_size_) {
5000 LOG(ERROR) << "VFY: invalid arg count (" << expected_args
5001 << ") exceeds outsSize (" << code_item->outs_size_ << ")";
5002 *failure = VERIFY_ERROR_GENERIC;
5003 return NULL;
5004 }
5005
5006 sig = res_method->GetSignature()->ToModifiedUtf8();
5007 if (sig[0] != '(') {
5008 LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
5009 goto bad_sig;
5010 }
5011
5012 /*
5013 * Check the "this" argument, which must be an instance of the class
jeffhaod1f0fde2011-09-08 17:25:33 -07005014 * that declared the method. For an interface class, we don't do the
jeffhaobdb76512011-09-07 11:43:16 -07005015 * full interface merge, so we can't do a rigorous check here (which
5016 * is okay since we have to do it at runtime).
5017 */
5018 if (!res_method->IsStatic()) {
5019 Class* actual_this_ref;
5020 RegType actual_arg_type;
5021
5022 actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
5023 if (*failure != VERIFY_ERROR_NONE)
5024 return NULL;
5025
5026 if (RegTypeIsUninitReference(actual_arg_type) &&
5027 !res_method->GetName()->Equals("<init>")) {
5028 LOG(ERROR) << "VFY: 'this' arg must be initialized";
5029 *failure = VERIFY_ERROR_GENERIC;
5030 return NULL;
5031 }
5032 if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
5033 actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
5034 if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
5035 LOG(ERROR) << "VFY: 'this' arg '"
5036 << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
5037 << "' not instance of '"
5038 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5039 << "'";
5040 *failure = VERIFY_ERROR_GENERIC;
5041 return NULL;
5042 }
5043 }
5044 actual_args++;
5045 }
5046
5047 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07005048 * Process the target method's signature. This signature may or may not
jeffhaobdb76512011-09-07 11:43:16 -07005049 * have been verified, so we can't assume it's properly formed.
5050 */
5051 for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
jeffhaobdb76512011-09-07 11:43:16 -07005052 if (sig[sig_offset] == ')')
5053 break;
5054
5055 if (actual_args >= expected_args) {
5056 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
5057 << sig.substr(sig_offset) << ")";
5058 goto bad_sig;
5059 }
5060
5061 uint32_t get_reg;
5062 if (is_range)
5063 get_reg = dec_insn->vC_ + actual_args;
5064 else
5065 get_reg = dec_insn->arg_[actual_args];
5066
5067 switch (sig[sig_offset]) {
5068 case 'L':
5069 {
5070 Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
5071 failure);
5072 if (*failure != VERIFY_ERROR_NONE)
5073 goto bad_sig;
5074 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5075 failure);
5076 if (*failure != VERIFY_ERROR_NONE) {
5077 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5078 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5079 goto bad_sig;
5080 }
5081 sig_offset += sig.substr(sig_offset).find(';');
5082 }
5083 actual_args++;
5084 break;
5085 case '[':
5086 {
5087 Class* klass = LookupSignatureArrayClass(method,
5088 sig.substr(sig_offset), failure);
5089 if (*failure != VERIFY_ERROR_NONE)
5090 goto bad_sig;
5091 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5092 failure);
5093 if (*failure != VERIFY_ERROR_NONE) {
5094 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5095 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5096 goto bad_sig;
5097 }
5098 while (sig[sig_offset] == '[')
5099 sig_offset++;
5100 if (sig[sig_offset] == 'L')
5101 sig_offset += sig.substr(sig_offset).find(';');
5102 }
5103 actual_args++;
5104 break;
5105 case 'Z':
5106 VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
5107 actual_args++;
5108 break;
5109 case 'C':
5110 VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
5111 actual_args++;
5112 break;
5113 case 'B':
5114 VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
5115 actual_args++;
5116 break;
5117 case 'I':
5118 VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
5119 actual_args++;
5120 break;
5121 case 'S':
5122 VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
5123 actual_args++;
5124 break;
5125 case 'F':
5126 VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
5127 actual_args++;
5128 break;
5129 case 'D':
5130 VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
5131 actual_args += 2;
5132 break;
5133 case 'J':
5134 VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
5135 actual_args += 2;
5136 break;
5137 default:
5138 LOG(ERROR) << "VFY: invocation target: bad signature type char '"
5139 << sig << "'";
5140 goto bad_sig;
5141 }
5142 }
5143 if (sig[sig_offset] != ')') {
5144 LOG(ERROR) << "VFY: invocation target: bad signature '"
5145 << res_method->GetSignature()->ToModifiedUtf8() << "'";
5146 goto bad_sig;
5147 }
5148
5149 if (actual_args != expected_args) {
5150 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
5151 << actual_args;
5152 goto bad_sig;
5153 }
5154
5155 return res_method;
5156
5157bad_sig:
jeffhao2a8a90e2011-09-26 14:25:31 -07005158 LOG(ERROR) << "VFY: rejecting call to " << PrettyMethod(res_method);
jeffhaobdb76512011-09-07 11:43:16 -07005159 if (*failure == VERIFY_ERROR_NONE)
5160 *failure = VERIFY_ERROR_GENERIC;
5161 return NULL;
5162}
jeffhaoba5ebb92011-08-25 17:24:37 -07005163
jeffhaod1f0fde2011-09-08 17:25:33 -07005164DexVerifier::RegisterMap* DexVerifier::GenerateRegisterMapV(VerifierData* vdata)
5165{
5166 const DexFile::CodeItem* code_item = vdata->code_item_;
5167 int i, bytes_for_addr, gc_point_count;
5168
5169 if (code_item->registers_size_ >= 2048) {
5170 LOG(ERROR) << "ERROR: register map can't handle "
5171 << code_item->registers_size_ << " registers";
5172 return NULL;
5173 }
5174 uint8_t reg_width = (code_item->registers_size_ + 7) / 8;
5175
5176 /*
5177 * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
5178 * we only need 16 bits if we actually encode an address >= 256 -- if
5179 * the method has a section at the end without GC points (e.g. array
5180 * data) we don't need to count it. The situation is unusual, and
5181 * detecting it requires scanning the entire method, so we don't bother.
5182 */
5183 RegisterMapFormat format;
5184 if (code_item->insns_size_ < 256) {
5185 format = kRegMapFormatCompact8;
5186 bytes_for_addr = 1;
5187 } else {
5188 format = kRegMapFormatCompact16;
5189 bytes_for_addr = 2;
5190 }
5191
5192 /*
5193 * Count up the number of GC point instructions.
5194 *
5195 * NOTE: this does not automatically include the first instruction,
5196 * since we don't count method entry as a GC point.
5197 */
5198 gc_point_count = 0;
5199 for (i = 0; i < (int) code_item->insns_size_; i++) {
5200 if (InsnIsGcPoint(vdata->insn_flags_.get(), i))
5201 gc_point_count++;
5202 }
5203 if (gc_point_count >= 65536) {
5204 /* We could handle this, but in practice we don't get near this. */
5205 LOG(ERROR) << "ERROR: register map can't handle " << gc_point_count
5206 << " gc points in one method";
5207 return NULL;
5208 }
5209
5210 /* Calculate size of buffer to hold the map data. */
5211 uint32_t data_size = gc_point_count * (bytes_for_addr + reg_width);
5212
5213 RegisterMap* map = new RegisterMap(format, reg_width, gc_point_count,
jeffhaoa0a764a2011-09-16 10:43:38 -07005214 data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005215
5216 /* Populate it. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005217 uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005218 for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
5219 if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005220 DCHECK(vdata->register_lines_[i].reg_types_.get() != NULL);
jeffhaod1f0fde2011-09-08 17:25:33 -07005221 if (format == kRegMapFormatCompact8) {
5222 *map_data++ = i;
5223 } else /*kRegMapFormatCompact16*/ {
5224 *map_data++ = i & 0xff;
5225 *map_data++ = i >> 8;
5226 }
5227 OutputTypeVector(vdata->register_lines_[i].reg_types_.get(),
5228 code_item->registers_size_, map_data);
5229 map_data += reg_width;
5230 }
5231 }
5232
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005233 DCHECK_EQ((uint32_t) map_data - (uint32_t) map->data_, data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005234
5235 // TODO: Remove this check when it's really running...
5236#if 1
5237 if (!VerifyMap(vdata, map)) {
5238 LOG(ERROR) << "Map failed to verify";
5239 return NULL;
5240 }
5241#endif
5242
5243 /* Try to compress the map. */
Shih-wei Liao4f894e32011-09-27 21:33:19 -07005244#if 0
jeffhaod1f0fde2011-09-08 17:25:33 -07005245 RegisterMap* compress_map = CompressMapDifferential(map);
5246 if (compress_map != NULL) {
5247 // TODO: Remove this check when it's really running...
5248#if 1
5249 /*
5250 * Expand the compressed map we just created, and compare it
5251 * to the original. Abort the VM if it doesn't match up.
5252 */
5253 UniquePtr<RegisterMap> uncompressed_map(UncompressMapDifferential(compress_map));
5254 if (uncompressed_map.get() == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07005255 LOG(ERROR) << "Map failed to uncompress - " << PrettyMethod(vdata->method_);
jeffhaod1f0fde2011-09-08 17:25:33 -07005256 delete map;
5257 delete compress_map;
5258 /* bad - compression is broken or we're out of memory */
5259 return NULL;
5260 } else {
5261 if (!CompareMaps(map, uncompressed_map.get())) {
jeffhao2a8a90e2011-09-26 14:25:31 -07005262 LOG(ERROR) << "Map comparison failed - " << PrettyMethod(vdata->method_);
jeffhaod1f0fde2011-09-08 17:25:33 -07005263 delete map;
5264 delete compress_map;
5265 /* bad - compression is broken */
5266 return NULL;
5267 }
5268 }
5269#endif
5270 delete map;
5271 map = compress_map;
5272 }
Shih-wei Liao4f894e32011-09-27 21:33:19 -07005273#endif
jeffhaod1f0fde2011-09-08 17:25:33 -07005274 return map;
5275}
5276
jeffhaoa0a764a2011-09-16 10:43:38 -07005277DexVerifier::RegisterMap* DexVerifier::GetExpandedRegisterMapHelper(
5278 Method* method, RegisterMap* map) {
5279 RegisterMap* new_map;
5280
5281 if (map == NULL)
5282 return NULL;
5283
5284 /* TODO: sanity check to ensure this isn't called w/o external locking */
5285
5286 uint8_t format = map->header_->format_;
5287 switch (format) {
5288 case kRegMapFormatCompact8:
5289 case kRegMapFormatCompact16:
5290 /* already expanded */
5291 return map;
5292 case kRegMapFormatDifferential:
5293 new_map = UncompressMapDifferential(map);
5294 break;
5295 default:
5296 LOG(ERROR) << "Unknown format " << format
5297 << " in dvmGetExpandedRegisterMap";
5298 return NULL;
5299 }
5300
5301 if (new_map == NULL) {
5302 LOG(ERROR) << "Map failed to uncompress (fmt=" << format << ") "
jeffhao2a8a90e2011-09-26 14:25:31 -07005303 << PrettyMethod(method);
jeffhaoa0a764a2011-09-16 10:43:38 -07005304 return NULL;
5305 }
5306
5307 /* Update method, and free compressed map if it was sitting on the heap. */
Ian Rogersd6b1f612011-09-27 13:38:14 -07005308 //ByteArray* header = ByteArray::Alloc(sizeof(RegisterMapHeader));
5309 //ByteArray* data = ByteArray::Alloc(ComputeRegisterMapSize(map));
jeffhaoa0a764a2011-09-16 10:43:38 -07005310
Ian Rogersd6b1f612011-09-27 13:38:14 -07005311 //memcpy(header->GetData(), map->header_, sizeof(RegisterMapHeader));
5312 //memcpy(data->GetData(), map->data_, ComputeRegisterMapSize(map));
jeffhaoa0a764a2011-09-16 10:43:38 -07005313
Ian Rogersd6b1f612011-09-27 13:38:14 -07005314 //method->SetRegisterMapHeader(header);
5315 //method->SetRegisterMapData(data);
jeffhaoa0a764a2011-09-16 10:43:38 -07005316
5317 delete map;
5318 return new_map;
5319}
5320
5321const uint8_t* DexVerifier::RegisterMapGetLine(const RegisterMap* map, int addr) {
5322 int addr_width, line_width;
5323 uint8_t format = map->header_->format_;
5324 uint16_t num_entries = map->header_->num_entries_;
5325
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005326 DCHECK_GT(num_entries, 0);
jeffhaoa0a764a2011-09-16 10:43:38 -07005327
5328 switch (format) {
5329 case kRegMapFormatNone:
5330 return NULL;
5331 case kRegMapFormatCompact8:
5332 addr_width = 1;
5333 break;
5334 case kRegMapFormatCompact16:
5335 addr_width = 2;
5336 break;
5337 default:
5338 LOG(ERROR) << "Unknown format " << format;
5339 return NULL;
5340 }
5341
5342 line_width = addr_width + map->header_->reg_width_;
5343
5344 /*
5345 * Find the appropriate entry. Many maps are very small, some are very large.
5346 */
5347 static const int kSearchThreshold = 8;
5348 const uint8_t* data = NULL;
5349 int line_addr;
5350
5351 if (num_entries < kSearchThreshold) {
5352 int i;
5353 data = map->data_;
5354 for (i = num_entries; i > 0; i--) {
5355 line_addr = data[0];
5356 if (addr_width > 1)
5357 line_addr |= data[1] << 8;
5358 if (line_addr == addr)
5359 return data + addr_width;
5360
5361 data += line_width;
5362 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005363 DCHECK_EQ(data, map->data_ + line_width * num_entries);
jeffhaoa0a764a2011-09-16 10:43:38 -07005364 } else {
5365 int hi, lo, mid;
5366
5367 lo = 0;
5368 hi = num_entries -1;
5369
5370 while (hi >= lo) {
5371 mid = (hi + lo) / 2;
5372 data = map->data_ + line_width * mid;
5373
5374 line_addr = data[0];
5375 if (addr_width > 1)
5376 line_addr |= data[1] << 8;
5377
5378 if (addr > line_addr) {
5379 lo = mid + 1;
5380 } else if (addr < line_addr) {
5381 hi = mid - 1;
5382 } else {
5383 return data + addr_width;
5384 }
5385 }
5386 }
5387
5388 return NULL;
5389}
5390
jeffhaod1f0fde2011-09-08 17:25:33 -07005391void DexVerifier::OutputTypeVector(const RegType* regs, int insn_reg_count,
5392 uint8_t* data) {
5393 uint8_t val = 0;
5394 int i;
5395
5396 for (i = 0; i < insn_reg_count; i++) {
5397 RegType type = *regs++;
5398 val >>= 1;
5399 if (IsReferenceType(type))
5400 val |= 0x80; /* set hi bit */
5401
5402 if ((i & 0x07) == 7)
5403 *data++ = val;
5404 }
5405 if ((i & 0x07) != 0) {
5406 /* Flush bits from last byte. */
5407 val >>= 8 - (i & 0x07);
5408 *data++ = val;
5409 }
5410}
5411
5412bool DexVerifier::VerifyMap(VerifierData* vdata, const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005413 const uint8_t* raw_map = map->data_;
5414 uint8_t format = map->header_->format_;
5415 const int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005416 int ent;
5417
jeffhaoe23d93c2011-09-15 14:48:43 -07005418 if ((vdata->code_item_->registers_size_ + 7) / 8 != map->header_->reg_width_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005419 LOG(ERROR) << "GLITCH: registersSize=" << vdata->code_item_->registers_size_
jeffhaoe23d93c2011-09-15 14:48:43 -07005420 << ", reg_width=" << map->header_->reg_width_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005421 return false;
5422 }
5423
5424 for (ent = 0; ent < num_entries; ent++) {
5425 int addr;
5426
5427 switch (format) {
5428 case kRegMapFormatCompact8:
5429 addr = *raw_map++;
5430 break;
5431 case kRegMapFormatCompact16:
5432 addr = *raw_map++;
5433 addr |= (*raw_map++) << 8;
5434 break;
5435 default:
5436 LOG(FATAL) << "GLITCH: bad format (" << format << ")";
5437 return false;
5438 }
5439
5440 const RegType* regs = vdata->register_lines_[addr].reg_types_.get();
5441 if (regs == NULL) {
5442 LOG(ERROR) << "GLITCH: addr " << addr << " has no data";
5443 return false;
5444 }
5445
5446 uint8_t val = 0;
5447 int i;
5448
5449 for (i = 0; i < vdata->code_item_->registers_size_; i++) {
5450 bool bit_is_ref, reg_is_ref;
5451
5452 val >>= 1;
5453 if ((i & 0x07) == 0) {
5454 /* Load next byte of data. */
5455 val = *raw_map++;
5456 }
5457
5458 bit_is_ref = val & 0x01;
5459
5460 RegType type = regs[i];
5461 reg_is_ref = IsReferenceType(type);
5462
5463 if (bit_is_ref != reg_is_ref) {
5464 LOG(ERROR) << "GLITCH: addr " << addr << " reg " << i << ": bit="
5465 << bit_is_ref << " reg=" << reg_is_ref << "(" << type << ")";
5466 return false;
5467 }
5468 }
5469 /* Raw_map now points to the address field of the next entry. */
5470 }
5471
5472 return true;
5473}
5474
5475bool DexVerifier::CompareMaps(const RegisterMap* map1, const RegisterMap* map2)
5476{
5477 size_t size1, size2;
5478
5479 size1 = ComputeRegisterMapSize(map1);
5480 size2 = ComputeRegisterMapSize(map2);
5481 if (size1 != size2) {
5482 LOG(ERROR) << "CompareMaps: size mismatch (" << size1 << " vs " << size2
5483 << ")";
5484 return false;
5485 }
5486
jeffhaoe23d93c2011-09-15 14:48:43 -07005487 if (map1->header_->format_ != map2->header_->format_ ||
5488 map1->header_->reg_width_ != map2->header_->reg_width_ ||
jeffhaoa0a764a2011-09-16 10:43:38 -07005489 map1->header_->num_entries_ != map2->header_->num_entries_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005490 LOG(ERROR) << "CompareMaps: fields mismatch";
5491 }
jeffhaoe23d93c2011-09-15 14:48:43 -07005492 if (memcmp(map1->data_, map2->data_, size1) != 0) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005493 LOG(ERROR) << "CompareMaps: data mismatch";
5494 return false;
5495 }
5496
5497 return true;
5498}
5499
5500size_t DexVerifier::ComputeRegisterMapSize(const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005501 uint8_t format = map->header_->format_;
5502 uint16_t num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005503
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005504 DCHECK(map != NULL);
jeffhaod1f0fde2011-09-08 17:25:33 -07005505
5506 switch (format) {
5507 case kRegMapFormatNone:
5508 return 1;
5509 case kRegMapFormatCompact8:
jeffhaoe23d93c2011-09-15 14:48:43 -07005510 return (1 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005511 case kRegMapFormatCompact16:
jeffhaoe23d93c2011-09-15 14:48:43 -07005512 return (2 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005513 case kRegMapFormatDifferential:
5514 {
5515 /* Decoded ULEB128 length. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005516 const uint8_t* ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005517 return DecodeUnsignedLeb128(&ptr);
5518 }
5519 default:
5520 LOG(FATAL) << "Bad register map format " << format;
5521 return 0;
5522 }
5523}
5524
5525int DexVerifier::ComputeBitDiff(const uint8_t* bits1, const uint8_t* bits2,
5526 int byte_width, int* first_bit_changed_ptr, int* num_bits_changed_ptr,
5527 uint8_t* leb_out_buf) {
5528 int num_bits_changed = 0;
5529 int first_bit_changed = -1;
5530 int leb_size = 0;
5531 int byte_num;
5532
5533 /*
5534 * Run through the vectors, first comparing them at the byte level. This
5535 * will yield a fairly quick result if nothing has changed between them.
5536 */
5537 for (byte_num = 0; byte_num < byte_width; byte_num++) {
5538 uint8_t byte1 = *bits1++;
5539 uint8_t byte2 = *bits2++;
5540 if (byte1 != byte2) {
5541 /* Walk through the byte, identifying the changed bits. */
5542 int bit_num;
5543 for (bit_num = 0; bit_num < 8; bit_num++) {
5544 if (((byte1 >> bit_num) & 0x01) != ((byte2 >> bit_num) & 0x01)) {
5545 int bit_offset = (byte_num << 3) + bit_num;
5546
5547 if (first_bit_changed < 0)
5548 first_bit_changed = bit_offset;
5549 num_bits_changed++;
5550
5551 if (leb_out_buf == NULL) {
5552 leb_size += UnsignedLeb128Size(bit_offset);
5553 } else {
5554 uint8_t* cur_buf = leb_out_buf;
5555 leb_out_buf = WriteUnsignedLeb128(leb_out_buf, bit_offset);
5556 leb_size += leb_out_buf - cur_buf;
5557 }
5558 }
5559 }
5560 }
5561 }
5562
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005563 if (num_bits_changed > 0) {
5564 DCHECK_GE(first_bit_changed, 0);
5565 }
jeffhaod1f0fde2011-09-08 17:25:33 -07005566
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005567 if (first_bit_changed_ptr != NULL) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005568 *first_bit_changed_ptr = first_bit_changed;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005569 }
5570
5571 if (num_bits_changed_ptr != NULL) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005572 *num_bits_changed_ptr = num_bits_changed;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005573 }
jeffhaod1f0fde2011-09-08 17:25:33 -07005574
5575 return leb_size;
5576}
5577
5578DexVerifier::RegisterMap* DexVerifier::CompressMapDifferential(
5579 const RegisterMap* map) {
5580 int orig_size = ComputeRegisterMapSize(map);
5581 uint8_t* tmp_ptr;
5582 int addr_width;
5583
jeffhaoe23d93c2011-09-15 14:48:43 -07005584 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005585 switch (format) {
5586 case kRegMapFormatCompact8:
5587 addr_width = 1;
5588 break;
5589 case kRegMapFormatCompact16:
5590 addr_width = 2;
5591 break;
5592 default:
5593 LOG(ERROR) << "ERROR: can't compress map with format=" << format;
5594 return NULL;
5595 }
5596
jeffhaoe23d93c2011-09-15 14:48:43 -07005597 int reg_width = map->header_->reg_width_;
5598 int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005599
5600 if (num_entries <= 1) {
5601 return NULL;
5602 }
5603
5604 /*
5605 * We don't know how large the compressed data will be. It's possible
5606 * for it to expand and become larger than the original. The header
5607 * itself is variable-sized, so we generate everything into a temporary
5608 * buffer and then copy it to form-fitting storage once we know how big
5609 * it will be (and that it's smaller than the original).
5610 *
5611 * If we use a size that is equal to the size of the input map plus
5612 * a value longer than a single entry can possibly expand to, we need
5613 * only check for overflow at the end of each entry. The worst case
5614 * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
5615 * Addresses are 16 bits, so that's (1 + 3 + reg_width).
5616 *
5617 * The initial address offset and bit vector will take up less than
5618 * or equal to the amount of space required when uncompressed -- large
5619 * initial offsets are rejected.
5620 */
5621 UniquePtr<uint8_t[]> tmp_buf(new uint8_t[orig_size + (1 + 3 + reg_width)]);
5622
5623 tmp_ptr = tmp_buf.get();
5624
jeffhaoe23d93c2011-09-15 14:48:43 -07005625 const uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005626 const uint8_t* prev_bits;
5627 uint16_t addr, prev_addr;
5628
5629 addr = *map_data++;
5630 if (addr_width > 1)
5631 addr |= (*map_data++) << 8;
5632
5633 if (addr >= 128) {
5634 LOG(ERROR) << "Can't compress map with starting address >= 128";
5635 return NULL;
5636 }
5637
5638 /*
5639 * Start by writing the initial address and bit vector data. The high
5640 * bit of the initial address is used to indicate the required address
5641 * width (which the decoder can't otherwise determine without parsing
5642 * the compressed data).
5643 */
5644 *tmp_ptr++ = addr | (addr_width > 1 ? 0x80 : 0x00);
5645 memcpy(tmp_ptr, map_data, reg_width);
5646
5647 prev_bits = map_data;
5648 prev_addr = addr;
5649
5650 tmp_ptr += reg_width;
5651 map_data += reg_width;
5652
5653 /* Loop over all following entries. */
5654 for (int entry = 1; entry < num_entries; entry++) {
5655 int addr_diff;
5656 uint8_t key;
5657
5658 /* Pull out the address and figure out how to encode it. */
5659 addr = *map_data++;
5660 if (addr_width > 1)
5661 addr |= (*map_data++) << 8;
5662
5663 addr_diff = addr - prev_addr;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005664 DCHECK_GT(addr_diff, 0);
jeffhaod1f0fde2011-09-08 17:25:33 -07005665 if (addr_diff < 8) {
5666 /* Small difference, encode in 3 bits. */
5667 key = addr_diff -1; /* set 00000AAA */
5668 } else {
5669 /* Large difference, output escape code. */
5670 key = 0x07; /* escape code for AAA */
5671 }
5672
5673 int num_bits_changed, first_bit_changed, leb_size;
5674
5675 leb_size = ComputeBitDiff(prev_bits, map_data, reg_width,
5676 &first_bit_changed, &num_bits_changed, NULL);
5677
5678 if (num_bits_changed == 0) {
5679 /* set B to 1 and CCCC to zero to indicate no bits were changed */
5680 key |= 0x08;
5681 } else if (num_bits_changed == 1 && first_bit_changed < 16) {
5682 /* set B to 0 and CCCC to the index of the changed bit */
5683 key |= first_bit_changed << 4;
5684 } else if (num_bits_changed < 15 && leb_size < reg_width) {
5685 /* set B to 1 and CCCC to the number of bits */
5686 key |= 0x08 | (num_bits_changed << 4);
5687 } else {
5688 /* set B to 1 and CCCC to 0x0f so we store the entire vector */
5689 key |= 0x08 | 0xf0;
5690 }
5691
5692 /*
5693 * Encode output. Start with the key, follow with the address
5694 * diff (if it didn't fit in 3 bits), then the changed bit info.
5695 */
5696 *tmp_ptr++ = key;
5697 if ((key & 0x07) == 0x07)
5698 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, addr_diff);
5699
5700 if ((key & 0x08) != 0) {
5701 int bit_count = key >> 4;
5702 if (bit_count == 0) {
5703 /* nothing changed, no additional output required */
5704 } else if (bit_count == 15) {
5705 /* full vector is most compact representation */
5706 memcpy(tmp_ptr, map_data, reg_width);
5707 tmp_ptr += reg_width;
5708 } else {
5709 /* write bit indices in ULEB128 format */
5710 (void) ComputeBitDiff(prev_bits, map_data, reg_width,
5711 NULL, NULL, tmp_ptr);
5712 tmp_ptr += leb_size;
5713 }
5714 } else {
5715 /* single-bit changed, value encoded in key byte */
5716 }
5717
5718 prev_bits = map_data;
5719 prev_addr = addr;
5720 map_data += reg_width;
5721
5722 /* See if we've run past the original size. */
5723 if (tmp_ptr - tmp_buf.get() >= orig_size) {
5724 return NULL;
5725 }
5726 }
5727
5728 /*
5729 * Create a RegisterMap with the contents.
5730 *
5731 * TODO: consider using a threshold other than merely ">=". We would
5732 * get poorer compression but potentially use less native heap space.
5733 */
5734 int new_data_size = tmp_ptr - tmp_buf.get();
5735 int new_map_size = new_data_size + UnsignedLeb128Size(new_data_size);
5736
5737 if (new_map_size >= orig_size) {
5738 return NULL;
5739 }
5740
5741 RegisterMap* new_map = new RegisterMap(kRegMapFormatDifferential, reg_width,
jeffhaoa0a764a2011-09-16 10:43:38 -07005742 num_entries, new_map_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005743
jeffhaoe23d93c2011-09-15 14:48:43 -07005744 tmp_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005745 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, new_data_size);
5746 memcpy(tmp_ptr, tmp_buf.get(), new_data_size);
5747
5748 return new_map;
5749}
5750
5751DexVerifier::RegisterMap* DexVerifier::UncompressMapDifferential(
5752 const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005753 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005754 RegisterMapFormat new_format;
5755 int reg_width, num_entries, new_addr_width, new_data_size;
5756
5757 if (format != kRegMapFormatDifferential) {
5758 LOG(ERROR) << "Not differential (" << format << ")";
5759 return NULL;
5760 }
5761
jeffhaoe23d93c2011-09-15 14:48:43 -07005762 reg_width = map->header_->reg_width_;
5763 num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005764
5765 /* Get the data size; we can check this at the end. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005766 const uint8_t* src_ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005767 int expected_src_len = DecodeUnsignedLeb128(&src_ptr);
5768 const uint8_t* src_start = src_ptr;
5769
5770 /* Get the initial address and the 16-bit address flag. */
5771 int addr = *src_ptr & 0x7f;
5772 if ((*src_ptr & 0x80) == 0) {
5773 new_format = kRegMapFormatCompact8;
5774 new_addr_width = 1;
5775 } else {
5776 new_format = kRegMapFormatCompact16;
5777 new_addr_width = 2;
5778 }
5779 src_ptr++;
5780
5781 /* Now we know enough to allocate the new map. */
5782 new_data_size = (new_addr_width + reg_width) * num_entries;
5783 RegisterMap* new_map = new RegisterMap(new_format, reg_width, num_entries,
jeffhaoa0a764a2011-09-16 10:43:38 -07005784 new_data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005785
5786 /* Write the start address and initial bits to the new map. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005787 uint8_t* dst_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005788
5789 *dst_ptr++ = addr & 0xff;
5790 if (new_addr_width > 1)
5791 *dst_ptr++ = (uint8_t) (addr >> 8);
5792
5793 memcpy(dst_ptr, src_ptr, reg_width);
5794
5795 int prev_addr = addr;
5796 const uint8_t* prev_bits = dst_ptr; /* point at uncompressed data */
5797
5798 dst_ptr += reg_width;
5799 src_ptr += reg_width;
5800
5801 /* Walk through, uncompressing one line at a time. */
5802 int entry;
5803 for (entry = 1; entry < num_entries; entry++) {
5804 int addr_diff;
5805 uint8_t key;
5806
5807 key = *src_ptr++;
5808
5809 /* Get the address. */
5810 if ((key & 0x07) == 7) {
5811 /* Address diff follows in ULEB128. */
5812 addr_diff = DecodeUnsignedLeb128(&src_ptr);
5813 } else {
5814 addr_diff = (key & 0x07) +1;
5815 }
5816
5817 addr = prev_addr + addr_diff;
5818 *dst_ptr++ = addr & 0xff;
5819 if (new_addr_width > 1)
5820 *dst_ptr++ = (uint8_t) (addr >> 8);
5821
5822 /* Unpack the bits. */
5823 if ((key & 0x08) != 0) {
5824 int bit_count = (key >> 4);
5825 if (bit_count == 0) {
5826 /* No bits changed, just copy previous. */
5827 memcpy(dst_ptr, prev_bits, reg_width);
5828 } else if (bit_count == 15) {
5829 /* Full copy of bit vector is present; ignore prev_bits. */
5830 memcpy(dst_ptr, src_ptr, reg_width);
5831 src_ptr += reg_width;
5832 } else {
5833 /* Copy previous bits and modify listed indices. */
5834 memcpy(dst_ptr, prev_bits, reg_width);
5835 while (bit_count--) {
5836 int bit_index = DecodeUnsignedLeb128(&src_ptr);
5837 ToggleBit(dst_ptr, bit_index);
5838 }
5839 }
5840 } else {
5841 /* Copy previous bits and modify the specified one. */
5842 memcpy(dst_ptr, prev_bits, reg_width);
5843
5844 /* One bit, from 0-15 inclusive, was changed. */
5845 ToggleBit(dst_ptr, key >> 4);
5846 }
5847
5848 prev_addr = addr;
5849 prev_bits = dst_ptr;
5850 dst_ptr += reg_width;
5851 }
5852
jeffhaoe23d93c2011-09-15 14:48:43 -07005853 if (dst_ptr - new_map->data_ != new_data_size) {
5854 LOG(ERROR) << "ERROR: output " << dst_ptr - new_map->data_
jeffhaod1f0fde2011-09-08 17:25:33 -07005855 << " bytes, expected " << new_data_size;
5856 free(new_map);
5857 return NULL;
5858 }
5859
5860 if (src_ptr - src_start != expected_src_len) {
5861 LOG(ERROR) << "ERROR: consumed " << src_ptr - src_start
5862 << " bytes, expected " << expected_src_len;
5863 free(new_map);
5864 return NULL;
5865 }
5866
5867 return new_map;
5868}
5869
jeffhaoe0cfb6f2011-09-22 16:42:56 -07005870/* Dump the register types for the specifed address to the log file. */
5871void DexVerifier::DumpRegTypes(const VerifierData* vdata,
5872 const RegisterLine* register_line, int addr, const char* addr_name,
5873 const UninitInstanceMap* uninit_map) {
5874 const DexFile::CodeItem* code_item = vdata->code_item_;
5875 uint16_t reg_count = code_item->registers_size_;
5876 uint32_t insns_size = code_item->insns_size_;
5877 const InsnFlags* insn_flags = vdata->insn_flags_.get();
5878 const RegType* addr_regs = register_line->reg_types_.get();
5879 int full_reg_count = reg_count + kExtraRegs;
5880 bool branch_target = InsnIsBranchTarget(insn_flags, addr);
5881 int i;
5882
5883 CHECK(addr >= 0 && addr < (int) insns_size);
5884
5885 int reg_char_size = full_reg_count + (full_reg_count - 1) / 4 + 2 + 1;
5886 char reg_chars[reg_char_size + 1];
5887 memset(reg_chars, ' ', reg_char_size);
5888 reg_chars[0] = '[';
Elliott Hughes362f9bc2011-10-17 18:56:41 -07005889 if (reg_count == 0) {
jeffhaoe0cfb6f2011-09-22 16:42:56 -07005890 reg_chars[1] = ']';
Elliott Hughes362f9bc2011-10-17 18:56:41 -07005891 } else {
5892 reg_chars[1 + (reg_count - 1) + (reg_count - 1) / 4 + 1] = ']';
5893 }
jeffhaoe0cfb6f2011-09-22 16:42:56 -07005894 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