Rizin
unix-like reverse engineering framework and cli tools
analysis_dalvik.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021-2022 deroad <wargio@libero.it>
2 // SPDX-FileCopyrightText: 2010-2019 pancake <pancake@nopcode.org>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_types.h>
6 #include <rz_lib.h>
7 #include <rz_asm.h>
8 #include <rz_analysis.h>
9 
10 #include "../../asm/arch/dalvik/opcode.h"
11 #include "../../bin/format/dex/dex.h"
12 
13 static const char *getCond(ut8 cond) {
14  switch (cond) {
15  case 0x32: // if-eq
16  return "$z";
17  case 0x33: // if-ne
18  return "$z,!";
19  case 0x34: // if-lt
20  return "63,$c,!";
21  case 0x35: // if-ge
22  return "63,$c,$z,|";
23  case 0x36: // if-gt
24  return "63,$c";
25  case 0x37: // if-le
26  return "63,$c,!,$z,|";
27  }
28  return "";
29 }
30 
31 static const char *getCondz(ut8 cond) {
32  switch (cond) {
33  case 0x38: // if-eqz
34  return "NOP";
35  case 0x39: // if-nez
36  return "!";
37  case 0x3a: // if-ltz
38  return "0,==,63,$c,!";
39  case 0x3b: // if-gez
40  return "0,==,63,$c,$z,|";
41  case 0x3c: // if-gtz
42  return "0,==,63,$c";
43  case 0x3d: // if-lez
44  return "0,==,63,$c,!";
45  }
46  return "";
47 }
48 
49 static int dalvik_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask) {
50  int sz = dalvik_opcodes[data[0]].len;
51  if (!op || sz >= len) {
52  if (op && (mask & RZ_ANALYSIS_OP_MASK_DISASM)) {
53  op->mnemonic = strdup("invalid");
54  }
55  return -1;
56  }
57  op->size = sz;
58  op->nopcode = 1; // Necessary??
59  op->id = data[0];
60 
61  ut32 vA = 0;
62  ut32 vB = 0;
63  ut32 vC = 0;
64  if (len > 3) {
65  vA = data[1];
66  vB = data[2];
67  vC = data[3];
68  }
69  switch (data[0]) {
70  case 0xca: // rem-float:
71  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
72  // fallthrough
73  case 0x1b: // const-string/jumbo
74  case 0x14: // const
75  case 0x15: // const
76  case 0x16: // const
77  case 0x17: // const
78  case 0x42: // const
79  case 0x12: // const/4
80  {
82  ut32 vB = (data[1] & 0x0f);
83  ut32 vA = (data[1] & 0xf0) >> 4;
84  ut32 vC = (len > 4) ? rz_read_le32(data + 2) : 0x22;
85  // op->stackop = RZ_ANALYSIS_STACK_SET;
86  // op->ptr = vC; // why
87  ut64 val = vC ? vC : vA;
88  op->val = val;
89  // op->reg = vB;
90  op->nopcode = 2;
92  esilprintf(op, "0x%" PFMT64x ",v%d,=", val, vB);
93  }
94  } break;
95  case 0x01: // move
96  case 0x07: // move-object
97  case 0x04: // mov-wide
98  {
99  ut32 vB = (data[1] & 0x0f);
100  ut32 vA = (data[1] & 0xf0) >> 4;
101  if (vA == vB) {
102  op->type = RZ_ANALYSIS_OP_TYPE_NOP;
104  esilprintf(op, ",");
105  }
106  } else {
107  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
108  // op->stackop = RZ_ANALYSIS_STACK_SET;
109  // op->ptr = -vA;
111  esilprintf(op, "v%d,v%d,=", vA, vB);
112  }
113  }
114  } break;
115  case 0x02: // move/from16
116  case 0x03: // move/16
117  case 0x05: // move-wide/from16
118  case 0x06: // mov-wide&17
119  case 0x08: // move-object/from16
120  case 0x09: // move-object/16
121  case 0x13: // const/16
122  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
123  if (len > 2) {
124  int vA = (int)data[1];
125  ut32 vB = (data[3] << 8) | data[2];
127  esilprintf(op, "v%d,v%d,=", vA, vB);
128  }
129  op->val = vB;
130  }
131  break;
132  case 0x18: // const-wide
133  case 0x19: // const-wide
134  // 180001000101. const-wide v0:v1, 0x18201cd01010001
135  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
136  break;
137  case 0x0a: // move-result
138  case 0x0d: // move-exception
139  case 0x0c: // move-result-object
140  case 0x0b: // move-result-wide
141  // TODO: add MOVRET OP TYPE ??
142  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
144  ut32 vA = data[1];
145  esilprintf(op, "sp,v%d,=[8],8,sp,+=,8", vA);
146  }
147  break;
148  case 0x1a: // const-string
149  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
150  op->datatype = RZ_ANALYSIS_DATATYPE_STRING;
151  if (len > 2) {
152  ut32 vA = data[1];
153  ut32 vB = (data[3] << 8) | data[2];
154  ut64 offset = RZ_ANALYSIS_GET_OFFSET(analysis, 's', vB);
155  op->ptr = offset;
157  // op->refptr = 0;
158  esilprintf(op, "0x%" PFMT64x ",v%d,=", offset, vA);
159  }
160  }
161  break;
162  case 0x1c: // const-class
163  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
164  op->datatype = RZ_ANALYSIS_DATATYPE_CLASS;
165  break;
166  case 0x89: // float-to-double
167  case 0x8a: // double-to-int
168  case 0x87: // double-to-int
169  case 0x8c: // double-to-float
170  case 0x8b: // double-to-long
171  case 0x88: // float-to-long
172  case 0x86: // long-to-double
173  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
174  // fallthrough
175  case 0x81: // int-to-long
176  case 0x82: // int-to-float
177  case 0x85: // long-to-float
178  case 0x83: // int-to-double
179  case 0x8d: // int-to-byte
180  case 0x8e: // int-to-char
183  ut32 vA = (data[1] & 0x0f);
184  ut32 vB = (data[1] & 0xf0) >> 4;
185  esilprintf(op, "v%d,0xff,&,v%d,=", vB, vA);
186  }
187  break;
188  case 0x8f: // int-to-short
190  // op->datatype = RZ_ANALYSIS_DATATYPE_INT32 | RZ_ANALYSIS_DATATYPE_INT16;
192  ut32 vA = (data[1] & 0x0f);
193  ut32 vB = (data[1] & 0xf0) >> 4;
194  esilprintf(op, "v%d,0xffff,&,v%d,=", vB, vA);
195  }
196  break;
197  case 0x84: // long-to-int
200  ut32 vA = (data[1] & 0x0f);
201  ut32 vB = (data[1] & 0xf0) >> 4;
202  esilprintf(op, "v%d,0xffffffff,&,v%d,=", vB, vA);
203  }
204  break;
205  case 0x20: // instance-of
206  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
208  esilprintf(op, "%d,instanceof,%d,-,!,v%d,=", vC, vB, vA);
209  }
210  break;
211  case 0x21: // array-length
213  op->datatype = RZ_ANALYSIS_DATATYPE_ARRAY;
214  break;
215  case 0x44: // aget
216  case 0x45: // aget-bool
217  case 0x46:
218  case 0x47: // aget-bool
219  case 0x48: // aget-byte
220  case 0x49: // aget-char
221  case 0x4a: // aget-short
222  case 0x52: // iget
223  case 0x58: // iget-short
224  case 0x53: // iget-wide
225  case 0x56: // iget-byte
226  case 0x57: // iget-char
227  case 0xea: // sget-wide-volatile
228  case 0xf4: // iget-byte
229  case 0x66: // sget-short
230  case 0xfd: // sget-object
231  case 0x55: // iget-bool
232  case 0x60: // sget
233  case 0x61: //
234  case 0x64: // sget-byte
235  case 0x65: // sget-char
236  case 0xe3: // iget-volatile
237  case 0xe4: //
238  case 0xe5: // sget
239  case 0xe6: // sget
240  case 0xe7: // iget-object-volatile
241  case 0xe8: // iget-bool
242  case 0xf3: // iget-bool
243  case 0xf8: // iget-bool
244  case 0xf2: // iget-quick
246  break;
247  case 0x54: // iget-object
250  ut32 vA = (data[1] & 0x0f);
251  ut32 vB = (data[1] & 0xf0) >> 4;
252  ut32 vC = (data[2] & 0x0f);
253  esilprintf(op, "%d,v%d,iget,v%d,=", vC, vB, vA);
254  }
255  break;
256  case 0x63: // sget-boolean
257  op->datatype = RZ_ANALYSIS_DATATYPE_BOOLEAN;
260  ut32 vA = (data[1] & 0x0f);
261  ut32 vB = (data[1] & 0xf0) >> 4;
262  ut32 vC = (data[2] & 0x0f);
263  const char *vT = "-boolean";
264  esilprintf(op, "%d,%d,sget%s,v%d,=", vC, vB, vT, vA);
265  }
266  break;
267  case 0x62: // sget-object
268  {
269  op->datatype = RZ_ANALYSIS_DATATYPE_OBJECT;
271  ut32 vC = len > 3 ? (data[3] << 8) | data[2] : 0;
272  op->ptr = analysis->binb.get_offset(analysis->binb.bin, 'f', vC);
274  ut32 vA = (data[1] & 0x0f);
275  esilprintf(op, "%" PFMT64d ",v%d,=", op->ptr, vA);
276  }
277  } break;
278  case 0x6b: // sput-byte
279  case 0x6d: // sput-short
280  case 0xeb: // sput-wide-volatile
281  case 0x4b: // aput
282  case 0x4c: // aput-wide
283  case 0x4d: // aput-object
284  case 0x4e: // aput-bool
285  case 0x4f: //
286  case 0x5e: // iput-char
287  case 0xfc: // iput-object-volatile
288  case 0xf5: // iput-quick
289  case 0x5c: // iput-bool
290  case 0x69: // sput-object
291  case 0x5f: // iput-wide
292  case 0xe9: // iput-wide-volatile
293  case 0xf6: // iput-wide
294  case 0xf7: // iput-wide
295  case 0x67: // iput-wide
296  case 0x59: // iput-wide
297  case 0x5a: // iput-wide
298  case 0x5b: // iput-wide
299  case 0x5d: // iput-wide
300  case 0x50: //
301  case 0x51: // aput-short
302  case 0x68: // sput-wide
303  case 0x6a: // sput-boolean
304  case 0x6c: // sput-wide
305  case 0xfe: // sput
306  {
308  ut32 vC = len > 3 ? (data[3] << 8) | data[2] : 0;
309  op->ptr = analysis->binb.get_offset(analysis->binb.bin, 'f', vC);
310  }
312  ut32 vA = (data[1] & 0x0f);
313  esilprintf(op, "%" PFMT64d ",v%d,=", op->ptr, vA);
314  }
315  break;
316  case 0xad: // mul-double
317  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
318  op->type = RZ_ANALYSIS_OP_TYPE_MUL;
320  esilprintf(op, "v%d,v%d,*,v%d,=", vC, vB, vA);
321  }
322  break;
323  case 0x9d:
324  case 0xc8: // mul-float
325  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
326  /* fall through */
327  case 0xcd:
328  case 0xd2: // mul-int/lit16
329  case 0x92:
330  case 0xb2:
331  op->type = RZ_ANALYSIS_OP_TYPE_MUL;
333  ut32 vA = (data[1] & 0x0f);
334  ut32 vB = (data[1] & 0xf0) >> 4;
335  ut32 vC = (data[2] << 8) | data[3];
336  esilprintf(op, "%d,v%d,*,v%d,=", vC, vB, vA);
337  op->val = vC;
338  }
339  break;
340  case 0x7c: // not-int
341  case 0x7e: // not-long
342  op->type = RZ_ANALYSIS_OP_TYPE_NOT;
343  break;
344  case 0xa4: // shr-long
345  case 0xba: // ushr-int/2addr
346  case 0xe2: // ushr-int
347  case 0xa5: // ushr-long
348  case 0x9a: // ushr-long
349  case 0xc5: // ushr-long/2addr
350  case 0xc4: // shr-long/2addr
351  case 0xe1: // shr-int/lit8
352  case 0x99: // shr-int
353  op->type = RZ_ANALYSIS_OP_TYPE_SHR;
354  break;
355  case 0xaa: // rem-float
356  case 0xcf: // rem-double
357  case 0xaf: // rem-double
358  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
359  // fallthrough
360  case 0xb4: // rem-int/2addr
361  case 0xdc: // rem-int/lit8
362  case 0xd4: // rem-int
363  case 0xbf: // rem-long/2addr
364  case 0x9f: // rem-long
365  case 0x94: // rem-int
366  op->type = RZ_ANALYSIS_OP_TYPE_MOD; // mod = rem
367  break;
368  case 0xd7:
369  case 0xd9:
370  case 0xda:
371  case 0xde:
372 
373  case 0x95: // and-int
374  case 0x96: // or-int
375  op->type = RZ_ANALYSIS_OP_TYPE_OR;
376  break;
377  case 0xc2: // xor-long
378  case 0x97: // xor-int
379  case 0xdf: // xor-int/lit16
380  case 0xa2: // xor-long
381  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
382  break;
383  case 0xc9: // div-float
384  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
385  // fallthrough
386  case 0x93: // div-int
387  case 0xd3: // div-int/lit16
388  case 0xdb: // div-int/lit8
389  case 0xce: // div-double
390  case 0x9e: // div-double
391  case 0xbe: // div-double
392  case 0xae: // div-double
393  case 0xa9: // div-float
394  case 0xb3: // div-int/2addr
395  op->type = RZ_ANALYSIS_OP_TYPE_DIV;
396  break;
397  case 0x0e: // return-void
398  case 0x0f: // return
399  case 0x10: // return-wide
400  case 0x11: // return-object
401  case 0xf1: // return-void-barrier
402  op->type = RZ_ANALYSIS_OP_TYPE_RET;
403  op->eob = true;
405  if (data[0] == 0x0e) { // return-void
406  esilprintf(op, "sp,[8],ip,=,8,sp,+=");
407  } else {
408  ut32 vA = data[1];
409  esilprintf(op, "sp,[8],ip,=,8,sp,+=,8,sp,-=,v%d,sp,=[8]", vA);
410  }
411  }
412  break;
413  case 0x28: // goto
414  if (len > 1) {
415  st32 rel = (signed char)data[1];
416  op->jump = addr + (rel * 2);
417  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
419  esilprintf(op, "0x%" PFMT64x ",ip,=", op->jump);
420  }
421  }
422  break;
423  case 0x29: // goto/16
424  if (len > 3) {
425  st32 rel = (short)(data[3] << 8 | data[2]);
426  op->jump = addr + (rel * 2);
427  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
429  esilprintf(op, "0x%" PFMT64x ",ip,=", op->jump);
430  }
431  }
432  break;
433  case 0x2a: // goto/32
434  if (len > 5) {
435  st32 rel = (st32)(data[2] | (data[3] << 8) | (data[4] << 16) | (data[5] << 24));
436  op->jump = addr + (rel * 2);
437  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
439  esilprintf(op, "0x%" PFMT64x ",ip,=", op->jump);
440  }
441  }
442  break;
443  case 0x2c:
444  case 0x2b:
446  break;
447  case 0x3e: // glitch 0 width instruction .. invalid instruction
448  case 0x43:
449  op->type = RZ_ANALYSIS_OP_TYPE_ILL;
450  op->size = 1;
451  op->eob = true;
453  esilprintf(op, ",");
454  }
455  break;
456  case 0x2d: // cmpl-float
457  case 0x2e: // cmpg-float
458  case 0x3f: // cmpg-float // ???? wrong disasm imho 2e0f12003f0f
459  case 0x2f: // cmpl-double
460  case 0x30: // cmlg-double
461  case 0x31: // cmp-long
462  case 0x1f: // check-cast
463  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
464  break;
465  case 0x32: // if-eq
466  case 0x33: // if-ne
467  case 0x34: // if-lt
468  case 0x35: // if-ge
469  case 0x36: // if-gt
470  case 0x37: // if-le
472  if (len > 3) {
473  int rel = (int)(data[3] << 8 | data[2]);
474  op->jump = addr + (rel * 2);
475  op->fail = addr + sz;
477  ut32 vA = data[1];
478  ut32 vB = data[2];
479  const char *cond = getCond(data[0]);
480  esilprintf(op, "v%d,v%d,==,%s,?{,%" PFMT64d ",ip,=}", vB, vA, cond, op->jump);
481  }
482  }
483  break;
484  case 0x38: // if-eqz
485  case 0x39: // if-nez
486  case 0x3a: // if-ltz
487  case 0x3b: // if-gez
488  case 0x3c: // if-gtz
489  case 0x3d: // if-lez
491  if (len > 3) {
492  int rel = (int)(data[3] << 8 | data[2]);
493  op->jump = addr + (rel * 2);
494  op->fail = addr + sz;
496  ut32 vA = data[1];
497  const char *cond = getCondz(data[0]);
498  esilprintf(op, "v%d,%s,?{,%" PFMT64d ",ip,=}", vA, cond, op->jump);
499  }
500  }
501  break;
502  case 0xec: // breakpoint
505  esilprintf(op, "TRAP");
506  }
507  break;
508  case 0x1d: // monitor-enter
510  op->stackop = RZ_ANALYSIS_STACK_INC;
511  op->stackptr = 1;
513  esilprintf(op, ",");
514  }
515  break;
516  case 0x1e: // monitor-exit /// wrong type?
517  op->type = RZ_ANALYSIS_OP_TYPE_POP;
518  op->stackop = RZ_ANALYSIS_STACK_INC;
519  op->stackptr = -1;
521  esilprintf(op, ",");
522  }
523  break;
524  case 0x73: // invalid
525  break;
526  case 0x6f: // invoke-super
527  case 0x70: // invoke-direct
528  case 0x71: // invoke-static
529  case 0x72: // invoke-interface
530  case 0x77: //
531  case 0xb9: // invokeinterface
532  case 0xb7: // invokespecial
533  case 0xb6: // invokevirtual
534  case 0x6e: // invoke-virtual
535  if (len > 3) {
536  ut32 vB = (data[3] << 8) | data[2];
537  ut64 dst = analysis->binb.get_offset(analysis->binb.bin, 'm', vB);
538  if (dst == UT64_MAX) {
540  } else {
542  op->jump = dst;
543  }
544  op->fail = addr + sz;
546  esilprintf(op, "8,sp,-=,0x%" PFMT64x ",sp,=[8],0x%" PFMT64x ",ip,=", op->fail, op->jump);
547  }
548  }
549  break;
550  case 0x78: // invokeinterface/range
551  case 0xf0: // invoke-object-init-range
552  case 0xf9: // invoke-virtual-quick/range
553  case 0xfb: // invoke-super-quick/range
554  case 0x74: // invoke-virtual/range
555  case 0x75: // invoke-super/range
556  case 0x76: // invoke-direct/range
557  case 0xfa: // invoke-super-quick // invoke-polymorphic
558  if (len > 3) {
559  ut32 vB = (data[3] << 8) | data[2];
560  ut64 dst = analysis->binb.get_offset(analysis->binb.bin, 'm', vB);
561  op->fail = addr + sz;
562  if (dst == UT64_MAX) {
564  } else {
566  op->jump = dst;
568  esilprintf(op, "8,sp,-=,0x%" PFMT64x ",sp,=[8],0x%" PFMT64x ",ip,=", op->fail, op->jump);
569  }
570  }
571  } else {
573  }
574  break;
575  case 0x27: // throw
576  {
579  ut32 vA = data[1];
580  esilprintf(op, "v%d,TRAP", vA);
581  }
582  } break;
583  case 0xee: // execute-inline
584  case 0xef: // execute-inline/range
585  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
586  break;
587  case 0xed: // throw-verification-error
589  break;
590  case 0x22: // new-instance
591  op->type = RZ_ANALYSIS_OP_TYPE_NEW;
592  if (len > 2) {
593  // resolve class name for vB
594  int vB = (data[3] << 8) | data[2];
595  ut64 off = RZ_ANALYSIS_GET_OFFSET(analysis, 't', vB);
596  op->ptr = off;
598  int vA = (int)data[1];
599  esilprintf(op, "%" PFMT64d ",new,v%d,=", off, vA);
600  }
601  }
602  break;
603  case 0x23: // new-array
604  op->type = RZ_ANALYSIS_OP_TYPE_NEW;
605  // 0x1c, 0x1f, 0x22
606  if (len > 2 && mask & RZ_ANALYSIS_OP_MASK_ESIL) {
607  ut32 vA = (data[1] & 0x0f);
608  ut32 vB = (data[1] & 0xf0) >> 4;
609  ut32 vC = (int)data[2] | (data[3] << 8);
610  esilprintf(op, "%d,%d,new-array,v%d,=", vC, vB, vA);
611  }
612  break;
613  case 0x24: // filled-new-array
614  case 0x25: // filled-new-array-range
615  case 0x26: // filled-new-array-data
616  op->type = RZ_ANALYSIS_OP_TYPE_NEW;
617  // 0x1c, 0x1f, 0x22
618  if (len > 2) {
619  // int vA = (int) data[1];
620  int vB = (data[3] << 8) | data[2];
621  // resolve class name for vB
622  ut64 off = RZ_ANALYSIS_GET_OFFSET(analysis, 't', vB);
623  op->ptr = off;
624  }
625  break;
626  case 0x00: // nop
627  op->type = RZ_ANALYSIS_OP_TYPE_NOP;
629  esilprintf(op, ",");
630  }
631  break;
632  case 0x90: // add-int
633  case 0x9b: // add-long
634  case 0xa6: // add-float
635  case 0xac: // add-double
636  case 0xb0: // add-int/2addr
637  case 0xbb: // add-long/2addr
638  case 0xc6: // add-float/2addr
639  case 0xcb: // add-double/2addr
640  case 0xd0: // add-int/lit16
641  case 0xd8: // add-int/lit8
642  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
644  ut32 vB = (data[1] & 0x0f);
645  ut32 vA = (data[1] & 0xf0) >> 4;
646  esilprintf(op, "v%d,v%d,+=", vB, vA);
647  }
648  break;
649  case 0xa7: // sub-float
650  case 0xcc: // sub-double
651  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
652  /* fall through */
653  case 0xc7:
654  case 0xbc:
655  case 0x91:
656  case 0xb1: // sub-int/2addr
657  case 0xd1: // sub-int/2addr
658  case 0x9c: // sub-long
659  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
661  esilprintf(op, "v%d,v%d,-,v%d,=", vC, vB, vA);
662  }
663  break;
664  case 0x7b: // neg-int
665  case 0x7d: // neg-long
666  case 0x7f: // neg-float
667  case 0x80: // neg-double
668  op->type = RZ_ANALYSIS_OP_TYPE_NOT;
669  break;
670  case 0xa0: // and-long
671  case 0xc0: // and-long
672  case 0xdd: // and-long
673  case 0xd5: // and-long
674  case 0xb5: // and-int
675  op->type = RZ_ANALYSIS_OP_TYPE_AND;
676  break;
677  case 0xd6: // orint/lit16
678  case 0xc1: // or-long/2addr
679  case 0xa1: // or-long
680  op->type = RZ_ANALYSIS_OP_TYPE_OR;
682  ut32 vA = (data[1] & 0x0f);
683  ut32 vB = (data[1] & 0xf0) >> 4;
684  ut32 vC = (data[2] << 8) | data[3];
685  esilprintf(op, "%d,v%d,|,v%d,=", vC, vB, vA);
686  op->val = vC;
687  }
688  break;
689  case 0xe0: // lshl
690  case 0xc3: // lshl
691  case 0xa3: // shl-long
692  case 0x98: // shl-long
693  case 0xb8: // shl-int/2addr
694  op->type = RZ_ANALYSIS_OP_TYPE_SHL;
695  break;
696  }
697 
698  if ((op->type == RZ_ANALYSIS_OP_TYPE_JMP || op->type == RZ_ANALYSIS_OP_TYPE_RET) &&
699  len > op->size && data[op->size] == 0x0d) {
700  // if the return/goto is followed by a move-exception then the analysis should keep going.
701  // this is because the function is supposed to have a try-catch
702  op->eob = false;
703  op->cond = RZ_TYPE_COND_EXCEPTION;
704  }
705 
706  return sz;
707 }
708 
709 static char *get_reg_profile(RzAnalysis *analysis) {
710  const char *p =
711  "=PC ip\n"
712  "=SP sp\n"
713  "=BP bp\n"
714  "=A0 v0\n"
715  "=A1 v1\n"
716  "=A2 v2\n"
717  "=A3 v3\n"
718  "=SN v0\n"
719  "gpr v0 .32 0 0\n"
720  "gpr v1 .32 4 0\n"
721  "gpr v2 .32 8 0\n"
722  "gpr v3 .32 12 0\n"
723  "gpr v4 .32 16 0\n"
724  "gpr v5 .32 20 0\n"
725  "gpr v6 .32 24 0\n"
726  "gpr v7 .32 28 0\n"
727  "gpr v8 .32 32 0\n"
728  "gpr v9 .32 36 0\n"
729  "gpr v10 .32 40 0\n"
730  "gpr v11 .32 44 0\n"
731  "gpr v12 .32 48 0\n"
732  "gpr v13 .32 52 0\n"
733  "gpr v14 .32 56 0\n"
734  "gpr v15 .32 60 0\n"
735  "gpr v16 .32 40 0\n"
736  "gpr v17 .32 44 0\n"
737  "gpr v18 .32 48 0\n"
738  "gpr v19 .32 52 0\n"
739  "gpr v20 .32 56 0\n"
740  "gpr v21 .32 60 0\n"
741  "gpr v22 .32 64 0\n"
742  "gpr v23 .32 68 0\n"
743  "gpr v24 .32 72 0\n"
744  "gpr v25 .32 76 0\n"
745  "gpr v26 .32 80 0\n"
746  "gpr v27 .32 84 0\n"
747  "gpr v28 .32 88 0\n"
748  "gpr v29 .32 92 0\n"
749  "gpr v30 .32 96 0\n"
750  "gpr v31 .32 100 0\n"
751  "gpr v32 .32 104 0\n"
752  "gpr v33 .32 108 0\n"
753  "gpr v34 .32 112 0\n"
754  "gpr ip .32 116 0\n"
755  "gpr sp .32 120 0\n"
756  "gpr bp .32 124 0\n";
757  return strdup(p);
758 }
759 
761  .name = "dalvik",
762  .arch = "dalvik",
763  .get_reg_profile = &get_reg_profile,
764  .license = "LGPL3",
765  .bits = 32,
766  .esil = false,
767  .desc = "Dalvik (Android VM) bytecode analysis plugin",
768  .op = &dalvik_op,
769 };
770 
771 #ifndef RZ_PLUGIN_INCORE
774  .data = &rz_analysis_plugin_dalvik,
776 };
777 #endif
size_t len
Definition: 6502dis.c:15
static const char * getCondz(ut8 cond)
static char * get_reg_profile(RzAnalysis *analysis)
RzAnalysisPlugin rz_analysis_plugin_dalvik
static int dalvik_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
static const char * getCond(ut8 cond)
RZ_API RzLibStruct rizin_plugin
#define mask()
ut16 val
Definition: armass64_const.h:6
#define RZ_API
static const struct dalvik_opcodes_t dalvik_opcodes[256]
Definition: opcode.h:52
uint32_t ut32
voidpf uLong offset
Definition: ioapi.h:144
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
char * dst
Definition: lz4.h:724
int off
Definition: pal.c:13
#define esilprintf(op, fmt,...)
Definition: rz_analysis.h:29
@ RZ_ANALYSIS_STACK_INC
Definition: rz_analysis.h:457
@ RZ_ANALYSIS_OP_FAMILY_FPU
Definition: rz_analysis.h:313
#define RZ_ANALYSIS_GET_OFFSET(x, y, z)
Definition: rz_analysis.h:105
@ RZ_ANALYSIS_DATATYPE_STRING
Definition: rz_analysis.h:800
@ RZ_ANALYSIS_DATATYPE_ARRAY
Definition: rz_analysis.h:798
@ RZ_ANALYSIS_DATATYPE_CLASS
Definition: rz_analysis.h:801
@ RZ_ANALYSIS_DATATYPE_BOOLEAN
Definition: rz_analysis.h:802
@ RZ_ANALYSIS_DATATYPE_OBJECT
Definition: rz_analysis.h:799
RzAnalysisOpMask
Definition: rz_analysis.h:439
@ RZ_ANALYSIS_OP_MASK_DISASM
Definition: rz_analysis.h:445
@ RZ_ANALYSIS_OP_MASK_ESIL
Definition: rz_analysis.h:441
@ RZ_ANALYSIS_OP_TYPE_CMP
Definition: rz_analysis.h:399
@ RZ_ANALYSIS_OP_TYPE_SUB
Definition: rz_analysis.h:402
@ RZ_ANALYSIS_OP_TYPE_LOAD
Definition: rz_analysis.h:416
@ RZ_ANALYSIS_OP_TYPE_MUL
Definition: rz_analysis.h:404
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_ANALYSIS_OP_TYPE_AND
Definition: rz_analysis.h:411
@ RZ_ANALYSIS_OP_TYPE_MOD
Definition: rz_analysis.h:422
@ RZ_ANALYSIS_OP_TYPE_SWI
Definition: rz_analysis.h:393
@ RZ_ANALYSIS_OP_TYPE_TRAP
Definition: rz_analysis.h:392
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_ADD
Definition: rz_analysis.h:401
@ RZ_ANALYSIS_OP_TYPE_SWITCH
Definition: rz_analysis.h:423
@ RZ_ANALYSIS_OP_TYPE_OR
Definition: rz_analysis.h:410
@ RZ_ANALYSIS_OP_TYPE_STORE
Definition: rz_analysis.h:415
@ RZ_ANALYSIS_OP_TYPE_PUSH
Definition: rz_analysis.h:397
@ RZ_ANALYSIS_OP_TYPE_SHR
Definition: rz_analysis.h:406
@ RZ_ANALYSIS_OP_TYPE_POP
Definition: rz_analysis.h:398
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_ANALYSIS_OP_TYPE_DIV
Definition: rz_analysis.h:405
@ RZ_ANALYSIS_OP_TYPE_CAST
Definition: rz_analysis.h:426
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_SHL
Definition: rz_analysis.h:407
@ RZ_ANALYSIS_OP_TYPE_ILL
Definition: rz_analysis.h:387
@ RZ_ANALYSIS_OP_TYPE_UCALL
Definition: rz_analysis.h:379
@ RZ_ANALYSIS_OP_TYPE_NOT
Definition: rz_analysis.h:414
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
@ RZ_ANALYSIS_OP_TYPE_NOP
Definition: rz_analysis.h:389
@ RZ_ANALYSIS_OP_TYPE_XOR
Definition: rz_analysis.h:412
@ RZ_ANALYSIS_OP_TYPE_NEW
Definition: rz_analysis.h:427
@ RZ_ANALYSIS_OP_TYPE_LENGTH
Definition: rz_analysis.h:425
#define rz_warn_if_reached()
Definition: rz_assert.h:29
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
@ RZ_TYPE_COND_EXCEPTION
Definition: rz_type.h:203
#define PFMT64d
Definition: rz_types.h:394
#define PFMT64x
Definition: rz_types.h:393
#define UT64_MAX
Definition: rz_types_base.h:86
#define st32
Definition: rz_types_base.h:12
#define RZ_VERSION
Definition: rz_version.h:8
static int
Definition: sfsocketcall.h:114
#define cond(bop, top, mask, flags)
const char * version
Definition: rz_analysis.h:1239
RzBinBind binb
Definition: rz_analysis.h:579
RzBin * bin
Definition: rz_bin.h:807
RzBinGetOffset get_offset
Definition: rz_bin.h:808
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58