Rizin
unix-like reverse engineering framework and cli tools
dis.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2007 sorbo
2 // SPDX-FileCopyrightText: 2010-2019 pancake <pancake@nopcode.org>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <fcntl.h>
8 #include <string.h>
9 #include <stdarg.h>
10 #include <stdint.h>
11 #include "dis.h"
12 
13 static struct state _state;
14 
15 #include <rz_types.h>
16 #include <rz_util/rz_assert.h>
17 
18 static inline struct state *get_state(void) {
19  memset(&_state, 0, sizeof(struct state));
20  return &_state;
21 }
22 
23 static uint16_t i2u16(struct instruction *in) {
24  return *((uint16_t *)in);
25 }
26 
27 #if 0
28 static void output(struct state *s, char *fmt, ...)
29 {
30  va_list ap;
31 
32  va_start(ap, fmt);
33  cons_printf(fmt, ap);
34  //vfprintf(s->s_out, fmt, ap);
35  va_end(ap);
36 }
37 #endif
38 
39 static void decode_unknown(struct state *s, struct directive *d) {
40 #if 0
41  printf("Opcode 0x%x reg %d mode %d operand 0x%x",
42  in->in_opcode, in->in_reg, in->in_mode, in->in_operand);
43 #endif
44  sprintf(d->d_asm, "DC 0x%4x", i2u16(&d->d_inst));
45 }
46 
47 static int decode_fixed(struct state *s, struct directive *d) {
48  *d->d_asm = '\0';
49  switch (i2u16(&d->d_inst)) {
50  case INST_NOP:
51  if (s->s_prefix) {
52  return 0;
53  }
54  s->s_nop++;
55  strcpy(d->d_asm, "nop");
56  break;
57  case INST_BRK: strcpy(d->d_asm, "brk"); break;
58  case INST_SLEEP: strcpy(d->d_asm, "sleep"); break;
59  case INST_SIF: strcpy(d->d_asm, "sif"); break;
60  case INST_BC: strcpy(d->d_asm, "bc"); break;
61  case INST_BRXL: strcpy(d->d_asm, "brxl"); break;
62  case INST_U:
63  strcpy(d->d_asm, "");
64  s->s_u = 1;
65  break;
66  case INST_RTS: strcpy(d->d_asm, "rts"); break;
67  }
68  return d->d_asm[0] != 0;
69 }
70 
71 static char *regname(int reg) {
72  switch (reg) {
73  case REG_AH: return "AH";
74  case REG_AL: return "AL";
75  case REG_X: return "X";
76  case REG_Y: return "Y";
77  }
78  return NULL;
79 }
80 
81 static int get_num(int num, int shift) {
82  char x = (char)((num >> shift) & 0xff);
83  return (int)(x << shift);
84 }
85 
86 static int get_operand(struct state *s, struct directive *d) {
87  int total = get_num(d->d_inst.in_operand, 0);
88  if (s->s_prefix)
89  total += get_num(s->s_prefix_val, 8);
90  if (s->s_prefix == 2)
91  total += get_num(s->s_prefix_val, 16);
92  return total;
93 }
94 
95 static int decode_known(struct state *s, struct directive *d) {
96  char *op = NULL;
97  char *regn = NULL;
98  int reg = 0;
99  int ptr = 1;
100  int idx = 1;
101  int imm = 0;
102  int rel = 0;
103  char fmt[16];
104  char tmp[128];
105  int fmtsz;
106  int branch = 0;
107  struct instruction *in = &d->d_inst;
108  // int operand;
109  char *sign = "";
110  int rti = 0;
111 
112  switch (in->in_opcode) {
113  case 0:
114  if (in->in_reg == 0 && in->in_mode == 0) {
115  if (s->s_prefix == 0)
116  s->s_prefix_val = 0;
117  s->s_prefix++;
118 
119  if (s->s_prefix == 2)
120  s->s_prefix_val <<= 8;
121 #if 0
122  /* XXX we need to look ahead more to see if we're
123  * getting a branch instruction */
124  if (s->s_nopd && in->in_operand == 0x80)
125  strcpy(s->s_nopd->d_asm, "");
126 #endif
127  s->s_prefix_val |= in->in_operand << 8;
128 
129  strcpy(d->d_asm, "");
130  return 1;
131  }
132 
133  switch (i2u16(in) & 0xf) {
134  case 1:
135  op = "st";
136  regn = "FLAGS";
137  break;
138  case 2:
139  op = "st";
140  regn = "UX";
141  break;
142  case 3:
143  op = "st";
144  regn = "UY";
145  break;
146  case 5:
147  op = "ld";
148  regn = "FLAGS";
149  break;
150  case 6:
151  op = "ld";
152  regn = "UX";
153  break;
154  case 7:
155  op = "ld";
156  regn = "UY";
157  break;
158  case 0xa:
159  op = "st";
160  regn = "XH";
161  break;
162  case 0xd:
163  op = "rti";
164  regn = "";
165  rti = 1;
166  break;
167  case 0xe:
168  op = "ld";
169  regn = "XH";
170  break;
171  }
172  break;
173 
174  case 1:
175  op = "ld";
176  reg = 1;
177  ptr = 1;
178  idx = 1;
179  imm = 1;
180  break;
181  case 2:
182  if (in->in_mode == DATA_MODE_IMMEDIATE) {
183  op = "print";
184  imm = 1;
185  reg = 1;
186  } else {
187  op = "st";
188  reg = 1;
189  ptr = 1;
190  idx = 1;
191  }
192  break;
193  case 3:
194  op = "add";
195  reg = 1;
196  ptr = 1;
197  idx = 1;
198  imm = 1;
199  break;
200  case 4:
201  op = "addc";
202  reg = 1;
203  ptr = 1;
204  idx = 1;
205  imm = 1;
206  break;
207  case 5:
208  op = "sub";
209  reg = 1;
210  ptr = 1;
211  idx = 1;
212  imm = 1;
213  break;
214  case 6:
215  op = "subc";
216  reg = 1;
217  ptr = 1;
218  idx = 1;
219  imm = 1;
220  break;
221  case 7:
222  op = "nadd";
223  reg = 1;
224  ptr = 1;
225  idx = 1;
226  imm = 1;
227  break;
228  case 8:
229  op = "cmp";
230  reg = 1;
231  ptr = 1;
232  idx = 1;
233  imm = 1;
234  break;
235  case 0x9:
236  switch (in->in_reg) {
237  case 0:
238  if (s->s_u)
239  op = "umult";
240  else
241  op = "smult";
242  imm = 1;
243  s->s_u = 0;
244  idx = 1;
245  ptr = 1;
246  break;
247  case 1:
248  if (s->s_u)
249  op = "udiv";
250  else
251  op = "sdiv";
252  s->s_u = 0;
253  imm = 1;
254  break;
255  case 2:
256  op = "tst";
257  imm = 1;
258  ptr = 1;
259  idx = 1;
260  break;
261  case 3:
262  branch = 1;
263  op = "bsr";
264  ptr = 1;
265  idx = 1;
266  if (in->in_mode == ADDR_MODE_RELATIVE)
267  rel = 1;
268  break;
269  }
270  break;
271  case 0xa:
272  switch (in->in_reg) {
273  case 0:
274  op = "asl";
275  imm = 1;
276  break;
277  case 1:
278  if (s->s_u)
279  op = "lsr";
280  else
281  op = "asr";
282  s->s_u = 0;
283  imm = 1;
284  idx = 1;
285  ptr = 1;
286  break;
287  case 2:
288  op = "rol";
289  imm = 1;
290  break;
291  case 3:
292  op = "ror";
293  imm = 1;
294  break;
295  }
296  break;
297 
298  case 0xb:
299  op = "or";
300  reg = 1;
301  ptr = 1;
302  idx = 1;
303  imm = 1;
304  break;
305  case 0xc:
306  op = "and";
307  reg = 1;
308  ptr = 1;
309  idx = 1;
310  imm = 1;
311  break;
312  case 0xd:
313  op = "xor";
314  reg = 1;
315  ptr = 1;
316  idx = 1;
317  imm = 1;
318  break;
319  case 0xe:
320  branch = 1;
321  if (in->in_mode == ADDR_MODE_RELATIVE)
322  rel = 1;
323  switch (in->in_reg) {
324  case 0:
325  op = "bra";
326  ptr = 1;
327  idx = 1;
328 #if 0
329  if (s->s_nopd) {
330  op = "bra2"; /* XXX need bra3 support */
331  strcpy(s->s_nopd->d_asm, "");
332  }
333 #endif
334  break;
335 
336  case 1:
337  op = "blt"; /* yummy */
338  break;
339  case 2:
340  op = "bpl";
341  break;
342  case 3:
343  op = "bmi";
344  break;
345  }
346  break;
347  case 0xf:
348  branch = 1;
349  if (in->in_mode == ADDR_MODE_RELATIVE)
350  rel = 1;
351  switch (in->in_reg) {
352  case 0: op = "bne"; break;
353  case 1: op = "beq"; break;
354  case 2: op = "bcc"; break;
355  case 3: op = "bcs"; break;
356  }
357  break;
358  }
359 
360  if (!op)
361  return 0;
362 
363  if (ptr && in->in_mode == DATA_MODE_IMMEDIATE)
364  ptr = 0;
365 
366  if (branch && in->in_mode == ADDR_MODE_X_RELATIVE)
367  ptr = 0;
368 
369  if (idx && (!(in->in_mode & 2)))
370  idx = 0;
371 
372  if (regn) {
373  ptr = 1;
374  idx = 1;
375  reg = 1;
376  }
377 
378  sprintf(d->d_asm, "%s ", op);
379  if (reg) {
380  char *r = regn;
381  if (!r) {
382  r = regname(in->in_reg);
383  }
384  if (r && !rti) {
385  if ((strlen(r) + 4 + strlen(d->d_asm)) < sizeof(d->d_asm)) {
386  strcat(d->d_asm, r);
387  strcat(d->d_asm, ", ");
388  }
389  }
390  }
391  if (ptr) {
392  strcat(d->d_asm, "@");
393  rel = 0;
394  } else if (imm) {
395  strcat(d->d_asm, "#");
396  }
397  if (idx && ptr) {
398  strcat(d->d_asm, "(");
399  }
400 
401  d->d_prefix = s->s_prefix;
402 // d->d_operand = get_operand(s, d);
403 #if 1
404  if ((branch && idx) || rti) {
405  d->d_operand = get_operand(s, d);
406  if (d->d_operand < 0) {
407  d->d_operand *= -1;
408  sign = "-";
409  }
410  } else {
411  d->d_operand = s->s_prefix_val | in->in_operand;
412  if (d->d_operand & 0x80) {
413  if (d->d_prefix) {
414  if (!rel)
415  d->d_operand -= 0x100;
416  } else
417  d->d_operand |= 0xff00;
418  }
419  }
420 #endif
421 #if 0
422  operand = d->d_operand;
423  if (operand < 0)
424  operand *= -1;
425 #endif
426  fmtsz = 4;
427  if (d->d_operand & 0xff0000)
428  fmtsz += 2;
429 
430  // can be cleaned, no need to fmtsz
431  snprintf(fmt, sizeof(fmt), "%s0x%%.%dX", sign, fmtsz);
432  snprintf(tmp, sizeof(tmp), fmt, d->d_operand);
433  strcat(d->d_asm, tmp);
434 
435  if (idx) {
436  char *r = in->in_mode == DATA_MODE_INDEXED_X ? "X" : "Y";
437  if (regn)
438  r = "Y";
439  snprintf(tmp, sizeof(tmp), ", %s", r);
440  strcat(d->d_asm, tmp);
441  if (ptr)
442  strcat(d->d_asm, ")");
443  }
444 
445  return 1;
446 }
447 
448 static void xap_decode(struct state *s, struct directive *d) {
449  int prefix = s->s_prefix;
450  if (!decode_fixed(s, d))
451  if (!decode_known(s, d))
452  decode_unknown(s, d);
453  if (s->s_prefix == prefix)
454  s->s_prefix_val = s->s_prefix = 0;
455 }
456 
457 static int read_bin(struct state *s, struct directive *d) {
458  memcpy(&d->d_inst, s->s_buf, sizeof(d->d_inst));
459  d->d_off = s->s_off++;
460  return 1;
461 }
462 
463 static inline struct directive *next_inst(struct state *s) {
464  int rd;
465  struct directive *d = malloc(sizeof(*d));
466  if (!d) {
467  perror("malloc()");
468  return NULL;
469  }
470  memset(d, 0, sizeof(*d));
471 #if 0
472  if (s->s_format)
473  rd = read_text(s, d);
474  else
475 #endif
476  rd = read_bin(s, d);
477  if (!rd) {
478  free(d);
479  return NULL;
480  }
481 
482  return d;
483 }
484 
485 #if 0
486 static void own(struct state *s)
487 {
488  struct directive *d;
489  struct directive *last = &s->s_dirs;
490  struct label *l;
491  int flush = 0;
492  char fname[128];
493  char *fnamep;
494 
495  snprintf(fname, sizeof(fname), "%s", s->s_fname);
496  fnamep = strchr(fname, '.');
497  if (fnamep)
498  *fnamep = 0;
499  output(s, "\tMODULE %s\n"
500  "\t.CODE\n"
501  "\t.LARGE\n"
502  "\n", fname);
503 
504  /* decode instructions */
505  s->s_off = 0;
506  while ((d = next_inst(s))) {
507  xap_decode(s, d);
508 
509  if (s->s_ff_quirk) {
510  strcpy(last->d_asm, "DC\t0x8000");
511 
512  sprintf(d->d_asm, "DC\t0x%.4x", i2u16(&d->d_inst));
513  s->s_ff_quirk = 0;
514  }
515 
516  if (s->s_nopd) {
517  last->d_next = s->s_nopd;
518  last = s->s_nopd;
519  s->s_nopd = NULL;
520  s->s_nop = 0;
521  }
522 
523  if (s->s_nop) {
524  rz_return_if_fail (!s->s_nopd);
525  s->s_nopd = d;
526  } else {
527  last->d_next = d;
528  last = d;
529  }
530 
531 #if 1
532  if (flush++ > 10000) {
533  printf("@0x%.6x\r", d->d_off);
534  fflush(stdout);
535  flush = 0;
536  }
537 #endif
538  }
539  if (s->s_nopd)
540  last->d_next = s->s_nopd;
541  printf("\n");
542 
543  /* print them */
544  d = s->s_dirs.d_next;
545  l = s->s_labels.l_next;
546  while (d) {
547 
548  /* print any labels first */
549  while (l) {
550  if (l->l_off > d->d_off)
551  break;
552 
553  print_label(s, l);
554  l = l->l_next;
555  }
556 
557  add_comment(s, d);
558  output(s, "\t%s\n", d->d_asm);
559 
560  d = d->d_next;
561  }
562  if (l) {
563  print_label(s, l);
565  }
566 
567  output(s, "\n\tENDMOD\n");
568 }
569 #endif
#define rd()
#define imm
operand
Definition: arc-opc.c:39
static RZ_NULLABLE RzILOpBitVector * shift(RzILOpBitVector *val, RZ_NULLABLE RzILOpBool **carry_out, arm_shifter type, RZ_OWN RzILOpBitVector *dist)
Definition: arm_il32.c:190
const lzma_allocator const uint8_t * in
Definition: block.h:527
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
#define INST_SLEEP
Definition: dis.h:70
#define REG_AH
Definition: dis.h:77
#define INST_SIF
Definition: dis.h:72
#define INST_BRK
Definition: dis.h:69
#define REG_AL
Definition: dis.h:78
#define INST_RTS
Definition: dis.h:73
#define REG_Y
Definition: dis.h:80
#define REG_X
Definition: dis.h:79
#define INST_NOP
Definition: dis.h:68
#define INST_U
Definition: dis.h:71
#define ADDR_MODE_RELATIVE
Definition: dis.h:87
#define ADDR_MODE_X_RELATIVE
Definition: dis.h:88
#define INST_BC
Definition: dis.h:75
#define DATA_MODE_INDEXED_X
Definition: dis.h:84
#define INST_BRXL
Definition: dis.h:74
#define DATA_MODE_IMMEDIATE
Definition: dis.h:82
unsigned short prefix[65536]
Definition: gun.c:163
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
snprintf
Definition: kernel.h:364
sprintf
Definition: kernel.h:365
#define reg(n)
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static bool print_label(void *user, const void *k, const void *v)
Definition: rz-asm.c:391
void * malloc(size_t size)
Definition: malloc.c:123
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
int x
Definition: mipsasm.c:20
int idx
Definition: setup.py:197
static RzSocket * s
Definition: rtr.c:28
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
unsigned short uint16_t
Definition: sftypes.h:30
#define d(i)
Definition: sha256.c:44
Definition: dis.h:26
struct directive * d_next
Definition: dis.h:32
char d_asm[128]
Definition: dis.h:31
Definition: dis.h:35
unsigned int l_off
Definition: dis.h:37
struct label * l_next
Definition: dis.h:40
Definition: dis.h:43
Definition: dis.c:32
static void add_comment(RzCore *core, ut64 addr, const char *prompt)
Definition: visual.c:1277
static void xap_decode(struct state *s, struct directive *d)
Definition: dis.c:448
static struct state _state
Definition: dis.c:13
static void decode_unknown(struct state *s, struct directive *d)
Definition: dis.c:39
static int read_bin(struct state *s, struct directive *d)
Definition: dis.c:457
static struct directive * next_inst(struct state *s)
Definition: dis.c:463
static char * regname(int reg)
Definition: dis.c:71
static struct state * get_state(void)
Definition: dis.c:18
static int get_operand(struct state *s, struct directive *d)
Definition: dis.c:86
static int get_num(int num, int shift)
Definition: dis.c:81
static int decode_fixed(struct state *s, struct directive *d)
Definition: dis.c:47
static int decode_known(struct state *s, struct directive *d)
Definition: dis.c:95
static uint16_t i2u16(struct instruction *in)
Definition: dis.c:23
diff_output_t output
Definition: zipcmp.c:237