Rizin
unix-like reverse engineering framework and cli tools
analysis_arm_hacks.inc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2018 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "rz_analysis.h"
5 
6 static int hack_handle_dp_reg(ut32 insn, RzAnalysisOp *op) {
7  const bool op0 = (insn >> 30) & 0x1;
8  const bool op1 = (insn >> 28) & 0x1;
9  const ut8 op2 = (insn >> 21) & 0xf;
10 
11  // Data-processing (2 source)
12  if (!op0 && op1 && op2 == 6) {
13  const bool sf = (insn >> 31) & 0x1;
14  const bool S = (insn >> 29) & 0x1;
15  const ut8 opcode = (insn >> 10) & 0x1f;
16  if (sf) {
17  if (!S) {
18  if (opcode == 4) {
19  // irg
21  return op->size = 4;
22  } else if (opcode == 0) {
23  // subp
25  return op->size = 4;
26  } else if (opcode == 5) {
27  // gmi
29  return op->size = 4;
30  }
31  } else if (S && opcode == 0) {
32  // subps
34  return op->size = 4;
35  }
36  }
37  }
38  return -1;
39 }
40 
41 static int hack_handle_ldst(ut32 insn, RzAnalysisOp *op) {
42  const ut8 op0 = (insn >> 28) & 0xf;
43  const bool op1 = (insn >> 26) & 0x1;
44  ut8 op2 = (insn >> 23) & 0x3;
45  const bool op3 = (insn >> 21) & 0x1;
46 
47  // Load/store memory tags
48  if (op0 == 13 && !op1 && (op2 == 2 || op2 == 3) && op3) {
49  const ut8 opc = (insn >> 22) & 0x3;
50  op2 = (insn >> 10) & 0x3;
51  if (op2 > 0) {
52  switch (opc) {
53  case 0:
54  // stg
56  return op->size = 4;
57  case 1:
58  // stzg
60  return op->size = 4;
61  case 2:
62  // st2g
64  return op->size = 4;
65  case 3:
66  // stz2g
68  return op->size = 4;
69  }
70  } else if (op2 == 0) {
71  switch (opc) {
72  case 0:
73  // stzgm
75  return op->size = 4;
76  case 1:
77  // ldg
79  return op->size = 4;
80  case 2:
81  // stgm
83  return op->size = 4;
84  case 3:
85  // ldgm
87  return op->size = 4;
88  }
89  }
90  // Load/store register pair
91  } else if ((op0 & 0x3) == 2) {
92  const ut8 opc = (insn >> 30) & 0x3;
93  const bool V = (insn >> 26) & 0x1;
94  const bool L = (insn >> 22) & 0x1;
95  if (opc == 1 && !V && !L) {
96  // stgp
98  return op->size = 4;
99  }
100  }
101  return -1;
102 }
103 
104 static int hack_handle_dp_imm(ut32 insn, RzAnalysisOp *op) {
105  const ut8 op0 = (insn >> 23) & 0x7;
106 
107  // Add/subtract (immediate, with tags)
108  if (op0 == 3) {
109  const bool sf = (insn >> 31) & 0x1;
110  const bool op_ = (insn >> 30) & 0x1;
111  const bool S = (insn >> 29) & 0x1;
112  const bool o2 = (insn >> 22) & 0x1;
113  if (sf && !S && !o2) {
114  if (op_) {
115  // subg
116  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
117  return op->size = 4;
118  }
119  // addg
120  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
121  return op->size = 4;
122  }
123  }
124  return -1;
125 }
126 
127 static int hack_handle_br_exc_sys(ut32 insn, RzAnalysisOp *op) {
128  const ut8 op0 = (insn >> 29) & 0x7;
129  const ut16 op1 = (insn >> 12) & 0x3fff;
130  ut8 op2 = insn & 0x1f;
131 
132  // Hints
133  if (op0 == 6 && op1 == 4146 && op2 == 31) {
134  const ut8 CRm = (insn >> 8) & 0xf;
135  op2 = (insn >> 5) & 0x7;
136  if (CRm == 4 && (op2 & 1) == 0) {
137  switch (op2) {
138  case 0:
139  case 2:
140  case 4:
141  case 6:
142  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
143  return op->size = 4;
144  }
145  }
146  }
147  return -1;
148 }
149 
150 static inline int hackyArmAnal(RzAnalysis *a, RzAnalysisOp *op, const ut8 *buf, int len) {
151  int ret = -1;
152  // Hacky support for ARMv8.3 and ARMv8.5
153  if (a->bits == 64 && len >= 4) {
154  ut32 insn = rz_read_ble32(buf, a->big_endian);
155  int insn_class = (insn >> 25) & 0xf;
156  // xpaci // e#43c1da
157  if (!memcmp(buf + 1, "\x43\xc1\xda", 3)) {
158  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
159  return op->size = 4;
160  }
161  // retaa
162  if (!memcmp(buf, "\xff\x0b\x5f\xd6", 4)) {
163  op->type = RZ_ANALYSIS_OP_TYPE_RET;
164  return op->size = 4;
165  }
166  // retab
167  if (!memcmp(buf, "\xff\x0f\x5f\xd6", 4)) {
168  op->type = RZ_ANALYSIS_OP_TYPE_RET;
169  return op->size = 4;
170  }
171 
172  switch (insn_class) {
173  // Data Processing -- Register
174  case 5:
175  case 13:
176  // irg, subp, gmi, subps
177  ret = hack_handle_dp_reg(insn, op);
178  break;
179  // Data Processing -- Immediate
180  case 8:
181  case 9:
182  // addg, subg
183  ret = hack_handle_dp_imm(insn, op);
184  break;
185  case 10:
186  case 11:
187  // bti
188  ret = hack_handle_br_exc_sys(insn, op);
189  break;
190  // Loads and Stores
191  case 4:
192  case 6:
193  case 12:
194  case 14:
195  // stg, stzgm, ldg, stzg, st2g, stgm, stz2g, ldgm, stgp
196  ret = hack_handle_ldst(insn, op);
197  break;
198  default:
199  break;
200  }
201 
202  if (ret > 0) {
204  }
205  }
206  return ret;
207 }
size_t len
Definition: 6502dis.c:15
uint16_t ut16
uint32_t ut32
static ut64 opc
Definition: desil.c:33
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
@ RZ_ANALYSIS_OP_FAMILY_SECURITY
Definition: rz_analysis.h:320
@ 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_ADD
Definition: rz_analysis.h:401
@ RZ_ANALYSIS_OP_TYPE_STORE
Definition: rz_analysis.h:415
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
static ut32 rz_read_ble32(const void *src, bool big_endian)
Definition: rz_endian.h:497
#define a(i)
Definition: sha256.c:41
#define V(handle, symbol)
Definition: dis.c:32
#define L
Definition: zip_err_str.c:7
#define S
Definition: zip_err_str.c:9