blob: 6c7335ecb697553b45e260b5bfac7f26339b6a00 [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));
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700348 SirtRef<ByteArray> header(ByteArray::Alloc(sizeof(RegisterMapHeader)));
349 if (header.get() == NULL) {
350 return false;
351 }
352 SirtRef<ByteArray> data(ByteArray::Alloc(ComputeRegisterMapSize(map.get())));
353 if (data.get() == NULL) {
354 return false;
355 }
jeffhaoe23d93c2011-09-15 14:48:43 -0700356
jeffhaoa0a764a2011-09-16 10:43:38 -0700357 memcpy(header->GetData(), map.get()->header_, sizeof(RegisterMapHeader));
358 memcpy(data->GetData(), map.get()->data_, ComputeRegisterMapSize(map.get()));
jeffhaoe23d93c2011-09-15 14:48:43 -0700359
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700360 method->SetRegisterMapHeader(header.get());
361 method->SetRegisterMapData(data.get());
jeffhaoba5ebb92011-08-25 17:24:37 -0700362
jeffhaobdb76512011-09-07 11:43:16 -0700363 return true;
364}
365
366bool DexVerifier::ComputeWidthsAndCountOps(VerifierData* vdata) {
367 const uint16_t* insns = vdata->code_item_->insns_;
368 uint32_t insns_size = vdata->code_item_->insns_size_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700369 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700370 const byte* ptr = reinterpret_cast<const byte*>(insns);
371 const Instruction* inst = Instruction::At(ptr);
372 size_t new_instance_count = 0;
373 size_t monitor_enter_count = 0;
374 size_t width = 0;
375
376 while (width < insns_size) {
377 Instruction::Code opcode = inst->Opcode();
378 if (opcode == Instruction::NEW_INSTANCE) {
379 new_instance_count++;
380 } else if (opcode == Instruction::MONITOR_ENTER) {
381 monitor_enter_count++;
382 }
383
384 insn_flags[width] |= inst->Size();
385 width += inst->Size();
386 inst = inst->Next();
387 }
388
389 if (width != insns_size) {
390 LOG(ERROR) << "VFY: code did not end where expected (" << width << " vs. "
391 << insns_size << ")";
392 return false;
393 }
394
395 vdata->new_instance_count_ = new_instance_count;
396 vdata->monitor_enter_count_ = monitor_enter_count;
397 return true;
398}
399
400bool DexVerifier::ScanTryCatchBlocks(VerifierData* vdata) {
401 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700402 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700403 uint32_t insns_size = code_item->insns_size_;
404 uint32_t tries_size = code_item->tries_size_;
405
406 if (tries_size == 0) {
407 return true;
408 }
409
410 const DexFile::TryItem* tries = DexFile::dexGetTryItems(*code_item, 0);
411
412 for (uint32_t idx = 0; idx < tries_size; idx++) {
413 const DexFile::TryItem* try_item = &tries[idx];
414 uint32_t start = try_item->start_addr_;
415 uint32_t end = start + try_item->insn_count_;
416
417 if ((start >= end) || (start >= insns_size) || (end > insns_size)) {
418 LOG(ERROR) << "VFY: bad exception entry: startAddr=" << start
419 << " endAddr=" << end << " (size=" << insns_size << ")";
420 return false;
421 }
422
423 if (InsnGetWidth(insn_flags, start) == 0) {
424 LOG(ERROR) << "VFY: 'try' block starts inside an instruction ("
425 << start << ")";
426 return false;
427 }
428
429 uint32_t addr;
430 for (addr = start; addr < end; addr += InsnGetWidth(insn_flags, addr)) {
431 InsnSetInTry(insn_flags, addr);
432 }
433 }
434
435 /* Iterate over each of the handlers to verify target addresses. */
436 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
437 uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
438 for (uint32_t idx = 0; idx < handlers_size; idx++) {
439 DexFile::CatchHandlerIterator iterator(handlers_ptr);
440
441 for (; !iterator.HasNext(); iterator.Next()) {
442 uint32_t addr = iterator.Get().address_;
443 if (InsnGetWidth(insn_flags, addr) == 0) {
444 LOG(ERROR) << "VFY: exception handler starts at bad address ("
445 << addr << ")";
446 return false;
447 }
448
449 InsnSetBranchTarget(insn_flags, addr);
450 }
451
452 handlers_ptr = iterator.GetData();
453 }
454
455 return true;
456}
457
458bool DexVerifier::GetBranchOffset(const DexFile::CodeItem* code_item,
459 const InsnFlags insn_flags[], uint32_t cur_offset, int32_t* pOffset,
jeffhaoba5ebb92011-08-25 17:24:37 -0700460 bool* pConditional, bool* selfOkay) {
461 const uint16_t* insns = code_item->insns_ + cur_offset;
462
463 switch (*insns & 0xff) {
464 case Instruction::GOTO:
465 *pOffset = ((int16_t) *insns) >> 8;
466 *pConditional = false;
467 *selfOkay = false;
468 break;
469 case Instruction::GOTO_32:
470 *pOffset = insns[1] | (((uint32_t) insns[2]) << 16);
471 *pConditional = false;
472 *selfOkay = true;
473 break;
474 case Instruction::GOTO_16:
475 *pOffset = (int16_t) insns[1];
476 *pConditional = false;
477 *selfOkay = false;
478 break;
479 case Instruction::IF_EQ:
480 case Instruction::IF_NE:
481 case Instruction::IF_LT:
482 case Instruction::IF_GE:
483 case Instruction::IF_GT:
484 case Instruction::IF_LE:
485 case Instruction::IF_EQZ:
486 case Instruction::IF_NEZ:
487 case Instruction::IF_LTZ:
488 case Instruction::IF_GEZ:
489 case Instruction::IF_GTZ:
490 case Instruction::IF_LEZ:
491 *pOffset = (int16_t) insns[1];
492 *pConditional = true;
493 *selfOkay = false;
494 break;
495 default:
496 return false;
497 break;
498 }
499
500 return true;
501}
502
jeffhaobdb76512011-09-07 11:43:16 -0700503bool DexVerifier::CheckArrayData(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700504 uint32_t cur_offset) {
505 const uint32_t insn_count = code_item->insns_size_;
506 const uint16_t* insns = code_item->insns_ + cur_offset;
507 const uint16_t* array_data;
508 int32_t array_data_offset;
509
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700510 DCHECK_LT(cur_offset, insn_count);
jeffhaoba5ebb92011-08-25 17:24:37 -0700511
512 /* make sure the start of the array data table is in range */
513 array_data_offset = insns[1] | (((int32_t) insns[2]) << 16);
514 if ((int32_t) cur_offset + array_data_offset < 0 ||
515 cur_offset + array_data_offset + 2 >= insn_count)
516 {
517 LOG(ERROR) << "VFY: invalid array data start: at " << cur_offset
518 << ", data offset " << array_data_offset << ", count "
519 << insn_count;
520 return false;
521 }
522
523 /* offset to array data table is a relative branch-style offset */
524 array_data = insns + array_data_offset;
525
526 /* make sure the table is 32-bit aligned */
527 if ((((uint32_t) array_data) & 0x03) != 0) {
528 LOG(ERROR) << "VFY: unaligned array data table: at " << cur_offset
529 << ", data offset " << array_data_offset;
530 return false;
531 }
532
533 uint32_t value_width = array_data[1];
534 uint32_t value_count = *(uint32_t*) (&array_data[2]);
535 uint32_t table_size = 4 + (value_width * value_count + 1) / 2;
536
537 /* make sure the end of the switch is in range */
538 if (cur_offset + array_data_offset + table_size > insn_count) {
539 LOG(ERROR) << "VFY: invalid array data end: at " << cur_offset
540 << ", data offset " << array_data_offset << ", end "
541 << cur_offset + array_data_offset + table_size << ", count "
542 << insn_count;
543 return false;
544 }
545
546 return true;
547}
548
jeffhaobdb76512011-09-07 11:43:16 -0700549bool DexVerifier::CheckNewInstance(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700550 if (idx >= dex_file->GetHeader().type_ids_size_) {
551 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
552 << dex_file->GetHeader().type_ids_size_ << ")";
553 return false;
554 }
555
556 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
557 if (descriptor[0] != 'L') {
558 LOG(ERROR) << "VFY: can't call new-instance on type '"
559 << descriptor << "'";
560 return false;
561 }
562
563 return true;
564}
565
jeffhaobdb76512011-09-07 11:43:16 -0700566bool DexVerifier::CheckNewArray(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700567 if (idx >= dex_file->GetHeader().type_ids_size_) {
568 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
569 << dex_file->GetHeader().type_ids_size_ << ")";
570 return false;
571 }
572
573 int bracket_count = 0;
574 const char* descriptor = dex_file->dexStringByTypeIdx(idx);
575 const char* cp = descriptor;
576 while (*cp++ == '[')
577 bracket_count++;
578
579 if (bracket_count == 0) {
580 /* The given class must be an array type. */
581 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
582 << "' (not an array)";
583 return false;
584 } else if (bracket_count > 255) {
585 /* It is illegal to create an array of more than 255 dimensions. */
586 LOG(ERROR) << "VFY: can't new-array class '" << descriptor
587 << "' (exceeds limit)";
588 return false;
589 }
590
591 return true;
592}
593
jeffhaobdb76512011-09-07 11:43:16 -0700594bool DexVerifier::CheckTypeIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700595 if (idx >= dex_file->GetHeader().type_ids_size_) {
596 LOG(ERROR) << "VFY: bad type index " << idx << " (max "
597 << dex_file->GetHeader().type_ids_size_ << ")";
598 return false;
599 }
600 return true;
601}
602
jeffhaobdb76512011-09-07 11:43:16 -0700603bool DexVerifier::CheckFieldIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700604 if (idx >= dex_file->GetHeader().field_ids_size_) {
605 LOG(ERROR) << "VFY: bad field index " << idx << " (max "
606 << dex_file->GetHeader().field_ids_size_ << ")";
607 return false;
608 }
609 return true;
610}
611
jeffhaobdb76512011-09-07 11:43:16 -0700612bool DexVerifier::CheckMethodIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700613 if (idx >= dex_file->GetHeader().method_ids_size_) {
614 LOG(ERROR) << "VFY: bad method index " << idx << " (max "
615 << dex_file->GetHeader().method_ids_size_ << ")";
616 return false;
617 }
618 return true;
619}
620
jeffhaobdb76512011-09-07 11:43:16 -0700621bool DexVerifier::CheckStringIndex(const DexFile* dex_file, uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700622 if (idx >= dex_file->GetHeader().string_ids_size_) {
623 LOG(ERROR) << "VFY: bad string index " << idx << " (max "
624 << dex_file->GetHeader().string_ids_size_ << ")";
625 return false;
626 }
627 return true;
628}
629
jeffhaobdb76512011-09-07 11:43:16 -0700630bool DexVerifier::CheckRegisterIndex(const DexFile::CodeItem* code_item,
631 uint32_t idx) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700632 if (idx >= code_item->registers_size_) {
633 LOG(ERROR) << "VFY: register index out of range (" << idx << " >= "
634 << code_item->registers_size_ << ")";
635 return false;
636 }
637 return true;
638}
639
jeffhaobdb76512011-09-07 11:43:16 -0700640bool DexVerifier::CheckWideRegisterIndex(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700641 uint32_t idx) {
642 if (idx + 1 >= code_item->registers_size_) {
643 LOG(ERROR) << "VFY: wide register index out of range (" << idx
644 << "+1 >= " << code_item->registers_size_ << ")";
645 return false;
646 }
647 return true;
648}
649
jeffhaobdb76512011-09-07 11:43:16 -0700650bool DexVerifier::CheckVarArgRegs(const DexFile::CodeItem* code_item,
651 uint32_t vA, uint32_t arg[]) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700652 uint16_t registers_size = code_item->registers_size_;
653 uint32_t idx;
654
655 if (vA > 5) {
656 LOG(ERROR) << "VFY: invalid arg count (" << vA << ") in non-range invoke)";
657 return false;
658 }
659
660 for (idx = 0; idx < vA; idx++) {
661 if (arg[idx] > registers_size) {
662 LOG(ERROR) << "VFY: invalid reg index (" << arg[idx]
663 << ") in non-range invoke (> " << registers_size << ")";
664 return false;
665 }
666 }
667
668 return true;
669}
670
jeffhaobdb76512011-09-07 11:43:16 -0700671bool DexVerifier::CheckVarArgRangeRegs(const DexFile::CodeItem* code_item,
jeffhaoba5ebb92011-08-25 17:24:37 -0700672 uint32_t vA, uint32_t vC) {
673 uint16_t registers_size = code_item->registers_size_;
674
675 /*
676 * vA/vC are unsigned 8-bit/16-bit quantities for /range instructions,
677 * so there's no risk of integer overflow when adding them here.
678 */
679 if (vA + vC > registers_size) {
680 LOG(ERROR) << "VFY: invalid reg index " << vA << "+" << vC
681 << " in range invoke (> " << registers_size << ")";
682 return false;
683 }
684
685 return true;
686}
687
jeffhaobdb76512011-09-07 11:43:16 -0700688bool DexVerifier::CheckSwitchTargets(const DexFile::CodeItem* code_item,
689 InsnFlags insn_flags[], uint32_t cur_offset) {
jeffhaoba5ebb92011-08-25 17:24:37 -0700690 const uint32_t insn_count = code_item->insns_size_;
691 const uint16_t* insns = code_item->insns_ + cur_offset;
692 const uint16_t* switch_insns;
693 uint16_t expected_signature;
694 uint32_t switch_count, table_size;
695 int32_t switch_offset, keys_offset, targets_offset;
696 int32_t offset, abs_offset;
697 uint32_t targ;
698
699 /* make sure the start of the switch is in range */
700 switch_offset = insns[1] | ((int32_t) insns[2]) << 16;
701 if ((int32_t) cur_offset + switch_offset < 0 ||
702 cur_offset + switch_offset + 2 >= insn_count) {
703 LOG(ERROR) << "VFY: invalid switch start: at " << cur_offset
704 << ", switch offset " << switch_offset << ", count "
705 << insn_count;
706 return false;
707 }
708
709 /* offset to switch table is a relative branch-style offset */
710 switch_insns = insns + switch_offset;
711
712 /* make sure the table is 32-bit aligned */
713 if ((((uint32_t) switch_insns) & 0x03) != 0) {
714 LOG(ERROR) << "VFY: unaligned switch table: at " << cur_offset
715 << ", switch offset " << switch_offset;
716 return false;
717 }
718
719 switch_count = switch_insns[1];
720
721 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
722 /* 0=sig, 1=count, 2/3=firstKey */
723 targets_offset = 4;
724 keys_offset = -1;
725 expected_signature = Instruction::kPackedSwitchSignature;
726 } else {
727 /* 0=sig, 1=count, 2..count*2 = keys */
728 keys_offset = 2;
729 targets_offset = 2 + 2 * switch_count;
730 expected_signature = Instruction::kSparseSwitchSignature;
731 }
732 table_size = targets_offset + switch_count * 2;
733
734 if (switch_insns[0] != expected_signature) {
jeffhaobdb76512011-09-07 11:43:16 -0700735 LOG(ERROR) << "VFY: wrong signature for switch table (0x" << std::hex
736 << switch_insns[0] << ", wanted 0x" << expected_signature << ")"
737 << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700738 return false;
739 }
740
741 /* make sure the end of the switch is in range */
742 if (cur_offset + switch_offset + table_size > (uint32_t) insn_count) {
743 LOG(ERROR) << "VFY: invalid switch end: at " << cur_offset
744 << ", switch offset " << switch_offset << ", end "
745 << cur_offset + switch_offset + table_size << ", count "
746 << insn_count;
747 return false;
748 }
749
750 /* for a sparse switch, verify the keys are in ascending order */
751 if (keys_offset > 0 && switch_count > 1) {
752 int32_t last_key;
753
754 last_key = switch_insns[keys_offset] |
755 (switch_insns[keys_offset + 1] << 16);
756 for (targ = 1; targ < switch_count; targ++) {
757 int32_t key = (int32_t) switch_insns[keys_offset + targ * 2] |
758 (int32_t) (switch_insns[keys_offset + targ * 2 + 1] << 16);
759 if (key <= last_key) {
760 LOG(ERROR) << "VFY: invalid packed switch: last key=" << last_key
761 << ", this=" << key;
762 return false;
763 }
764
765 last_key = key;
766 }
767 }
768
769 /* verify each switch target */
770 for (targ = 0; targ < switch_count; targ++) {
771 offset = (int32_t) switch_insns[targets_offset + targ * 2] |
772 (int32_t) (switch_insns[targets_offset + targ * 2 + 1] << 16);
773 abs_offset = cur_offset + offset;
774
775 if (abs_offset < 0 || abs_offset >= (int32_t) insn_count ||
776 !InsnIsOpcode(insn_flags, abs_offset)) {
777 LOG(ERROR) << "VFY: invalid switch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700778 << std::hex << abs_offset << ") at " << cur_offset << std::dec
779 << "[" << targ << "]";
jeffhaoba5ebb92011-08-25 17:24:37 -0700780 return false;
781 }
jeffhaobdb76512011-09-07 11:43:16 -0700782 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700783 }
784
785 return true;
786}
787
jeffhaobdb76512011-09-07 11:43:16 -0700788bool DexVerifier::CheckBranchTarget(const DexFile::CodeItem* code_item,
789 InsnFlags insn_flags[], uint32_t cur_offset) {
790 const uint32_t insn_count = code_item->insns_size_;
jeffhaoba5ebb92011-08-25 17:24:37 -0700791 int32_t offset, abs_offset;
792 bool isConditional, selfOkay;
793
794 if (!GetBranchOffset(code_item, insn_flags, cur_offset, &offset,
795 &isConditional, &selfOkay))
796 return false;
797
798 if (!selfOkay && offset == 0) {
jeffhaobdb76512011-09-07 11:43:16 -0700799 LOG(ERROR) << "VFY: branch offset of zero not allowed at" << std::hex
800 << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700801 return false;
802 }
803
804 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700805 * Check for 32-bit overflow. This isn't strictly necessary if we can
jeffhaoba5ebb92011-08-25 17:24:37 -0700806 * depend on the VM to have identical "wrap-around" behavior, but
807 * it's unwise to depend on that.
808 */
809 if (((int64_t) cur_offset + (int64_t) offset) !=
jeffhaobdb76512011-09-07 11:43:16 -0700810 (int64_t) (cur_offset + offset)) {
811 LOG(ERROR) << "VFY: branch target overflow " << std::hex << cur_offset
812 << std::dec << " +" << offset;
jeffhaoba5ebb92011-08-25 17:24:37 -0700813 return false;
814 }
815 abs_offset = cur_offset + offset;
jeffhaobdb76512011-09-07 11:43:16 -0700816 if (abs_offset < 0 || (uint32_t) abs_offset >= insn_count ||
jeffhaoba5ebb92011-08-25 17:24:37 -0700817 !InsnIsOpcode(insn_flags, abs_offset))
818 {
819 LOG(ERROR) << "VFY: invalid branch target " << offset << " (-> "
jeffhaobdb76512011-09-07 11:43:16 -0700820 << std::hex << abs_offset << ") at " << cur_offset << std::dec;
jeffhaoba5ebb92011-08-25 17:24:37 -0700821 return false;
822 }
jeffhaobdb76512011-09-07 11:43:16 -0700823 InsnSetBranchTarget(insn_flags, abs_offset);
jeffhaoba5ebb92011-08-25 17:24:37 -0700824
825 return true;
826}
827
jeffhaobdb76512011-09-07 11:43:16 -0700828bool DexVerifier::InitRegisterTable(VerifierData* vdata,
829 RegisterTable* reg_table, RegisterTrackingMode track_regs_for) {
830 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700831 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -0700832 uint16_t registers_size = code_item->registers_size_;
833 uint32_t insns_size = code_item->insns_size_;
834 uint32_t i;
835
836 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700837 * Every address gets a RegisterLine struct. This is wasteful, but
jeffhaobdb76512011-09-07 11:43:16 -0700838 * not so much that it's worth chasing through an extra level of
839 * indirection.
840 */
841 reg_table->insn_reg_count_plus_ = registers_size + kExtraRegs;
Elliott Hughes5fe594f2011-09-08 12:33:17 -0700842 reg_table->register_lines_.reset(new RegisterLine[insns_size]());
jeffhaobdb76512011-09-07 11:43:16 -0700843
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700844 DCHECK_GT(insns_size, 0U);
jeffhaobdb76512011-09-07 11:43:16 -0700845
846 bool track_monitors;
847 //if (gDvm.monitorVerification) {
848 //track_monitors = (vdata->monitor_enter_count_ != 0);
849 //} else {
850 track_monitors = false;
851 //}
852
853 /*
854 * Allocate entries in the sparse register line table.
855 *
856 * There is a RegisterLine associated with every address, but not
857 * every RegisterLine has non-NULL pointers to storage for its fields.
858 */
859 for (i = 0; i < insns_size; i++) {
860 bool interesting;
861
862 switch (track_regs_for) {
863 case kTrackRegsAll:
864 interesting = InsnIsOpcode(insn_flags, i);
865 break;
866 case kTrackRegsGcPoints:
867 interesting = InsnIsGcPoint(insn_flags, i) ||
868 InsnIsBranchTarget(insn_flags, i);
869 break;
870 case kTrackRegsBranches:
871 interesting = InsnIsBranchTarget(insn_flags, i);
872 break;
873 default:
874 return false;
875 }
876
877 if (interesting) {
878 reg_table->register_lines_[i].Alloc(reg_table->insn_reg_count_plus_,
879 track_monitors);
880 }
881 }
882
883 /*
884 * Allocate space for our "temporary" register lines.
885 */
886 reg_table->work_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
887 reg_table->saved_line_.Alloc(reg_table->insn_reg_count_plus_, track_monitors);
888
889 return true;
890}
891
892DexVerifier::UninitInstanceMap* DexVerifier::CreateUninitInstanceMap(
893 VerifierData* vdata) {
894 Method* method = vdata->method_;
895 const DexFile::CodeItem* code_item = vdata->code_item_;
896 size_t new_instance_count = vdata->new_instance_count_;
897
898 if (IsInitMethod(method)) {
899 new_instance_count++;
900 }
901
902 /*
903 * Allocate the header and map as a single unit.
904 *
905 * TODO: consider having a static instance so we can avoid allocations.
906 * I don't think the verifier is guaranteed to be single-threaded when
907 * running in the VM (rather than dexopt), so that must be taken into
908 * account.
909 */
910 UninitInstanceMap* uninit_map = new UninitInstanceMap(new_instance_count);
911
912 size_t idx = 0;
913 if (IsInitMethod(method)) {
914 uninit_map->map_[idx++].addr_ = kUninitThisArgAddr;
915 }
916
917 /*
918 * Run through and find the new-instance instructions.
919 */
920 uint32_t addr = 0;
921 uint32_t insns_size = code_item->insns_size_;
922 const byte* ptr = reinterpret_cast<const byte*>(code_item->insns_);
jeffhaoba5ebb92011-08-25 17:24:37 -0700923 const Instruction* inst = Instruction::At(ptr);
jeffhaobdb76512011-09-07 11:43:16 -0700924 while (addr < insns_size) {
925 Instruction::Code opcode = inst->Opcode();
926 if (opcode == Instruction::NEW_INSTANCE) {
927 uninit_map->map_[idx++].addr_ = addr;
928 }
jeffhaoba5ebb92011-08-25 17:24:37 -0700929
jeffhaobdb76512011-09-07 11:43:16 -0700930 addr += inst->Size();
jeffhaoba5ebb92011-08-25 17:24:37 -0700931 inst = inst->Next();
932 }
933
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700934 CHECK_EQ(idx, new_instance_count);
jeffhaobdb76512011-09-07 11:43:16 -0700935 return uninit_map;
936}
937
938bool DexVerifier::IsInitMethod(const Method* method) {
939 return (method->GetName()->Equals("<init>"));
940}
941
942Class* DexVerifier::LookupClassByDescriptor(const Method* method,
943 const char* descriptor, VerifyError* failure) {
944 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700945 * The compiler occasionally puts references to nonexistent classes in
946 * signatures. For example, if you have a non-static inner class with no
947 * constructor, the compiler provides a private <init> for you.
948 * Constructing the class requires <init>(parent), but the outer class can't
949 * call that because the method is private. So the compiler generates a
950 * package-scope <init>(parent,bogus) method that just calls the regular
951 * <init> (the "bogus" part being necessary to distinguish the signature of
952 * the synthetic method). Treating the bogus class as an instance of
953 * java.lang.Object allows the verifier to process the class successfully.
jeffhaobdb76512011-09-07 11:43:16 -0700954 */
955 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
956 const ClassLoader* class_loader =
957 method->GetDeclaringClass()->GetClassLoader();
958 Class* klass = class_linker->FindClass(descriptor, class_loader);
959
960 if (klass == NULL) {
961 Thread::Current()->ClearException();
962 if (strchr(descriptor, '$') != NULL) {
963 LOG(INFO) << "VFY: unable to find class referenced in signature ("
964 << descriptor << ")";
965 } else {
966 LOG(ERROR) << "VFY: unable to find class referenced in signature ("
967 << descriptor << ")";
968 }
969
970 /* Check if the descriptor is an array. */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700971 if (descriptor[0] == '[' && descriptor[1] != '\0') {
jeffhaobdb76512011-09-07 11:43:16 -0700972 /*
973 * There should never be a problem loading primitive arrays.
974 */
975 if (descriptor[1] != 'L' && descriptor[1] != '[') {
976 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor
977 << "'";
978 *failure = VERIFY_ERROR_GENERIC;
979 }
980
981 /*
jeffhaod1f0fde2011-09-08 17:25:33 -0700982 * Try to continue with base array type. This will let us pass basic
983 * stuff (e.g. get array len) that wouldn't fly with an Object. This
984 * is NOT correct if the missing type is a primitive array, but we
985 * should never have a problem loading those. (I'm not convinced this
986 * is correct or even useful. Just use Object here?)
jeffhaobdb76512011-09-07 11:43:16 -0700987 */
988 klass = class_linker->FindClass("[Ljava/lang/Object;", class_loader);
989 } else if (descriptor[0] == 'L') {
990 /*
991 * We are looking at a non-array reference descriptor;
992 * try to continue with base reference type.
993 */
994 klass = class_linker->FindSystemClass("Ljava/lang/Object;");
995 } else {
996 /* We are looking at a primitive type. */
997 LOG(ERROR) << "VFY: invalid char in signature in '" << descriptor << "'";
998 *failure = VERIFY_ERROR_GENERIC;
999 }
1000
1001 if (klass == NULL) {
1002 *failure = VERIFY_ERROR_GENERIC;
1003 }
1004 }
1005
1006 if (klass->IsPrimitive()) {
1007 LOG(ERROR) << "VFY: invalid use of primitive type '" << descriptor << "'";
1008 *failure = VERIFY_ERROR_GENERIC;
1009 klass = NULL;
1010 }
1011
1012 return klass;
1013}
1014
1015Class* DexVerifier::LookupSignatureClass(const Method* method, std::string sig,
1016 VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001017 DCHECK_EQ(sig[0], 'L');
jeffhaobdb76512011-09-07 11:43:16 -07001018 size_t end = sig.find(';');
1019
1020 if (end == std::string::npos) {
1021 LOG(ERROR) << "VFY: bad signature component '" << sig << "' (missing ';')";
1022 *failure = VERIFY_ERROR_GENERIC;
1023 return NULL;
1024 }
1025
1026 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1027 failure);
1028}
1029
1030Class* DexVerifier::LookupSignatureArrayClass(const Method* method,
1031 std::string sig, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001032 DCHECK_EQ(sig[0], '[');
jeffhaobdb76512011-09-07 11:43:16 -07001033 size_t end = 0;
1034
1035 while (sig[end] == '[')
1036 end++;
1037
1038 if (sig[end] == 'L') {
1039 end = sig.find(';');
1040 if (end == std::string::npos) {
1041 LOG(ERROR) << "VFY: bad signature component '" << sig
1042 << "' (missing ';')";
1043 *failure = VERIFY_ERROR_GENERIC;
1044 return NULL;
1045 }
1046 }
1047
1048 return LookupClassByDescriptor(method, sig.substr(0, end + 1).c_str(),
1049 failure);
1050}
1051
1052bool DexVerifier::SetTypesFromSignature(VerifierData* vdata, RegType* reg_types)
1053{
1054 Method* method = vdata->method_;
1055 const DexFile* dex_file = vdata->dex_file_;
1056 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001057 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001058
1059 int arg_start = code_item->registers_size_ - code_item->ins_size_;
1060 int expected_args = code_item->ins_size_; /* long/double count as two */
1061 int actual_args = 0;
1062
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001063 DCHECK_GE(arg_start, 0); /* should have been verified earlier */
jeffhaobdb76512011-09-07 11:43:16 -07001064
1065 /*
1066 * Include the "this" pointer.
1067 */
1068 if (!method->IsStatic()) {
1069 /*
1070 * If this is a constructor for a class other than java.lang.Object,
jeffhaod1f0fde2011-09-08 17:25:33 -07001071 * mark the first ("this") argument as uninitialized. This restricts
jeffhaobdb76512011-09-07 11:43:16 -07001072 * field access until the superclass constructor is called.
1073 */
1074 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1075 Class* klass_object = class_linker->FindSystemClass("Ljava/lang/Object;");
1076 if (IsInitMethod(method) && method->GetDeclaringClass() != klass_object) {
1077 int idx = SetUninitInstance(uninit_map, kUninitThisArgAddr,
1078 method->GetDeclaringClass());
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001079 DCHECK_EQ(idx, 0);
jeffhaobdb76512011-09-07 11:43:16 -07001080 reg_types[arg_start + actual_args] = RegTypeFromUninitIndex(idx);
1081 } else {
1082 reg_types[arg_start + actual_args] =
1083 RegTypeFromClass(method->GetDeclaringClass());
1084 }
1085 actual_args++;
1086 }
1087
1088 const DexFile::ProtoId& proto_id =
1089 dex_file->GetProtoId(method->GetProtoIdx());
1090 DexFile::ParameterIterator iterator(*dex_file, proto_id);
1091 VerifyError failure = VERIFY_ERROR_NONE;
1092
1093 for (; iterator.HasNext(); iterator.Next()) {
1094 const char* descriptor = iterator.GetDescriptor();
1095
1096 if (descriptor == NULL) {
1097 break;
1098 }
1099
1100 if (actual_args >= expected_args) {
1101 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
1102 << descriptor << ")";
1103 return false;
1104 }
1105
1106 switch (*descriptor) {
1107 case 'L':
1108 case '[':
1109 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001110 * We assume that reference arguments are initialized. The only way
1111 * it could be otherwise (assuming the caller was verified) is if
1112 * the current method is <init>, but in that case it's effectively
1113 * considered initialized the instant we reach here (in the sense
1114 * that we can return without doing anything or call virtual methods).
jeffhaobdb76512011-09-07 11:43:16 -07001115 */
1116 {
1117 Class* klass =
1118 LookupClassByDescriptor(method, descriptor, &failure);
1119 if (failure != VERIFY_ERROR_NONE)
1120 return false;
1121 reg_types[arg_start + actual_args] = RegTypeFromClass(klass);
1122 }
1123 actual_args++;
1124 break;
1125 case 'Z':
1126 reg_types[arg_start + actual_args] = kRegTypeBoolean;
1127 actual_args++;
1128 break;
1129 case 'C':
1130 reg_types[arg_start + actual_args] = kRegTypeChar;
1131 actual_args++;
1132 break;
1133 case 'B':
1134 reg_types[arg_start + actual_args] = kRegTypeByte;
1135 actual_args++;
1136 break;
1137 case 'I':
1138 reg_types[arg_start + actual_args] = kRegTypeInteger;
1139 actual_args++;
1140 break;
1141 case 'S':
1142 reg_types[arg_start + actual_args] = kRegTypeShort;
1143 actual_args++;
1144 break;
1145 case 'F':
1146 reg_types[arg_start + actual_args] = kRegTypeFloat;
1147 actual_args++;
1148 break;
1149 case 'D':
1150 reg_types[arg_start + actual_args] = kRegTypeDoubleLo;
1151 reg_types[arg_start + actual_args +1] = kRegTypeDoubleHi;
1152 actual_args += 2;
1153 break;
1154 case 'J':
1155 reg_types[arg_start + actual_args] = kRegTypeLongLo;
1156 reg_types[arg_start + actual_args +1] = kRegTypeLongHi;
1157 actual_args += 2;
1158 break;
1159 default:
1160 LOG(ERROR) << "VFY: unexpected signature type char '" << descriptor
1161 << "'";
1162 return false;
1163 }
1164 }
1165
1166 if (actual_args != expected_args) {
1167 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
1168 << actual_args;
jeffhaoba5ebb92011-08-25 17:24:37 -07001169 return false;
1170 }
1171
jeffhaobdb76512011-09-07 11:43:16 -07001172 const char* descriptor = dex_file->GetReturnTypeDescriptor(proto_id);
1173
1174 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001175 * Validate return type. We don't do the type lookup; just want to make
1176 * sure that it has the right format. Only major difference from the
jeffhaobdb76512011-09-07 11:43:16 -07001177 * method argument format is that 'V' is supported.
1178 */
1179 switch (*descriptor) {
1180 case 'I':
1181 case 'C':
1182 case 'S':
1183 case 'B':
1184 case 'Z':
1185 case 'V':
1186 case 'F':
1187 case 'D':
1188 case 'J':
1189 if (*(descriptor + 1) != '\0')
1190 return false;
1191 break;
1192 case '[':
1193 /* single/multi, object/primitive */
1194 while (*++descriptor == '[')
1195 ;
1196 if (*descriptor == 'L') {
1197 while (*++descriptor != ';' && *descriptor != '\0')
1198 ;
1199 if (*descriptor != ';')
1200 return false;
1201 } else {
1202 if (*(descriptor+1) != '\0')
1203 return false;
1204 }
1205 break;
1206 case 'L':
1207 /* could be more thorough here, but shouldn't be required */
1208 while (*++descriptor != ';' && *descriptor != '\0')
1209 ;
1210 if (*descriptor != ';')
1211 return false;
1212 break;
1213 default:
1214 return false;
1215 }
1216
jeffhaoba5ebb92011-08-25 17:24:37 -07001217 return true;
1218}
1219
jeffhaobdb76512011-09-07 11:43:16 -07001220int DexVerifier::SetUninitInstance(UninitInstanceMap* uninit_map, int addr,
1221 Class* klass) {
1222 int idx;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001223 DCHECK(klass != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07001224
jeffhaod1f0fde2011-09-08 17:25:33 -07001225 /* TODO: binary search when num_entries > 8 */
jeffhaobdb76512011-09-07 11:43:16 -07001226 for (idx = uninit_map->num_entries_ - 1; idx >= 0; idx--) {
1227 if (uninit_map->map_[idx].addr_ == addr) {
1228 if (uninit_map->map_[idx].klass_ != NULL &&
1229 uninit_map->map_[idx].klass_ != klass) {
1230 LOG(ERROR) << "VFY: addr " << addr << " already set to "
1231 << (int) uninit_map->map_[idx].klass_ << ", not setting to "
1232 << (int) klass;
1233 return -1; // already set to something else??
1234 }
1235 uninit_map->map_[idx].klass_ = klass;
1236 return idx;
1237 }
1238 }
1239
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001240 LOG(FATAL) << "VFY: addr " << addr << " not found in uninit map";
jeffhaobdb76512011-09-07 11:43:16 -07001241 return -1;
1242}
1243
1244bool DexVerifier::CodeFlowVerifyMethod(VerifierData* vdata,
1245 RegisterTable* reg_table) {
1246 const Method* method = vdata->method_;
1247 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001248 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001249 const uint16_t* insns = code_item->insns_;
jeffhaoba5ebb92011-08-25 17:24:37 -07001250 uint32_t insns_size = code_item->insns_size_;
jeffhaobdb76512011-09-07 11:43:16 -07001251 size_t insn_idx, start_guess;
jeffhaoba5ebb92011-08-25 17:24:37 -07001252
jeffhaobdb76512011-09-07 11:43:16 -07001253 /* Begin by marking the first instruction as "changed". */
1254 InsnSetChanged(insn_flags, 0, true);
jeffhaoba5ebb92011-08-25 17:24:37 -07001255
jeffhaobdb76512011-09-07 11:43:16 -07001256 start_guess = 0;
jeffhaoba5ebb92011-08-25 17:24:37 -07001257
jeffhaobdb76512011-09-07 11:43:16 -07001258 /* Continue until no instructions are marked "changed". */
1259 while (true) {
1260 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001261 * Find the first marked one. Use "start_guess" as a way to find
jeffhaobdb76512011-09-07 11:43:16 -07001262 * one quickly.
1263 */
1264 for (insn_idx = start_guess; insn_idx < insns_size; insn_idx++) {
1265 if (InsnIsChanged(insn_flags, insn_idx))
1266 break;
1267 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001268
jeffhaobdb76512011-09-07 11:43:16 -07001269 if (insn_idx == insns_size) {
1270 if (start_guess != 0) {
1271 /* try again, starting from the top */
1272 start_guess = 0;
1273 continue;
1274 } else {
1275 /* all flags are clear */
1276 break;
1277 }
1278 }
1279
1280 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001281 * We carry the working set of registers from instruction to instruction.
1282 * If this address can be the target of a branch (or throw) instruction,
1283 * or if we're skipping around chasing "changed" flags, we need to load
1284 * the set of registers from the table.
jeffhaobdb76512011-09-07 11:43:16 -07001285 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001286 * Because we always prefer to continue on to the next instruction, we
1287 * should never have a situation where we have a stray "changed" flag set
1288 * on an instruction that isn't a branch target.
jeffhaobdb76512011-09-07 11:43:16 -07001289 */
1290 if (InsnIsBranchTarget(insn_flags, insn_idx)) {
1291 RegisterLine* work_line = &reg_table->work_line_;
1292 CopyLineFromTable(work_line, reg_table, insn_idx);
1293 } else {
1294#ifndef NDEBUG
1295 /*
1296 * Sanity check: retrieve the stored register line (assuming
1297 * a full table) and make sure it actually matches.
1298 */
1299 RegisterLine* register_line = GetRegisterLine(reg_table, insn_idx);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001300 if (register_line->reg_types_.get() != NULL && CompareLineToTable(reg_table,
jeffhaobdb76512011-09-07 11:43:16 -07001301 insn_idx, &reg_table->work_line_) != 0) {
jeffhao2a8a90e2011-09-26 14:25:31 -07001302 LOG(ERROR) << "HUH? work_line diverged in " << PrettyMethod(method);
jeffhaobdb76512011-09-07 11:43:16 -07001303 }
1304#endif
1305 }
1306
1307 if (!CodeFlowVerifyInstruction(vdata, reg_table, insn_idx, &start_guess)) {
jeffhao2a8a90e2011-09-26 14:25:31 -07001308 LOG(ERROR) << "VFY: failure to verify " << PrettyMethod(method);
jeffhaoba5ebb92011-08-25 17:24:37 -07001309 return false;
1310 }
1311
jeffhaobdb76512011-09-07 11:43:16 -07001312 /* Clear "changed" and mark as visited. */
1313 InsnSetVisited(insn_flags, insn_idx, true);
1314 InsnSetChanged(insn_flags, insn_idx, false);
1315 }
jeffhaoba5ebb92011-08-25 17:24:37 -07001316
jeffhaobdb76512011-09-07 11:43:16 -07001317 if (DEAD_CODE_SCAN && ((method->GetAccessFlags() & kAccWritable) == 0)) {
1318 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001319 * Scan for dead code. There's nothing "evil" about dead code
jeffhaobdb76512011-09-07 11:43:16 -07001320 * (besides the wasted space), but it indicates a flaw somewhere
1321 * down the line, possibly in the verifier.
1322 *
1323 * If we've substituted "always throw" instructions into the stream,
1324 * we are almost certainly going to have some dead code.
1325 */
1326 int dead_start = -1;
1327 for (insn_idx = 0; insn_idx < insns_size;
1328 insn_idx += InsnGetWidth(insn_flags, insn_idx)) {
1329 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001330 * Switch-statement data doesn't get "visited" by scanner. It
jeffhaobdb76512011-09-07 11:43:16 -07001331 * may or may not be preceded by a padding NOP (for alignment).
1332 */
1333 if (insns[insn_idx] == Instruction::kPackedSwitchSignature ||
1334 insns[insn_idx] == Instruction::kSparseSwitchSignature ||
1335 insns[insn_idx] == Instruction::kArrayDataSignature ||
1336 (insns[insn_idx] == Instruction::NOP &&
1337 (insns[insn_idx + 1] == Instruction::kPackedSwitchSignature ||
1338 insns[insn_idx + 1] == Instruction::kSparseSwitchSignature ||
1339 insns[insn_idx + 1] == Instruction::kArrayDataSignature))) {
1340 InsnSetVisited(insn_flags, insn_idx, true);
1341 }
1342
1343 if (!InsnIsVisited(insn_flags, insn_idx)) {
1344 if (dead_start < 0)
1345 dead_start = insn_idx;
1346 } else 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);
jeffhaobdb76512011-09-07 11:43:16 -07001349 dead_start = -1;
1350 }
1351 }
1352 if (dead_start >= 0) {
jeffhaobdb76512011-09-07 11:43:16 -07001353 LOG(INFO) << "VFY: dead code 0x" << std::hex << dead_start << "-"
jeffhao2a8a90e2011-09-26 14:25:31 -07001354 << insn_idx - 1 << std::dec << " in " << PrettyMethod(method);
jeffhaoba5ebb92011-08-25 17:24:37 -07001355 }
1356 }
1357
jeffhaobdb76512011-09-07 11:43:16 -07001358 return true;
1359}
1360
1361bool DexVerifier::CodeFlowVerifyInstruction(VerifierData* vdata,
1362 RegisterTable* reg_table, uint32_t insn_idx, size_t* start_guess) {
1363 const Method* method = vdata->method_;
1364 Class* klass = method->GetDeclaringClass();
1365 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001366 InsnFlags* insn_flags = vdata->insn_flags_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001367 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001368 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07001369 const uint16_t* insns = code_item->insns_ + insn_idx;
1370 uint32_t insns_size = code_item->insns_size_;
1371 uint32_t registers_size = code_item->registers_size_;
1372
1373#ifdef VERIFIER_STATS
1374 if (InsnIsVisited(insn_flags, insn_idx)) {
1375 gDvm.verifierStats.instrsReexamined++;
1376 } else {
1377 gDvm.verifierStats.instrsExamined++;
1378 }
1379#endif
1380
1381 /*
1382 * Once we finish decoding the instruction, we need to figure out where
jeffhaod1f0fde2011-09-08 17:25:33 -07001383 * we can go from here. There are three possible ways to transfer
jeffhaobdb76512011-09-07 11:43:16 -07001384 * control to another statement:
1385 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001386 * (1) Continue to the next instruction. Applies to all but
jeffhaobdb76512011-09-07 11:43:16 -07001387 * unconditional branches, method returns, and exception throws.
jeffhaod1f0fde2011-09-08 17:25:33 -07001388 * (2) Branch to one or more possible locations. Applies to branches
jeffhaobdb76512011-09-07 11:43:16 -07001389 * and switch statements.
jeffhaod1f0fde2011-09-08 17:25:33 -07001390 * (3) Exception handlers. Applies to any instruction that can
jeffhaobdb76512011-09-07 11:43:16 -07001391 * throw an exception that is handled by an encompassing "try"
1392 * block.
1393 *
1394 * We can also return, in which case there is no successor instruction
1395 * from this point.
1396 *
1397 * The behavior can be determined from the OpcodeFlags.
1398 */
1399 RegisterLine* work_line = &reg_table->work_line_;
1400 const DexFile* dex_file = vdata->dex_file_;
1401 const byte* ptr = reinterpret_cast<const byte*>(insns);
1402 const Instruction* inst = Instruction::At(ptr);
1403 Instruction::DecodedInstruction dec_insn(inst);
1404 int opcode_flag = inst->Flag();
1405
1406 Class* res_class;
1407 int32_t branch_target = 0;
1408 RegType tmp_type;
1409 bool just_set_result = false;
1410 VerifyError failure = VERIFY_ERROR_NONE;
1411
1412 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001413 * Make a copy of the previous register state. If the instruction
jeffhaobdb76512011-09-07 11:43:16 -07001414 * can throw an exception, we will copy/merge this into the "catch"
1415 * address rather than work_line, because we don't want the result
1416 * from the "successful" code path (e.g. a check-cast that "improves"
1417 * a type) to be visible to the exception handler.
1418 */
1419 if ((opcode_flag & Instruction::kThrow) != 0 &&
1420 InsnIsInTry(insn_flags, insn_idx)) {
1421 CopyRegisterLine(&reg_table->saved_line_, work_line,
1422 reg_table->insn_reg_count_plus_);
1423 } else {
1424#ifndef NDEBUG
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001425 memset(reg_table->saved_line_.reg_types_.get(), 0xdd,
jeffhaobdb76512011-09-07 11:43:16 -07001426 reg_table->insn_reg_count_plus_ * sizeof(RegType));
1427#endif
1428 }
1429
1430 switch (dec_insn.opcode_) {
1431 case Instruction::NOP:
1432 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001433 * A "pure" NOP has no effect on anything. Data tables start with
jeffhaobdb76512011-09-07 11:43:16 -07001434 * a signature that looks like a NOP; if we see one of these in
1435 * the course of executing code then we have a problem.
1436 */
1437 if (dec_insn.vA_ != 0) {
1438 LOG(ERROR) << "VFY: encountered data table in instruction stream";
1439 failure = VERIFY_ERROR_GENERIC;
1440 }
1441 break;
1442
1443 case Instruction::MOVE:
1444 case Instruction::MOVE_FROM16:
1445 case Instruction::MOVE_16:
1446 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategory1nr,
1447 &failure);
1448 break;
1449 case Instruction::MOVE_WIDE:
1450 case Instruction::MOVE_WIDE_FROM16:
1451 case Instruction::MOVE_WIDE_16:
1452 CopyRegister2(work_line, dec_insn.vA_, dec_insn.vB_, &failure);
1453 break;
1454 case Instruction::MOVE_OBJECT:
1455 case Instruction::MOVE_OBJECT_FROM16:
1456 case Instruction::MOVE_OBJECT_16:
1457 CopyRegister1(work_line, dec_insn.vA_, dec_insn.vB_, kTypeCategoryRef,
1458 &failure);
1459 break;
1460
1461 /*
1462 * The move-result instructions copy data out of a "pseudo-register"
jeffhaod1f0fde2011-09-08 17:25:33 -07001463 * with the results from the last method invocation. In practice we
jeffhaobdb76512011-09-07 11:43:16 -07001464 * might want to hold the result in an actual CPU register, so the
1465 * Dalvik spec requires that these only appear immediately after an
1466 * invoke or filled-new-array.
1467 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001468 * These calls invalidate the "result" register. (This is now
jeffhaobdb76512011-09-07 11:43:16 -07001469 * redundant with the reset done below, but it can make the debug info
1470 * easier to read in some cases.)
1471 */
1472 case Instruction::MOVE_RESULT:
1473 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1474 kTypeCategory1nr, &failure);
1475 break;
1476 case Instruction::MOVE_RESULT_WIDE:
1477 CopyResultRegister2(work_line, registers_size, dec_insn.vA_, &failure);
1478 break;
1479 case Instruction::MOVE_RESULT_OBJECT:
1480 CopyResultRegister1(work_line, registers_size, dec_insn.vA_,
1481 kTypeCategoryRef, &failure);
1482 break;
1483
1484 case Instruction::MOVE_EXCEPTION:
1485 /*
1486 * This statement can only appear as the first instruction in an
1487 * exception handler (though not all exception handlers need to
jeffhaod1f0fde2011-09-08 17:25:33 -07001488 * have one of these). We verify that as part of extracting the
jeffhaobdb76512011-09-07 11:43:16 -07001489 * exception type from the catch block list.
1490 *
1491 * "res_class" will hold the closest common superclass of all
1492 * exceptions that can be handled here.
1493 */
1494 res_class = GetCaughtExceptionType(vdata, insn_idx, &failure);
1495 if (res_class == NULL) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001496 DCHECK(failure != VERIFY_ERROR_NONE);
jeffhaobdb76512011-09-07 11:43:16 -07001497 } else {
1498 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1499 }
1500 break;
1501
1502 case Instruction::RETURN_VOID:
1503 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1504 failure = VERIFY_ERROR_GENERIC;
1505 } else if (GetMethodReturnType(dex_file, method) != kRegTypeUnknown) {
1506 LOG(ERROR) << "VFY: return-void not expected";
1507 failure = VERIFY_ERROR_GENERIC;
1508 }
1509 break;
1510 case Instruction::RETURN:
1511 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1512 failure = VERIFY_ERROR_GENERIC;
1513 } else {
1514 /* check the method signature */
1515 RegType return_type = GetMethodReturnType(dex_file, method);
1516 CheckTypeCategory(return_type, kTypeCategory1nr, &failure);
1517 if (failure != VERIFY_ERROR_NONE)
1518 LOG(ERROR) << "VFY: return-1nr not expected";
1519
1520 /*
1521 * compiler may generate synthetic functions that write byte
1522 * values into boolean fields. Also, it may use integer values
1523 * for boolean, byte, short, and character return types.
1524 */
1525 RegType src_type = GetRegisterType(work_line, dec_insn.vA_);
1526 if ((return_type == kRegTypeBoolean && src_type == kRegTypeByte) ||
1527 ((return_type == kRegTypeBoolean || return_type == kRegTypeByte ||
1528 return_type == kRegTypeShort || return_type == kRegTypeChar) &&
1529 src_type == kRegTypeInteger))
1530 return_type = src_type;
1531
1532 /* check the register contents */
1533 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1534 if (failure != VERIFY_ERROR_NONE) {
1535 LOG(ERROR) << "VFY: return-1nr on invalid register v" << dec_insn.vA_;
1536 }
1537 }
1538 break;
1539 case Instruction::RETURN_WIDE:
1540 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1541 failure = VERIFY_ERROR_GENERIC;
1542 } else {
1543 RegType return_type;
1544
1545 /* check the method signature */
1546 return_type = GetMethodReturnType(dex_file, method);
1547 CheckTypeCategory(return_type, kTypeCategory2, &failure);
1548 if (failure != VERIFY_ERROR_NONE)
1549 LOG(ERROR) << "VFY: return-wide not expected";
1550
1551 /* check the register contents */
1552 VerifyRegisterType(work_line, dec_insn.vA_, return_type, &failure);
1553 if (failure != VERIFY_ERROR_NONE) {
1554 LOG(ERROR) << "VFY: return-wide on invalid register pair v"
1555 << dec_insn.vA_;
1556 }
1557 }
1558 break;
1559 case Instruction::RETURN_OBJECT:
1560 if (!CheckConstructorReturn(method, work_line, registers_size)) {
1561 failure = VERIFY_ERROR_GENERIC;
1562 } else {
1563 RegType return_type = GetMethodReturnType(dex_file, method);
1564 CheckTypeCategory(return_type, kTypeCategoryRef, &failure);
1565 if (failure != VERIFY_ERROR_NONE) {
1566 LOG(ERROR) << "VFY: return-object not expected";
1567 break;
1568 }
1569
1570 /* return_type is the *expected* return type, not register value */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001571 DCHECK(return_type != kRegTypeZero);
1572 DCHECK(!RegTypeIsUninitReference(return_type));
jeffhaobdb76512011-09-07 11:43:16 -07001573
1574 /*
1575 * Verify that the reference in vAA is an instance of the type
jeffhaod1f0fde2011-09-08 17:25:33 -07001576 * in "return_type". The Zero type is allowed here. If the
jeffhaobdb76512011-09-07 11:43:16 -07001577 * method is declared to return an interface, then any
1578 * initialized reference is acceptable.
1579 *
1580 * Note GetClassFromRegister fails if the register holds an
1581 * uninitialized reference, so we do not allow them to be
1582 * returned.
1583 */
1584 Class* decl_class = RegTypeInitializedReferenceToClass(return_type);
1585 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1586 if (failure != VERIFY_ERROR_NONE)
1587 break;
1588 if (res_class != NULL) {
1589 if (!decl_class->IsInterface() &&
jeffhaobdb76512011-09-07 11:43:16 -07001590 !decl_class->IsAssignableFrom(res_class)) {
1591 LOG(ERROR) << "VFY: returning " << std::hex
1592 << res_class->GetDescriptor()->ToModifiedUtf8()
1593 << " (cl=0x" << (int) res_class->GetClassLoader()
1594 << "), declared "
1595 << decl_class->GetDescriptor()->ToModifiedUtf8()
1596 << " (cl=0x" << (int) decl_class->GetClassLoader()
1597 << ")" << std::dec;
1598 failure = VERIFY_ERROR_GENERIC;
1599 break;
1600 }
1601 }
1602 }
1603 break;
1604
1605 case Instruction::CONST_4:
1606 case Instruction::CONST_16:
1607 case Instruction::CONST:
1608 /* could be boolean, int, float, or a null reference */
1609 SetRegisterType(work_line, dec_insn.vA_,
1610 DetermineCat1Const((int32_t) dec_insn.vB_));
1611 break;
1612 case Instruction::CONST_HIGH16:
1613 /* could be boolean, int, float, or a null reference */
1614 SetRegisterType(work_line, dec_insn.vA_,
1615 DetermineCat1Const((int32_t) dec_insn.vB_ << 16));
1616 break;
1617 case Instruction::CONST_WIDE_16:
1618 case Instruction::CONST_WIDE_32:
1619 case Instruction::CONST_WIDE:
1620 case Instruction::CONST_WIDE_HIGH16:
1621 /* could be long or double; resolved upon use */
1622 SetRegisterType(work_line, dec_insn.vA_, kRegTypeConstLo);
1623 break;
1624 case Instruction::CONST_STRING:
1625 case Instruction::CONST_STRING_JUMBO:
1626 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1627 class_linker->FindSystemClass("Ljava/lang/String;")));
1628 break;
1629 case Instruction::CONST_CLASS:
1630 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001631 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001632 if (res_class == NULL) {
1633 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1634 LOG(ERROR) << "VFY: unable to resolve const-class " << dec_insn.vB_
1635 << " (" << bad_class_desc << ") in "
1636 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001637 DCHECK(failure != VERIFY_ERROR_GENERIC);
1638 } else {
1639 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(
1640 class_linker->FindSystemClass("Ljava/lang/Class;")));
jeffhaobdb76512011-09-07 11:43:16 -07001641 }
1642 break;
1643
1644 case Instruction::MONITOR_ENTER:
1645 HandleMonitorEnter(work_line, dec_insn.vA_, insn_idx, &failure);
1646 break;
1647 case Instruction::MONITOR_EXIT:
1648 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07001649 * monitor-exit instructions are odd. They can throw exceptions,
jeffhaobdb76512011-09-07 11:43:16 -07001650 * but when they do they act as if they succeeded and the PC is
jeffhaod1f0fde2011-09-08 17:25:33 -07001651 * pointing to the following instruction. (This behavior goes back
jeffhaobdb76512011-09-07 11:43:16 -07001652 * to the need to handle asynchronous exceptions, a now-deprecated
1653 * feature that Dalvik doesn't support.)
1654 *
jeffhaod1f0fde2011-09-08 17:25:33 -07001655 * In practice we don't need to worry about this. The only
jeffhaobdb76512011-09-07 11:43:16 -07001656 * exceptions that can be thrown from monitor-exit are for a
jeffhaod1f0fde2011-09-08 17:25:33 -07001657 * null reference and -exit without a matching -enter. If the
jeffhaobdb76512011-09-07 11:43:16 -07001658 * structured locking checks are working, the former would have
1659 * failed on the -enter instruction, and the latter is impossible.
1660 *
1661 * This is fortunate, because issue 3221411 prevents us from
1662 * chasing the "can throw" path when monitor verification is
jeffhaod1f0fde2011-09-08 17:25:33 -07001663 * enabled. If we can fully verify the locking we can ignore
jeffhaobdb76512011-09-07 11:43:16 -07001664 * some catch blocks (which will show up as "dead" code when
1665 * we skip them here); if we can't, then the code path could be
1666 * "live" so we still need to check it.
1667 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07001668 if (work_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07001669 opcode_flag &= ~Instruction::kThrow;
1670 HandleMonitorExit(work_line, dec_insn.vA_, insn_idx, &failure);
1671 break;
1672
1673 case Instruction::CHECK_CAST:
1674 /*
1675 * If this instruction succeeds, we will promote register vA to
jeffhaod1f0fde2011-09-08 17:25:33 -07001676 * the type in vB. (This could be a demotion -- not expected, so
jeffhaobdb76512011-09-07 11:43:16 -07001677 * we don't try to address it.)
1678 *
1679 * If it fails, an exception is thrown, which we deal with later
1680 * by ignoring the update to dec_insn.vA_ when branching to a handler.
1681 */
jeffhao98eacac2011-09-14 16:11:53 -07001682 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001683 if (res_class == NULL) {
1684 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1685 LOG(ERROR) << "VFY: unable to resolve check-cast " << dec_insn.vB_
1686 << " (" << bad_class_desc << ") in "
1687 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001688 DCHECK(failure != VERIFY_ERROR_GENERIC);
1689 } else {
1690 RegType orig_type = GetRegisterType(work_line, dec_insn.vA_);
1691 if (!RegTypeIsReference(orig_type)) {
1692 LOG(ERROR) << "VFY: check-cast on non-reference in v" << dec_insn.vA_;
1693 failure = VERIFY_ERROR_GENERIC;
jeffhaobdb76512011-09-07 11:43:16 -07001694 break;
1695 }
jeffhao2a8a90e2011-09-26 14:25:31 -07001696 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
jeffhaobdb76512011-09-07 11:43:16 -07001697 }
1698 break;
1699 case Instruction::INSTANCE_OF:
1700 /* make sure we're checking a reference type */
1701 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1702 if (!RegTypeIsReference(tmp_type)) {
1703 LOG(ERROR) << "VFY: vB not a reference (" << tmp_type << ")";
1704 failure = VERIFY_ERROR_GENERIC;
1705 break;
1706 }
1707
1708 /* make sure we can resolve the class; access check is important */
jeffhao98eacac2011-09-14 16:11:53 -07001709 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001710 if (res_class == NULL) {
1711 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1712 LOG(ERROR) << "VFY: unable to resolve instanceof " << dec_insn.vC_
1713 << " (" << bad_class_desc << ") in "
1714 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001715 DCHECK(failure != VERIFY_ERROR_GENERIC);
1716 } else {
1717 /* result is boolean */
1718 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
jeffhaobdb76512011-09-07 11:43:16 -07001719 }
1720 break;
1721
1722 case Instruction::ARRAY_LENGTH:
1723 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
1724 if (failure != VERIFY_ERROR_NONE)
1725 break;
1726 if (res_class != NULL && !res_class->IsArrayClass()) {
1727 LOG(ERROR) << "VFY: array-length on non-array";
1728 failure = VERIFY_ERROR_GENERIC;
1729 break;
1730 }
1731 SetRegisterType(work_line, dec_insn.vA_, kRegTypeInteger);
1732 break;
1733
1734 case Instruction::NEW_INSTANCE:
jeffhao2a8a90e2011-09-26 14:25:31 -07001735 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
1736 if (res_class == NULL) {
1737 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1738 LOG(ERROR) << "VFY: unable to resolve new-instance " << dec_insn.vB_
1739 << " (" << bad_class_desc << ") in "
1740 << klass->GetDescriptor()->ToModifiedUtf8();
1741 DCHECK(failure != VERIFY_ERROR_GENERIC);
1742 } else {
jeffhaobdb76512011-09-07 11:43:16 -07001743 RegType uninit_type;
1744
1745 /* can't create an instance of an interface or abstract class */
1746 if (res_class->IsAbstract() || res_class->IsInterface()) {
1747 LOG(ERROR) << "VFY: new-instance on interface or abstract class"
1748 << res_class->GetDescriptor()->ToModifiedUtf8();
1749 failure = VERIFY_ERROR_INSTANTIATION;
1750 break;
1751 }
1752
1753 /* add resolved class to uninit map if not already there */
1754 int uidx = SetUninitInstance(uninit_map, insn_idx, res_class);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001755 DCHECK_GE(uidx, 0);
jeffhaobdb76512011-09-07 11:43:16 -07001756 uninit_type = RegTypeFromUninitIndex(uidx);
1757
1758 /*
1759 * Any registers holding previous allocations from this address
1760 * that have not yet been initialized must be marked invalid.
1761 */
1762 MarkUninitRefsAsInvalid(work_line, registers_size, uninit_map,
1763 uninit_type);
1764
1765 /* add the new uninitialized reference to the register ste */
1766 SetRegisterType(work_line, dec_insn.vA_, uninit_type);
1767 }
jeffhao2a8a90e2011-09-26 14:25:31 -07001768 break;
Elliott Hughes362f9bc2011-10-17 18:56:41 -07001769 case Instruction::NEW_ARRAY:
jeffhao98eacac2011-09-14 16:11:53 -07001770 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vC_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001771 if (res_class == NULL) {
1772 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vC_);
1773 LOG(ERROR) << "VFY: unable to resolve new-array " << dec_insn.vC_
1774 << " (" << bad_class_desc << ") in "
1775 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001776 DCHECK(failure != VERIFY_ERROR_GENERIC);
1777 } else if (!res_class->IsArrayClass()) {
jeffhaobdb76512011-09-07 11:43:16 -07001778 LOG(ERROR) << "VFY: new-array on non-array class";
1779 failure = VERIFY_ERROR_GENERIC;
1780 } else {
1781 /* make sure "size" register is valid type */
1782 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeInteger, &failure);
1783 /* set register type to array class */
1784 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(res_class));
1785 }
1786 break;
1787 case Instruction::FILLED_NEW_ARRAY:
1788 case Instruction::FILLED_NEW_ARRAY_RANGE:
jeffhao98eacac2011-09-14 16:11:53 -07001789 res_class = ResolveClassAndCheckAccess(dex_file, dec_insn.vB_, klass, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07001790 if (res_class == NULL) {
1791 const char* bad_class_desc = dex_file->dexStringByTypeIdx(dec_insn.vB_);
1792 LOG(ERROR) << "VFY: unable to resolve filled-array " << dec_insn.vB_
1793 << " (" << bad_class_desc << ") in "
1794 << klass->GetDescriptor()->ToModifiedUtf8();
jeffhao2a8a90e2011-09-26 14:25:31 -07001795 DCHECK(failure != VERIFY_ERROR_GENERIC);
1796 } else if (!res_class->IsArrayClass()) {
jeffhaobdb76512011-09-07 11:43:16 -07001797 LOG(ERROR) << "VFY: filled-new-array on non-array class";
1798 failure = VERIFY_ERROR_GENERIC;
1799 } else {
jeffhaoe0cfb6f2011-09-22 16:42:56 -07001800 bool is_range = (dec_insn.opcode_ == Instruction::FILLED_NEW_ARRAY_RANGE);
jeffhaobdb76512011-09-07 11:43:16 -07001801
1802 /* check the arguments to the instruction */
1803 VerifyFilledNewArrayRegs(method, work_line, &dec_insn, res_class,
1804 is_range, &failure);
1805 /* filled-array result goes into "result" register */
1806 SetResultRegisterType(work_line, registers_size,
1807 RegTypeFromClass(res_class));
1808 just_set_result = true;
1809 }
1810 break;
1811
1812 case Instruction::CMPL_FLOAT:
1813 case Instruction::CMPG_FLOAT:
1814 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeFloat, &failure);
1815 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeFloat, &failure);
1816 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1817 break;
1818 case Instruction::CMPL_DOUBLE:
1819 case Instruction::CMPG_DOUBLE:
1820 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeDoubleLo, &failure);
1821 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeDoubleLo, &failure);
1822 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1823 break;
1824 case Instruction::CMP_LONG:
1825 VerifyRegisterType(work_line, dec_insn.vB_, kRegTypeLongLo, &failure);
1826 VerifyRegisterType(work_line, dec_insn.vC_, kRegTypeLongLo, &failure);
1827 SetRegisterType(work_line, dec_insn.vA_, kRegTypeBoolean);
1828 break;
1829
1830 case Instruction::THROW:
1831 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1832 if (failure == VERIFY_ERROR_NONE && res_class != NULL) {
1833 Class* throwable_class =
1834 class_linker->FindSystemClass("Ljava/lang/Throwable;");
1835 if (!throwable_class->IsAssignableFrom(res_class)) {
1836 LOG(ERROR) << "VFY: thrown class "
1837 << res_class->GetDescriptor()->ToModifiedUtf8()
1838 << " not instanceof Throwable",
1839 failure = VERIFY_ERROR_GENERIC;
1840 }
1841 }
1842 break;
1843
1844 case Instruction::GOTO:
1845 case Instruction::GOTO_16:
1846 case Instruction::GOTO_32:
1847 /* no effect on or use of registers */
1848 break;
1849
1850 case Instruction::PACKED_SWITCH:
1851 case Instruction::SPARSE_SWITCH:
1852 /* verify that vAA is an integer, or can be converted to one */
1853 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeInteger, &failure);
1854 break;
1855
1856 case Instruction::FILL_ARRAY_DATA:
1857 {
1858 RegType value_type;
1859 const uint16_t *array_data;
1860 uint16_t elem_width;
1861
1862 /* Similar to the verification done for APUT */
1863 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
1864 if (failure != VERIFY_ERROR_NONE)
1865 break;
1866
1867 /* res_class can be null if the reg type is Zero */
1868 if (res_class == NULL)
1869 break;
1870
1871 Class::PrimitiveType prim_type =
1872 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001873 if (!res_class->IsArrayClass() ||
jeffhaobdb76512011-09-07 11:43:16 -07001874 prim_type == Class::kPrimNot || prim_type == Class::kPrimVoid) {
1875 LOG(ERROR) << "VFY: invalid fill-array-data on " <<
1876 res_class->GetDescriptor()->ToModifiedUtf8();
1877 failure = VERIFY_ERROR_GENERIC;
1878 break;
1879 }
1880
1881 value_type = PrimitiveTypeToRegType(prim_type);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001882 DCHECK(value_type != kRegTypeUnknown);
jeffhaobdb76512011-09-07 11:43:16 -07001883
1884 /*
1885 * Now verify if the element width in the table matches the element
1886 * width declared in the array
1887 */
1888 array_data = insns + (insns[1] | (((int32_t) insns[2]) << 16));
1889 if (array_data[0] != Instruction::kArrayDataSignature) {
1890 LOG(ERROR) << "VFY: invalid magic for array-data";
1891 failure = VERIFY_ERROR_GENERIC;
1892 break;
1893 }
1894
1895 switch (prim_type) {
1896 case Class::kPrimBoolean:
1897 case Class::kPrimByte:
1898 elem_width = 1;
1899 break;
1900 case Class::kPrimChar:
1901 case Class::kPrimShort:
1902 elem_width = 2;
1903 break;
1904 case Class::kPrimFloat:
1905 case Class::kPrimInt:
1906 elem_width = 4;
1907 break;
1908 case Class::kPrimDouble:
1909 case Class::kPrimLong:
1910 elem_width = 8;
1911 break;
1912 default:
1913 elem_width = 0;
1914 break;
1915 }
1916
1917 /*
1918 * Since we don't compress the data in Dex, expect to see equal
1919 * width of data stored in the table and expected from the array
1920 * class.
1921 */
1922 if (array_data[1] != elem_width) {
1923 LOG(ERROR) << "VFY: array-data size mismatch (" << array_data[1]
1924 << " vs " << elem_width << ")";
1925 failure = VERIFY_ERROR_GENERIC;
1926 }
1927 }
1928 break;
1929
1930 case Instruction::IF_EQ:
1931 case Instruction::IF_NE:
1932 {
1933 RegType type1, type2;
1934
1935 type1 = GetRegisterType(work_line, dec_insn.vA_);
1936 type2 = GetRegisterType(work_line, dec_insn.vB_);
1937
1938 /* both references? */
1939 if (RegTypeIsReference(type1) && RegTypeIsReference(type2))
1940 break;
1941
1942 /* both category-1nr? */
1943 CheckTypeCategory(type1, kTypeCategory1nr, &failure);
1944 CheckTypeCategory(type2, kTypeCategory1nr, &failure);
1945 if (failure != VERIFY_ERROR_NONE) {
1946 LOG(ERROR) << "VFY: args to if-eq/if-ne must both be refs or cat1";
1947 break;
1948 }
1949 }
1950 break;
1951 case Instruction::IF_LT:
1952 case Instruction::IF_GE:
1953 case Instruction::IF_GT:
1954 case Instruction::IF_LE:
1955 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
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 tmp_type = GetRegisterType(work_line, dec_insn.vB_);
1962 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1963 if (failure != VERIFY_ERROR_NONE) {
1964 LOG(ERROR) << "VFY: args to 'if' must be cat-1nr";
1965 break;
1966 }
1967 break;
1968 case Instruction::IF_EQZ:
1969 case Instruction::IF_NEZ:
1970 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1971 if (RegTypeIsReference(tmp_type))
1972 break;
1973 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1974 if (failure != VERIFY_ERROR_NONE)
1975 LOG(ERROR) << "VFY: expected cat-1 arg to if";
1976 break;
1977 case Instruction::IF_LTZ:
1978 case Instruction::IF_GEZ:
1979 case Instruction::IF_GTZ:
1980 case Instruction::IF_LEZ:
1981 tmp_type = GetRegisterType(work_line, dec_insn.vA_);
1982 CheckTypeCategory(tmp_type, kTypeCategory1nr, &failure);
1983 if (failure != VERIFY_ERROR_NONE)
1984 LOG(ERROR) << "VFY: expected cat-1 arg to if";
1985 break;
1986
1987 case Instruction::AGET:
1988 tmp_type = kRegTypeConstInteger;
1989 goto aget_1nr_common;
1990 case Instruction::AGET_BOOLEAN:
1991 tmp_type = kRegTypeBoolean;
1992 goto aget_1nr_common;
1993 case Instruction::AGET_BYTE:
1994 tmp_type = kRegTypeByte;
1995 goto aget_1nr_common;
1996 case Instruction::AGET_CHAR:
1997 tmp_type = kRegTypeChar;
1998 goto aget_1nr_common;
1999 case Instruction::AGET_SHORT:
2000 tmp_type = kRegTypeShort;
2001 goto aget_1nr_common;
2002aget_1nr_common:
2003 {
2004 RegType src_type, index_type;
2005
2006 index_type = GetRegisterType(work_line, dec_insn.vC_);
2007 CheckArrayIndexType(method, index_type, &failure);
2008 if (failure != VERIFY_ERROR_NONE)
2009 break;
2010
2011 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2012 if (failure != VERIFY_ERROR_NONE)
2013 break;
2014 if (res_class != NULL) {
2015 /* verify the class */
2016 Class::PrimitiveType prim_type =
2017 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002018 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002019 LOG(ERROR) << "VFY: invalid aget-1nr target "
2020 << res_class->GetDescriptor()->ToModifiedUtf8();
2021 failure = VERIFY_ERROR_GENERIC;
2022 break;
2023 }
2024
2025 /* make sure array type matches instruction */
2026 src_type = PrimitiveTypeToRegType(prim_type);
2027
2028 /* differentiate between float and int */
2029 if (src_type == kRegTypeFloat || src_type == kRegTypeInteger)
2030 tmp_type = src_type;
2031
2032 if (tmp_type != src_type) {
2033 LOG(ERROR) << "VFY: invalid aget-1nr, array type=" << src_type
2034 << " with inst type=" << tmp_type << " (on "
2035 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2036 failure = VERIFY_ERROR_GENERIC;
2037 break;
2038 }
jeffhaobdb76512011-09-07 11:43:16 -07002039 }
2040 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2041 }
2042 break;
2043
2044 case Instruction::AGET_WIDE:
2045 {
2046 RegType dst_type, index_type;
2047
2048 index_type = GetRegisterType(work_line, dec_insn.vC_);
2049 CheckArrayIndexType(method, index_type, &failure);
2050 if (failure != VERIFY_ERROR_NONE)
2051 break;
2052
2053 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2054 if (failure != VERIFY_ERROR_NONE)
2055 break;
2056 if (res_class != NULL) {
2057 /* verify the class */
2058 Class::PrimitiveType prim_type =
2059 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002060 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002061 LOG(ERROR) << "VFY: invalid aget-wide target "
2062 << res_class->GetDescriptor()->ToModifiedUtf8();
2063 failure = VERIFY_ERROR_GENERIC;
2064 break;
2065 }
2066
2067 /* try to refine "dst_type" */
2068 switch (prim_type) {
2069 case Class::kPrimLong:
2070 dst_type = kRegTypeLongLo;
2071 break;
2072 case Class::kPrimDouble:
2073 dst_type = kRegTypeDoubleLo;
2074 break;
2075 default:
2076 LOG(ERROR) << "VFY: invalid aget-wide on "
2077 << res_class->GetDescriptor()->ToModifiedUtf8();
2078 dst_type = kRegTypeUnknown;
2079 failure = VERIFY_ERROR_GENERIC;
2080 break;
2081 }
2082 } else {
2083 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002084 * Null array ref; this code path will fail at runtime. We
jeffhaobdb76512011-09-07 11:43:16 -07002085 * know this is either long or double, so label it const.
2086 */
2087 dst_type = kRegTypeConstLo;
2088 }
2089 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2090 }
2091 break;
2092
2093 case Instruction::AGET_OBJECT:
2094 {
2095 RegType dst_type, index_type;
2096
2097 index_type = GetRegisterType(work_line, dec_insn.vC_);
2098 CheckArrayIndexType(method, index_type, &failure);
2099 if (failure != VERIFY_ERROR_NONE)
2100 break;
2101
2102 /* get the class of the array we're pulling an object from */
2103 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2104 if (failure != VERIFY_ERROR_NONE)
2105 break;
2106 if (res_class != NULL) {
2107 Class* element_class;
2108
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002109 DCHECK(res_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002110 if (!res_class->IsArrayClass()) {
2111 LOG(ERROR) << "VFY: aget-object on non-array class";
2112 failure = VERIFY_ERROR_GENERIC;
2113 break;
2114 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002115 DCHECK(res_class->GetComponentType() != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002116
2117 /*
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002118 * Find the element class.
jeffhaobdb76512011-09-07 11:43:16 -07002119 */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002120 element_class = res_class->GetComponentType();
2121 if (element_class->IsPrimitive()) {
jeffhaobdb76512011-09-07 11:43:16 -07002122 LOG(ERROR) << "VFY: aget-object on non-ref array class ("
2123 << res_class->GetDescriptor()->ToModifiedUtf8() << ")";
2124 failure = VERIFY_ERROR_GENERIC;
2125 break;
2126 }
2127
2128 dst_type = RegTypeFromClass(element_class);
2129 } else {
2130 /*
2131 * The array reference is NULL, so the current code path will
jeffhaod1f0fde2011-09-08 17:25:33 -07002132 * throw an exception. For proper merging with later code
jeffhaobdb76512011-09-07 11:43:16 -07002133 * paths, and correct handling of "if-eqz" tests on the
2134 * result of the array get, we want to treat this as a null
2135 * reference.
2136 */
2137 dst_type = kRegTypeZero;
2138 }
2139 SetRegisterType(work_line, dec_insn.vA_, dst_type);
2140 }
2141 break;
2142 case Instruction::APUT:
2143 tmp_type = kRegTypeInteger;
2144 goto aput_1nr_common;
2145 case Instruction::APUT_BOOLEAN:
2146 tmp_type = kRegTypeBoolean;
2147 goto aput_1nr_common;
2148 case Instruction::APUT_BYTE:
2149 tmp_type = kRegTypeByte;
2150 goto aput_1nr_common;
2151 case Instruction::APUT_CHAR:
2152 tmp_type = kRegTypeChar;
2153 goto aput_1nr_common;
2154 case Instruction::APUT_SHORT:
2155 tmp_type = kRegTypeShort;
2156 goto aput_1nr_common;
2157aput_1nr_common:
2158 {
2159 RegType src_type, dst_type, index_type;
2160
2161 index_type = GetRegisterType(work_line, dec_insn.vC_);
2162 CheckArrayIndexType(method, index_type, &failure);
2163 if (failure != VERIFY_ERROR_NONE)
2164 break;
2165
2166 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2167 if (failure != VERIFY_ERROR_NONE)
2168 break;
2169
2170 /* res_class can be null if the reg type is Zero */
2171 if (res_class == NULL)
2172 break;
2173
2174 Class::PrimitiveType prim_type =
2175 res_class->GetComponentType()->GetPrimitiveType();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002176 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot) {
jeffhaobdb76512011-09-07 11:43:16 -07002177 LOG(ERROR) << "VFY: invalid aput-1nr on "
2178 << res_class->GetDescriptor()->ToModifiedUtf8();
2179 failure = VERIFY_ERROR_GENERIC;
2180 break;
2181 }
2182
2183 /* verify that instruction matches array */
2184 dst_type = PrimitiveTypeToRegType(prim_type);
2185
2186 /* correct if float */
2187 if (dst_type == kRegTypeFloat)
2188 tmp_type = kRegTypeFloat;
2189
2190 /* make sure the source register has the correct type */
2191 src_type = GetRegisterType(work_line, dec_insn.vA_);
2192 if (!CanConvertTo1nr(src_type, tmp_type)) {
2193 LOG(ERROR) << "VFY: invalid reg type " << src_type
2194 << " on aput instr (need " << tmp_type << ")";
2195 failure = VERIFY_ERROR_GENERIC;
2196 break;
2197 }
2198
2199 VerifyRegisterType(work_line, dec_insn.vA_, dst_type, &failure);
2200
2201 if (failure != VERIFY_ERROR_NONE || dst_type == kRegTypeUnknown ||
2202 tmp_type != dst_type) {
2203 LOG(ERROR) << "VFY: invalid aput-1nr on "
2204 << res_class->GetDescriptor()->ToModifiedUtf8()
2205 << " (inst=" << tmp_type << " dst=" << dst_type << ")";
2206 failure = VERIFY_ERROR_GENERIC;
2207 break;
2208 }
2209 }
2210 break;
2211 case Instruction::APUT_WIDE:
2212 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2213 CheckArrayIndexType(method, tmp_type, &failure);
2214 if (failure != VERIFY_ERROR_NONE)
2215 break;
2216
2217 res_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2218 if (failure != VERIFY_ERROR_NONE)
2219 break;
2220 if (res_class != NULL) {
2221 Class::PrimitiveType prim_type =
2222 res_class->GetComponentType()->GetPrimitiveType();
2223 /* verify the class and try to refine "dst_type" */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002224 if (!res_class->IsArrayClass() || prim_type == Class::kPrimNot)
jeffhaobdb76512011-09-07 11:43:16 -07002225 {
2226 LOG(ERROR) << "VFY: invalid aput-wide on "
2227 << res_class->GetDescriptor()->ToModifiedUtf8();
2228 failure = VERIFY_ERROR_GENERIC;
2229 break;
2230 }
2231
2232 switch (prim_type) {
2233 case Class::kPrimLong:
2234 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo,
2235 &failure);
2236 break;
2237 case Class::kPrimDouble:
2238 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2239 &failure);
2240 break;
2241 default:
2242 LOG(ERROR) << "VFY: invalid aput-wide on "
2243 << res_class->GetDescriptor()->ToModifiedUtf8();
2244 failure = VERIFY_ERROR_GENERIC;
2245 break;
2246 }
2247 }
2248 break;
2249 case Instruction::APUT_OBJECT:
2250 tmp_type = GetRegisterType(work_line, dec_insn.vC_);
2251 CheckArrayIndexType(method, tmp_type, &failure);
2252 if (failure != VERIFY_ERROR_NONE)
2253 break;
2254
2255 /* get the ref we're storing; Zero is okay, Uninit is not */
2256 res_class = GetClassFromRegister(work_line, dec_insn.vA_, &failure);
2257 if (failure != VERIFY_ERROR_NONE)
2258 break;
2259 if (res_class != NULL) {
2260 Class* array_class;
2261 Class* element_class;
2262
2263 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002264 * Get the array class. If the array ref is null, we won't
jeffhaobdb76512011-09-07 11:43:16 -07002265 * have type information (and we'll crash at runtime with a
2266 * null pointer exception).
2267 */
2268 array_class = GetClassFromRegister(work_line, dec_insn.vB_, &failure);
2269
2270 if (array_class != NULL) {
2271 /* see if the array holds a compatible type */
2272 if (!array_class->IsArrayClass()) {
2273 LOG(ERROR) << "VFY: invalid aput-object on "
2274 << array_class->GetDescriptor()->ToModifiedUtf8();
2275 failure = VERIFY_ERROR_GENERIC;
2276 break;
2277 }
2278
2279 /*
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002280 * Find the element class.
jeffhaobdb76512011-09-07 11:43:16 -07002281 *
2282 * All we want to check here is that the element type is a
jeffhaod1f0fde2011-09-08 17:25:33 -07002283 * reference class. We *don't* check instanceof here, because
jeffhaobdb76512011-09-07 11:43:16 -07002284 * you can still put a String into a String[] after the latter
2285 * has been cast to an Object[].
2286 */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002287 element_class = array_class->GetComponentType();
2288 if (element_class->IsPrimitive()) {
jeffhaobdb76512011-09-07 11:43:16 -07002289 LOG(ERROR) << "VFY: invalid aput-object of "
2290 << res_class->GetDescriptor()->ToModifiedUtf8()
2291 << " into "
2292 << array_class->GetDescriptor()->ToModifiedUtf8();
2293 failure = VERIFY_ERROR_GENERIC;
2294 break;
2295 }
2296 }
2297 }
2298 break;
2299
2300 case Instruction::IGET:
2301 tmp_type = kRegTypeInteger;
2302 goto iget_1nr_common;
2303 case Instruction::IGET_BOOLEAN:
2304 tmp_type = kRegTypeBoolean;
2305 goto iget_1nr_common;
2306 case Instruction::IGET_BYTE:
2307 tmp_type = kRegTypeByte;
2308 goto iget_1nr_common;
2309 case Instruction::IGET_CHAR:
2310 tmp_type = kRegTypeChar;
2311 goto iget_1nr_common;
2312 case Instruction::IGET_SHORT:
2313 tmp_type = kRegTypeShort;
2314 goto iget_1nr_common;
2315iget_1nr_common:
2316 {
2317 Field* inst_field;
2318 RegType obj_type, field_type;
2319
2320 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2321 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2322 if (failure != VERIFY_ERROR_NONE)
2323 break;
2324
2325 /* make sure the field's type is compatible with expectation */
jeffhao2a8a90e2011-09-26 14:25:31 -07002326 field_type = PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
jeffhaobdb76512011-09-07 11:43:16 -07002327
2328 /* correct if float */
2329 if (field_type == kRegTypeFloat)
2330 tmp_type = kRegTypeFloat;
2331
2332 if (field_type == kRegTypeUnknown || tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002333 LOG(ERROR) << "VFY: invalid iget-1nr of " << PrettyField(inst_field)
jeffhaobdb76512011-09-07 11:43:16 -07002334 << " (inst=" << tmp_type << " field=" << field_type << ")";
2335 failure = VERIFY_ERROR_GENERIC;
2336 break;
2337 }
2338
2339 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2340 }
2341 break;
2342 case Instruction::IGET_WIDE:
2343 {
jeffhaobdb76512011-09-07 11:43:16 -07002344 Field* inst_field;
2345 RegType obj_type;
2346
2347 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2348 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002349 if (failure != VERIFY_ERROR_NONE)
2350 break;
2351 /* check the type, which should be prim */
2352 switch (inst_field->GetType()->GetPrimitiveType()) {
2353 case Class::kPrimDouble:
jeffhao2a8a90e2011-09-26 14:25:31 -07002354 SetRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo);
jeffhaobdb76512011-09-07 11:43:16 -07002355 break;
2356 case Class::kPrimLong:
jeffhao2a8a90e2011-09-26 14:25:31 -07002357 SetRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo);
jeffhaobdb76512011-09-07 11:43:16 -07002358 break;
2359 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002360 LOG(ERROR) << "VFY: invalid iget-wide of " << PrettyField(inst_field);
jeffhaobdb76512011-09-07 11:43:16 -07002361 failure = VERIFY_ERROR_GENERIC;
2362 break;
2363 }
jeffhaobdb76512011-09-07 11:43:16 -07002364 }
2365 break;
2366 case Instruction::IGET_OBJECT:
2367 {
2368 Class* field_class;
2369 Field* inst_field;
2370 RegType obj_type;
2371
2372 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2373 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2374 if (failure != VERIFY_ERROR_NONE)
2375 break;
2376 field_class = inst_field->GetType();
2377 if (field_class == NULL) {
2378 /* class not found or primitive type */
2379 LOG(ERROR) << "VFY: unable to recover field class from "
2380 << inst_field->GetName()->ToModifiedUtf8();
2381 failure = VERIFY_ERROR_GENERIC;
2382 break;
2383 }
jeffhao2a8a90e2011-09-26 14:25:31 -07002384 DCHECK(!field_class->IsPrimitive()) << PrettyClass(field_class);
2385 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
jeffhaobdb76512011-09-07 11:43:16 -07002386 }
2387 break;
2388 case Instruction::IPUT:
2389 tmp_type = kRegTypeInteger;
2390 goto iput_1nr_common;
2391 case Instruction::IPUT_BOOLEAN:
2392 tmp_type = kRegTypeBoolean;
2393 goto iput_1nr_common;
2394 case Instruction::IPUT_BYTE:
2395 tmp_type = kRegTypeByte;
2396 goto iput_1nr_common;
2397 case Instruction::IPUT_CHAR:
2398 tmp_type = kRegTypeChar;
2399 goto iput_1nr_common;
2400 case Instruction::IPUT_SHORT:
2401 tmp_type = kRegTypeShort;
2402 goto iput_1nr_common;
2403iput_1nr_common:
2404 {
2405 RegType src_type, field_type, obj_type;
2406 Field* inst_field;
2407
2408 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2409 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2410 if (failure != VERIFY_ERROR_NONE)
2411 break;
2412 CheckFinalFieldAccess(method, inst_field, &failure);
2413 if (failure != VERIFY_ERROR_NONE)
2414 break;
2415
2416 /* get type of field we're storing into */
jeffhao2a8a90e2011-09-26 14:25:31 -07002417 field_type = PrimitiveTypeToRegType(inst_field->GetType()->GetPrimitiveType());
jeffhaobdb76512011-09-07 11:43:16 -07002418 src_type = GetRegisterType(work_line, dec_insn.vA_);
2419
2420 /* correct if float */
2421 if (field_type == kRegTypeFloat)
2422 tmp_type = kRegTypeFloat;
2423
2424 /*
2425 * compiler can generate synthetic functions that write byte values
2426 * into boolean fields.
2427 */
2428 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2429 tmp_type = kRegTypeByte;
2430 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2431 field_type = kRegTypeByte;
2432
2433 /* make sure the source register has the correct type */
2434 if (!CanConvertTo1nr(src_type, tmp_type)) {
2435 LOG(ERROR) << "VFY: invalid reg type " << src_type
2436 << " on iput instr (need " << tmp_type << ")",
2437 failure = VERIFY_ERROR_GENERIC;
2438 break;
2439 }
2440
2441 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2442
2443 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2444 tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002445 LOG(ERROR) << "VFY: invalid iput-1nr of " << PrettyField(inst_field)
jeffhaobdb76512011-09-07 11:43:16 -07002446 << " (inst=" << tmp_type << " field=" << field_type << ")";
2447 failure = VERIFY_ERROR_GENERIC;
2448 break;
2449 }
2450 }
2451 break;
2452 case Instruction::IPUT_WIDE:
jeffhao2a8a90e2011-09-26 14:25:31 -07002453 {
2454 Field* inst_field;
2455 RegType obj_type;
jeffhaobdb76512011-09-07 11:43:16 -07002456
jeffhao2a8a90e2011-09-26 14:25:31 -07002457 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2458 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2459 if (failure != VERIFY_ERROR_NONE)
2460 break;
2461 CheckFinalFieldAccess(method, inst_field, &failure);
2462 if (failure != VERIFY_ERROR_NONE)
2463 break;
jeffhaobdb76512011-09-07 11:43:16 -07002464
jeffhao2a8a90e2011-09-26 14:25:31 -07002465 /* check the type, which should be prim */
2466 switch (inst_field->GetType()->GetPrimitiveType()) {
2467 case Class::kPrimDouble:
2468 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2469 &failure);
2470 break;
2471 case Class::kPrimLong:
2472 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2473 break;
2474 default:
2475 LOG(ERROR) << "VFY: invalid iput-wide of " << PrettyField(inst_field);
2476 failure = VERIFY_ERROR_GENERIC;
2477 break;
jeffhaobdb76512011-09-07 11:43:16 -07002478 }
jeffhao2a8a90e2011-09-26 14:25:31 -07002479 break;
2480 }
jeffhaobdb76512011-09-07 11:43:16 -07002481 case Instruction::IPUT_OBJECT:
2482 {
2483 Class* field_class;
2484 Class* value_class;
2485 Field* inst_field;
2486 RegType obj_type, value_type;
2487
2488 obj_type = GetRegisterType(work_line, dec_insn.vB_);
2489 inst_field = GetInstField(vdata, obj_type, dec_insn.vC_, &failure);
2490 if (failure != VERIFY_ERROR_NONE)
2491 break;
Brian Carlstrom65ca0772011-09-24 16:03:08 -07002492 DCHECK(inst_field != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002493 CheckFinalFieldAccess(method, inst_field, &failure);
2494 if (failure != VERIFY_ERROR_NONE)
2495 break;
2496
2497 field_class = inst_field->GetType();
2498 if (field_class == NULL) {
2499 LOG(ERROR) << "VFY: unable to recover field class from '"
2500 << inst_field->GetName()->ToModifiedUtf8() << "'";
2501 failure = VERIFY_ERROR_GENERIC;
2502 break;
2503 }
2504
2505 value_type = GetRegisterType(work_line, dec_insn.vA_);
2506 if (!RegTypeIsReference(value_type)) {
2507 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2508 << " into ref field '"
2509 << inst_field->GetName()->ToModifiedUtf8() << "' ("
2510 << field_class->GetDescriptor()->ToModifiedUtf8() << ")";
2511 failure = VERIFY_ERROR_GENERIC;
2512 break;
2513 }
2514 if (value_type != kRegTypeZero) {
2515 value_class = RegTypeInitializedReferenceToClass(value_type);
2516 if (value_class == NULL) {
2517 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2518 << " into ref field";
2519 failure = VERIFY_ERROR_GENERIC;
2520 break;
2521 }
2522 /* allow if field is any interface or field is base class */
2523 if (!field_class->IsInterface() &&
2524 !field_class->IsAssignableFrom(value_class)) {
jeffhaobdb76512011-09-07 11:43:16 -07002525 LOG(ERROR) << "VFY: storing type '"
2526 << value_class->GetDescriptor()->ToModifiedUtf8()
2527 << "' into field type '"
2528 << field_class->GetDescriptor()->ToModifiedUtf8()
jeffhao2a8a90e2011-09-26 14:25:31 -07002529 << "' (" << PrettyField(inst_field) << ")";
jeffhaobdb76512011-09-07 11:43:16 -07002530 failure = VERIFY_ERROR_GENERIC;
2531 break;
2532 }
2533 }
2534 }
2535 break;
2536
2537 case Instruction::SGET:
2538 tmp_type = kRegTypeInteger;
2539 goto sget_1nr_common;
2540 case Instruction::SGET_BOOLEAN:
2541 tmp_type = kRegTypeBoolean;
2542 goto sget_1nr_common;
2543 case Instruction::SGET_BYTE:
2544 tmp_type = kRegTypeByte;
2545 goto sget_1nr_common;
2546 case Instruction::SGET_CHAR:
2547 tmp_type = kRegTypeChar;
2548 goto sget_1nr_common;
2549 case Instruction::SGET_SHORT:
2550 tmp_type = kRegTypeShort;
2551 goto sget_1nr_common;
2552sget_1nr_common:
2553 {
2554 Field* static_field;
2555 RegType field_type;
2556
2557 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2558 if (failure != VERIFY_ERROR_NONE)
2559 break;
2560
2561 /*
2562 * Make sure the field's type is compatible with expectation.
2563 * We can get ourselves into trouble if we mix & match loads
2564 * and stores with different widths, so rather than just checking
2565 * "CanConvertTo1nr" we require that the field types have equal
2566 * widths.
2567 */
2568 field_type =
2569 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2570
2571 /* correct if float */
2572 if (field_type == kRegTypeFloat)
2573 tmp_type = kRegTypeFloat;
2574
2575 if (tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002576 LOG(ERROR) << "VFY: invalid sget-1nr of " << PrettyField(static_field)
jeffhaobdb76512011-09-07 11:43:16 -07002577 << " (inst=" << tmp_type << " actual=" << field_type
2578 << ")";
2579 failure = VERIFY_ERROR_GENERIC;
2580 break;
2581 }
2582
2583 SetRegisterType(work_line, dec_insn.vA_, tmp_type);
2584 }
2585 break;
2586 case Instruction::SGET_WIDE:
2587 {
jeffhao2a8a90e2011-09-26 14:25:31 -07002588 Field* static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002589 if (failure != VERIFY_ERROR_NONE)
2590 break;
2591 /* check the type, which should be prim */
2592 switch (static_field->GetType()->GetPrimitiveType()) {
2593 case Class::kPrimDouble:
jeffhao2a8a90e2011-09-26 14:25:31 -07002594 SetRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo);
jeffhaobdb76512011-09-07 11:43:16 -07002595 break;
2596 case Class::kPrimLong:
jeffhao2a8a90e2011-09-26 14:25:31 -07002597 SetRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo);
jeffhaobdb76512011-09-07 11:43:16 -07002598 break;
2599 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002600 LOG(ERROR) << "VFY: invalid sget-wide of " << PrettyField(static_field);
jeffhaobdb76512011-09-07 11:43:16 -07002601 failure = VERIFY_ERROR_GENERIC;
2602 break;
2603 }
jeffhaobdb76512011-09-07 11:43:16 -07002604 }
2605 break;
2606 case Instruction::SGET_OBJECT:
2607 {
jeffhao2a8a90e2011-09-26 14:25:31 -07002608 Field* static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
jeffhaobdb76512011-09-07 11:43:16 -07002609 if (failure != VERIFY_ERROR_NONE)
2610 break;
jeffhao2a8a90e2011-09-26 14:25:31 -07002611 Class* field_class = static_field->GetType();
jeffhaobdb76512011-09-07 11:43:16 -07002612 if (field_class == NULL) {
2613 LOG(ERROR) << "VFY: unable to recover field class from '"
2614 << static_field->GetName()->ToModifiedUtf8() << "'";
2615 failure = VERIFY_ERROR_GENERIC;
2616 break;
2617 }
2618 if (field_class->IsPrimitive()) {
2619 LOG(ERROR) << "VFY: attempt to get prim field with sget-object";
2620 failure = VERIFY_ERROR_GENERIC;
2621 break;
2622 }
2623 SetRegisterType(work_line, dec_insn.vA_, RegTypeFromClass(field_class));
2624 }
2625 break;
2626 case Instruction::SPUT:
2627 tmp_type = kRegTypeInteger;
2628 goto sput_1nr_common;
2629 case Instruction::SPUT_BOOLEAN:
2630 tmp_type = kRegTypeBoolean;
2631 goto sput_1nr_common;
2632 case Instruction::SPUT_BYTE:
2633 tmp_type = kRegTypeByte;
2634 goto sput_1nr_common;
2635 case Instruction::SPUT_CHAR:
2636 tmp_type = kRegTypeChar;
2637 goto sput_1nr_common;
2638 case Instruction::SPUT_SHORT:
2639 tmp_type = kRegTypeShort;
2640 goto sput_1nr_common;
2641sput_1nr_common:
2642 {
2643 RegType src_type, field_type;
2644 Field* static_field;
2645
2646 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2647 if (failure != VERIFY_ERROR_NONE)
2648 break;
2649 CheckFinalFieldAccess(method, static_field, &failure);
2650 if (failure != VERIFY_ERROR_NONE)
2651 break;
2652
2653 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002654 * Get type of field we're storing into. We know that the
jeffhaobdb76512011-09-07 11:43:16 -07002655 * contents of the register match the instruction, but we also
2656 * need to ensure that the instruction matches the field type.
2657 * Using e.g. sput-short to write into a 32-bit integer field
2658 * can lead to trouble if we do 16-bit writes.
2659 */
2660 field_type =
2661 PrimitiveTypeToRegType(static_field->GetType()->GetPrimitiveType());
2662 src_type = GetRegisterType(work_line, dec_insn.vA_);
2663
2664 /* correct if float */
2665 if (field_type == kRegTypeFloat)
2666 tmp_type = kRegTypeFloat;
2667
2668 /*
2669 * compiler can generate synthetic functions that write byte values
2670 * into boolean fields.
2671 */
2672 if (tmp_type == kRegTypeBoolean && src_type == kRegTypeByte)
2673 tmp_type = kRegTypeByte;
2674 if (field_type == kRegTypeBoolean && src_type == kRegTypeByte)
2675 field_type = kRegTypeByte;
2676
2677 /* make sure the source register has the correct type */
2678 if (!CanConvertTo1nr(src_type, tmp_type)) {
2679 LOG(ERROR) << "VFY: invalid reg type " << src_type
2680 << " on sput instr (need " << tmp_type << ")";
2681 failure = VERIFY_ERROR_GENERIC;
2682 break;
2683 }
2684
2685 VerifyRegisterType(work_line, dec_insn.vA_, field_type, &failure);
2686
2687 if (failure != VERIFY_ERROR_NONE || field_type == kRegTypeUnknown ||
2688 tmp_type != field_type) {
jeffhao2a8a90e2011-09-26 14:25:31 -07002689 LOG(ERROR) << "VFY: invalid sput-1nr of " << PrettyField(static_field)
jeffhaobdb76512011-09-07 11:43:16 -07002690 << " (inst=" << tmp_type << " actual=" << field_type
2691 << ")";
2692 failure = VERIFY_ERROR_GENERIC;
2693 break;
2694 }
2695 }
2696 break;
2697 case Instruction::SPUT_WIDE:
2698 Field* static_field;
2699
2700 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2701 if (failure != VERIFY_ERROR_NONE)
2702 break;
2703 CheckFinalFieldAccess(method, static_field, &failure);
2704 if (failure != VERIFY_ERROR_NONE)
2705 break;
2706
2707 /* check the type, which should be prim */
2708 switch (static_field->GetType()->GetPrimitiveType()) {
2709 case Class::kPrimDouble:
2710 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeDoubleLo,
2711 &failure);
2712 break;
2713 case Class::kPrimLong:
2714 VerifyRegisterType(work_line, dec_insn.vA_, kRegTypeLongLo, &failure);
2715 break;
2716 default:
jeffhao2a8a90e2011-09-26 14:25:31 -07002717 LOG(ERROR) << "VFY: invalid sput-wide of " << PrettyField(static_field);
jeffhaobdb76512011-09-07 11:43:16 -07002718 failure = VERIFY_ERROR_GENERIC;
2719 break;
2720 }
2721 break;
2722 case Instruction::SPUT_OBJECT:
2723 {
2724 Class* field_class;
2725 Class* value_class;
2726 Field* static_field;
2727 RegType value_type;
2728
2729 static_field = GetStaticField(vdata, dec_insn.vB_, &failure);
2730 if (failure != VERIFY_ERROR_NONE)
2731 break;
2732 CheckFinalFieldAccess(method, static_field, &failure);
2733 if (failure != VERIFY_ERROR_NONE)
2734 break;
2735
2736 field_class = static_field->GetType();
2737 if (field_class == NULL) {
2738 LOG(ERROR) << "VFY: unable to recover field class from '"
2739 << static_field->GetName()->ToModifiedUtf8() << "'";
2740 failure = VERIFY_ERROR_GENERIC;
2741 break;
2742 }
2743
2744 value_type = GetRegisterType(work_line, dec_insn.vA_);
2745 if (!RegTypeIsReference(value_type)) {
2746 LOG(ERROR) << "VFY: storing non-ref v" << dec_insn.vA_
2747 << " into ref field '"
2748 << static_field->GetName()->ToModifiedUtf8() << "' ("
2749 << field_class->GetDescriptor()->ToModifiedUtf8() << ")",
2750 failure = VERIFY_ERROR_GENERIC;
2751 break;
2752 }
2753 if (value_type != kRegTypeZero) {
2754 value_class = RegTypeInitializedReferenceToClass(value_type);
2755 if (value_class == NULL) {
2756 LOG(ERROR) << "VFY: storing uninit ref v" << dec_insn.vA_
2757 << " into ref field";
2758 failure = VERIFY_ERROR_GENERIC;
2759 break;
2760 }
2761 /* allow if field is any interface or field is base class */
2762 if (!field_class->IsInterface() &&
2763 !field_class->IsAssignableFrom(value_class)) {
jeffhaobdb76512011-09-07 11:43:16 -07002764 LOG(ERROR) << "VFY: storing type '"
2765 << value_class->GetDescriptor()->ToModifiedUtf8()
2766 << "' into field type '"
2767 << field_class->GetDescriptor()->ToModifiedUtf8()
jeffhao2a8a90e2011-09-26 14:25:31 -07002768 << "' (" << PrettyField(static_field) << ")";
jeffhaobdb76512011-09-07 11:43:16 -07002769 failure = VERIFY_ERROR_GENERIC;
2770 break;
2771 }
2772 }
2773 }
2774 break;
2775
2776 case Instruction::INVOKE_VIRTUAL:
2777 case Instruction::INVOKE_VIRTUAL_RANGE:
2778 case Instruction::INVOKE_SUPER:
2779 case Instruction::INVOKE_SUPER_RANGE:
2780 {
2781 Method* called_method;
2782 RegType return_type;
2783 bool is_range;
2784 bool is_super;
2785
2786 is_range = (dec_insn.opcode_ == Instruction::INVOKE_VIRTUAL_RANGE ||
2787 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2788 is_super = (dec_insn.opcode_ == Instruction::INVOKE_SUPER ||
2789 dec_insn.opcode_ == Instruction::INVOKE_SUPER_RANGE);
2790
2791 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2792 &dec_insn, METHOD_VIRTUAL, is_range, is_super, &failure);
2793 if (failure != VERIFY_ERROR_NONE)
2794 break;
2795 return_type = GetMethodReturnType(dex_file, called_method);
2796 SetResultRegisterType(work_line, registers_size, return_type);
2797 just_set_result = true;
2798 }
2799 break;
2800 case Instruction::INVOKE_DIRECT:
2801 case Instruction::INVOKE_DIRECT_RANGE:
2802 {
2803 RegType return_type;
2804 Method* called_method;
2805 bool is_range;
2806
2807 is_range = (dec_insn.opcode_ == Instruction::INVOKE_DIRECT_RANGE);
2808 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2809 &dec_insn, METHOD_DIRECT, is_range, false, &failure);
2810 if (failure != VERIFY_ERROR_NONE)
2811 break;
2812
2813 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07002814 * Some additional checks when calling <init>. We know from
jeffhaobdb76512011-09-07 11:43:16 -07002815 * the invocation arg check that the "this" argument is an
jeffhaod1f0fde2011-09-08 17:25:33 -07002816 * instance of called_method->klass. Now we further restrict
jeffhaobdb76512011-09-07 11:43:16 -07002817 * that to require that called_method->klass is the same as
2818 * this->klass or this->super, allowing the latter only if
2819 * the "this" argument is the same as the "this" argument to
2820 * this method (which implies that we're in <init> ourselves).
2821 */
2822 if (IsInitMethod(called_method)) {
2823 RegType this_type;
2824 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2825 if (failure != VERIFY_ERROR_NONE)
2826 break;
2827
2828 /* no null refs allowed (?) */
2829 if (this_type == kRegTypeZero) {
2830 LOG(ERROR) << "VFY: unable to initialize null ref";
2831 failure = VERIFY_ERROR_GENERIC;
2832 break;
2833 }
2834
2835 Class* this_class;
2836
2837 this_class = RegTypeReferenceToClass(this_type, uninit_map);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07002838 DCHECK(this_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07002839
2840 /* must be in same class or in superclass */
2841 if (called_method->GetDeclaringClass() == this_class->GetSuperClass())
2842 {
2843 if (this_class != method->GetDeclaringClass()) {
2844 LOG(ERROR) << "VFY: invoke-direct <init> on super only "
2845 << "allowed for 'this' in <init>";
2846 failure = VERIFY_ERROR_GENERIC;
2847 break;
2848 }
2849 } else if (called_method->GetDeclaringClass() != this_class) {
2850 LOG(ERROR) << "VFY: invoke-direct <init> must be on current "
2851 << "class or super";
2852 failure = VERIFY_ERROR_GENERIC;
2853 break;
2854 }
2855
2856 /* arg must be an uninitialized reference */
2857 if (!RegTypeIsUninitReference(this_type)) {
2858 LOG(ERROR) << "VFY: can only initialize the uninitialized";
2859 failure = VERIFY_ERROR_GENERIC;
2860 break;
2861 }
2862
2863 /*
2864 * Replace the uninitialized reference with an initialized
jeffhaod1f0fde2011-09-08 17:25:33 -07002865 * one, and clear the entry in the uninit map. We need to
jeffhaobdb76512011-09-07 11:43:16 -07002866 * do this for all registers that have the same object
2867 * instance in them, not just the "this" register.
2868 */
2869 MarkRefsAsInitialized(work_line, registers_size, uninit_map,
2870 this_type, &failure);
2871 if (failure != VERIFY_ERROR_NONE)
2872 break;
jeffhao2a8a90e2011-09-26 14:25:31 -07002873 }
jeffhaobdb76512011-09-07 11:43:16 -07002874 return_type = GetMethodReturnType(dex_file, called_method);
2875 SetResultRegisterType(work_line, registers_size, return_type);
2876 just_set_result = true;
2877 }
2878 break;
2879 case Instruction::INVOKE_STATIC:
2880 case Instruction::INVOKE_STATIC_RANGE:
2881 {
2882 RegType return_type;
2883 Method* called_method;
2884 bool is_range;
2885
2886 is_range = (dec_insn.opcode_ == Instruction::INVOKE_STATIC_RANGE);
2887 called_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2888 &dec_insn, METHOD_STATIC, is_range, false, &failure);
2889 if (failure != VERIFY_ERROR_NONE)
2890 break;
2891
2892 return_type = GetMethodReturnType(dex_file, called_method);
2893 SetResultRegisterType(work_line, registers_size, return_type);
2894 just_set_result = true;
2895 }
2896 break;
2897 case Instruction::INVOKE_INTERFACE:
2898 case Instruction::INVOKE_INTERFACE_RANGE:
2899 {
2900 RegType /*this_type,*/ return_type;
2901 Method* abs_method;
2902 bool is_range;
2903
2904 is_range = (dec_insn.opcode_ == Instruction::INVOKE_INTERFACE_RANGE);
2905 abs_method = VerifyInvocationArgs(vdata, work_line, registers_size,
2906 &dec_insn, METHOD_INTERFACE, is_range, false, &failure);
2907 if (failure != VERIFY_ERROR_NONE)
2908 break;
2909
2910#if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
2911 /*
2912 * Get the type of the "this" arg, which should always be an
jeffhaod1f0fde2011-09-08 17:25:33 -07002913 * interface class. Because we don't do a full merge on
jeffhaobdb76512011-09-07 11:43:16 -07002914 * interface classes, this might have reduced to Object.
2915 */
2916 this_type = GetInvocationThis(work_line, &dec_insn, &failure);
2917 if (failure != VERIFY_ERROR_NONE)
2918 break;
2919
2920 if (this_type == kRegTypeZero) {
2921 /* null pointer always passes (and always fails at runtime) */
2922 } else {
2923 Class* this_class;
2924
2925 this_class = RegTypeInitializedReferenceToClass(this_type);
2926 if (this_class == NULL) {
2927 LOG(ERROR) << "VFY: interface call on uninitialized";
2928 failure = VERIFY_ERROR_GENERIC;
2929 break;
2930 }
2931
2932 /*
2933 * Either "this_class" needs to be the interface class that
2934 * defined abs_method, or abs_method's class needs to be one
jeffhaod1f0fde2011-09-08 17:25:33 -07002935 * of the interfaces implemented by "this_class". (Or, if
jeffhaobdb76512011-09-07 11:43:16 -07002936 * we couldn't complete the merge, this will be Object.)
2937 */
2938 if (this_class != abs_method->GetDeclaringClass() &&
2939 this_class != class_linker->FindSystemClass("Ljava/lang/Object;") &&
2940 !this_class->Implements(abs_method->GetDeclaringClass())) {
2941 LOG(ERROR) << "VFY: unable to match abs_method '"
2942 << abs_method->GetName()->ToModifiedUtf8() << "' with "
2943 << this_class->GetDescriptor()->ToModifiedUtf8()
2944 << " interfaces";
2945 failure = VERIFY_ERROR_GENERIC;
2946 break;
2947 }
2948 }
2949#endif
2950
2951 /*
2952 * We don't have an object instance, so we can't find the
jeffhaod1f0fde2011-09-08 17:25:33 -07002953 * concrete method. However, all of the type information is
jeffhaobdb76512011-09-07 11:43:16 -07002954 * in the abstract method, so we're good.
2955 */
2956 return_type = GetMethodReturnType(dex_file, abs_method);
2957 SetResultRegisterType(work_line, registers_size, return_type);
2958 just_set_result = true;
2959 }
2960 break;
2961
2962 case Instruction::NEG_INT:
2963 case Instruction::NOT_INT:
2964 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
2965 &failure);
2966 break;
2967 case Instruction::NEG_LONG:
2968 case Instruction::NOT_LONG:
2969 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo, &failure);
2970 break;
2971 case Instruction::NEG_FLOAT:
2972 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat, &failure);
2973 break;
2974 case Instruction::NEG_DOUBLE:
2975 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
2976 &failure);
2977 break;
2978 case Instruction::INT_TO_LONG:
2979 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeInteger,
2980 &failure);
2981 break;
2982 case Instruction::INT_TO_FLOAT:
2983 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeInteger, &failure);
2984 break;
2985 case Instruction::INT_TO_DOUBLE:
2986 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeInteger,
2987 &failure);
2988 break;
2989 case Instruction::LONG_TO_INT:
2990 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeLongLo,
2991 &failure);
2992 break;
2993 case Instruction::LONG_TO_FLOAT:
2994 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeLongLo, &failure);
2995 break;
2996 case Instruction::LONG_TO_DOUBLE:
2997 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeLongLo,
2998 &failure);
2999 break;
3000 case Instruction::FLOAT_TO_INT:
3001 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeFloat, &failure);
3002 break;
3003 case Instruction::FLOAT_TO_LONG:
3004 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeFloat, &failure);
3005 break;
3006 case Instruction::FLOAT_TO_DOUBLE:
3007 CheckUnop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeFloat,
3008 &failure);
3009 break;
3010 case Instruction::DOUBLE_TO_INT:
3011 CheckUnop(work_line, &dec_insn, kRegTypeInteger, kRegTypeDoubleLo,
3012 &failure);
3013 break;
3014 case Instruction::DOUBLE_TO_LONG:
3015 CheckUnop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeDoubleLo,
3016 &failure);
3017 break;
3018 case Instruction::DOUBLE_TO_FLOAT:
3019 CheckUnop(work_line, &dec_insn, kRegTypeFloat, kRegTypeDoubleLo,
3020 &failure);
3021 break;
3022 case Instruction::INT_TO_BYTE:
3023 CheckUnop(work_line, &dec_insn, kRegTypeByte, kRegTypeInteger, &failure);
3024 break;
3025 case Instruction::INT_TO_CHAR:
3026 CheckUnop(work_line, &dec_insn, kRegTypeChar, kRegTypeInteger, &failure);
3027 break;
3028 case Instruction::INT_TO_SHORT:
3029 CheckUnop(work_line, &dec_insn, kRegTypeShort, kRegTypeInteger, &failure);
3030 break;
3031
3032 case Instruction::ADD_INT:
3033 case Instruction::SUB_INT:
3034 case Instruction::MUL_INT:
3035 case Instruction::REM_INT:
3036 case Instruction::DIV_INT:
3037 case Instruction::SHL_INT:
3038 case Instruction::SHR_INT:
3039 case Instruction::USHR_INT:
3040 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3041 kRegTypeInteger, false, &failure);
3042 break;
3043 case Instruction::AND_INT:
3044 case Instruction::OR_INT:
3045 case Instruction::XOR_INT:
3046 CheckBinop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3047 kRegTypeInteger, true, &failure);
3048 break;
3049 case Instruction::ADD_LONG:
3050 case Instruction::SUB_LONG:
3051 case Instruction::MUL_LONG:
3052 case Instruction::DIV_LONG:
3053 case Instruction::REM_LONG:
3054 case Instruction::AND_LONG:
3055 case Instruction::OR_LONG:
3056 case Instruction::XOR_LONG:
3057 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3058 kRegTypeLongLo, false, &failure);
3059 break;
3060 case Instruction::SHL_LONG:
3061 case Instruction::SHR_LONG:
3062 case Instruction::USHR_LONG:
3063 /* shift distance is Int, making these different from other binops */
3064 CheckBinop(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3065 kRegTypeInteger, false, &failure);
3066 break;
3067 case Instruction::ADD_FLOAT:
3068 case Instruction::SUB_FLOAT:
3069 case Instruction::MUL_FLOAT:
3070 case Instruction::DIV_FLOAT:
3071 case Instruction::REM_FLOAT:
3072 CheckBinop(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3073 kRegTypeFloat, false, &failure);
3074 break;
3075 case Instruction::ADD_DOUBLE:
3076 case Instruction::SUB_DOUBLE:
3077 case Instruction::MUL_DOUBLE:
3078 case Instruction::DIV_DOUBLE:
3079 case Instruction::REM_DOUBLE:
3080 CheckBinop(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3081 kRegTypeDoubleLo, false, &failure);
3082 break;
3083 case Instruction::ADD_INT_2ADDR:
3084 case Instruction::SUB_INT_2ADDR:
3085 case Instruction::MUL_INT_2ADDR:
3086 case Instruction::REM_INT_2ADDR:
3087 case Instruction::SHL_INT_2ADDR:
3088 case Instruction::SHR_INT_2ADDR:
3089 case Instruction::USHR_INT_2ADDR:
3090 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3091 kRegTypeInteger, false, &failure);
3092 break;
3093 case Instruction::AND_INT_2ADDR:
3094 case Instruction::OR_INT_2ADDR:
3095 case Instruction::XOR_INT_2ADDR:
3096 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3097 kRegTypeInteger, true, &failure);
3098 break;
3099 case Instruction::DIV_INT_2ADDR:
3100 CheckBinop2addr(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger,
3101 kRegTypeInteger, false, &failure);
3102 break;
3103 case Instruction::ADD_LONG_2ADDR:
3104 case Instruction::SUB_LONG_2ADDR:
3105 case Instruction::MUL_LONG_2ADDR:
3106 case Instruction::DIV_LONG_2ADDR:
3107 case Instruction::REM_LONG_2ADDR:
3108 case Instruction::AND_LONG_2ADDR:
3109 case Instruction::OR_LONG_2ADDR:
3110 case Instruction::XOR_LONG_2ADDR:
3111 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3112 kRegTypeLongLo, false, &failure);
3113 break;
3114 case Instruction::SHL_LONG_2ADDR:
3115 case Instruction::SHR_LONG_2ADDR:
3116 case Instruction::USHR_LONG_2ADDR:
3117 CheckBinop2addr(work_line, &dec_insn, kRegTypeLongLo, kRegTypeLongLo,
3118 kRegTypeInteger, false, &failure);
3119 break;
3120 case Instruction::ADD_FLOAT_2ADDR:
3121 case Instruction::SUB_FLOAT_2ADDR:
3122 case Instruction::MUL_FLOAT_2ADDR:
3123 case Instruction::DIV_FLOAT_2ADDR:
3124 case Instruction::REM_FLOAT_2ADDR:
3125 CheckBinop2addr(work_line, &dec_insn, kRegTypeFloat, kRegTypeFloat,
3126 kRegTypeFloat, false, &failure);
3127 break;
3128 case Instruction::ADD_DOUBLE_2ADDR:
3129 case Instruction::SUB_DOUBLE_2ADDR:
3130 case Instruction::MUL_DOUBLE_2ADDR:
3131 case Instruction::DIV_DOUBLE_2ADDR:
3132 case Instruction::REM_DOUBLE_2ADDR:
3133 CheckBinop2addr(work_line, &dec_insn, kRegTypeDoubleLo, kRegTypeDoubleLo,
3134 kRegTypeDoubleLo, false, &failure);
3135 break;
3136 case Instruction::ADD_INT_LIT16:
3137 case Instruction::RSUB_INT:
3138 case Instruction::MUL_INT_LIT16:
3139 case Instruction::DIV_INT_LIT16:
3140 case Instruction::REM_INT_LIT16:
3141 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3142 &failure);
3143 break;
3144 case Instruction::AND_INT_LIT16:
3145 case Instruction::OR_INT_LIT16:
3146 case Instruction::XOR_INT_LIT16:
3147 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3148 &failure);
3149 break;
3150 case Instruction::ADD_INT_LIT8:
3151 case Instruction::RSUB_INT_LIT8:
3152 case Instruction::MUL_INT_LIT8:
3153 case Instruction::DIV_INT_LIT8:
3154 case Instruction::REM_INT_LIT8:
3155 case Instruction::SHL_INT_LIT8:
3156 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, false,
3157 &failure);
3158 break;
3159 case Instruction::SHR_INT_LIT8:
3160 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
jeffhaob4df5142011-09-19 20:25:32 -07003161 false);
jeffhaobdb76512011-09-07 11:43:16 -07003162 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3163 &failure);
3164 break;
3165 case Instruction::USHR_INT_LIT8:
3166 tmp_type = AdjustForRightShift(work_line, dec_insn.vB_, dec_insn.vC_,
jeffhaob4df5142011-09-19 20:25:32 -07003167 true);
jeffhaobdb76512011-09-07 11:43:16 -07003168 CheckLitop(work_line, &dec_insn, tmp_type, kRegTypeInteger, false,
3169 &failure);
3170 break;
3171 case Instruction::AND_INT_LIT8:
3172 case Instruction::OR_INT_LIT8:
3173 case Instruction::XOR_INT_LIT8:
3174 CheckLitop(work_line, &dec_insn, kRegTypeInteger, kRegTypeInteger, true,
3175 &failure);
3176 break;
3177
3178 /*
3179 * This falls into the general category of "optimized" instructions,
jeffhaod1f0fde2011-09-08 17:25:33 -07003180 * which don't generally appear during verification. Because it's
jeffhaobdb76512011-09-07 11:43:16 -07003181 * inserted in the course of verification, we can expect to see it here.
3182 */
jeffhaob4df5142011-09-19 20:25:32 -07003183 case Instruction::THROW_VERIFICATION_ERROR:
jeffhaobdb76512011-09-07 11:43:16 -07003184 break;
3185
3186 /*
3187 * Verifying "quickened" instructions is tricky, because we have
jeffhaod1f0fde2011-09-08 17:25:33 -07003188 * discarded the original field/method information. The byte offsets
jeffhaobdb76512011-09-07 11:43:16 -07003189 * and vtable indices only have meaning in the context of an object
3190 * instance.
3191 *
3192 * If a piece of code declares a local reference variable, assigns
3193 * null to it, and then issues a virtual method call on it, we
jeffhaod1f0fde2011-09-08 17:25:33 -07003194 * cannot evaluate the method call during verification. This situation
jeffhaobdb76512011-09-07 11:43:16 -07003195 * isn't hard to handle, since we know the call will always result in an
jeffhaod1f0fde2011-09-08 17:25:33 -07003196 * NPE, and the arguments and return value don't matter. Any code that
jeffhaobdb76512011-09-07 11:43:16 -07003197 * depends on the result of the method call is inaccessible, so the
3198 * fact that we can't fully verify anything that comes after the bad
3199 * call is not a problem.
3200 *
3201 * We must also consider the case of multiple code paths, only some of
jeffhaod1f0fde2011-09-08 17:25:33 -07003202 * which involve a null reference. We can completely verify the method
jeffhaobdb76512011-09-07 11:43:16 -07003203 * if we sidestep the results of executing with a null reference.
3204 * For example, if on the first pass through the code we try to do a
3205 * virtual method invocation through a null ref, we have to skip the
3206 * method checks and have the method return a "wildcard" type (which
jeffhaod1f0fde2011-09-08 17:25:33 -07003207 * merges with anything to become that other thing). The move-result
jeffhaobdb76512011-09-07 11:43:16 -07003208 * will tell us if it's a reference, single-word numeric, or double-word
jeffhaod1f0fde2011-09-08 17:25:33 -07003209 * value. We continue to perform the verification, and at the end of
jeffhaobdb76512011-09-07 11:43:16 -07003210 * the function any invocations that were never fully exercised are
3211 * marked as null-only.
3212 *
jeffhaod1f0fde2011-09-08 17:25:33 -07003213 * We would do something similar for the field accesses. The field's
jeffhaobdb76512011-09-07 11:43:16 -07003214 * type, once known, can be used to recover the width of short integers.
3215 * If the object reference was null, the field-get returns the "wildcard"
3216 * type, which is acceptable for any operation.
3217 */
3218 case Instruction::UNUSED_EE:
3219 case Instruction::UNUSED_EF:
3220 case Instruction::UNUSED_F2:
3221 case Instruction::UNUSED_F3:
3222 case Instruction::UNUSED_F4:
3223 case Instruction::UNUSED_F5:
3224 case Instruction::UNUSED_F6:
3225 case Instruction::UNUSED_F7:
3226 case Instruction::UNUSED_F8:
3227 case Instruction::UNUSED_F9:
3228 case Instruction::UNUSED_FA:
3229 case Instruction::UNUSED_FB:
3230 //case Instruction::EXECUTE_INLINE:
3231 //case Instruction::EXECUTE_INLINE_RANGE:
3232 //case Instruction::IGET_QUICK:
3233 //case Instruction::IGET_WIDE_QUICK:
3234 //case Instruction::IGET_OBJECT_QUICK:
3235 //case Instruction::IPUT_QUICK:
3236 //case Instruction::IPUT_WIDE_QUICK:
3237 //case Instruction::IPUT_OBJECT_QUICK:
3238 //case Instruction::INVOKE_VIRTUAL_QUICK:
3239 //case Instruction::INVOKE_VIRTUAL_QUICK_RANGE:
3240 //case Instruction::INVOKE_SUPER_QUICK:
3241 //case Instruction::INVOKE_SUPER_QUICK_RANGE:
3242 /* fall through to failure */
3243
3244 /*
3245 * These instructions are equivalent (from the verifier's point of view)
jeffhaod1f0fde2011-09-08 17:25:33 -07003246 * to the original form. The change was made for correctness rather
jeffhaobdb76512011-09-07 11:43:16 -07003247 * than improved performance (except for invoke-object-init, which
jeffhaod1f0fde2011-09-08 17:25:33 -07003248 * provides both). The substitution takes place after verification
jeffhaobdb76512011-09-07 11:43:16 -07003249 * completes, though, so we don't expect to see them here.
3250 */
3251 case Instruction::UNUSED_F0:
3252 case Instruction::UNUSED_F1:
3253 case Instruction::UNUSED_E3:
3254 case Instruction::UNUSED_E8:
3255 case Instruction::UNUSED_E7:
3256 case Instruction::UNUSED_E4:
3257 case Instruction::UNUSED_E9:
3258 case Instruction::UNUSED_FC:
3259 case Instruction::UNUSED_E5:
3260 case Instruction::UNUSED_EA:
3261 case Instruction::UNUSED_FD:
3262 case Instruction::UNUSED_E6:
3263 case Instruction::UNUSED_EB:
3264 case Instruction::UNUSED_FE:
3265 //case Instruction::INVOKE_OBJECT_INIT_RANGE:
3266 //case Instruction::RETURN_VOID_BARRIER:
3267 //case Instruction::IGET_VOLATILE:
3268 //case Instruction::IGET_WIDE_VOLATILE:
3269 //case Instruction::IGET_OBJECT_VOLATILE:
3270 //case Instruction::IPUT_VOLATILE:
3271 //case Instruction::IPUT_WIDE_VOLATILE:
3272 //case Instruction::IPUT_OBJECT_VOLATILE:
3273 //case Instruction::SGET_VOLATILE:
3274 //case Instruction::SGET_WIDE_VOLATILE:
3275 //case Instruction::SGET_OBJECT_VOLATILE:
3276 //case Instruction::SPUT_VOLATILE:
3277 //case Instruction::SPUT_WIDE_VOLATILE:
3278 //case Instruction::SPUT_OBJECT_VOLATILE:
3279 /* fall through to failure */
3280
3281 /* These should never appear during verification. */
3282 case Instruction::UNUSED_3E:
3283 case Instruction::UNUSED_3F:
3284 case Instruction::UNUSED_40:
3285 case Instruction::UNUSED_41:
3286 case Instruction::UNUSED_42:
3287 case Instruction::UNUSED_43:
3288 case Instruction::UNUSED_73:
3289 case Instruction::UNUSED_79:
3290 case Instruction::UNUSED_7A:
3291 case Instruction::UNUSED_EC:
3292 case Instruction::UNUSED_FF:
3293 //case Instruction::BREAKPOINT:
3294 //case Instruction::DISPATCH_FF:
3295 failure = VERIFY_ERROR_GENERIC;
3296 break;
3297
3298 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003299 * DO NOT add a "default" clause here. Without it the compiler will
jeffhaobdb76512011-09-07 11:43:16 -07003300 * complain if an instruction is missing (which is desirable).
3301 */
3302 }
3303
3304 if (failure != VERIFY_ERROR_NONE) {
jeffhaobdb76512011-09-07 11:43:16 -07003305 if (failure == VERIFY_ERROR_GENERIC) {
3306 /* immediate failure, reject class */
3307 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3308 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
3309 return false;
3310 } else {
3311 /* replace opcode and continue on */
3312 LOG(ERROR) << "VFY: replacing opcode 0x" << std::hex
3313 << (int) dec_insn.opcode_ << " at 0x" << insn_idx << std::dec;
jeffhaob4df5142011-09-19 20:25:32 -07003314 if (!ReplaceFailingInstruction(code_item, insn_idx, failure)) {
jeffhaobdb76512011-09-07 11:43:16 -07003315 LOG(ERROR) << "VFY: rejecting opcode 0x" << std::hex
3316 << (int) dec_insn.opcode_ << " at 0x" << insn_idx
3317 << std::dec;
3318 return false;
3319 }
3320 /* IMPORTANT: method->insns may have been changed */
3321 insns = code_item->insns_ + insn_idx;
3322
3323 /* continue on as if we just handled a throw-verification-error */
3324 failure = VERIFY_ERROR_NONE;
3325 opcode_flag = Instruction::kThrow;
3326 }
3327 }
3328
3329 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003330 * If we didn't just set the result register, clear it out. This
jeffhaobdb76512011-09-07 11:43:16 -07003331 * ensures that you can only use "move-result" immediately after the
jeffhaod1f0fde2011-09-08 17:25:33 -07003332 * result is set. (We could check this statically, but it's not
jeffhaobdb76512011-09-07 11:43:16 -07003333 * expensive and it makes our debugging output cleaner.)
3334 */
3335 if (!just_set_result) {
3336 int reg = RESULT_REGISTER(registers_size);
3337 SetRegisterType(work_line, reg, kRegTypeUnknown);
3338 SetRegisterType(work_line, reg + 1, kRegTypeUnknown);
3339 }
3340
jeffhaoa0a764a2011-09-16 10:43:38 -07003341 /* Handle "continue". Tag the next consecutive instruction. */
jeffhaobdb76512011-09-07 11:43:16 -07003342 if ((opcode_flag & Instruction::kContinue) != 0) {
3343 size_t insn_width = InsnGetWidth(insn_flags, insn_idx);
3344 if (insn_idx + insn_width >= insns_size) {
3345 LOG(ERROR) << "VFY: execution can walk off end of code area (from 0x"
3346 << std::hex << insn_idx << std::dec << ")";
3347 return false;
3348 }
3349
3350 /*
3351 * The only way to get to a move-exception instruction is to get
jeffhaod1f0fde2011-09-08 17:25:33 -07003352 * thrown there. Make sure the next instruction isn't one.
jeffhaobdb76512011-09-07 11:43:16 -07003353 */
3354 if (!CheckMoveException(code_item->insns_, insn_idx + insn_width))
3355 return false;
3356
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003357 if (GetRegisterLine(reg_table, insn_idx + insn_width)->reg_types_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003358 /*
3359 * Merge registers into what we have for the next instruction,
3360 * and set the "changed" flag if needed.
3361 */
3362 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + insn_width,
3363 work_line))
3364 return false;
3365 } else {
3366 /*
3367 * We're not recording register data for the next instruction,
jeffhaod1f0fde2011-09-08 17:25:33 -07003368 * so we don't know what the prior state was. We have to
jeffhaobdb76512011-09-07 11:43:16 -07003369 * assume that something has changed and re-evaluate it.
3370 */
3371 InsnSetChanged(insn_flags, insn_idx + insn_width, true);
3372 }
3373 }
3374
3375 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003376 * Handle "branch". Tag the branch target.
jeffhaobdb76512011-09-07 11:43:16 -07003377 *
3378 * NOTE: instructions like Instruction::EQZ provide information about the
jeffhaod1f0fde2011-09-08 17:25:33 -07003379 * state of the register when the branch is taken or not taken. For example,
jeffhaobdb76512011-09-07 11:43:16 -07003380 * somebody could get a reference field, check it for zero, and if the
3381 * branch is taken immediately store that register in a boolean field
jeffhaod1f0fde2011-09-08 17:25:33 -07003382 * since the value is known to be zero. We do not currently account for
jeffhaobdb76512011-09-07 11:43:16 -07003383 * that, and will reject the code.
3384 *
3385 * TODO: avoid re-fetching the branch target
3386 */
3387 if ((opcode_flag & Instruction::kBranch) != 0) {
3388 bool isConditional, selfOkay;
3389
3390 if (!GetBranchOffset(code_item, insn_flags, insn_idx, &branch_target,
3391 &isConditional, &selfOkay)) {
3392 /* should never happen after static verification */
3393 LOG(ERROR) << "VFY: bad branch at 0x" << std::hex << insn_idx << std::dec;
3394 return false;
3395 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003396 DCHECK_EQ(isConditional, (opcode_flag & Instruction::kContinue) != 0);
jeffhaobdb76512011-09-07 11:43:16 -07003397
3398 if (!CheckMoveException(code_item->insns_, insn_idx + branch_target))
3399 return false;
3400
3401 /* update branch target, set "changed" if appropriate */
3402 if (!UpdateRegisters(insn_flags, reg_table, insn_idx + branch_target,
3403 work_line))
3404 return false;
3405 }
3406
3407 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003408 * Handle "switch". Tag all possible branch targets.
jeffhaobdb76512011-09-07 11:43:16 -07003409 *
3410 * We've already verified that the table is structurally sound, so we
3411 * just need to walk through and tag the targets.
3412 */
3413 if ((opcode_flag & Instruction::kSwitch) != 0) {
3414 int offset_to_switch = insns[1] | (((int32_t) insns[2]) << 16);
3415 const uint16_t* switch_insns = insns + offset_to_switch;
3416 int switch_count = switch_insns[1];
3417 int offset_to_targets, targ;
3418
3419 if ((*insns & 0xff) == Instruction::PACKED_SWITCH) {
3420 /* 0 = sig, 1 = count, 2/3 = first key */
3421 offset_to_targets = 4;
3422 } else {
3423 /* 0 = sig, 1 = count, 2..count * 2 = keys */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003424 DCHECK((*insns & 0xff) == Instruction::SPARSE_SWITCH);
jeffhaobdb76512011-09-07 11:43:16 -07003425 offset_to_targets = 2 + 2 * switch_count;
3426 }
3427
3428 /* verify each switch target */
3429 for (targ = 0; targ < switch_count; targ++) {
3430 int offset;
3431 uint32_t abs_offset;
3432
3433 /* offsets are 32-bit, and only partly endian-swapped */
3434 offset = switch_insns[offset_to_targets + targ * 2] |
3435 (((int32_t) switch_insns[offset_to_targets + targ * 2 + 1]) << 16);
3436 abs_offset = insn_idx + offset;
3437
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003438 DCHECK_LT(abs_offset, insns_size);
jeffhaobdb76512011-09-07 11:43:16 -07003439
3440 if (!CheckMoveException(code_item->insns_, abs_offset))
3441 return false;
3442
3443 if (!UpdateRegisters(insn_flags, reg_table, abs_offset, work_line))
3444 return false;
3445 }
3446 }
3447
3448 /*
3449 * Handle instructions that can throw and that are sitting in a
jeffhaod1f0fde2011-09-08 17:25:33 -07003450 * "try" block. (If they're not in a "try" block when they throw,
jeffhaobdb76512011-09-07 11:43:16 -07003451 * control transfers out of the method.)
3452 */
3453 if ((opcode_flag & Instruction::kThrow) != 0 &&
3454 InsnIsInTry(insn_flags, insn_idx)) {
3455 bool has_catch_all = false;
3456 DexFile::CatchHandlerIterator iterator = DexFile::dexFindCatchHandler(
3457 *code_item, insn_idx);
3458
3459 for (; !iterator.HasNext(); iterator.Next()) {
3460 if (iterator.Get().type_idx_ == DexFile::kDexNoIndex)
3461 has_catch_all = true;
3462
3463 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003464 * Merge registers into the "catch" block. We want to use the
3465 * "savedRegs" rather than "work_regs", because at runtime the
3466 * exception will be thrown before the instruction modifies any
3467 * registers.
jeffhaobdb76512011-09-07 11:43:16 -07003468 */
3469 if (!UpdateRegisters(insn_flags, reg_table, iterator.Get().address_,
3470 &reg_table->saved_line_))
3471 return false;
3472 }
3473
3474 /*
3475 * If the monitor stack depth is nonzero, there must be a "catch all"
jeffhaod1f0fde2011-09-08 17:25:33 -07003476 * handler for this instruction. This does apply to monitor-exit
jeffhaobdb76512011-09-07 11:43:16 -07003477 * because of async exception handling.
3478 */
3479 if (work_line->monitor_stack_top_ != 0 && !has_catch_all) {
3480 /*
3481 * The state in work_line reflects the post-execution state.
3482 * If the current instruction is a monitor-enter and the monitor
3483 * stack was empty, we don't need a catch-all (if it throws,
3484 * it will do so before grabbing the lock).
3485 */
3486 if (!(dec_insn.opcode_ == Instruction::MONITOR_ENTER &&
3487 work_line->monitor_stack_top_ == 1))
3488 {
3489 LOG(ERROR) << "VFY: no catch-all for instruction at 0x" << std::hex
3490 << insn_idx << std::dec;
3491 return false;
3492 }
3493 }
3494 }
3495
jeffhaod1f0fde2011-09-08 17:25:33 -07003496 /* If we're returning from the method, make sure monitor stack is empty. */
jeffhaobdb76512011-09-07 11:43:16 -07003497 if ((opcode_flag & Instruction::kReturn) != 0 &&
3498 work_line->monitor_stack_top_ != 0) {
3499 LOG(ERROR) << "VFY: return with stack depth="
3500 << work_line->monitor_stack_top_ << " at 0x" << std::hex
3501 << insn_idx << std::dec;
3502 return false;
3503 }
3504
3505 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07003506 * Update start_guess. Advance to the next instruction of that's
3507 * possible, otherwise use the branch target if one was found. If
jeffhaobdb76512011-09-07 11:43:16 -07003508 * neither of those exists we're in a return or throw; leave start_guess
3509 * alone and let the caller sort it out.
3510 */
3511 if ((opcode_flag & Instruction::kContinue) != 0) {
3512 *start_guess = insn_idx + InsnGetWidth(insn_flags, insn_idx);
3513 } else if ((opcode_flag & Instruction::kBranch) != 0) {
3514 /* we're still okay if branch_target is zero */
3515 *start_guess = insn_idx + branch_target;
3516 }
3517
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003518 DCHECK_LT(*start_guess, insns_size);
Brian Carlstrom03c99df2011-09-18 10:52:00 -07003519 DCHECK_NE(InsnGetWidth(insn_flags, *start_guess), 0);
jeffhaobdb76512011-09-07 11:43:16 -07003520
3521 return true;
3522}
3523
3524bool DexVerifier::ReplaceFailingInstruction(const DexFile::CodeItem* code_item,
jeffhaob4df5142011-09-19 20:25:32 -07003525 int insn_idx, VerifyError failure) {
jeffhaobdb76512011-09-07 11:43:16 -07003526 const uint16_t* insns = code_item->insns_ + insn_idx;
3527 const byte* ptr = reinterpret_cast<const byte*>(insns);
3528 const Instruction* inst = Instruction::At(ptr);
3529 Instruction::Code opcode = inst->Opcode();
3530 VerifyErrorRefType ref_type;
3531
3532 /*
3533 * Generate the new instruction out of the old.
3534 *
3535 * First, make sure this is an instruction we're expecting to stomp on.
3536 */
3537 switch (opcode) {
3538 case Instruction::CONST_CLASS: // insn[1] == class ref, 2 bytes
3539 case Instruction::CHECK_CAST:
3540 case Instruction::INSTANCE_OF:
3541 case Instruction::NEW_INSTANCE:
3542 case Instruction::NEW_ARRAY:
3543 case Instruction::FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
3544 case Instruction::FILLED_NEW_ARRAY_RANGE:
3545 ref_type = VERIFY_ERROR_REF_CLASS;
3546 break;
3547
3548 case Instruction::IGET: // insn[1] == field ref, 2 bytes
3549 case Instruction::IGET_BOOLEAN:
3550 case Instruction::IGET_BYTE:
3551 case Instruction::IGET_CHAR:
3552 case Instruction::IGET_SHORT:
3553 case Instruction::IGET_WIDE:
3554 case Instruction::IGET_OBJECT:
3555 case Instruction::IPUT:
3556 case Instruction::IPUT_BOOLEAN:
3557 case Instruction::IPUT_BYTE:
3558 case Instruction::IPUT_CHAR:
3559 case Instruction::IPUT_SHORT:
3560 case Instruction::IPUT_WIDE:
3561 case Instruction::IPUT_OBJECT:
3562 case Instruction::SGET:
3563 case Instruction::SGET_BOOLEAN:
3564 case Instruction::SGET_BYTE:
3565 case Instruction::SGET_CHAR:
3566 case Instruction::SGET_SHORT:
3567 case Instruction::SGET_WIDE:
3568 case Instruction::SGET_OBJECT:
3569 case Instruction::SPUT:
3570 case Instruction::SPUT_BOOLEAN:
3571 case Instruction::SPUT_BYTE:
3572 case Instruction::SPUT_CHAR:
3573 case Instruction::SPUT_SHORT:
3574 case Instruction::SPUT_WIDE:
3575 case Instruction::SPUT_OBJECT:
3576 ref_type = VERIFY_ERROR_REF_FIELD;
3577 break;
3578
3579 case Instruction::INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3580 case Instruction::INVOKE_VIRTUAL_RANGE:
3581 case Instruction::INVOKE_SUPER:
3582 case Instruction::INVOKE_SUPER_RANGE:
3583 case Instruction::INVOKE_DIRECT:
3584 case Instruction::INVOKE_DIRECT_RANGE:
3585 case Instruction::INVOKE_STATIC:
3586 case Instruction::INVOKE_STATIC_RANGE:
3587 case Instruction::INVOKE_INTERFACE:
3588 case Instruction::INVOKE_INTERFACE_RANGE:
3589 ref_type = VERIFY_ERROR_REF_METHOD;
3590 break;
3591
3592 default:
3593 /* could handle this in a generic way, but this is probably safer */
3594 LOG(ERROR) << "GLITCH: verifier asked to replace opcode 0x" << std::hex
3595 << (int) opcode << std::dec;
3596 return false;
3597 }
3598
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003599 DCHECK(inst->IsThrow());
jeffhaobdb76512011-09-07 11:43:16 -07003600
3601 /* write a NOP over the third code unit, if necessary */
jeffhaob4df5142011-09-19 20:25:32 -07003602 int width = inst->Size();
jeffhaobdb76512011-09-07 11:43:16 -07003603 switch (width) {
3604 case 2:
3605 /* nothing to do */
3606 break;
3607 case 3:
jeffhaob4df5142011-09-19 20:25:32 -07003608 UpdateCodeUnit(insns + 2, Instruction::NOP);
jeffhaobdb76512011-09-07 11:43:16 -07003609 break;
3610 default:
3611 /* whoops */
3612 LOG(FATAL) << "ERROR: stomped a " << width
3613 << "-unit instruction with a verifier error";
3614 }
3615
3616 /* encode the opcode, with the failure code in the high byte */
jeffhaob4df5142011-09-19 20:25:32 -07003617 DCHECK(width == 2 || width == 3);
3618 uint16_t new_val = Instruction::THROW_VERIFICATION_ERROR |
3619 (failure << 8) | (ref_type << (8 + kVerifyErrorRefTypeShift));
3620 UpdateCodeUnit(insns, new_val);
jeffhaobdb76512011-09-07 11:43:16 -07003621
3622 return true;
3623}
3624
jeffhaob4df5142011-09-19 20:25:32 -07003625void DexVerifier::UpdateCodeUnit(const uint16_t* ptr, uint16_t new_val) {
3626 *(uint16_t*) ptr = new_val;
3627}
3628
jeffhaobdb76512011-09-07 11:43:16 -07003629void DexVerifier::HandleMonitorEnter(RegisterLine* work_line, uint32_t reg_idx,
3630 uint32_t insn_idx, VerifyError* failure) {
3631 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3632 LOG(ERROR) << "VFY: monitor-enter on non-object";
3633 *failure = VERIFY_ERROR_GENERIC;
3634 return;
3635 }
3636
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003637 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003638 return;
3639 }
3640
3641 if (work_line->monitor_stack_top_ == kMaxMonitorStackDepth) {
3642 LOG(ERROR) << "VFY: monitor-enter stack overflow (" << kMaxMonitorStackDepth
3643 << ")";
3644 *failure = VERIFY_ERROR_GENERIC;
3645 return;
3646 }
3647
3648 /*
3649 * Push an entry on the stack, and set a bit in the register flags to
3650 * indicate that it's associated with this register.
3651 */
3652 work_line->monitor_entries_[reg_idx] |= 1 << work_line->monitor_stack_top_;
3653 work_line->monitor_stack_[work_line->monitor_stack_top_++] = insn_idx;
3654}
3655
jeffhaobdb76512011-09-07 11:43:16 -07003656void DexVerifier::HandleMonitorExit(RegisterLine* work_line, uint32_t reg_idx,
3657 uint32_t insn_idx, VerifyError* failure) {
3658 if (!RegTypeIsReference(GetRegisterType(work_line, reg_idx))) {
3659 LOG(ERROR) << "VFY: monitor-exit on non-object";
3660 *failure = VERIFY_ERROR_GENERIC;
3661 return;
3662 }
3663
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003664 if (work_line->monitor_entries_.get() == NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07003665 return;
3666 }
3667
3668 if (work_line->monitor_stack_top_ == 0) {
3669 LOG(ERROR) << "VFY: monitor-exit stack underflow";
3670 *failure = VERIFY_ERROR_GENERIC;
3671 return;
3672 }
3673
3674 /*
3675 * Confirm that the entry at the top of the stack is associated with
jeffhaod1f0fde2011-09-08 17:25:33 -07003676 * the register. Pop the top entry off.
jeffhaobdb76512011-09-07 11:43:16 -07003677 */
3678 work_line->monitor_stack_top_--;
3679#ifdef BUG_3215458_FIXED
3680 /*
3681 * TODO: This code can safely be enabled if know we are working on
3682 * a dex file of format version 036 or later. (That is, we'll need to
3683 * add a check for the version number.)
3684 */
3685 if ((work_line->monitor_entries_[reg_idx] &
3686 (1 << work_line->monitor_stack_top_)) == 0) {
3687 LOG(ERROR) << "VFY: monitor-exit bit " << work_line->monitor_stack_top_
3688 << " not set: addr=0x" << std::hex << insn_idx << std::dec
3689 << " (bits[" << reg_idx << "]=" << std::hex
3690 << work_line->monitor_entries_[reg_idx] << std::dec << ")";
3691 *failure = VERIFY_ERROR_GENERIC;
3692 return;
3693 }
3694#endif
3695 work_line->monitor_stack_[work_line->monitor_stack_top_] = 0;
3696
3697 /* Clear the bit from the register flags. */
3698 work_line->monitor_entries_[reg_idx] &= ~(1 << work_line->monitor_stack_top_);
3699}
3700
3701Field* DexVerifier::GetInstField(VerifierData* vdata, RegType obj_type,
3702 int field_idx, VerifyError* failure) {
3703 Method* method = vdata->method_;
3704 const DexFile* dex_file = vdata->dex_file_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003705 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003706 bool must_be_local = false;
3707
3708 if (!RegTypeIsReference(obj_type)) {
3709 LOG(ERROR) << "VFY: attempt to access field in non-reference type "
3710 << obj_type;
3711 *failure = VERIFY_ERROR_GENERIC;
jeffhaob4df5142011-09-19 20:25:32 -07003712 return NULL;
jeffhaobdb76512011-09-07 11:43:16 -07003713 }
3714
jeffhaob4df5142011-09-19 20:25:32 -07003715 Field* field = ResolveFieldAndCheckAccess(dex_file, field_idx,
3716 method->GetDeclaringClass(), failure, false);
jeffhaobdb76512011-09-07 11:43:16 -07003717 if (field == NULL) {
3718 LOG(ERROR) << "VFY: unable to resolve instance field " << field_idx;
jeffhao2a8a90e2011-09-26 14:25:31 -07003719 return NULL;
jeffhaobdb76512011-09-07 11:43:16 -07003720 }
3721
3722 if (obj_type == kRegTypeZero)
3723 return field;
3724
3725 /*
3726 * Access to fields in uninitialized objects is allowed if this is
3727 * the <init> method for the object and the field in question is
3728 * declared by this class.
3729 */
jeffhaob4df5142011-09-19 20:25:32 -07003730 Class* obj_class = RegTypeReferenceToClass(obj_type, uninit_map);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07003731 DCHECK(obj_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07003732 if (RegTypeIsUninitReference(obj_type)) {
3733 if (!IsInitMethod(method) || method->GetDeclaringClass() != obj_class) {
3734 LOG(ERROR) << "VFY: attempt to access field via uninitialized ref";
3735 *failure = VERIFY_ERROR_GENERIC;
3736 return field;
3737 }
3738 must_be_local = true;
3739 }
3740
jeffhaobdb76512011-09-07 11:43:16 -07003741 if (!field->GetDeclaringClass()->IsAssignableFrom(obj_class)) {
jeffhao2a8a90e2011-09-26 14:25:31 -07003742 LOG(ERROR) << "VFY: invalid field access (field " << PrettyField(field)
3743 << ", through " << obj_class->GetDescriptor()->ToModifiedUtf8()
3744 << " ref)";
jeffhaobdb76512011-09-07 11:43:16 -07003745 *failure = VERIFY_ERROR_NO_FIELD;
3746 return field;
3747 }
3748
3749 if (must_be_local) {
3750 bool found = false;
3751 /* for uninit ref, make sure it's defined by this class, not super */
3752 for (uint32_t i = 0; i < obj_class->NumInstanceFields(); i++) {
3753 found |= (field == obj_class->GetInstanceField(i));
3754 }
3755 if (!found) {
3756 LOG(ERROR) << "VFY: invalid constructor field access (field "
3757 << field->GetName()->ToModifiedUtf8() << " in "
3758 << obj_class->GetDescriptor()->ToModifiedUtf8() << ")";
3759 *failure = VERIFY_ERROR_GENERIC;
3760 return field;
3761 }
3762 }
3763
3764 return field;
3765}
3766
3767Field* DexVerifier::GetStaticField(VerifierData* vdata, int field_idx,
3768 VerifyError* failure) {
3769 Method* method = vdata->method_;
3770 const DexFile* dex_file = vdata->dex_file_;
jeffhaob4df5142011-09-19 20:25:32 -07003771 Field* field = ResolveFieldAndCheckAccess(dex_file, field_idx,
3772 method->GetDeclaringClass(), failure, true);
jeffhaobdb76512011-09-07 11:43:16 -07003773 if (field == NULL) {
jeffhaob4df5142011-09-19 20:25:32 -07003774 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
3775 LOG(ERROR) << "VFY: unable to resolve static field " << field_idx << " ("
3776 << dex_file->GetFieldName(field_id) << ") in "
3777 << dex_file->GetFieldClassDescriptor(field_id);
3778 *failure = VERIFY_ERROR_NO_FIELD;
jeffhaobdb76512011-09-07 11:43:16 -07003779 }
3780
3781 return field;
3782}
3783
3784Class* DexVerifier::GetCaughtExceptionType(VerifierData* vdata, int insn_idx,
3785 VerifyError* failure) {
3786 const DexFile* dex_file = vdata->dex_file_;
3787 const DexFile::CodeItem* code_item = vdata->code_item_;
3788 Method* method = vdata->method_;
3789 Class* common_super = NULL;
3790 uint32_t handlers_size;
jeffhaoba5ebb92011-08-25 17:24:37 -07003791 const byte* handlers_ptr = DexFile::dexGetCatchHandlerData(*code_item, 0);
jeffhao2a8a90e2011-09-26 14:25:31 -07003792 VerifyError local_failure;
jeffhaobdb76512011-09-07 11:43:16 -07003793
3794 if (code_item->tries_size_ != 0) {
3795 handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
3796 } else {
3797 handlers_size = 0;
3798 }
3799
3800 for (uint32_t i = 0; i < handlers_size; i++) {
jeffhaoba5ebb92011-08-25 17:24:37 -07003801 DexFile::CatchHandlerIterator iterator(handlers_ptr);
3802
3803 for (; !iterator.HasNext(); iterator.Next()) {
jeffhaobdb76512011-09-07 11:43:16 -07003804 DexFile::CatchHandlerItem handler = iterator.Get();
3805 if (handler.address_ == (uint32_t) insn_idx) {
3806 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
3807 Class* klass;
jeffhaoba5ebb92011-08-25 17:24:37 -07003808
jeffhaobdb76512011-09-07 11:43:16 -07003809 if (handler.type_idx_ == DexFile::kDexNoIndex) {
3810 klass = class_linker->FindSystemClass("Ljava/lang/Throwable;");
3811 } else {
jeffhao98eacac2011-09-14 16:11:53 -07003812 klass = ResolveClassAndCheckAccess(dex_file, handler.type_idx_,
jeffhao2a8a90e2011-09-26 14:25:31 -07003813 method->GetDeclaringClass(), &local_failure);
jeffhaobdb76512011-09-07 11:43:16 -07003814 }
3815
3816 if (klass == NULL) {
3817 LOG(ERROR) << "VFY: unable to resolve exception class "
3818 << handler.type_idx_ << " ("
3819 << dex_file->dexStringByTypeIdx(handler.type_idx_) << ")";
jeffhaod1f0fde2011-09-08 17:25:33 -07003820 /* TODO: do we want to keep going? If we don't fail this we run
3821 * the risk of having a non-Throwable introduced at runtime.
3822 * However, that won't pass an instanceof test, so is essentially
3823 * harmless.
jeffhaobdb76512011-09-07 11:43:16 -07003824 */
3825 } else {
3826 if (common_super == NULL)
3827 common_super = klass;
3828 else
3829 common_super = FindCommonSuperclass(klass, common_super);
3830 }
3831 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003832 }
3833
3834 handlers_ptr = iterator.GetData();
3835 }
3836
jeffhaobdb76512011-09-07 11:43:16 -07003837 if (common_super == NULL) {
3838 /* no catch blocks, or no catches with classes we can find */
3839 LOG(ERROR) << "VFY: unable to find exception handler at addr 0x" << std::hex
3840 << insn_idx << std::dec;
3841 *failure = VERIFY_ERROR_GENERIC;
3842 }
3843
3844 return common_super;
jeffhaoba5ebb92011-08-25 17:24:37 -07003845}
3846
jeffhaobdb76512011-09-07 11:43:16 -07003847DexVerifier::RegType DexVerifier::GetMethodReturnType(const DexFile* dex_file,
3848 const Method* method) {
3849 Class* klass = method->GetReturnType();
3850 if (klass->IsPrimitive())
3851 return PrimitiveTypeToRegType(klass->GetPrimitiveType());
3852 else
3853 return RegTypeFromClass(klass);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003854}
3855
jeffhaobdb76512011-09-07 11:43:16 -07003856Class* DexVerifier::GetClassFromRegister(const RegisterLine* register_line,
3857 uint32_t vsrc, VerifyError* failure) {
3858 /* get the element type of the array held in vsrc */
3859 RegType type = GetRegisterType(register_line, vsrc);
jeffhaoba5ebb92011-08-25 17:24:37 -07003860
jeffhaobdb76512011-09-07 11:43:16 -07003861 /* if "always zero", we allow it to fail at runtime */
3862 if (type == kRegTypeZero)
3863 return NULL;
3864
3865 if (!RegTypeIsReference(type)) {
3866 LOG(ERROR) << "VFY: tried to get class from non-ref register v" << vsrc
3867 << " (type=" << type << ")",
3868 *failure = VERIFY_ERROR_GENERIC;
3869 return NULL;
3870 }
3871 if (RegTypeIsUninitReference(type)) {
3872 LOG(ERROR) << "VFY: register " << vsrc << " holds uninitialized reference";
3873 *failure = VERIFY_ERROR_GENERIC;
3874 return NULL;
jeffhaoba5ebb92011-08-25 17:24:37 -07003875 }
3876
jeffhaobdb76512011-09-07 11:43:16 -07003877 return RegTypeInitializedReferenceToClass(type);
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07003878}
3879
jeffhaobdb76512011-09-07 11:43:16 -07003880DexVerifier::RegType DexVerifier::GetInvocationThis(
3881 const RegisterLine* register_line,
3882 const Instruction::DecodedInstruction* dec_insn, VerifyError* failure) {
3883 if (dec_insn->vA_ < 1) {
3884 LOG(ERROR) << "VFY: invoke lacks 'this'";
3885 *failure = VERIFY_ERROR_GENERIC;
3886 return kRegTypeUnknown;
jeffhaoba5ebb92011-08-25 17:24:37 -07003887 }
jeffhaobdb76512011-09-07 11:43:16 -07003888
3889 /* get the element type of the array held in vsrc */
3890 RegType this_type = GetRegisterType(register_line, dec_insn->vC_);
3891 if (!RegTypeIsReference(this_type)) {
3892 LOG(ERROR) << "VFY: tried to get class from non-ref register v"
3893 << dec_insn->vC_ << " (type=" << this_type << ")";
3894 *failure = VERIFY_ERROR_GENERIC;
3895 return kRegTypeUnknown;
3896 }
3897
3898 return this_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003899}
3900
jeffhaobdb76512011-09-07 11:43:16 -07003901void DexVerifier::SetRegisterType(RegisterLine* register_line, uint32_t vdst,
3902 RegType new_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003903 RegType* insn_regs = register_line->reg_types_.get();
jeffhaoba5ebb92011-08-25 17:24:37 -07003904
jeffhaobdb76512011-09-07 11:43:16 -07003905 switch (new_type) {
3906 case kRegTypeUnknown:
3907 case kRegTypeBoolean:
3908 case kRegTypeOne:
3909 case kRegTypeConstByte:
3910 case kRegTypeConstPosByte:
3911 case kRegTypeConstShort:
3912 case kRegTypeConstPosShort:
3913 case kRegTypeConstChar:
3914 case kRegTypeConstInteger:
3915 case kRegTypeByte:
3916 case kRegTypePosByte:
3917 case kRegTypeShort:
3918 case kRegTypePosShort:
3919 case kRegTypeChar:
3920 case kRegTypeInteger:
3921 case kRegTypeFloat:
3922 case kRegTypeZero:
3923 case kRegTypeUninit:
3924 insn_regs[vdst] = new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003925 break;
jeffhaobdb76512011-09-07 11:43:16 -07003926 case kRegTypeConstLo:
3927 case kRegTypeLongLo:
3928 case kRegTypeDoubleLo:
3929 insn_regs[vdst] = new_type;
3930 insn_regs[vdst + 1] = new_type + 1;
3931 break;
3932 case kRegTypeConstHi:
3933 case kRegTypeLongHi:
3934 case kRegTypeDoubleHi:
3935 /* should never set these explicitly */
3936 LOG(FATAL) << "BUG: explicit set of high register type";
3937 break;
3938
3939 default:
3940 /* can't switch for ref types, so we check explicitly */
3941 if (RegTypeIsReference(new_type)) {
3942 insn_regs[vdst] = new_type;
3943
3944 /*
3945 * In most circumstances we won't see a reference to a primitive
3946 * class here (e.g. "D"), since that would mean the object in the
jeffhaod1f0fde2011-09-08 17:25:33 -07003947 * register is actually a primitive type. It can happen as the
jeffhaobdb76512011-09-07 11:43:16 -07003948 * result of an assumed-successful check-cast instruction in
jeffhaod1f0fde2011-09-08 17:25:33 -07003949 * which the second argument refers to a primitive class. (In
jeffhaobdb76512011-09-07 11:43:16 -07003950 * practice, such an instruction will always throw an exception.)
3951 *
3952 * This is not an issue for instructions like const-class, where
3953 * the object in the register is a java.lang.Class instance.
3954 */
3955 break;
3956 }
3957 /* bad type - fall through */
3958
3959 case kRegTypeConflict: // should only be set during a merge
3960 LOG(FATAL) << "BUG: set register to unknown type " << new_type;
jeffhaoba5ebb92011-08-25 17:24:37 -07003961 break;
3962 }
3963
jeffhaobdb76512011-09-07 11:43:16 -07003964 /*
3965 * Clear the monitor entry bits for this register.
3966 */
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003967 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07003968 register_line->monitor_entries_[vdst] = 0;
3969}
3970
3971void DexVerifier::VerifyRegisterType(RegisterLine* register_line, uint32_t vsrc,
3972 RegType check_type, VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07003973 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07003974 RegType src_type = insn_regs[vsrc];
3975
3976 switch (check_type) {
3977 case kRegTypeFloat:
3978 case kRegTypeBoolean:
3979 case kRegTypePosByte:
3980 case kRegTypeByte:
3981 case kRegTypePosShort:
3982 case kRegTypeShort:
3983 case kRegTypeChar:
3984 case kRegTypeInteger:
3985 if (!CanConvertTo1nr(src_type, check_type)) {
3986 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
3987 << ", wanted " << check_type;
3988 *failure = VERIFY_ERROR_GENERIC;
3989 }
3990 /* Update type if result is float */
3991 if (check_type == kRegTypeFloat) {
3992 SetRegisterType(register_line, vsrc, check_type);
3993 } else {
3994 /* Update const type to actual type after use */
3995 SetRegisterType(register_line, vsrc, ConstTypeToRegType(src_type));
3996 }
jeffhaoba5ebb92011-08-25 17:24:37 -07003997 break;
jeffhaobdb76512011-09-07 11:43:16 -07003998 case kRegTypeLongLo:
3999 case kRegTypeDoubleLo:
4000 if (insn_regs[vsrc + 1] != src_type + 1) {
4001 LOG(ERROR) << "VFY: register2 v" << vsrc << "-" << vsrc + 1
4002 << " values " << insn_regs[vsrc] << ","
4003 << insn_regs[vsrc + 1];
4004 *failure = VERIFY_ERROR_GENERIC;
4005 } else if (!CanConvertTo2(src_type, check_type)) {
4006 LOG(ERROR) << "VFY: register2 v" << vsrc << " type " << src_type
4007 << ", wanted " << check_type;
4008 *failure = VERIFY_ERROR_GENERIC;
4009 }
4010 /* Update type if source is from const */
4011 if (src_type == kRegTypeConstLo) {
4012 SetRegisterType(register_line, vsrc, check_type);
4013 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004014 break;
jeffhaobdb76512011-09-07 11:43:16 -07004015 case kRegTypeConstLo:
4016 case kRegTypeConstHi:
4017 case kRegTypeLongHi:
4018 case kRegTypeDoubleHi:
4019 case kRegTypeZero:
4020 case kRegTypeOne:
4021 case kRegTypeUnknown:
4022 case kRegTypeConflict:
4023 /* should never be checking for these explicitly */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004024 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004025 *failure = VERIFY_ERROR_GENERIC;
4026 return;
4027 case kRegTypeUninit:
4028 default:
4029 /* make sure check_type is initialized reference */
4030 if (!RegTypeIsReference(check_type)) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004031 LOG(FATAL) << "VFY: unexpected check type " << check_type;
jeffhaobdb76512011-09-07 11:43:16 -07004032 *failure = VERIFY_ERROR_GENERIC;
4033 break;
4034 }
4035 if (RegTypeIsUninitReference(check_type)) {
4036 LOG(ERROR) << "VFY: uninitialized ref not expected as reg check";
4037 *failure = VERIFY_ERROR_GENERIC;
4038 break;
4039 }
4040 /* make sure src_type is initialized reference or always-NULL */
4041 if (!RegTypeIsReference(src_type)) {
4042 LOG(ERROR) << "VFY: register1 v" << vsrc << " type " << src_type
4043 << ", wanted ref";
4044 *failure = VERIFY_ERROR_GENERIC;
4045 break;
4046 }
4047 if (RegTypeIsUninitReference(src_type)) {
4048 LOG(ERROR) << "VFY: register1 v" << vsrc << " holds uninitialized ref";
4049 *failure = VERIFY_ERROR_GENERIC;
4050 break;
4051 }
4052 /* if the register isn't Zero, make sure it's an instance of check */
4053 if (src_type != kRegTypeZero) {
4054 Class* src_class = RegTypeInitializedReferenceToClass(src_type);
4055 Class* check_class = RegTypeInitializedReferenceToClass(check_type);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004056 DCHECK(src_class != NULL);
4057 DCHECK(check_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004058
jeffhaoe0cfb6f2011-09-22 16:42:56 -07004059 if (check_class->IsInterface()) {
4060 /*
4061 * All objects implement all interfaces as far as the verifier is
4062 * concerned. The runtime has to sort it out. See coments above
4063 * FindCommonSuperclass.
4064 */
4065 } else {
4066 if (!check_class->IsAssignableFrom(src_class)) {
4067 LOG(ERROR) << "VFY: " << src_class->GetDescriptor()->ToModifiedUtf8()
4068 << " is not instance of "
4069 << check_class->GetDescriptor()->ToModifiedUtf8();
4070 *failure = VERIFY_ERROR_GENERIC;
4071 }
jeffhaobdb76512011-09-07 11:43:16 -07004072 }
4073 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004074 break;
4075 }
jeffhaobdb76512011-09-07 11:43:16 -07004076}
jeffhaoba5ebb92011-08-25 17:24:37 -07004077
jeffhaobdb76512011-09-07 11:43:16 -07004078void DexVerifier::SetResultRegisterType(RegisterLine* register_line,
4079 const int insn_reg_count, RegType new_type) {
4080 SetRegisterType(register_line, RESULT_REGISTER(insn_reg_count), new_type);
4081}
4082
4083void DexVerifier::MarkRefsAsInitialized(RegisterLine* register_line,
4084 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type,
4085 VerifyError* failure) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004086 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004087 Class* klass = GetUninitInstance(uninit_map,
4088 RegTypeToUninitIndex(uninit_type));
4089
4090 if (klass == NULL) {
4091 LOG(ERROR) << "VFY: unable to find type=" << std::hex << uninit_type
4092 << std::dec << " (idx=" << RegTypeToUninitIndex(uninit_type)
4093 << ")";
4094 *failure = VERIFY_ERROR_GENERIC;
4095 return;
jeffhaoba5ebb92011-08-25 17:24:37 -07004096 }
4097
jeffhaobdb76512011-09-07 11:43:16 -07004098 RegType init_type = RegTypeFromClass(klass);
4099 int changed = 0;
4100 for (int i = 0; i < insn_reg_count; i++) {
4101 if (insn_regs[i] == uninit_type) {
4102 insn_regs[i] = init_type;
4103 changed++;
4104 }
4105 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004106 DCHECK_GT(changed, 0);
jeffhaobdb76512011-09-07 11:43:16 -07004107
4108 return;
4109}
4110
4111void DexVerifier::MarkUninitRefsAsInvalid(RegisterLine* register_line,
4112 int insn_reg_count, UninitInstanceMap* uninit_map, RegType uninit_type) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004113 RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004114
4115 for (int i = 0; i < insn_reg_count; i++) {
4116 if (insn_regs[i] == uninit_type) {
4117 insn_regs[i] = kRegTypeConflict;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004118 if (register_line->monitor_entries_.get() != NULL)
jeffhaobdb76512011-09-07 11:43:16 -07004119 register_line->monitor_entries_[i] = 0;
4120 }
4121 }
4122}
4123
4124void DexVerifier::CopyRegister1(RegisterLine* register_line, uint32_t vdst,
4125 uint32_t vsrc, TypeCategory cat, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004126 DCHECK(cat == kTypeCategory1nr || cat == kTypeCategoryRef);
jeffhaobdb76512011-09-07 11:43:16 -07004127 RegType type = GetRegisterType(register_line, vsrc);
4128 CheckTypeCategory(type, cat, failure);
4129 if (*failure != VERIFY_ERROR_NONE) {
4130 LOG(ERROR) << "VFY: copy1 v" << vdst << "<-v" << vsrc << " type=" << type
4131 << " cat=" << (int) cat;
4132 } else {
4133 SetRegisterType(register_line, vdst, type);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004134 if (cat == kTypeCategoryRef && register_line->monitor_entries_.get() != NULL) {
jeffhaobdb76512011-09-07 11:43:16 -07004135 register_line->monitor_entries_[vdst] =
4136 register_line->monitor_entries_[vsrc];
4137 }
4138 }
4139}
4140
4141void DexVerifier::CopyRegister2(RegisterLine* register_line, uint32_t vdst,
4142 uint32_t vsrc, VerifyError* failure) {
4143 RegType type_l = GetRegisterType(register_line, vsrc);
4144 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4145
4146 CheckTypeCategory(type_l, kTypeCategory2, failure);
4147 CheckWidePair(type_l, type_h, failure);
4148 if (*failure != VERIFY_ERROR_NONE) {
4149 LOG(ERROR) << "VFY: copy2 v" << vdst << "<-v" << vsrc << " type=" << type_l
4150 << "/" << type_h;
4151 } else {
4152 SetRegisterType(register_line, vdst, type_l);
4153 }
4154}
4155
4156void DexVerifier::CopyResultRegister1(RegisterLine* register_line,
4157 const int insn_reg_count, uint32_t vdst, TypeCategory cat,
4158 VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004159 DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
jeffhaobdb76512011-09-07 11:43:16 -07004160
4161 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4162 RegType type = GetRegisterType(register_line, vsrc);
4163 CheckTypeCategory(type, cat, failure);
4164 if (*failure != VERIFY_ERROR_NONE) {
4165 LOG(ERROR) << "VFY: copyRes1 v" << vdst << "<-v" << vsrc << " cat="
4166 << (int) cat << " type=" << type;
4167 } else {
4168 SetRegisterType(register_line, vdst, type);
4169 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4170 }
4171}
4172
4173/*
jeffhaod1f0fde2011-09-08 17:25:33 -07004174 * Implement "move-result-wide". Copy the category-2 value from the result
jeffhaobdb76512011-09-07 11:43:16 -07004175 * register to another register, and reset the result register.
4176 */
4177void DexVerifier::CopyResultRegister2(RegisterLine* register_line,
4178 const int insn_reg_count, uint32_t vdst, VerifyError* failure) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004179 DCHECK_LT(vdst, static_cast<uint32_t>(insn_reg_count));
jeffhaobdb76512011-09-07 11:43:16 -07004180
4181 uint32_t vsrc = RESULT_REGISTER(insn_reg_count);
4182 RegType type_l = GetRegisterType(register_line, vsrc);
4183 RegType type_h = GetRegisterType(register_line, vsrc + 1);
4184 CheckTypeCategory(type_l, kTypeCategory2, failure);
4185 CheckWidePair(type_l, type_h, failure);
4186 if (*failure != VERIFY_ERROR_NONE) {
4187 LOG(ERROR) << "VFY: copyRes2 v" << vdst << "<-v" << vsrc << " type="
4188 << type_l << "/" << type_h;
4189 } else {
4190 SetRegisterType(register_line, vdst, type_l);
4191 SetRegisterType(register_line, vsrc, kRegTypeUnknown);
4192 SetRegisterType(register_line, vsrc + 1, kRegTypeUnknown);
4193 }
4194}
4195
4196int DexVerifier::GetClassDepth(Class* klass) {
4197 int depth = 0;
4198 while (klass->GetSuperClass() != NULL) {
4199 klass = klass->GetSuperClass();
4200 depth++;
4201 }
4202 return depth;
4203}
4204
4205Class* DexVerifier::DigForSuperclass(Class* c1, Class* c2) {
4206 int depth1, depth2;
4207
4208 depth1 = GetClassDepth(c1);
4209 depth2 = GetClassDepth(c2);
4210
4211 /* pull the deepest one up */
4212 if (depth1 > depth2) {
4213 while (depth1 > depth2) {
4214 c1 = c1->GetSuperClass();
4215 depth1--;
4216 }
4217 } else {
4218 while (depth2 > depth1) {
4219 c2 = c2->GetSuperClass();
4220 depth2--;
4221 }
jeffhaoba5ebb92011-08-25 17:24:37 -07004222 }
4223
jeffhaobdb76512011-09-07 11:43:16 -07004224 /* walk up in lock-step */
4225 while (c1 != c2) {
4226 c1 = c1->GetSuperClass();
4227 c2 = c2->GetSuperClass();
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004228 DCHECK(c1 != NULL);
4229 DCHECK(c2 != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004230 }
4231
4232 return c1;
4233}
4234
4235Class* DexVerifier::FindCommonArraySuperclass(Class* c1, Class* c2) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004236 DCHECK(c1->IsArrayClass());
4237 DCHECK(c2->IsArrayClass());
4238 Class* e1 = c1->GetComponentType();
4239 Class* e2 = c2->GetComponentType();
4240 if (e1->IsPrimitive() || e2->IsPrimitive()) {
4241 return c1->GetSuperClass(); // == java.lang.Object
jeffhaobdb76512011-09-07 11:43:16 -07004242 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004243 Class* common_elem = FindCommonSuperclass(c1->GetComponentType(), c2->GetComponentType());
4244 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4245 const ClassLoader* class_loader = c1->GetClassLoader();
4246 std::string descriptor = "[" + common_elem->GetDescriptor()->ToModifiedUtf8();
4247 Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
4248 DCHECK(array_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004249 return array_class;
4250}
4251
4252Class* DexVerifier::FindCommonSuperclass(Class* c1, Class* c2) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004253 DCHECK(!c1->IsPrimitive()) << PrettyClass(c1);
4254 DCHECK(!c2->IsPrimitive()) << PrettyClass(c2);
jeffhaobdb76512011-09-07 11:43:16 -07004255
4256 if (c1 == c2)
4257 return c1;
4258
jeffhao5dbddee2011-09-07 16:38:26 -07004259 if (c1->IsInterface() && c1->IsAssignableFrom(c2)) {
jeffhaobdb76512011-09-07 11:43:16 -07004260 return c1;
4261 }
jeffhao5dbddee2011-09-07 16:38:26 -07004262 if (c2->IsInterface() && c2->IsAssignableFrom(c1)) {
jeffhaobdb76512011-09-07 11:43:16 -07004263 return c2;
4264 }
4265 if (c1->IsArrayClass() && c2->IsArrayClass()) {
4266 return FindCommonArraySuperclass(c1, c2);
4267 }
4268
4269 return DigForSuperclass(c1, c2);
4270}
4271
jeffhao98eacac2011-09-14 16:11:53 -07004272Class* DexVerifier::ResolveClassAndCheckAccess(const DexFile* dex_file,
jeffhaob4df5142011-09-19 20:25:32 -07004273 uint32_t class_idx, const Class* referrer, VerifyError* failure) {
jeffhao98eacac2011-09-14 16:11:53 -07004274 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
4275 Class* res_class = class_linker->ResolveType(*dex_file, class_idx, referrer);
4276
4277 if (res_class == NULL) {
buzbeec0ecd652011-09-25 18:11:54 -07004278 Thread::Current()->ClearException();
jeffhaoe0cfb6f2011-09-22 16:42:56 -07004279 LOG(ERROR) << "VFY: can't find class with index 0x" << std::hex << class_idx << std::dec;
jeffhao2a8a90e2011-09-26 14:25:31 -07004280 *failure = VERIFY_ERROR_NO_CLASS;
jeffhao98eacac2011-09-14 16:11:53 -07004281 return NULL;
4282 }
4283
4284 /* Check if access is allowed. */
4285 if (!referrer->CanAccess(res_class)) {
4286 LOG(ERROR) << "VFY: illegal class access: "
4287 << referrer->GetDescriptor()->ToModifiedUtf8() << " -> "
4288 << res_class->GetDescriptor()->ToModifiedUtf8();
4289 *failure = VERIFY_ERROR_ACCESS_CLASS;
4290 return NULL;
4291 }
4292
4293 return res_class;
4294}
4295
jeffhaob4df5142011-09-19 20:25:32 -07004296Method* DexVerifier::ResolveMethodAndCheckAccess(const DexFile* dex_file,
4297 uint32_t method_idx, const Class* referrer, VerifyError* failure,
4298 bool is_direct) {
4299 DexCache* dex_cache = referrer->GetDexCache();
4300 Method* res_method = dex_cache->GetResolvedMethod(method_idx);
4301
4302 if (res_method == NULL) {
4303 const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
4304 Class* klass = ResolveClassAndCheckAccess(dex_file, method_id.class_idx_, referrer, failure);
4305 if (klass == NULL) {
4306 DCHECK(*failure != VERIFY_ERROR_NONE);
4307 return NULL;
4308 }
4309
4310 const char* name = dex_file->dexStringById(method_id.name_idx_);
4311 std::string signature(dex_file->CreateMethodDescriptor(method_id.proto_idx_, NULL));
4312 if (is_direct) {
4313 res_method = klass->FindDirectMethod(name, signature);
4314 } else if (klass->IsInterface()) {
4315 res_method = klass->FindInterfaceMethod(name, signature);
4316 } else {
4317 res_method = klass->FindVirtualMethod(name, signature);
4318 }
4319 if (res_method != NULL) {
4320 dex_cache->SetResolvedMethod(method_idx, res_method);
4321 } else {
4322 LOG(ERROR) << "VFY: couldn't find method "
4323 << klass->GetDescriptor()->ToModifiedUtf8() << "." << name
4324 << " " << signature;
4325 *failure = VERIFY_ERROR_NO_METHOD;
4326 return NULL;
4327 }
4328 }
4329
4330 /* Check if access is allowed. */
jeffhao4a801a42011-09-23 13:53:40 -07004331 if (!referrer->CanAccessMember(res_method->GetDeclaringClass(), res_method->GetAccessFlags())) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004332 LOG(ERROR) << "VFY: illegal method access (call " << PrettyMethod(res_method)
4333 << " from " << referrer->GetDescriptor()->ToModifiedUtf8() << ")";
jeffhaob4df5142011-09-19 20:25:32 -07004334 *failure = VERIFY_ERROR_ACCESS_METHOD;
4335 return NULL;
4336 }
4337
4338 return res_method;
4339}
4340
4341Field* DexVerifier::ResolveFieldAndCheckAccess(const DexFile* dex_file,
4342 uint32_t field_idx, const Class* referrer, VerifyError* failure,
4343 bool is_static) {
4344 DexCache* dex_cache = referrer->GetDexCache();
4345 Field* res_field = dex_cache->GetResolvedField(field_idx);
4346
4347 if (res_field == NULL) {
4348 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
4349 Class* klass = ResolveClassAndCheckAccess(dex_file, field_id.class_idx_, referrer, failure);
4350 if (klass == NULL) {
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004351 DCHECK(*failure != VERIFY_ERROR_NONE) << PrettyClass(referrer);
jeffhaob4df5142011-09-19 20:25:32 -07004352 return NULL;
4353 }
4354
4355 Class* field_type = ResolveClassAndCheckAccess(dex_file, field_id.type_idx_, referrer, failure);
4356 if (field_type == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004357 DCHECK(*failure != VERIFY_ERROR_NONE) << PrettyClass(referrer) << " " << PrettyClass(klass);
jeffhaob4df5142011-09-19 20:25:32 -07004358 return NULL;
4359 }
4360
4361 const char* name = dex_file->dexStringById(field_id.name_idx_);
4362 if (is_static) {
4363 res_field = klass->FindStaticField(name, field_type);
4364 } else {
4365 res_field = klass->FindInstanceField(name, field_type);
4366 }
4367 if (res_field != NULL) {
Elliott Hughes4a2b4172011-09-20 17:08:25 -07004368 dex_cache->SetResolvedField(field_idx, res_field);
jeffhaob4df5142011-09-19 20:25:32 -07004369 } else {
4370 LOG(ERROR) << "VFY: couldn't find field "
4371 << klass->GetDescriptor()->ToModifiedUtf8() << "." << name;
4372 *failure = VERIFY_ERROR_NO_FIELD;
4373 return NULL;
4374 }
4375 }
4376
4377 /* Check if access is allowed. */
jeffhao4a801a42011-09-23 13:53:40 -07004378 if (!referrer->CanAccessMember(res_field->GetDeclaringClass(), res_field->GetAccessFlags())) {
jeffhaob4df5142011-09-19 20:25:32 -07004379 LOG(ERROR) << "VFY: access denied from "
4380 << referrer->GetDescriptor()->ToModifiedUtf8() << " to field "
jeffhao2a8a90e2011-09-26 14:25:31 -07004381 << PrettyField(res_field);
jeffhaob4df5142011-09-19 20:25:32 -07004382 *failure = VERIFY_ERROR_ACCESS_FIELD;
4383 return NULL;
4384 }
4385
4386 return res_field;
4387}
4388
jeffhaobdb76512011-09-07 11:43:16 -07004389DexVerifier::RegType DexVerifier::MergeTypes(RegType type1, RegType type2,
4390 bool* changed) {
4391 RegType result;
4392
jeffhao98eacac2011-09-14 16:11:53 -07004393 /* Check for trivial case so we don't have to hit memory. */
jeffhaobdb76512011-09-07 11:43:16 -07004394 if (type1 == type2)
4395 return type1;
4396
4397 /*
4398 * Use the table if we can, and reject any attempts to merge something
4399 * from the table with a reference type.
4400 *
4401 * Uninitialized references are composed of the enum ORed with an
jeffhaod1f0fde2011-09-08 17:25:33 -07004402 * index value. The uninitialized table entry at index zero *will*
4403 * show up as a simple kRegTypeUninit value. Since this cannot be
jeffhaobdb76512011-09-07 11:43:16 -07004404 * merged with anything but itself, the rules do the right thing.
4405 */
4406 if (type1 < kRegTypeMAX) {
4407 if (type2 < kRegTypeMAX) {
4408 result = merge_table_[type1][type2];
4409 } else {
4410 /* simple + reference == conflict, usually */
4411 if (type1 == kRegTypeZero)
4412 result = type2;
4413 else
4414 result = kRegTypeConflict;
4415 }
4416 } else {
4417 if (type2 < kRegTypeMAX) {
4418 /* reference + simple == conflict, usually */
4419 if (type2 == kRegTypeZero)
4420 result = type1;
4421 else
4422 result = kRegTypeConflict;
4423 } else {
4424 /* merging two references */
4425 if (RegTypeIsUninitReference(type1) ||
4426 RegTypeIsUninitReference(type2))
4427 {
4428 /* can't merge uninit with anything but self */
4429 result = kRegTypeConflict;
4430 } else {
4431 Class* klass1 = RegTypeInitializedReferenceToClass(type1);
4432 Class* klass2 = RegTypeInitializedReferenceToClass(type2);
4433 Class* merged_class = FindCommonSuperclass(klass1, klass2);
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004434 DCHECK(merged_class != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004435 result = RegTypeFromClass(merged_class);
4436 }
4437 }
4438 }
4439
4440 if (result != type1)
4441 *changed = true;
jeffhaoba5ebb92011-08-25 17:24:37 -07004442 return result;
jeffhaobdb76512011-09-07 11:43:16 -07004443}
4444
4445DexVerifier::MonitorEntries DexVerifier::MergeMonitorEntries(
4446 MonitorEntries ents1, MonitorEntries ents2, bool* changed) {
4447 MonitorEntries result = ents1 & ents2;
4448 if (result != ents1)
4449 *changed = true;
4450 return result;
4451}
4452
4453bool DexVerifier::UpdateRegisters(InsnFlags* insn_flags,
4454 RegisterTable* reg_table, int next_insn, const RegisterLine* work_line) {
4455 const size_t insn_reg_count_plus = reg_table->insn_reg_count_plus_;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004456 DCHECK(work_line != NULL);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004457 const RegType* work_regs = work_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004458
4459 if (!InsnIsVisitedOrChanged(insn_flags, next_insn)) {
4460 /*
4461 * We haven't processed this instruction before, and we haven't
jeffhaod1f0fde2011-09-08 17:25:33 -07004462 * touched the registers here, so there's nothing to "merge". Copy
4463 * the registers over and mark it as changed. (This is the only
jeffhaobdb76512011-09-07 11:43:16 -07004464 * way a register can transition out of "unknown", so this is not
4465 * just an optimization.)
4466 */
4467 CopyLineToTable(reg_table, next_insn, work_line);
4468 InsnSetChanged(insn_flags, next_insn, true);
4469 } else {
4470 /* Merge registers, set Changed only if different */
4471 RegisterLine* target_line = GetRegisterLine(reg_table, next_insn);
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004472 RegType* target_regs = target_line->reg_types_.get();
4473 MonitorEntries* work_mon_ents = work_line->monitor_entries_.get();
4474 MonitorEntries* target_mon_ents = target_line->monitor_entries_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004475 bool changed = false;
4476 unsigned int idx;
4477
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004478 DCHECK(target_regs != NULL);
jeffhaobdb76512011-09-07 11:43:16 -07004479 if (target_mon_ents != NULL) {
4480 /* Monitor stacks must be identical. */
4481 if (target_line->monitor_stack_top_ != work_line->monitor_stack_top_) {
4482 LOG(ERROR) << "VFY: mismatched stack depth "
4483 << target_line->monitor_stack_top_ << " vs. "
4484 << work_line->monitor_stack_top_ << " at 0x"
4485 << std::hex << next_insn << std::dec;
4486 return false;
4487 }
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004488 if (memcmp(target_line->monitor_stack_.get(), work_line->monitor_stack_.get(),
jeffhaobdb76512011-09-07 11:43:16 -07004489 target_line->monitor_stack_top_ * sizeof(uint32_t)) != 0) {
4490 LOG(ERROR) << "VFY: mismatched monitor stacks at 0x" << std::hex
4491 << next_insn << std::dec;
4492 return false;
4493 }
4494 }
4495
4496 for (idx = 0; idx < insn_reg_count_plus; idx++) {
4497 target_regs[idx] = MergeTypes(target_regs[idx], work_regs[idx], &changed);
4498
4499 if (target_mon_ents != NULL) {
4500 target_mon_ents[idx] = MergeMonitorEntries(target_mon_ents[idx],
4501 work_mon_ents[idx], &changed);
4502 }
4503 }
4504
4505 if (changed) {
4506 InsnSetChanged(insn_flags, next_insn, true);
4507 }
4508 }
4509
4510 return true;
4511}
4512
4513bool DexVerifier::CanConvertTo1nr(RegType src_type, RegType check_type) {
4514 static const char conv_tab[kRegType1nrEND - kRegType1nrSTART + 1]
4515 [kRegType1nrEND - kRegType1nrSTART + 1] =
4516 {
4517 /* chk: 0 1 Z y Y h H c i b B s S C I F */
4518 { /*0*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4519 { /*1*/ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4520 { /*Z*/ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
4521 { /*y*/ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
4522 { /*Y*/ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 },
4523 { /*h*/ 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
4524 { /*H*/ 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1 },
4525 { /*c*/ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1 },
4526 { /*i*/ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1 },
4527 { /*b*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
4528 { /*B*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0 },
4529 { /*s*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0 },
4530 { /*S*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 },
4531 { /*C*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 },
4532 { /*I*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 },
4533 { /*F*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
4534 };
4535
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004536 DCHECK(check_type >= kRegType1nrSTART);
4537 DCHECK(check_type <= kRegType1nrEND);
jeffhaobdb76512011-09-07 11:43:16 -07004538
4539 if (src_type >= kRegType1nrSTART && src_type <= kRegType1nrEND)
4540 return (bool) conv_tab[src_type - kRegType1nrSTART]
4541 [check_type - kRegType1nrSTART];
4542
4543 return false;
4544}
4545
4546bool DexVerifier::CanConvertTo2(RegType src_type, RegType check_type) {
4547 return ((src_type == kRegTypeConstLo || src_type == check_type) &&
4548 (check_type == kRegTypeLongLo || check_type == kRegTypeDoubleLo));
4549}
4550
4551DexVerifier::RegType DexVerifier::PrimitiveTypeToRegType(
4552 Class::PrimitiveType prim_type) {
4553 switch (prim_type) {
4554 case Class::kPrimBoolean: return kRegTypeBoolean;
4555 case Class::kPrimByte: return kRegTypeByte;
4556 case Class::kPrimShort: return kRegTypeShort;
4557 case Class::kPrimChar: return kRegTypeChar;
4558 case Class::kPrimInt: return kRegTypeInteger;
4559 case Class::kPrimLong: return kRegTypeLongLo;
4560 case Class::kPrimFloat: return kRegTypeFloat;
4561 case Class::kPrimDouble: return kRegTypeDoubleLo;
4562 case Class::kPrimVoid:
4563 default: {
4564 return kRegTypeUnknown;
4565 }
4566 }
4567}
4568
4569DexVerifier::RegType DexVerifier::ConstTypeToRegType(RegType const_type) {
4570 switch (const_type) {
4571 case kRegTypeConstPosByte: return kRegTypePosByte;
4572 case kRegTypeConstByte: return kRegTypeByte;
4573 case kRegTypeConstPosShort: return kRegTypePosShort;
4574 case kRegTypeConstShort: return kRegTypeShort;
4575 case kRegTypeConstChar: return kRegTypeChar;
4576 case kRegTypeConstInteger: return kRegTypeInteger;
4577 default: {
4578 return const_type;
4579 }
4580 }
4581}
4582
4583char DexVerifier::DetermineCat1Const(int32_t value) {
4584 if (value < -32768)
4585 return kRegTypeConstInteger;
4586 else if (value < -128)
4587 return kRegTypeConstShort;
4588 else if (value < 0)
4589 return kRegTypeConstByte;
4590 else if (value == 0)
4591 return kRegTypeZero;
4592 else if (value == 1)
4593 return kRegTypeOne;
4594 else if (value < 128)
4595 return kRegTypeConstPosByte;
4596 else if (value < 32768)
4597 return kRegTypeConstPosShort;
4598 else if (value < 65536)
4599 return kRegTypeConstChar;
4600 else
4601 return kRegTypeConstInteger;
4602}
4603
4604void DexVerifier::CheckFinalFieldAccess(const Method* method,
4605 const Field* field, VerifyError* failure) {
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004606 DCHECK(field != NULL);
4607 if (!field->IsFinal()) {
jeffhaobdb76512011-09-07 11:43:16 -07004608 return;
Brian Carlstrom65ca0772011-09-24 16:03:08 -07004609 }
jeffhaobdb76512011-09-07 11:43:16 -07004610
4611 /* make sure we're in the same class */
4612 if (method->GetDeclaringClass() != field->GetDeclaringClass()) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004613 LOG(ERROR) << "VFY: can't modify final field " << PrettyField(field);
jeffhaobdb76512011-09-07 11:43:16 -07004614 *failure = VERIFY_ERROR_ACCESS_FIELD;
4615 return;
4616 }
4617}
4618
4619void DexVerifier::CheckArrayIndexType(const Method* method, RegType reg_type,
4620 VerifyError* failure) {
4621 if (*failure == VERIFY_ERROR_NONE) {
4622 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004623 * The 1nr types are interchangeable at this level. We could
jeffhaobdb76512011-09-07 11:43:16 -07004624 * do something special if we can definitively identify it as a
4625 * float, but there's no real value in doing so.
4626 */
4627 CheckTypeCategory(reg_type, kTypeCategory1nr, failure);
4628 if (*failure != VERIFY_ERROR_NONE) {
4629 LOG(ERROR) << "Invalid reg type for array index (" << reg_type << ")";
4630 }
4631 }
4632}
4633
4634bool DexVerifier::CheckConstructorReturn(const Method* method,
4635 const RegisterLine* register_line, const int insn_reg_count) {
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004636 const RegType* insn_regs = register_line->reg_types_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004637
4638 if (!IsInitMethod(method))
4639 return true;
4640
4641 RegType uninit_this = RegTypeFromUninitIndex(kUninitThisArgSlot);
4642
4643 for (int i = 0; i < insn_reg_count; i++) {
4644 if (insn_regs[i] == uninit_this) {
4645 LOG(ERROR) << "VFY: <init> returning without calling superclass init";
4646 return false;
4647 }
4648 }
4649 return true;
4650}
4651
4652bool DexVerifier::CheckMoveException(const uint16_t* insns, int insn_idx) {
4653 if ((insns[insn_idx] & 0xff) == Instruction::MOVE_EXCEPTION) {
4654 LOG(ERROR) << "VFY: invalid use of move-exception";
4655 return false;
4656 }
4657 return true;
4658}
4659
4660void DexVerifier::CheckTypeCategory(RegType type, TypeCategory cat,
4661 VerifyError* failure) {
4662 switch (cat) {
4663 case kTypeCategory1nr:
4664 switch (type) {
4665 case kRegTypeZero:
4666 case kRegTypeOne:
4667 case kRegTypeBoolean:
4668 case kRegTypeConstPosByte:
4669 case kRegTypeConstByte:
4670 case kRegTypeConstPosShort:
4671 case kRegTypeConstShort:
4672 case kRegTypeConstChar:
4673 case kRegTypeConstInteger:
4674 case kRegTypePosByte:
4675 case kRegTypeByte:
4676 case kRegTypePosShort:
4677 case kRegTypeShort:
4678 case kRegTypeChar:
4679 case kRegTypeInteger:
4680 case kRegTypeFloat:
4681 break;
4682 default:
4683 *failure = VERIFY_ERROR_GENERIC;
4684 break;
4685 }
4686 break;
4687 case kTypeCategory2:
4688 switch (type) {
4689 case kRegTypeConstLo:
4690 case kRegTypeLongLo:
4691 case kRegTypeDoubleLo:
4692 break;
4693 default:
4694 *failure = VERIFY_ERROR_GENERIC;
4695 break;
4696 }
4697 break;
4698 case kTypeCategoryRef:
4699 if (type != kRegTypeZero && !RegTypeIsReference(type))
4700 *failure = VERIFY_ERROR_GENERIC;
4701 break;
4702 default:
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004703 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004704 *failure = VERIFY_ERROR_GENERIC;
4705 break;
4706 }
4707}
4708
4709void DexVerifier::CheckWidePair(RegType type_l, RegType type_h,
4710 VerifyError* failure) {
4711 if ((type_h != type_l + 1))
4712 *failure = VERIFY_ERROR_GENERIC;
4713}
4714
4715void DexVerifier::CheckUnop(RegisterLine* register_line,
4716 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4717 RegType src_type, VerifyError* failure) {
4718 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4719 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4720}
4721
4722bool DexVerifier::UpcastBooleanOp(RegisterLine* register_line, uint32_t reg1,
4723 uint32_t reg2) {
4724 RegType type1, type2;
4725
4726 type1 = GetRegisterType(register_line, reg1);
4727 type2 = GetRegisterType(register_line, reg2);
4728
4729 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || type1 == kRegTypeOne) &&
4730 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || type2 == kRegTypeOne)) {
4731 return true;
4732 }
4733 return false;
4734}
4735
4736void DexVerifier::CheckLitop(RegisterLine* register_line,
4737 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4738 RegType src_type, bool check_boolean_op, VerifyError* failure) {
4739 VerifyRegisterType(register_line, dec_insn->vB_, src_type, failure);
4740
4741 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004742 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004743
4744 /* check vB with the call, then check the constant manually */
4745 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vB_)
4746 && (dec_insn->vC_ == 0 || dec_insn->vC_ == 1)) {
4747 dst_type = kRegTypeBoolean;
4748 }
4749 }
4750
4751 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4752}
4753
4754void DexVerifier::CheckBinop(RegisterLine* register_line,
4755 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4756 RegType src_type1, RegType src_type2, bool check_boolean_op,
4757 VerifyError* failure) {
4758 VerifyRegisterType(register_line, dec_insn->vB_, src_type1, failure);
4759 VerifyRegisterType(register_line, dec_insn->vC_, src_type2, failure);
4760
4761 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004762 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004763 if (UpcastBooleanOp(register_line, dec_insn->vB_, dec_insn->vC_))
4764 dst_type = kRegTypeBoolean;
4765 }
4766
4767 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4768}
4769
4770void DexVerifier::CheckBinop2addr(RegisterLine* register_line,
4771 Instruction::DecodedInstruction* dec_insn, RegType dst_type,
4772 RegType src_type1, RegType src_type2, bool check_boolean_op,
4773 VerifyError* failure) {
4774 VerifyRegisterType(register_line, dec_insn->vA_, src_type1, failure);
4775 VerifyRegisterType(register_line, dec_insn->vB_, src_type2, failure);
4776
4777 if ((*failure == VERIFY_ERROR_NONE) && check_boolean_op) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004778 DCHECK(dst_type == kRegTypeInteger);
jeffhaobdb76512011-09-07 11:43:16 -07004779 if (UpcastBooleanOp(register_line, dec_insn->vA_, dec_insn->vB_))
4780 dst_type = kRegTypeBoolean;
4781 }
4782
4783 SetRegisterType(register_line, dec_insn->vA_, dst_type);
4784}
4785
4786DexVerifier::RegType DexVerifier::AdjustForRightShift(
4787 RegisterLine* register_line, int reg, unsigned int shift_count,
jeffhaob4df5142011-09-19 20:25:32 -07004788 bool is_unsigned_shift) {
jeffhaobdb76512011-09-07 11:43:16 -07004789 RegType src_type = GetRegisterType(register_line, reg);
4790 RegType new_type;
4791
4792 /* convert const derived types to their actual types */
4793 src_type = ConstTypeToRegType(src_type);
4794
4795 /* no-op */
4796 if (shift_count == 0)
4797 return src_type;
4798
4799 /* safe defaults */
4800 if (is_unsigned_shift)
4801 new_type = kRegTypeInteger;
4802 else
4803 new_type = src_type;
4804
4805 if (shift_count >= 32) {
4806 LOG(ERROR) << "Got unexpectedly large shift count " << shift_count;
4807 /* fail? */
4808 return new_type;
4809 }
4810
4811 switch (src_type) {
4812 case kRegTypeInteger: /* 32-bit signed value */
4813 if (is_unsigned_shift) {
4814 if (shift_count > 24)
4815 new_type = kRegTypePosByte;
4816 else if (shift_count >= 16)
4817 new_type = kRegTypeChar;
4818 } else {
4819 if (shift_count >= 24)
4820 new_type = kRegTypeByte;
4821 else if (shift_count >= 16)
4822 new_type = kRegTypeShort;
4823 }
4824 break;
4825 case kRegTypeShort: /* 16-bit signed value */
4826 if (is_unsigned_shift) {
4827 /* default (kRegTypeInteger) is correct */
4828 } else {
4829 if (shift_count >= 8)
4830 new_type = kRegTypeByte;
4831 }
4832 break;
4833 case kRegTypePosShort: /* 15-bit unsigned value */
4834 if (shift_count >= 8)
4835 new_type = kRegTypePosByte;
4836 break;
4837 case kRegTypeChar: /* 16-bit unsigned value */
4838 if (shift_count > 8)
4839 new_type = kRegTypePosByte;
4840 break;
4841 case kRegTypeByte: /* 8-bit signed value */
4842 /* defaults (u=kRegTypeInteger / s=src_type) are correct */
4843 break;
4844 case kRegTypePosByte: /* 7-bit unsigned value */
4845 /* always use new_type=src_type */
4846 new_type = src_type;
4847 break;
4848 case kRegTypeZero: /* 1-bit unsigned value */
4849 case kRegTypeOne:
4850 case kRegTypeBoolean:
4851 /* unnecessary? */
4852 new_type = kRegTypeZero;
4853 break;
4854 default:
4855 /* long, double, references; shouldn't be here! */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004856 DCHECK(false);
jeffhaobdb76512011-09-07 11:43:16 -07004857 break;
4858 }
4859
4860 return new_type;
4861}
4862
4863void DexVerifier::VerifyFilledNewArrayRegs(const Method* method,
4864 RegisterLine* register_line,
4865 const Instruction::DecodedInstruction* dec_insn, Class* res_class,
4866 bool is_range, VerifyError* failure) {
4867 uint32_t arg_count = dec_insn->vA_;
4868 RegType expected_type;
4869 Class::PrimitiveType elem_type;
4870 unsigned int ui;
4871
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004872 DCHECK(res_class->IsArrayClass()) << PrettyClass(res_class);
jeffhaobdb76512011-09-07 11:43:16 -07004873 elem_type = res_class->GetComponentType()->GetPrimitiveType();
4874 if (elem_type == Class::kPrimNot) {
4875 expected_type = RegTypeFromClass(res_class->GetComponentType());
4876 } else {
4877 expected_type = PrimitiveTypeToRegType(elem_type);
4878 }
4879
4880 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004881 * Verify each register. If "arg_count" is bad, VerifyRegisterType()
4882 * will run off the end of the list and fail. It's legal, if silly,
jeffhaobdb76512011-09-07 11:43:16 -07004883 * for arg_count to be zero.
4884 */
4885 for (ui = 0; ui < arg_count; ui++) {
4886 uint32_t get_reg;
4887
4888 if (is_range)
4889 get_reg = dec_insn->vC_ + ui;
4890 else
4891 get_reg = dec_insn->arg_[ui];
4892
4893 VerifyRegisterType(register_line, get_reg, expected_type, failure);
4894 if (*failure != VERIFY_ERROR_NONE) {
4895 LOG(ERROR) << "VFY: filled-new-array arg " << ui << "(" << get_reg
4896 << ") not valid";
4897 return;
4898 }
4899 }
4900}
4901
4902bool DexVerifier::IsCorrectInvokeKind(MethodType method_type,
4903 Method* res_method) {
4904 switch (method_type) {
4905 case METHOD_DIRECT:
4906 return res_method->IsDirect();
4907 case METHOD_STATIC:
4908 return res_method->IsStatic();
4909 case METHOD_VIRTUAL:
4910 case METHOD_INTERFACE:
4911 return !res_method->IsDirect();
4912 default:
4913 return false;
4914 }
4915}
4916
4917Method* DexVerifier::VerifyInvocationArgs(VerifierData* vdata,
4918 RegisterLine* register_line, const int insn_reg_count,
4919 const Instruction::DecodedInstruction* dec_insn, MethodType method_type,
4920 bool is_range, bool is_super, VerifyError* failure) {
4921 Method* method = vdata->method_;
4922 const DexFile* dex_file = vdata->dex_file_;
4923 const DexFile::CodeItem* code_item = vdata->code_item_;
Elliott Hughes5fe594f2011-09-08 12:33:17 -07004924 UninitInstanceMap* uninit_map = vdata->uninit_map_.get();
jeffhaobdb76512011-09-07 11:43:16 -07004925
4926 Method* res_method;
4927 std::string sig;
4928 size_t sig_offset;
4929 int expected_args;
4930 int actual_args;
4931
4932 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07004933 * Resolve the method. This could be an abstract or concrete method
jeffhaobdb76512011-09-07 11:43:16 -07004934 * depending on what sort of call we're making.
4935 */
jeffhaob4df5142011-09-19 20:25:32 -07004936 res_method = ResolveMethodAndCheckAccess(dex_file, dec_insn->vB_, method->GetDeclaringClass(),
4937 failure, (method_type == METHOD_DIRECT || method_type == METHOD_STATIC));
jeffhaobdb76512011-09-07 11:43:16 -07004938
jeffhaobdb76512011-09-07 11:43:16 -07004939 if (res_method == NULL) {
jeffhao98eacac2011-09-14 16:11:53 -07004940 const DexFile::MethodId& method_id = dex_file->GetMethodId(dec_insn->vB_);
4941 const char* method_name = dex_file->GetMethodName(method_id);
Brian Carlstromaded5f72011-10-07 17:15:04 -07004942 std::string method_signature = dex_file->GetMethodSignature(method_id);
jeffhao98eacac2011-09-14 16:11:53 -07004943 const char* class_descriptor = dex_file->GetMethodClassDescriptor(method_id);
4944
4945 LOG(ERROR) << "VFY: unable to resolve method " << dec_insn->vB_ << ": "
Brian Carlstromaded5f72011-10-07 17:15:04 -07004946 << class_descriptor << "." << method_name << " " << method_signature;
jeffhaobdb76512011-09-07 11:43:16 -07004947 return NULL;
4948 }
jeffhaobdb76512011-09-07 11:43:16 -07004949
4950 /*
jeffhao2a8a90e2011-09-26 14:25:31 -07004951 * Make sure calls to "<init>" are "direct". There are additional restrictions
4952 * but we don't enfore them here.
jeffhaobdb76512011-09-07 11:43:16 -07004953 */
jeffhao2a8a90e2011-09-26 14:25:31 -07004954 if (res_method->GetName()->Equals("<init>") && method_type != METHOD_DIRECT) {
4955 LOG(ERROR) << "VFY: invalid call to " << PrettyMethod(res_method);
4956 goto bad_sig;
jeffhaobdb76512011-09-07 11:43:16 -07004957 }
4958
4959 /*
4960 * See if the method type implied by the invoke instruction matches the
4961 * access flags for the target method.
4962 */
4963 if (!IsCorrectInvokeKind(method_type, res_method)) {
4964 LOG(ERROR) << "VFY: invoke type does not match method type of "
jeffhao2a8a90e2011-09-26 14:25:31 -07004965 << PrettyMethod(res_method);
jeffhaobdb76512011-09-07 11:43:16 -07004966 *failure = VERIFY_ERROR_GENERIC;
4967 return NULL;
4968 }
4969
4970 /*
4971 * If we're using invoke-super(method), make sure that the executing
4972 * method's class' superclass has a vtable entry for the target method.
4973 */
4974 if (is_super) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07004975 DCHECK(method_type == METHOD_VIRTUAL);
jeffhaobdb76512011-09-07 11:43:16 -07004976 Class* super = method->GetDeclaringClass()->GetSuperClass();
4977 if (super == NULL || res_method->GetMethodIndex() > super->GetVTable()->GetLength()) {
4978 if (super == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07004979 LOG(ERROR) << "VFY: invalid invoke-super from " << PrettyMethod(method)
4980 << " to super -." << res_method->GetName()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07004981 << " " << res_method->GetSignature()->ToModifiedUtf8();
4982 } else {
jeffhao2a8a90e2011-09-26 14:25:31 -07004983 LOG(ERROR) << "VFY: invalid invoke-super from " << PrettyMethod(method)
4984 << " to super " << super->GetDescriptor()->ToModifiedUtf8()
jeffhaobdb76512011-09-07 11:43:16 -07004985 << "." << res_method->GetName()->ToModifiedUtf8()
4986 << " " << res_method->GetSignature()->ToModifiedUtf8();
4987 }
4988 *failure = VERIFY_ERROR_NO_METHOD;
4989 return NULL;
4990 }
4991 }
4992
4993 /*
4994 * We use vAA as our expected arg count, rather than res_method->insSize,
jeffhaod1f0fde2011-09-08 17:25:33 -07004995 * because we need to match the call to the signature. Also, we might
jeffhaobdb76512011-09-07 11:43:16 -07004996 * might be calling through an abstract method definition (which doesn't
4997 * have register count values).
4998 */
4999 expected_args = dec_insn->vA_;
5000 actual_args = 0;
5001
5002 /* caught by static verifier */
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005003 DCHECK(is_range || expected_args <= 5);
jeffhaobdb76512011-09-07 11:43:16 -07005004
5005 if (expected_args > code_item->outs_size_) {
5006 LOG(ERROR) << "VFY: invalid arg count (" << expected_args
5007 << ") exceeds outsSize (" << code_item->outs_size_ << ")";
5008 *failure = VERIFY_ERROR_GENERIC;
5009 return NULL;
5010 }
5011
5012 sig = res_method->GetSignature()->ToModifiedUtf8();
5013 if (sig[0] != '(') {
5014 LOG(ERROR) << "VFY: descriptor doesn't start with '(': " << sig;
5015 goto bad_sig;
5016 }
5017
5018 /*
5019 * Check the "this" argument, which must be an instance of the class
jeffhaod1f0fde2011-09-08 17:25:33 -07005020 * that declared the method. For an interface class, we don't do the
jeffhaobdb76512011-09-07 11:43:16 -07005021 * full interface merge, so we can't do a rigorous check here (which
5022 * is okay since we have to do it at runtime).
5023 */
5024 if (!res_method->IsStatic()) {
5025 Class* actual_this_ref;
5026 RegType actual_arg_type;
5027
5028 actual_arg_type = GetInvocationThis(register_line, dec_insn, failure);
5029 if (*failure != VERIFY_ERROR_NONE)
5030 return NULL;
5031
5032 if (RegTypeIsUninitReference(actual_arg_type) &&
5033 !res_method->GetName()->Equals("<init>")) {
5034 LOG(ERROR) << "VFY: 'this' arg must be initialized";
5035 *failure = VERIFY_ERROR_GENERIC;
5036 return NULL;
5037 }
5038 if (method_type != METHOD_INTERFACE && actual_arg_type != kRegTypeZero) {
5039 actual_this_ref = RegTypeReferenceToClass(actual_arg_type, uninit_map);
5040 if (!res_method->GetDeclaringClass()->IsAssignableFrom(actual_this_ref)) {
5041 LOG(ERROR) << "VFY: 'this' arg '"
5042 << actual_this_ref->GetDescriptor()->ToModifiedUtf8()
5043 << "' not instance of '"
5044 << res_method->GetDeclaringClass()->GetDescriptor()->ToModifiedUtf8()
5045 << "'";
5046 *failure = VERIFY_ERROR_GENERIC;
5047 return NULL;
5048 }
5049 }
5050 actual_args++;
5051 }
5052
5053 /*
jeffhaod1f0fde2011-09-08 17:25:33 -07005054 * Process the target method's signature. This signature may or may not
jeffhaobdb76512011-09-07 11:43:16 -07005055 * have been verified, so we can't assume it's properly formed.
5056 */
5057 for (sig_offset = 1; sig_offset < sig.size(); sig_offset++) {
jeffhaobdb76512011-09-07 11:43:16 -07005058 if (sig[sig_offset] == ')')
5059 break;
5060
5061 if (actual_args >= expected_args) {
5062 LOG(ERROR) << "VFY: expected " << expected_args << " args, found more ("
5063 << sig.substr(sig_offset) << ")";
5064 goto bad_sig;
5065 }
5066
5067 uint32_t get_reg;
5068 if (is_range)
5069 get_reg = dec_insn->vC_ + actual_args;
5070 else
5071 get_reg = dec_insn->arg_[actual_args];
5072
5073 switch (sig[sig_offset]) {
5074 case 'L':
5075 {
5076 Class* klass = LookupSignatureClass(method, sig.substr(sig_offset),
5077 failure);
5078 if (*failure != VERIFY_ERROR_NONE)
5079 goto bad_sig;
5080 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5081 failure);
5082 if (*failure != VERIFY_ERROR_NONE) {
5083 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5084 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5085 goto bad_sig;
5086 }
5087 sig_offset += sig.substr(sig_offset).find(';');
5088 }
5089 actual_args++;
5090 break;
5091 case '[':
5092 {
5093 Class* klass = LookupSignatureArrayClass(method,
5094 sig.substr(sig_offset), failure);
5095 if (*failure != VERIFY_ERROR_NONE)
5096 goto bad_sig;
5097 VerifyRegisterType(register_line, get_reg, RegTypeFromClass(klass),
5098 failure);
5099 if (*failure != VERIFY_ERROR_NONE) {
5100 LOG(ERROR) << "VFY: bad arg " << actual_args << " (into "
5101 << klass->GetDescriptor()->ToModifiedUtf8() << ")";
5102 goto bad_sig;
5103 }
5104 while (sig[sig_offset] == '[')
5105 sig_offset++;
5106 if (sig[sig_offset] == 'L')
5107 sig_offset += sig.substr(sig_offset).find(';');
5108 }
5109 actual_args++;
5110 break;
5111 case 'Z':
5112 VerifyRegisterType(register_line, get_reg, kRegTypeBoolean, failure);
5113 actual_args++;
5114 break;
5115 case 'C':
5116 VerifyRegisterType(register_line, get_reg, kRegTypeChar, failure);
5117 actual_args++;
5118 break;
5119 case 'B':
5120 VerifyRegisterType(register_line, get_reg, kRegTypeByte, failure);
5121 actual_args++;
5122 break;
5123 case 'I':
5124 VerifyRegisterType(register_line, get_reg, kRegTypeInteger, failure);
5125 actual_args++;
5126 break;
5127 case 'S':
5128 VerifyRegisterType(register_line, get_reg, kRegTypeShort, failure);
5129 actual_args++;
5130 break;
5131 case 'F':
5132 VerifyRegisterType(register_line, get_reg, kRegTypeFloat, failure);
5133 actual_args++;
5134 break;
5135 case 'D':
5136 VerifyRegisterType(register_line, get_reg, kRegTypeDoubleLo, failure);
5137 actual_args += 2;
5138 break;
5139 case 'J':
5140 VerifyRegisterType(register_line, get_reg, kRegTypeLongLo, failure);
5141 actual_args += 2;
5142 break;
5143 default:
5144 LOG(ERROR) << "VFY: invocation target: bad signature type char '"
5145 << sig << "'";
5146 goto bad_sig;
5147 }
5148 }
5149 if (sig[sig_offset] != ')') {
5150 LOG(ERROR) << "VFY: invocation target: bad signature '"
5151 << res_method->GetSignature()->ToModifiedUtf8() << "'";
5152 goto bad_sig;
5153 }
5154
5155 if (actual_args != expected_args) {
5156 LOG(ERROR) << "VFY: expected " << expected_args << " args, found "
5157 << actual_args;
5158 goto bad_sig;
5159 }
5160
5161 return res_method;
5162
5163bad_sig:
jeffhao2a8a90e2011-09-26 14:25:31 -07005164 LOG(ERROR) << "VFY: rejecting call to " << PrettyMethod(res_method);
jeffhaobdb76512011-09-07 11:43:16 -07005165 if (*failure == VERIFY_ERROR_NONE)
5166 *failure = VERIFY_ERROR_GENERIC;
5167 return NULL;
5168}
jeffhaoba5ebb92011-08-25 17:24:37 -07005169
jeffhaod1f0fde2011-09-08 17:25:33 -07005170DexVerifier::RegisterMap* DexVerifier::GenerateRegisterMapV(VerifierData* vdata)
5171{
5172 const DexFile::CodeItem* code_item = vdata->code_item_;
5173 int i, bytes_for_addr, gc_point_count;
5174
5175 if (code_item->registers_size_ >= 2048) {
5176 LOG(ERROR) << "ERROR: register map can't handle "
5177 << code_item->registers_size_ << " registers";
5178 return NULL;
5179 }
5180 uint8_t reg_width = (code_item->registers_size_ + 7) / 8;
5181
5182 /*
5183 * Decide if we need 8 or 16 bits to hold the address. Strictly speaking
5184 * we only need 16 bits if we actually encode an address >= 256 -- if
5185 * the method has a section at the end without GC points (e.g. array
5186 * data) we don't need to count it. The situation is unusual, and
5187 * detecting it requires scanning the entire method, so we don't bother.
5188 */
5189 RegisterMapFormat format;
5190 if (code_item->insns_size_ < 256) {
5191 format = kRegMapFormatCompact8;
5192 bytes_for_addr = 1;
5193 } else {
5194 format = kRegMapFormatCompact16;
5195 bytes_for_addr = 2;
5196 }
5197
5198 /*
5199 * Count up the number of GC point instructions.
5200 *
5201 * NOTE: this does not automatically include the first instruction,
5202 * since we don't count method entry as a GC point.
5203 */
5204 gc_point_count = 0;
5205 for (i = 0; i < (int) code_item->insns_size_; i++) {
5206 if (InsnIsGcPoint(vdata->insn_flags_.get(), i))
5207 gc_point_count++;
5208 }
5209 if (gc_point_count >= 65536) {
5210 /* We could handle this, but in practice we don't get near this. */
5211 LOG(ERROR) << "ERROR: register map can't handle " << gc_point_count
5212 << " gc points in one method";
5213 return NULL;
5214 }
5215
5216 /* Calculate size of buffer to hold the map data. */
5217 uint32_t data_size = gc_point_count * (bytes_for_addr + reg_width);
5218
5219 RegisterMap* map = new RegisterMap(format, reg_width, gc_point_count,
jeffhaoa0a764a2011-09-16 10:43:38 -07005220 data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005221
5222 /* Populate it. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005223 uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005224 for (i = 0; i < (int) vdata->code_item_->insns_size_; i++) {
5225 if (InsnIsGcPoint(vdata->insn_flags_.get(), i)) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005226 DCHECK(vdata->register_lines_[i].reg_types_.get() != NULL);
jeffhaod1f0fde2011-09-08 17:25:33 -07005227 if (format == kRegMapFormatCompact8) {
5228 *map_data++ = i;
5229 } else /*kRegMapFormatCompact16*/ {
5230 *map_data++ = i & 0xff;
5231 *map_data++ = i >> 8;
5232 }
5233 OutputTypeVector(vdata->register_lines_[i].reg_types_.get(),
5234 code_item->registers_size_, map_data);
5235 map_data += reg_width;
5236 }
5237 }
5238
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005239 DCHECK_EQ((uint32_t) map_data - (uint32_t) map->data_, data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005240
5241 // TODO: Remove this check when it's really running...
5242#if 1
5243 if (!VerifyMap(vdata, map)) {
5244 LOG(ERROR) << "Map failed to verify";
5245 return NULL;
5246 }
5247#endif
5248
5249 /* Try to compress the map. */
Shih-wei Liao4f894e32011-09-27 21:33:19 -07005250#if 0
jeffhaod1f0fde2011-09-08 17:25:33 -07005251 RegisterMap* compress_map = CompressMapDifferential(map);
5252 if (compress_map != NULL) {
5253 // TODO: Remove this check when it's really running...
5254#if 1
5255 /*
5256 * Expand the compressed map we just created, and compare it
5257 * to the original. Abort the VM if it doesn't match up.
5258 */
5259 UniquePtr<RegisterMap> uncompressed_map(UncompressMapDifferential(compress_map));
5260 if (uncompressed_map.get() == NULL) {
jeffhao2a8a90e2011-09-26 14:25:31 -07005261 LOG(ERROR) << "Map failed to uncompress - " << PrettyMethod(vdata->method_);
jeffhaod1f0fde2011-09-08 17:25:33 -07005262 delete map;
5263 delete compress_map;
5264 /* bad - compression is broken or we're out of memory */
5265 return NULL;
5266 } else {
5267 if (!CompareMaps(map, uncompressed_map.get())) {
jeffhao2a8a90e2011-09-26 14:25:31 -07005268 LOG(ERROR) << "Map comparison failed - " << PrettyMethod(vdata->method_);
jeffhaod1f0fde2011-09-08 17:25:33 -07005269 delete map;
5270 delete compress_map;
5271 /* bad - compression is broken */
5272 return NULL;
5273 }
5274 }
5275#endif
5276 delete map;
5277 map = compress_map;
5278 }
Shih-wei Liao4f894e32011-09-27 21:33:19 -07005279#endif
jeffhaod1f0fde2011-09-08 17:25:33 -07005280 return map;
5281}
5282
jeffhaoa0a764a2011-09-16 10:43:38 -07005283DexVerifier::RegisterMap* DexVerifier::GetExpandedRegisterMapHelper(
5284 Method* method, RegisterMap* map) {
5285 RegisterMap* new_map;
5286
5287 if (map == NULL)
5288 return NULL;
5289
5290 /* TODO: sanity check to ensure this isn't called w/o external locking */
5291
5292 uint8_t format = map->header_->format_;
5293 switch (format) {
5294 case kRegMapFormatCompact8:
5295 case kRegMapFormatCompact16:
5296 /* already expanded */
5297 return map;
5298 case kRegMapFormatDifferential:
5299 new_map = UncompressMapDifferential(map);
5300 break;
5301 default:
5302 LOG(ERROR) << "Unknown format " << format
5303 << " in dvmGetExpandedRegisterMap";
5304 return NULL;
5305 }
5306
5307 if (new_map == NULL) {
5308 LOG(ERROR) << "Map failed to uncompress (fmt=" << format << ") "
jeffhao2a8a90e2011-09-26 14:25:31 -07005309 << PrettyMethod(method);
jeffhaoa0a764a2011-09-16 10:43:38 -07005310 return NULL;
5311 }
5312
5313 /* Update method, and free compressed map if it was sitting on the heap. */
Brian Carlstrom40381fb2011-10-19 14:13:40 -07005314 //SirtRef<ByteArray> header(ByteArray::Alloc(sizeof(RegisterMapHeader)));
5315 //if (header.get() == NULL) {
5316 // return NULL;
5317 //}
5318 //SirtRef<ByteArray> data(ByteArray::Alloc(ComputeRegisterMapSize(map)));
5319 //if (data.get() == NULL) {
5320 // return NULL;
5321 //}
jeffhaoa0a764a2011-09-16 10:43:38 -07005322
Ian Rogersd6b1f612011-09-27 13:38:14 -07005323 //memcpy(header->GetData(), map->header_, sizeof(RegisterMapHeader));
5324 //memcpy(data->GetData(), map->data_, ComputeRegisterMapSize(map));
jeffhaoa0a764a2011-09-16 10:43:38 -07005325
Ian Rogersd6b1f612011-09-27 13:38:14 -07005326 //method->SetRegisterMapHeader(header);
5327 //method->SetRegisterMapData(data);
jeffhaoa0a764a2011-09-16 10:43:38 -07005328
5329 delete map;
5330 return new_map;
5331}
5332
5333const uint8_t* DexVerifier::RegisterMapGetLine(const RegisterMap* map, int addr) {
5334 int addr_width, line_width;
5335 uint8_t format = map->header_->format_;
5336 uint16_t num_entries = map->header_->num_entries_;
5337
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005338 DCHECK_GT(num_entries, 0);
jeffhaoa0a764a2011-09-16 10:43:38 -07005339
5340 switch (format) {
5341 case kRegMapFormatNone:
5342 return NULL;
5343 case kRegMapFormatCompact8:
5344 addr_width = 1;
5345 break;
5346 case kRegMapFormatCompact16:
5347 addr_width = 2;
5348 break;
5349 default:
5350 LOG(ERROR) << "Unknown format " << format;
5351 return NULL;
5352 }
5353
5354 line_width = addr_width + map->header_->reg_width_;
5355
5356 /*
5357 * Find the appropriate entry. Many maps are very small, some are very large.
5358 */
5359 static const int kSearchThreshold = 8;
5360 const uint8_t* data = NULL;
5361 int line_addr;
5362
5363 if (num_entries < kSearchThreshold) {
5364 int i;
5365 data = map->data_;
5366 for (i = num_entries; i > 0; i--) {
5367 line_addr = data[0];
5368 if (addr_width > 1)
5369 line_addr |= data[1] << 8;
5370 if (line_addr == addr)
5371 return data + addr_width;
5372
5373 data += line_width;
5374 }
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005375 DCHECK_EQ(data, map->data_ + line_width * num_entries);
jeffhaoa0a764a2011-09-16 10:43:38 -07005376 } else {
5377 int hi, lo, mid;
5378
5379 lo = 0;
5380 hi = num_entries -1;
5381
5382 while (hi >= lo) {
5383 mid = (hi + lo) / 2;
5384 data = map->data_ + line_width * mid;
5385
5386 line_addr = data[0];
5387 if (addr_width > 1)
5388 line_addr |= data[1] << 8;
5389
5390 if (addr > line_addr) {
5391 lo = mid + 1;
5392 } else if (addr < line_addr) {
5393 hi = mid - 1;
5394 } else {
5395 return data + addr_width;
5396 }
5397 }
5398 }
5399
5400 return NULL;
5401}
5402
jeffhaod1f0fde2011-09-08 17:25:33 -07005403void DexVerifier::OutputTypeVector(const RegType* regs, int insn_reg_count,
5404 uint8_t* data) {
5405 uint8_t val = 0;
5406 int i;
5407
5408 for (i = 0; i < insn_reg_count; i++) {
5409 RegType type = *regs++;
5410 val >>= 1;
5411 if (IsReferenceType(type))
5412 val |= 0x80; /* set hi bit */
5413
5414 if ((i & 0x07) == 7)
5415 *data++ = val;
5416 }
5417 if ((i & 0x07) != 0) {
5418 /* Flush bits from last byte. */
5419 val >>= 8 - (i & 0x07);
5420 *data++ = val;
5421 }
5422}
5423
5424bool DexVerifier::VerifyMap(VerifierData* vdata, const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005425 const uint8_t* raw_map = map->data_;
5426 uint8_t format = map->header_->format_;
5427 const int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005428 int ent;
5429
jeffhaoe23d93c2011-09-15 14:48:43 -07005430 if ((vdata->code_item_->registers_size_ + 7) / 8 != map->header_->reg_width_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005431 LOG(ERROR) << "GLITCH: registersSize=" << vdata->code_item_->registers_size_
jeffhaoe23d93c2011-09-15 14:48:43 -07005432 << ", reg_width=" << map->header_->reg_width_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005433 return false;
5434 }
5435
5436 for (ent = 0; ent < num_entries; ent++) {
5437 int addr;
5438
5439 switch (format) {
5440 case kRegMapFormatCompact8:
5441 addr = *raw_map++;
5442 break;
5443 case kRegMapFormatCompact16:
5444 addr = *raw_map++;
5445 addr |= (*raw_map++) << 8;
5446 break;
5447 default:
5448 LOG(FATAL) << "GLITCH: bad format (" << format << ")";
5449 return false;
5450 }
5451
5452 const RegType* regs = vdata->register_lines_[addr].reg_types_.get();
5453 if (regs == NULL) {
5454 LOG(ERROR) << "GLITCH: addr " << addr << " has no data";
5455 return false;
5456 }
5457
5458 uint8_t val = 0;
5459 int i;
5460
5461 for (i = 0; i < vdata->code_item_->registers_size_; i++) {
5462 bool bit_is_ref, reg_is_ref;
5463
5464 val >>= 1;
5465 if ((i & 0x07) == 0) {
5466 /* Load next byte of data. */
5467 val = *raw_map++;
5468 }
5469
5470 bit_is_ref = val & 0x01;
5471
5472 RegType type = regs[i];
5473 reg_is_ref = IsReferenceType(type);
5474
5475 if (bit_is_ref != reg_is_ref) {
5476 LOG(ERROR) << "GLITCH: addr " << addr << " reg " << i << ": bit="
5477 << bit_is_ref << " reg=" << reg_is_ref << "(" << type << ")";
5478 return false;
5479 }
5480 }
5481 /* Raw_map now points to the address field of the next entry. */
5482 }
5483
5484 return true;
5485}
5486
5487bool DexVerifier::CompareMaps(const RegisterMap* map1, const RegisterMap* map2)
5488{
5489 size_t size1, size2;
5490
5491 size1 = ComputeRegisterMapSize(map1);
5492 size2 = ComputeRegisterMapSize(map2);
5493 if (size1 != size2) {
5494 LOG(ERROR) << "CompareMaps: size mismatch (" << size1 << " vs " << size2
5495 << ")";
5496 return false;
5497 }
5498
jeffhaoe23d93c2011-09-15 14:48:43 -07005499 if (map1->header_->format_ != map2->header_->format_ ||
5500 map1->header_->reg_width_ != map2->header_->reg_width_ ||
jeffhaoa0a764a2011-09-16 10:43:38 -07005501 map1->header_->num_entries_ != map2->header_->num_entries_) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005502 LOG(ERROR) << "CompareMaps: fields mismatch";
5503 }
jeffhaoe23d93c2011-09-15 14:48:43 -07005504 if (memcmp(map1->data_, map2->data_, size1) != 0) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005505 LOG(ERROR) << "CompareMaps: data mismatch";
5506 return false;
5507 }
5508
5509 return true;
5510}
5511
5512size_t DexVerifier::ComputeRegisterMapSize(const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005513 uint8_t format = map->header_->format_;
5514 uint16_t num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005515
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005516 DCHECK(map != NULL);
jeffhaod1f0fde2011-09-08 17:25:33 -07005517
5518 switch (format) {
5519 case kRegMapFormatNone:
5520 return 1;
5521 case kRegMapFormatCompact8:
jeffhaoe23d93c2011-09-15 14:48:43 -07005522 return (1 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005523 case kRegMapFormatCompact16:
jeffhaoe23d93c2011-09-15 14:48:43 -07005524 return (2 + map->header_->reg_width_) * num_entries;
jeffhaod1f0fde2011-09-08 17:25:33 -07005525 case kRegMapFormatDifferential:
5526 {
5527 /* Decoded ULEB128 length. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005528 const uint8_t* ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005529 return DecodeUnsignedLeb128(&ptr);
5530 }
5531 default:
5532 LOG(FATAL) << "Bad register map format " << format;
5533 return 0;
5534 }
5535}
5536
5537int DexVerifier::ComputeBitDiff(const uint8_t* bits1, const uint8_t* bits2,
5538 int byte_width, int* first_bit_changed_ptr, int* num_bits_changed_ptr,
5539 uint8_t* leb_out_buf) {
5540 int num_bits_changed = 0;
5541 int first_bit_changed = -1;
5542 int leb_size = 0;
5543 int byte_num;
5544
5545 /*
5546 * Run through the vectors, first comparing them at the byte level. This
5547 * will yield a fairly quick result if nothing has changed between them.
5548 */
5549 for (byte_num = 0; byte_num < byte_width; byte_num++) {
5550 uint8_t byte1 = *bits1++;
5551 uint8_t byte2 = *bits2++;
5552 if (byte1 != byte2) {
5553 /* Walk through the byte, identifying the changed bits. */
5554 int bit_num;
5555 for (bit_num = 0; bit_num < 8; bit_num++) {
5556 if (((byte1 >> bit_num) & 0x01) != ((byte2 >> bit_num) & 0x01)) {
5557 int bit_offset = (byte_num << 3) + bit_num;
5558
5559 if (first_bit_changed < 0)
5560 first_bit_changed = bit_offset;
5561 num_bits_changed++;
5562
5563 if (leb_out_buf == NULL) {
5564 leb_size += UnsignedLeb128Size(bit_offset);
5565 } else {
5566 uint8_t* cur_buf = leb_out_buf;
5567 leb_out_buf = WriteUnsignedLeb128(leb_out_buf, bit_offset);
5568 leb_size += leb_out_buf - cur_buf;
5569 }
5570 }
5571 }
5572 }
5573 }
5574
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005575 if (num_bits_changed > 0) {
5576 DCHECK_GE(first_bit_changed, 0);
5577 }
jeffhaod1f0fde2011-09-08 17:25:33 -07005578
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005579 if (first_bit_changed_ptr != NULL) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005580 *first_bit_changed_ptr = first_bit_changed;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005581 }
5582
5583 if (num_bits_changed_ptr != NULL) {
jeffhaod1f0fde2011-09-08 17:25:33 -07005584 *num_bits_changed_ptr = num_bits_changed;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005585 }
jeffhaod1f0fde2011-09-08 17:25:33 -07005586
5587 return leb_size;
5588}
5589
5590DexVerifier::RegisterMap* DexVerifier::CompressMapDifferential(
5591 const RegisterMap* map) {
5592 int orig_size = ComputeRegisterMapSize(map);
5593 uint8_t* tmp_ptr;
5594 int addr_width;
5595
jeffhaoe23d93c2011-09-15 14:48:43 -07005596 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005597 switch (format) {
5598 case kRegMapFormatCompact8:
5599 addr_width = 1;
5600 break;
5601 case kRegMapFormatCompact16:
5602 addr_width = 2;
5603 break;
5604 default:
5605 LOG(ERROR) << "ERROR: can't compress map with format=" << format;
5606 return NULL;
5607 }
5608
jeffhaoe23d93c2011-09-15 14:48:43 -07005609 int reg_width = map->header_->reg_width_;
5610 int num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005611
5612 if (num_entries <= 1) {
5613 return NULL;
5614 }
5615
5616 /*
5617 * We don't know how large the compressed data will be. It's possible
5618 * for it to expand and become larger than the original. The header
5619 * itself is variable-sized, so we generate everything into a temporary
5620 * buffer and then copy it to form-fitting storage once we know how big
5621 * it will be (and that it's smaller than the original).
5622 *
5623 * If we use a size that is equal to the size of the input map plus
5624 * a value longer than a single entry can possibly expand to, we need
5625 * only check for overflow at the end of each entry. The worst case
5626 * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
5627 * Addresses are 16 bits, so that's (1 + 3 + reg_width).
5628 *
5629 * The initial address offset and bit vector will take up less than
5630 * or equal to the amount of space required when uncompressed -- large
5631 * initial offsets are rejected.
5632 */
5633 UniquePtr<uint8_t[]> tmp_buf(new uint8_t[orig_size + (1 + 3 + reg_width)]);
5634
5635 tmp_ptr = tmp_buf.get();
5636
jeffhaoe23d93c2011-09-15 14:48:43 -07005637 const uint8_t* map_data = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005638 const uint8_t* prev_bits;
5639 uint16_t addr, prev_addr;
5640
5641 addr = *map_data++;
5642 if (addr_width > 1)
5643 addr |= (*map_data++) << 8;
5644
5645 if (addr >= 128) {
5646 LOG(ERROR) << "Can't compress map with starting address >= 128";
5647 return NULL;
5648 }
5649
5650 /*
5651 * Start by writing the initial address and bit vector data. The high
5652 * bit of the initial address is used to indicate the required address
5653 * width (which the decoder can't otherwise determine without parsing
5654 * the compressed data).
5655 */
5656 *tmp_ptr++ = addr | (addr_width > 1 ? 0x80 : 0x00);
5657 memcpy(tmp_ptr, map_data, reg_width);
5658
5659 prev_bits = map_data;
5660 prev_addr = addr;
5661
5662 tmp_ptr += reg_width;
5663 map_data += reg_width;
5664
5665 /* Loop over all following entries. */
5666 for (int entry = 1; entry < num_entries; entry++) {
5667 int addr_diff;
5668 uint8_t key;
5669
5670 /* Pull out the address and figure out how to encode it. */
5671 addr = *map_data++;
5672 if (addr_width > 1)
5673 addr |= (*map_data++) << 8;
5674
5675 addr_diff = addr - prev_addr;
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07005676 DCHECK_GT(addr_diff, 0);
jeffhaod1f0fde2011-09-08 17:25:33 -07005677 if (addr_diff < 8) {
5678 /* Small difference, encode in 3 bits. */
5679 key = addr_diff -1; /* set 00000AAA */
5680 } else {
5681 /* Large difference, output escape code. */
5682 key = 0x07; /* escape code for AAA */
5683 }
5684
5685 int num_bits_changed, first_bit_changed, leb_size;
5686
5687 leb_size = ComputeBitDiff(prev_bits, map_data, reg_width,
5688 &first_bit_changed, &num_bits_changed, NULL);
5689
5690 if (num_bits_changed == 0) {
5691 /* set B to 1 and CCCC to zero to indicate no bits were changed */
5692 key |= 0x08;
5693 } else if (num_bits_changed == 1 && first_bit_changed < 16) {
5694 /* set B to 0 and CCCC to the index of the changed bit */
5695 key |= first_bit_changed << 4;
5696 } else if (num_bits_changed < 15 && leb_size < reg_width) {
5697 /* set B to 1 and CCCC to the number of bits */
5698 key |= 0x08 | (num_bits_changed << 4);
5699 } else {
5700 /* set B to 1 and CCCC to 0x0f so we store the entire vector */
5701 key |= 0x08 | 0xf0;
5702 }
5703
5704 /*
5705 * Encode output. Start with the key, follow with the address
5706 * diff (if it didn't fit in 3 bits), then the changed bit info.
5707 */
5708 *tmp_ptr++ = key;
5709 if ((key & 0x07) == 0x07)
5710 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, addr_diff);
5711
5712 if ((key & 0x08) != 0) {
5713 int bit_count = key >> 4;
5714 if (bit_count == 0) {
5715 /* nothing changed, no additional output required */
5716 } else if (bit_count == 15) {
5717 /* full vector is most compact representation */
5718 memcpy(tmp_ptr, map_data, reg_width);
5719 tmp_ptr += reg_width;
5720 } else {
5721 /* write bit indices in ULEB128 format */
5722 (void) ComputeBitDiff(prev_bits, map_data, reg_width,
5723 NULL, NULL, tmp_ptr);
5724 tmp_ptr += leb_size;
5725 }
5726 } else {
5727 /* single-bit changed, value encoded in key byte */
5728 }
5729
5730 prev_bits = map_data;
5731 prev_addr = addr;
5732 map_data += reg_width;
5733
5734 /* See if we've run past the original size. */
5735 if (tmp_ptr - tmp_buf.get() >= orig_size) {
5736 return NULL;
5737 }
5738 }
5739
5740 /*
5741 * Create a RegisterMap with the contents.
5742 *
5743 * TODO: consider using a threshold other than merely ">=". We would
5744 * get poorer compression but potentially use less native heap space.
5745 */
5746 int new_data_size = tmp_ptr - tmp_buf.get();
5747 int new_map_size = new_data_size + UnsignedLeb128Size(new_data_size);
5748
5749 if (new_map_size >= orig_size) {
5750 return NULL;
5751 }
5752
5753 RegisterMap* new_map = new RegisterMap(kRegMapFormatDifferential, reg_width,
jeffhaoa0a764a2011-09-16 10:43:38 -07005754 num_entries, new_map_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005755
jeffhaoe23d93c2011-09-15 14:48:43 -07005756 tmp_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005757 tmp_ptr = WriteUnsignedLeb128(tmp_ptr, new_data_size);
5758 memcpy(tmp_ptr, tmp_buf.get(), new_data_size);
5759
5760 return new_map;
5761}
5762
5763DexVerifier::RegisterMap* DexVerifier::UncompressMapDifferential(
5764 const RegisterMap* map) {
jeffhaoe23d93c2011-09-15 14:48:43 -07005765 uint8_t format = map->header_->format_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005766 RegisterMapFormat new_format;
5767 int reg_width, num_entries, new_addr_width, new_data_size;
5768
5769 if (format != kRegMapFormatDifferential) {
5770 LOG(ERROR) << "Not differential (" << format << ")";
5771 return NULL;
5772 }
5773
jeffhaoe23d93c2011-09-15 14:48:43 -07005774 reg_width = map->header_->reg_width_;
5775 num_entries = map->header_->num_entries_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005776
5777 /* Get the data size; we can check this at the end. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005778 const uint8_t* src_ptr = map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005779 int expected_src_len = DecodeUnsignedLeb128(&src_ptr);
5780 const uint8_t* src_start = src_ptr;
5781
5782 /* Get the initial address and the 16-bit address flag. */
5783 int addr = *src_ptr & 0x7f;
5784 if ((*src_ptr & 0x80) == 0) {
5785 new_format = kRegMapFormatCompact8;
5786 new_addr_width = 1;
5787 } else {
5788 new_format = kRegMapFormatCompact16;
5789 new_addr_width = 2;
5790 }
5791 src_ptr++;
5792
5793 /* Now we know enough to allocate the new map. */
5794 new_data_size = (new_addr_width + reg_width) * num_entries;
5795 RegisterMap* new_map = new RegisterMap(new_format, reg_width, num_entries,
jeffhaoa0a764a2011-09-16 10:43:38 -07005796 new_data_size);
jeffhaod1f0fde2011-09-08 17:25:33 -07005797
5798 /* Write the start address and initial bits to the new map. */
jeffhaoe23d93c2011-09-15 14:48:43 -07005799 uint8_t* dst_ptr = new_map->data_;
jeffhaod1f0fde2011-09-08 17:25:33 -07005800
5801 *dst_ptr++ = addr & 0xff;
5802 if (new_addr_width > 1)
5803 *dst_ptr++ = (uint8_t) (addr >> 8);
5804
5805 memcpy(dst_ptr, src_ptr, reg_width);
5806
5807 int prev_addr = addr;
5808 const uint8_t* prev_bits = dst_ptr; /* point at uncompressed data */
5809
5810 dst_ptr += reg_width;
5811 src_ptr += reg_width;
5812
5813 /* Walk through, uncompressing one line at a time. */
5814 int entry;
5815 for (entry = 1; entry < num_entries; entry++) {
5816 int addr_diff;
5817 uint8_t key;
5818
5819 key = *src_ptr++;
5820
5821 /* Get the address. */
5822 if ((key & 0x07) == 7) {
5823 /* Address diff follows in ULEB128. */
5824 addr_diff = DecodeUnsignedLeb128(&src_ptr);
5825 } else {
5826 addr_diff = (key & 0x07) +1;
5827 }
5828
5829 addr = prev_addr + addr_diff;
5830 *dst_ptr++ = addr & 0xff;
5831 if (new_addr_width > 1)
5832 *dst_ptr++ = (uint8_t) (addr >> 8);
5833
5834 /* Unpack the bits. */
5835 if ((key & 0x08) != 0) {
5836 int bit_count = (key >> 4);
5837 if (bit_count == 0) {
5838 /* No bits changed, just copy previous. */
5839 memcpy(dst_ptr, prev_bits, reg_width);
5840 } else if (bit_count == 15) {
5841 /* Full copy of bit vector is present; ignore prev_bits. */
5842 memcpy(dst_ptr, src_ptr, reg_width);
5843 src_ptr += reg_width;
5844 } else {
5845 /* Copy previous bits and modify listed indices. */
5846 memcpy(dst_ptr, prev_bits, reg_width);
5847 while (bit_count--) {
5848 int bit_index = DecodeUnsignedLeb128(&src_ptr);
5849 ToggleBit(dst_ptr, bit_index);
5850 }
5851 }
5852 } else {
5853 /* Copy previous bits and modify the specified one. */
5854 memcpy(dst_ptr, prev_bits, reg_width);
5855
5856 /* One bit, from 0-15 inclusive, was changed. */
5857 ToggleBit(dst_ptr, key >> 4);
5858 }
5859
5860 prev_addr = addr;
5861 prev_bits = dst_ptr;
5862 dst_ptr += reg_width;
5863 }
5864
jeffhaoe23d93c2011-09-15 14:48:43 -07005865 if (dst_ptr - new_map->data_ != new_data_size) {
5866 LOG(ERROR) << "ERROR: output " << dst_ptr - new_map->data_
jeffhaod1f0fde2011-09-08 17:25:33 -07005867 << " bytes, expected " << new_data_size;
5868 free(new_map);
5869 return NULL;
5870 }
5871
5872 if (src_ptr - src_start != expected_src_len) {
5873 LOG(ERROR) << "ERROR: consumed " << src_ptr - src_start
5874 << " bytes, expected " << expected_src_len;
5875 free(new_map);
5876 return NULL;
5877 }
5878
5879 return new_map;
5880}
5881
jeffhaoe0cfb6f2011-09-22 16:42:56 -07005882/* Dump the register types for the specifed address to the log file. */
5883void DexVerifier::DumpRegTypes(const VerifierData* vdata,
5884 const RegisterLine* register_line, int addr, const char* addr_name,
5885 const UninitInstanceMap* uninit_map) {
5886 const DexFile::CodeItem* code_item = vdata->code_item_;
5887 uint16_t reg_count = code_item->registers_size_;
5888 uint32_t insns_size = code_item->insns_size_;
5889 const InsnFlags* insn_flags = vdata->insn_flags_.get();
5890 const RegType* addr_regs = register_line->reg_types_.get();
5891 int full_reg_count = reg_count + kExtraRegs;
5892 bool branch_target = InsnIsBranchTarget(insn_flags, addr);
5893 int i;
5894
5895 CHECK(addr >= 0 && addr < (int) insns_size);
5896
5897 int reg_char_size = full_reg_count + (full_reg_count - 1) / 4 + 2 + 1;
5898 char reg_chars[reg_char_size + 1];
5899 memset(reg_chars, ' ', reg_char_size);
5900 reg_chars[0] = '[';
Elliott Hughes362f9bc2011-10-17 18:56:41 -07005901 if (reg_count == 0) {
jeffhaoe0cfb6f2011-09-22 16:42:56 -07005902 reg_chars[1] = ']';
Elliott Hughes362f9bc2011-10-17 18:56:41 -07005903 } else {
5904 reg_chars[1 + (reg_count - 1) + (reg_count - 1) / 4 + 1] = ']';
5905 }
jeffhaoe0cfb6f2011-09-22 16:42:56 -07005906 reg_chars[reg_char_size] = '\0';
5907
5908 for (i = 0; i < reg_count + kExtraRegs; i++) {
5909 char tch;
5910
5911 switch (addr_regs[i]) {
5912 case kRegTypeUnknown: tch = '.'; break;
5913 case kRegTypeConflict: tch = 'X'; break;
5914 case kRegTypeZero: tch = '0'; break;
5915 case kRegTypeOne: tch = '1'; break;
5916 case kRegTypeBoolean: tch = 'Z'; break;
5917 case kRegTypeConstPosByte: tch = 'y'; break;
5918 case kRegTypeConstByte: tch = 'Y'; break;
5919 case kRegTypeConstPosShort: tch = 'h'; break;
5920 case kRegTypeConstShort: tch = 'H'; break;
5921 case kRegTypeConstChar: tch = 'c'; break;
5922 case kRegTypeConstInteger: tch = 'i'; break;
5923 case kRegTypePosByte: tch = 'b'; break;
5924 case kRegTypeByte: tch = 'B'; break;
5925 case kRegTypePosShort: tch = 's'; break;
5926 case kRegTypeShort: tch = 'S'; break;
5927 case kRegTypeChar: tch = 'C'; break;
5928 case kRegTypeInteger: tch = 'I'; break;
5929 case kRegTypeFloat: tch = 'F'; break;
5930 case kRegTypeConstLo: tch = 'N'; break;
5931 case kRegTypeConstHi: tch = 'n'; break;
5932 case kRegTypeLongLo: tch = 'J'; break;
5933 case kRegTypeLongHi: tch = 'j'; break;
5934 case kRegTypeDoubleLo: tch = 'D'; break;
5935 case kRegTypeDoubleHi: tch = 'd'; break;
5936 default:
5937 if (RegTypeIsReference(addr_regs[i])) {
5938 if (RegTypeIsUninitReference(addr_regs[i]))
5939 tch = 'U';
5940 else
5941 tch = 'L';
5942 } else {
5943 tch = '*';
5944 CHECK(false);
5945 }
5946 break;
5947 }
5948
5949 if (i < reg_count)
5950 reg_chars[1 + i + (i / 4)] = tch;
5951 else
5952 reg_chars[1 + i + (i / 4) + 2] = tch;
5953 }
5954
5955 if (addr == 0 && addr_name != NULL) {
5956 char start = branch_target ? '>' : ' ';
5957 LOG(INFO) << start << addr_name << " " << reg_chars << " mst="
5958 << register_line->monitor_stack_top_;
5959 } else {
5960 char start = branch_target ? '>' : ' ';
5961 LOG(INFO) << start << "0x" << std::hex << addr << std::dec << " "
5962 << reg_chars << " mst=" << register_line->monitor_stack_top_;
5963 }
5964
5965 for (i = 0; i < reg_count + kExtraRegs; i++) {
5966 if (RegTypeIsReference(addr_regs[i]) && addr_regs[i] != kRegTypeZero) {
5967 Class* klass = RegTypeReferenceToClass(addr_regs[i], uninit_map);
5968 if (i < reg_count) {
5969 const char* undef = RegTypeIsUninitReference(addr_regs[i]) ? "[U]" : "";
5970 LOG(INFO) << " " << i << ": 0x" << std::hex << addr_regs[i] << std::dec
5971 << " " << undef << klass->GetDescriptor()->ToModifiedUtf8();
5972 } else {
5973 const char* undef = RegTypeIsUninitReference(addr_regs[i]) ? "[U]" : "";
5974 LOG(INFO) << " RS: 0x" << std::hex << addr_regs[i] << std::dec
5975 << " " << undef << klass->GetDescriptor()->ToModifiedUtf8();
5976 }
5977 }
5978 }
5979}
5980
Carl Shapiro0e5d75d2011-07-06 18:28:37 -07005981} // namespace art