Rizin
unix-like reverse engineering framework and cli tools
emit_arm.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2010-2011 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_egg.h>
5 #define attsyntax 0
6 
7 #define EMIT_NAME emit_arm
8 #define RZ_ARCH "arm"
9 #define RZ_SZ 8
10 #define RZ_SP "sp"
11 #define RZ_BP "fp"
12 #define RZ_AX "r7"
13 #define RZ_GP \
14  { "r0", "r1", "r2", "r3", "r4" }
15 #define RZ_TMP "r9"
16 #define RZ_NGP 5
17 
18 // no attsyntax for arm
19 static char *regs[] = RZ_GP;
20 static int lastarg = 0;
21 static char lastargs[16][32];
22 
23 static void emit_init(RzEgg *egg) {
24  /* TODO */
25 }
26 
27 static char *emit_syscall(RzEgg *egg, int num) {
28  int svc = 0;
29  switch (egg->os) {
30  case RZ_EGG_OS_DARWIN:
31  case RZ_EGG_OS_OSX:
32  case RZ_EGG_OS_IOS:
33  case RZ_EGG_OS_MACOS:
34  svc = 0x80;
35  break;
36  case RZ_EGG_OS_WATCHOS:
37  svc = 0x8000;
38  break;
39  case RZ_EGG_OS_LINUX:
40  svc = 0;
41  break;
42  }
43  return rz_str_newf(": mov " RZ_AX ", `.arg`\n: svc 0x%x\n", svc);
44 }
45 
46 static void emit_frame(RzEgg *egg, int sz) {
47  rz_egg_printf(egg, " push {fp,lr}\n");
48  if (sz > 0) {
49  rz_egg_printf(egg,
50  // " mov "RZ_BP", "RZ_SP"\n"
51  " add fp, sp, $4\n" // size of arguments
52  " sub sp, %d\n",
53  sz); // size of stackframe 8, 16, ..
54  }
55 }
56 
57 static void emit_frame_end(RzEgg *egg, int sz, int ctx) {
58  if (sz > 0) {
59  rz_egg_printf(egg, " add sp, fp, %d\n", sz);
60  }
61  if (ctx > 0) {
62  rz_egg_printf(egg, " pop {fp,pc}\n");
63  }
64 }
65 
66 static void emit_comment(RzEgg *egg, const char *fmt, ...) {
67  va_list ap;
68  char buf[1024];
69  va_start(ap, fmt);
70  vsnprintf(buf, sizeof(buf), fmt, ap);
71  rz_egg_printf(egg, "# %s\n", buf);
72  va_end(ap);
73 }
74 
75 static void emit_equ(RzEgg *egg, const char *key, const char *value) {
76  rz_egg_printf(egg, ".equ %s, %s\n", key, value);
77 }
78 
79 static void emit_syscall_args(RzEgg *egg, int nargs) {
80  int j, k;
81  for (j = 0; j < nargs; j++) {
82  k = j * RZ_SZ;
83  rz_egg_printf(egg, " ldr %s, [sp, %d]\n",
84  regs[j + 1], k ? k + 4 : k + 8);
85  }
86 }
87 
88 static void emit_set_string(RzEgg *egg, const char *dstvar, const char *str, int j) {
89  int rest, off = 0;
90  off = strlen(str) + 1;
91  rest = (off % 4);
92  if (rest) {
93  rest = 4 - rest;
94  }
95  off += rest - 4;
96  rz_egg_printf(egg, " add pc, %d\n", (off));
97  // XXX: does not handle \n and so on.. must use rz_util
98  // use rz_str_escape to handle \n
99  // do not forget mem leak
100  rz_egg_printf(egg, ".string \"%s\"\n", str = rz_str_escape(str));
101  free((char *)str);
102  if (rest) {
103  rz_egg_printf(egg, ".fill %d, 1, 0\n", (rest));
104  }
105  rz_egg_printf(egg, " sub r0, pc, %d\n", off + 12);
106  {
107  char str[32], *p = rz_egg_mkvar(egg, str, dstvar, 0);
108  // rz_egg_printf (egg, "DSTVAR=%s --> %s\n", dstvar, p);
109  rz_egg_printf(egg, " str r0, [%s]\n", p);
110  free(p);
111  }
112 }
113 
114 static void emit_jmp(RzEgg *egg, const char *str, int atr) {
115  if (atr) {
116  rz_egg_printf(egg, " ldr r0, %s", str);
117  rz_egg_printf(egg, " bx r0\n");
118  } else {
119  rz_egg_printf(egg, " b %s\n", str);
120  }
121 }
122 
123 static void emit_call(RzEgg *egg, const char *str, int atr) {
124  int i;
125  // rz_egg_printf (egg, " ARGS=%d CALL(%s,%d)\n", lastarg, str, atr);
126  for (i = 0; i < lastarg; i++) {
127  rz_egg_printf(egg, " ldr r%d, [%s]\n", lastarg - 1 - i, lastargs[i]);
128  lastargs[i][0] = 0;
129  }
130 
131  if (atr) {
132  rz_egg_printf(egg, " ldr r0, %s", str);
133  rz_egg_printf(egg, " blx r0\n");
134  } else {
135  rz_egg_printf(egg, " bl %s\n", str);
136  }
137 }
138 
139 static void emit_arg(RzEgg *egg, int xs, int num, const char *str) {
140  int d = atoi(str);
141  if (!attsyntax && (*str == '$')) {
142  str++;
143  }
144  lastarg = num;
145  switch (xs) {
146  case 0:
147  if (strchr(str, ',')) {
148  // rz_egg_printf (egg, ". str r0, [%s]\n", str);
149  strncpy(lastargs[num - 1], str, sizeof(lastargs[0]) - 1);
150  } else {
151  if (!atoi(str)) {
152  eprintf("WARNING: probably a bug?\n");
153  }
154  rz_egg_printf(egg, " mov r0, %s\n", str);
155  snprintf(lastargs[num - 1], sizeof(lastargs[0]), "sp, %d", 8 + (num * 4));
156  rz_egg_printf(egg, " str r0, [%s]\n", lastargs[num - 1]);
157  }
158  break;
159  case '*':
160  rz_egg_printf(egg, " push {%s}\n", str);
161  break;
162  case '&':
163  if (d) {
164  rz_egg_printf(egg, " add " RZ_BP ", %d\n", d);
165  }
166  rz_egg_printf(egg, " push {" RZ_BP "}\n");
167  if (d) {
168  rz_egg_printf(egg, " sub " RZ_BP ", %d\n", d);
169  }
170  break;
171  }
172 }
173 
174 static void emit_get_result(RzEgg *egg, const char *ocn) {
175  rz_egg_printf(egg, " mov %s, r0\n", ocn);
176 }
177 
178 static void emit_restore_stack(RzEgg *egg, int size) {
179  // XXX: must die.. or add emit_store_stack. not needed by ARM
180  // rz_egg_printf (egg, " add sp, %d\n", size);
181 }
182 
183 static void emit_get_while_end(RzEgg *egg, char *str, const char *ctxpush, const char *label) {
184  sprintf(str, " push {%s}\n b %s\n", ctxpush, label);
185 }
186 
187 static void emit_while_end(RzEgg *egg, const char *labelback) {
188  rz_egg_printf(egg,
189  " pop " RZ_AX "\n"
190  " cmp " RZ_AX ", " RZ_AX "\n" // XXX MUST SUPPORT != 0 COMPARE HERE
191  " beq %s\n",
192  labelback);
193 }
194 
195 static void emit_get_var(RzEgg *egg, int type, char *out, int idx) {
196  switch (type) {
197  case 0: sprintf(out, "sp, %d", idx - 1); break; /* variable */
198  case 1:
199  sprintf(out, "r%d", idx);
200  break; /* registers */
201  // sp,$%d", idx); break; /* argument */ // XXX: MUST BE r0, r1, r2, ..
202  }
203 }
204 
205 static void emit_trap(RzEgg *egg) {
206  rz_egg_printf(egg, " udf 16\n");
207 }
208 
209 static void emit_load_ptr(RzEgg *egg, const char *dst) {
210  rz_egg_printf(egg, " ldr r0, [fp, %d]\n", atoi(dst));
211 }
212 
213 static void emit_branch(RzEgg *egg, char *b, char *g, char *e, char *n, int sz, const char *dst) {
214  char *p, str[64];
215  char *arg = NULL;
216  char *op = "beq";
217  /* NOTE that jb/ja are inverted to fit cmp opcode */
218  if (b) {
219  *b = '\0';
220  op = e ? "bge" : "bgt";
221  arg = b + 1;
222  } else if (g) {
223  *g = '\0';
224  op = e ? "ble" : "blt";
225  arg = g + 1;
226  }
227  if (!arg) {
228  if (e) {
229  arg = e + 1;
230  op = "bne";
231  } else {
232  arg = "0";
233  op = n ? "bne" : "beq";
234  }
235  }
236 
237  if (*arg == '=') {
238  arg++; /* for <=, >=, ... */
239  }
240  p = rz_egg_mkvar(egg, str, arg, 0);
241  rz_egg_printf(egg, " pop " RZ_AX "\n"); /* TODO: add support for more than one arg get arg0 */
242  rz_egg_printf(egg, " cmp %s, " RZ_AX "\n", p);
243  // if (context>0)
244  rz_egg_printf(egg, " %s %s\n", op, dst);
245  free(p);
246 }
247 
248 static void emit_load(RzEgg *egg, const char *dst, int sz) {
249  switch (sz) {
250  case 'l':
251  rz_egg_printf(egg, " mov " RZ_AX ", %s\n", dst);
252  rz_egg_printf(egg, " mov " RZ_AX ", [" RZ_AX "]\n");
253  break;
254  case 'b':
255  rz_egg_printf(egg, " mov " RZ_AX ", %s\n", dst);
256  rz_egg_printf(egg, " movz " RZ_AX ", [" RZ_AX "]\n");
257  break;
258  default:
259  // TODO: unhandled?!?
260  rz_egg_printf(egg, " mov " RZ_AX ", %s\n", dst);
261  rz_egg_printf(egg, " mov " RZ_AX ", [" RZ_AX "]\n");
262  }
263 }
264 
265 static void emit_mathop(RzEgg *egg, int ch, int vs, int type, const char *eq, const char *p) {
266  char *op;
267  switch (ch) {
268  case '^': op = "eor"; break;
269  case '&': op = "and"; break;
270  case '|': op = "orr"; break;
271  case '-': op = "sub"; break;
272  case '+': op = "add"; break;
273  case '*': op = "mul"; break;
274  case '/': op = "div"; break;
275  default: op = "mov"; break;
276  }
277  if (!eq) {
278  eq = RZ_AX;
279  }
280  if (!p) {
281  p = RZ_AX;
282  }
283 #if 0
284  // TODO:
285  eprintf ("TYPE = %c\n", type);
286  eprintf (" %s%c %c%s, %s\n", op, vs, type, eq, p);
287  eprintf (" %s %s, [%s]\n", op, p, eq);
288 #endif
289  if (type == '*') {
290  rz_egg_printf(egg, " %s %s, [%s]\n", op, p, eq);
291  } else {
292  rz_egg_printf(egg, " %s %s, %s\n", op, p, eq);
293  }
294 }
295 
296 static const char *emit_regs(RzEgg *egg, int idx) {
297  return regs[idx % RZ_NGP];
298 }
299 
301  .arch = RZ_ARCH,
302  .size = RZ_SZ,
303  .jmp = emit_jmp,
304  .call = emit_call,
305  .init = emit_init,
306  .equ = emit_equ,
307  .regs = emit_regs,
308  // .sc = emit_sc,
309  .trap = emit_trap,
310  .frame = emit_frame,
311  .frame_end = emit_frame_end,
312  .comment = emit_comment,
313  .push_arg = emit_arg,
314  .restore_stack = emit_restore_stack,
315  .get_result = emit_get_result,
316  .syscall_args = emit_syscall_args,
317  .set_string = emit_set_string,
318  .get_var = emit_get_var,
319  .while_end = emit_while_end,
320  .get_while_end = emit_get_while_end,
321  .branch = emit_branch,
322  .load = emit_load,
323  .load_ptr = emit_load_ptr,
324  .mathop = emit_mathop,
325  .syscall = emit_syscall,
326 };
ut8 op
Definition: 6502dis.c:13
#define e(frag)
lzma_index ** i
Definition: index.h:629
static RzILOpEffect * svc(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1134
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static int value
Definition: cmd_api.c:93
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
const char * k
Definition: dsignal.c:11
RZ_API void rz_egg_printf(RzEgg *egg, const char *fmt,...)
Definition: egg.c:336
RZ_API char * rz_egg_mkvar(RzEgg *egg, char *out, const char *_str, int delta)
Definition: egg_lang.c:538
static void emit_comment(RzEgg *egg, const char *fmt,...)
Definition: emit_arm.c:66
#define attsyntax
Definition: emit_arm.c:5
static void emit_branch(RzEgg *egg, char *b, char *g, char *e, char *n, int sz, const char *dst)
Definition: emit_arm.c:213
static void emit_jmp(RzEgg *egg, const char *str, int atr)
Definition: emit_arm.c:114
#define EMIT_NAME
Definition: emit_arm.c:7
static void emit_call(RzEgg *egg, const char *str, int atr)
Definition: emit_arm.c:123
#define RZ_AX
Definition: emit_arm.c:12
#define RZ_ARCH
Definition: emit_arm.c:8
#define RZ_SZ
Definition: emit_arm.c:9
static char lastargs[16][32]
Definition: emit_arm.c:21
static void emit_init(RzEgg *egg)
Definition: emit_arm.c:23
static char * regs[]
Definition: emit_arm.c:19
static char * emit_syscall(RzEgg *egg, int num)
Definition: emit_arm.c:27
static void emit_frame_end(RzEgg *egg, int sz, int ctx)
Definition: emit_arm.c:57
static void emit_get_while_end(RzEgg *egg, char *str, const char *ctxpush, const char *label)
Definition: emit_arm.c:183
static void emit_trap(RzEgg *egg)
Definition: emit_arm.c:205
static void emit_restore_stack(RzEgg *egg, int size)
Definition: emit_arm.c:178
static void emit_while_end(RzEgg *egg, const char *labelback)
Definition: emit_arm.c:187
#define RZ_BP
Definition: emit_arm.c:11
static void emit_get_var(RzEgg *egg, int type, char *out, int idx)
Definition: emit_arm.c:195
static int lastarg
Definition: emit_arm.c:20
static void emit_load(RzEgg *egg, const char *dst, int sz)
Definition: emit_arm.c:248
#define RZ_GP
Definition: emit_arm.c:13
#define RZ_NGP
Definition: emit_arm.c:16
static const char * emit_regs(RzEgg *egg, int idx)
Definition: emit_arm.c:296
static void emit_arg(RzEgg *egg, int xs, int num, const char *str)
Definition: emit_arm.c:139
static void emit_mathop(RzEgg *egg, int ch, int vs, int type, const char *eq, const char *p)
Definition: emit_arm.c:265
static void emit_syscall_args(RzEgg *egg, int nargs)
Definition: emit_arm.c:79
static void emit_get_result(RzEgg *egg, const char *ocn)
Definition: emit_arm.c:174
static void emit_set_string(RzEgg *egg, const char *dstvar, const char *str, int j)
Definition: emit_arm.c:88
static void emit_frame(RzEgg *egg, int sz)
Definition: emit_arm.c:46
static void emit_load_ptr(RzEgg *egg, const char *dst)
Definition: emit_arm.c:209
static void emit_equ(RzEgg *egg, const char *key, const char *value)
Definition: emit_arm.c:75
struct @667 g
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
sprintf
Definition: kernel.h:365
vsnprintf
Definition: kernel.h:366
void * p
Definition: libc.cpp:67
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
char * dst
Definition: lz4.h:724
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
int off
Definition: pal.c:13
#define eprintf(x, y...)
Definition: rlcc.c:7
#define RZ_EGG_OS_IOS
Definition: rz_egg.h:131
#define RZ_EGG_OS_WATCHOS
Definition: rz_egg.h:130
#define RZ_EGG_OS_DARWIN
Definition: rz_egg.h:129
#define RZ_EGG_OS_MACOS
Definition: rz_egg.h:132
#define RZ_EGG_OS_OSX
Definition: rz_egg.h:128
#define RZ_EGG_OS_LINUX
Definition: rz_egg.h:127
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API RZ_OWN char * rz_str_escape(RZ_NONNULL const char *buf)
Definition: str.c:1550
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
Definition: dis.h:35
ut32 os
Definition: rz_egg.h:109
Definition: dis.c:32