Rizin
unix-like reverse engineering framework and cli tools
disassembly_53.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 // SPDX-FileCopyrightText: 2017 pancake <pancake@nopcode.org>
3 // SPDX-FileCopyrightText: 2021 Heersin <teablearcher@gmail.com>
4 
5 #include "arch_53.h"
6 
7 int lua53_disasm(RzAsmOp *op, const ut8 *buf, int len, LuaOpNameList opnames) {
8  if (len < 4) {
9  RZ_LOG_DEBUG("Cannot disassemble lua53 opcode (truncated).\n");
10  return 0;
11  }
14 
15  /* Pre fetch some args */
16  int a = GETARG_A(instruction);
17  int b = GETARG_B(instruction);
18  int c = GETARG_C(instruction);
19  int ax = GETARG_Ax(instruction);
20  int bx = GETARG_Bx(instruction);
21  int sbx = GETARG_sBx(instruction);
22 
23  // simplify test flag
24  int is_special_B = b & 0x100;
25  int is_special_C = c & 0x100;
26 
27  int special_c = 0xFF - c;
28  int special_b = 0xFF - b;
29 
30  char *asm_string;
31 
32  switch (opcode) {
33  case OP_LOADKX: /* A R(A) := Kst(extra arg) */
34  asm_string = luaop_new_str_1arg(opnames[opcode], a);
35  break;
36  case OP_MOVE: /* A B R(A) := R(B) */
37  case OP_SETUPVAL: /* A B UpValue[B] := R(A) */
38  case OP_UNM: /* A B R(A) := -R(B) */
39  case OP_BNOT: /* A B R(A) := ~R(B) */
40  case OP_NOT: /* A B R(A) := not R(B) */
41  case OP_LEN: /* A B R(A) := length of R(B) */
42  case OP_LOADNIL: /* A B R(A), R(A+1), ..., R(A+B) := nil */
43  case OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
44  case OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
45  case OP_GETUPVAL: /* A B R(A) := UpValue[B] */
46  asm_string = luaop_new_str_2arg(opnames[opcode], a, b);
47  break;
48  case OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
49  case OP_TFORCALL: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
50  asm_string = luaop_new_str_2arg(opnames[opcode], a, c);
51  break;
52  case OP_LOADK: /* A Bx R(A) := Kst(Bx) */
53  case OP_CLOSURE: /* A Bx R(A) := closure(KPROTO[Bx]) */
54  asm_string = luaop_new_str_2arg(opnames[opcode], a, bx);
55  break;
56  case OP_CONCAT: /* A B C R(A) := R(B).. ... ..R(C) */
57  case OP_TESTSET: /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
58  case OP_CALL: /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
59  case OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
60  case OP_NEWTABLE: /* A B C R(A) := {} (size = B,C) */
61  case OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
62  case OP_LOADBOOL: /* A B C R(A) := (Bool)B; if (C) pc++ */
63  case OP_SELF: /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
64  asm_string = luaop_new_str_3arg(opnames[opcode], a, b, c);
65  break;
66  case OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
67  case OP_GETTABLE: /* A B C R(A) := R(B)[RK(C)] */
68  if (is_special_C) {
69  asm_string = luaop_new_str_3arg(opnames[opcode], a, b, special_c);
70  } else {
71  asm_string = luaop_new_str_3arg(opnames[opcode], a, b, c);
72  }
73  break;
74  case OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
75  case OP_SETTABLE: /* A B C R(A)[RK(B)] := RK(C) */
76  case OP_ADD: /* A B C R(A) := RK(B) + RK(C) */
77  case OP_SUB: /* A B C R(A) := RK(B) - RK(C) */
78  case OP_MUL: /* A B C R(A) := RK(B) * RK(C) */
79  case OP_MOD: /* A B C R(A) := RK(B) % RK(C) */
80  case OP_POW: /* A B C R(A) := RK(B) ^ RK(C) */
81  case OP_DIV: /* A B C R(A) := RK(B) / RK(C) */
82  case OP_IDIV: /* A B C R(A) := RK(B) // RK(C) */
83  case OP_BAND: /* A B C R(A) := RK(B) & RK(C) */
84  case OP_BOR: /* A B C R(A) := RK(B) | RK(C) */
85  case OP_BXOR: /* A B C R(A) := RK(B) ~ RK(C) */
86  case OP_SHL: /* A B C R(A) := RK(B) << RK(C) */
87  case OP_SHR: /* A B C R(A) := RK(B) >> RK(C) */
88  case OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
89  case OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
90  case OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
91  if (is_special_B) {
92  if (is_special_C) {
93  asm_string = luaop_new_str_3arg(
94  opnames[opcode],
95  a, special_b, special_c);
96  } else {
97  asm_string = luaop_new_str_3arg(
98  opnames[opcode],
99  a, special_b, c);
100  }
101  } else {
102  if (is_special_C) {
103  asm_string = luaop_new_str_3arg(
104  opnames[opcode],
105  a, b, special_c);
106  } else {
107  asm_string = luaop_new_str_3arg(
108  opnames[opcode],
109  a, b, c);
110  }
111  }
112  break;
113  case OP_JMP: /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
114  case OP_FORLOOP: /* A sBx R(A)+=R(A+2);if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
115  case OP_FORPREP: /* A sBx R(A)-=R(A+2); pc+=sBx */
116  case OP_TFORLOOP: /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
117  asm_string = luaop_new_str_2arg(opnames[opcode], a, sbx);
118  break;
119  case OP_EXTRAARG: /* Ax extra (larger) argument for previous opcode */
120  asm_string = luaop_new_str_1arg(opnames[opcode], ax);
121  break;
122  default:
123  asm_string = rz_str_new("invalid");
124  break;
125  }
126 
127  rz_strbuf_append(&op->buf_asm, asm_string);
128  op->size = 4;
129  RZ_FREE(asm_string);
130  return 4;
131 }
size_t len
Definition: 6502dis.c:15
@ OP_DIV
Definition: 8051_ops.h:51
@ OP_ADD
Definition: 8051_ops.h:42
@ OP_MUL
Definition: 8051_ops.h:63
@ OP_JMP
Definition: 8051_ops.h:57
#define GETARG_A(i)
Definition: arch_53.h:176
#define GETARG_sBx(i)
Definition: arch_53.h:191
LuaOpCode
Definition: arch_53.h:62
@ OP_SETLIST
Definition: arch_53.h:122
@ OP_EQ
Definition: arch_53.h:104
@ OP_VARARG
Definition: arch_53.h:126
@ OP_CONCAT
Definition: arch_53.h:101
@ OP_BOR
Definition: arch_53.h:92
@ OP_SETTABLE
Definition: arch_53.h:78
@ OP_POW
Definition: arch_53.h:88
@ OP_NOT
Definition: arch_53.h:98
@ OP_TESTSET
Definition: arch_53.h:109
@ OP_MOD
Definition: arch_53.h:87
@ OP_CLOSURE
Definition: arch_53.h:124
@ OP_SETUPVAL
Definition: arch_53.h:77
@ OP_FORPREP
Definition: arch_53.h:117
@ OP_LEN
Definition: arch_53.h:99
@ OP_LOADNIL
Definition: arch_53.h:70
@ OP_BAND
Definition: arch_53.h:91
@ OP_SELF
Definition: arch_53.h:82
@ OP_SUB
Definition: arch_53.h:85
@ OP_SHR
Definition: arch_53.h:95
@ OP_LT
Definition: arch_53.h:105
@ OP_TFORLOOP
Definition: arch_53.h:120
@ OP_SHL
Definition: arch_53.h:94
@ OP_TEST
Definition: arch_53.h:108
@ OP_TFORCALL
Definition: arch_53.h:119
@ OP_FORLOOP
Definition: arch_53.h:115
@ OP_GETTABLE
Definition: arch_53.h:74
@ OP_LOADK
Definition: arch_53.h:67
@ OP_GETUPVAL
Definition: arch_53.h:71
@ OP_SETTABUP
Definition: arch_53.h:76
@ OP_IDIV
Definition: arch_53.h:90
@ OP_GETTABUP
Definition: arch_53.h:73
@ OP_LE
Definition: arch_53.h:106
@ OP_RETURN
Definition: arch_53.h:113
@ OP_BNOT
Definition: arch_53.h:97
@ OP_MOVE
Definition: arch_53.h:66
@ OP_UNM
Definition: arch_53.h:96
@ OP_EXTRAARG
Definition: arch_53.h:128
@ OP_LOADKX
Definition: arch_53.h:68
@ OP_NEWTABLE
Definition: arch_53.h:80
@ OP_LOADBOOL
Definition: arch_53.h:69
@ OP_BXOR
Definition: arch_53.h:93
@ OP_TAILCALL
Definition: arch_53.h:112
#define GETARG_B(i)
Definition: arch_53.h:179
#define GET_OPCODE(i)
Definition: arch_53.h:168
#define GETARG_Bx(i)
Definition: arch_53.h:185
#define GETARG_Ax(i)
Definition: arch_53.h:188
#define GETARG_C(i)
Definition: arch_53.h:182
uint32_t ut32
int lua53_disasm(RzAsmOp *op, const ut8 *buf, int len, LuaOpNameList opnames)
Definition: disassembly_53.c:7
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
char * luaop_new_str_2arg(char *opname, int a, int b)
Definition: lua_arch.c:42
char * luaop_new_str_3arg(char *opname, int a, int b, int c)
Definition: lua_arch.c:31
LuaInstruction lua_build_instruction(const ut8 *buf)
Definition: lua_arch.c:6
char * luaop_new_str_1arg(char *opname, int a)
Definition: lua_arch.c:53
char ** LuaOpNameList
Definition: lua_arch.h:30
#define OP_CALL
Definition: nios2.h:263
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
RZ_API char * rz_str_new(const char *str)
Definition: str.c:865
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
#define RZ_FREE(x)
Definition: rz_types.h:369
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
Definition: dis.c:32