Rizin
unix-like reverse engineering framework and cli tools
cil_dis.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2022 wingdeans <wingdeans@protonmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_types.h>
5 #include <rz_asm.h>
6 #include <rz_endian.h>
7 #include <rz_util/rz_strbuf.h>
8 #include "cil_dis.h"
9 
22 // Generate generic parameter types
23 #define DEF_READ_GENERIC(bytes, readtype, fmt) \
24  static int read_generic##readtype(int *pos, CILOp *op, const ut8 *buf, int len) { \
25  if (*pos + bytes > len) { \
26  return -1; \
27  } \
28  rz_strbuf_appendf(&op->strbuf, fmt, rz_read_at_le##readtype(buf, *pos)); \
29  *pos += bytes; \
30  return 0; \
31  }
32 
33 DEF_READ_GENERIC(1, 8, " 0x%X")
34 DEF_READ_GENERIC(2, 16, " 0x%X")
35 DEF_READ_GENERIC(4, 32, " 0x%X")
36 DEF_READ_GENERIC(8, 64, " 0x%llX")
37 
38 DEF_READ_GENERIC(4, _float, " %f")
39 DEF_READ_GENERIC(8, _double, " %f")
40 
41 static int read_InlineNone(int *pos, CILOp *op, const ut8 *buf, int len) {
42  return 0;
43 }
44 
45 #define read_ShortInlineVar read_generic8
46 #define read_ShortInlineI read_generic8
47 
48 #define read_InlineVar read_generic16
49 
50 #define read_InlineI read_generic32
51 #define read_InlineSig read_generic32
52 #define read_InlineType read_generic32
53 #define read_InlineField read_generic32
54 #define read_InlineString read_generic32
55 #define read_InlineTok read_generic32
56 
57 #define read_InlineI8 read_generic64
58 
59 #define read_ShortInlineR read_generic_float
60 #define read_InlineR read_generic_double
61 
62 // Special
63 static int read_InlineMethod(int *pos, CILOp *op, const ut8 *buf, int len) {
64  if (*pos + sizeof(ut32) > len) {
65  return -1;
66  }
67  ut32 tok = rz_read_at_le32(buf, *pos);
68  rz_strbuf_appendf(&op->strbuf, " 0x%X", tok);
69  op->tok = tok;
70  *pos += sizeof(ut32);
71  return 0;
72 }
73 
74 static int read_InlineBrTarget(int *pos, CILOp *op, const ut8 *buf, int len) {
75  if (*pos + sizeof(st32) > len) {
76  return -1;
77  }
78  st32 target = rz_read_at_le32(buf, *pos);
79  rz_strbuf_appendf(&op->strbuf, " %d", target);
80  op->target = target;
81  *pos += sizeof(st32);
82  return 0;
83 }
84 
85 static int read_ShortInlineBrTarget(int *pos, CILOp *op, const ut8 *buf, int len) {
86  if (*pos + sizeof(st8) > len) {
87  return -1;
88  }
89  st8 target = rz_read_at_le8(buf, *pos);
90  rz_strbuf_appendf(&op->strbuf, " %hhd", target);
91  op->target = target;
92  *pos += sizeof(st8);
93  return 0;
94 }
95 
96 static int read_InlineSwitch(int *pos, CILOp *op, const ut8 *buf, int len) {
97  if (*pos + sizeof(ut32) > len) {
98  return -1;
99  }
100 
102  *pos += sizeof(ut32);
103  if (*pos + count * 4 > len) {
104  return -1;
105  }
106  *pos += count * 4;
107  return 0;
108 }
109 
110 typedef struct {
111  char *str;
112  int (*read_param)(int *pos, CILOp *op, const ut8 *buf, int len);
113  bool prefix;
115 
128 #define OPCODE_SINGLE(name, string, param, byte, control) [name] = { .str = string, .read_param = read_##param },
130 #include "opcodes_single.def"
131  [0xFF] = { 0 }
132 };
133 
134 #define OPCODE_DOUBLE(name, string, param, byte, control) [name] = { .str = string, .read_param = read_##param },
135 #define OPCODE_PREFIX(name, string, param, byte, control) [name] = { \
136  .prefix = true, \
137  .str = string, \
138  .read_param = read_##param \
139 },
141 #include "opcodes_double.def"
142 #include "opcodes_prefix.def"
143  [0xFF] = { 0 }
144 };
145 
150 int cil_dis(CILOp *op, const ut8 *buf, int len) {
151  int pos = 0;
152  if (pos >= len) { // pos + 1 > len
153  return -1;
154  }
155 
156  ut8 byte;
157  rz_strbuf_init(&op->strbuf);
158 
159 start: // Taken after a prefix opcode has been consumed
160  byte = buf[pos++];
161 
162  CILOpcodeReader opcode_reader;
163  if (byte != 0xFE) { // Single-byte
164  op->byte1 = byte;
165  opcode_reader = opcode_readers_single[byte];
166  } else { // Double-byte
167  if (pos >= len) { // pos + 1 > len
168  return -1; // OOB
169  }
170 
171  op->byte1 = byte;
172  op->byte2 = byte = buf[pos++];
173  opcode_reader = opcode_readers_double[byte];
174  }
175 
176  if (!opcode_reader.str) {
177  return -1; // Invalid
178  }
179 
180  // Mnemonic
181  if (!rz_strbuf_append(&op->strbuf, opcode_reader.str)) {
182  return -1;
183  }
184 
185  // Dispatch based on opcode `param`
186  if (opcode_reader.read_param(&pos, op, buf, len)) {
187  return -1;
188  }
189 
190  if (opcode_reader.prefix) {
191  if (!rz_strbuf_append(&op->strbuf, " ")) { // extra space
192  return -1;
193  }
194  goto start; // continue
195  }
196 
197  op->size = pos;
198  return 0;
199 }
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
#define X(x, b, m)
static int read_InlineBrTarget(int *pos, CILOp *op, const ut8 *buf, int len)
Definition: cil_dis.c:74
static const CILOpcodeReader opcode_readers_single[]
Definition: cil_dis.c:129
static int read_ShortInlineBrTarget(int *pos, CILOp *op, const ut8 *buf, int len)
Definition: cil_dis.c:85
static int read_InlineMethod(int *pos, CILOp *op, const ut8 *buf, int len)
Definition: cil_dis.c:63
#define DEF_READ_GENERIC(bytes, readtype, fmt)
Definition: cil_dis.c:23
static const CILOpcodeReader opcode_readers_double[]
Definition: cil_dis.c:140
static int read_InlineNone(int *pos, CILOp *op, const ut8 *buf, int len)
Definition: cil_dis.c:41
int cil_dis(CILOp *op, const ut8 *buf, int len)
Disassemble a CIL buffer.
Definition: cil_dis.c:150
static int read_InlineSwitch(int *pos, CILOp *op, const ut8 *buf, int len)
Definition: cil_dis.c:96
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 count
Definition: sflib.h:98
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 static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
uint32_t ut32
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
#define const
Definition: ansidecl.h:240
int x
Definition: mipsasm.c:20
static ut32 rz_read_at_le32(const void *src, size_t offset)
Definition: rz_endian.h:248
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
static ut8 rz_read_at_le8(const void *src, size_t offset)
Definition: rz_endian.h:194
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
#define st8
Definition: rz_types_base.h:16
#define st32
Definition: rz_types_base.h:12
static int
Definition: sfsocketcall.h:114
#define f(i)
Definition: sha256.c:46
Definition: cil_dis.h:27
char * str
Definition: cil_dis.c:111
int(* read_param)(int *pos, CILOp *op, const ut8 *buf, int len)
Definition: cil_dis.c:112
int pos
Definition: main.c:11
Definition: dis.c:32