Rizin
unix-like reverse engineering framework and cli tools
analysis_or1k.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2019 v3l0c1r4pt0r <v3l0c1r4pt0r@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_asm.h>
5 #include <rz_analysis.h>
6 #include <rz_lib.h>
7 #include <or1k_disas.h>
8 
9 struct operands {
19 };
20 
21 static ut32 cpu[32] = { 0 }; /* register contents */
22 static ut32 cpu_enable; /* allows to treat only registers with known value as
23  valid */
24 
35  /* sign extension returns 32b unsigned N, then it is multiplied by 4, made
36  * signed to support negative offsets, added to address and made unsigned
37  * again */
38  return (ut64)((st64)((st32)(sign_extend(n, mask) << 2)) + addr);
39 }
40 
41 static int insn_to_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, insn_t *descr, insn_extra_t *extra, ut32 insn) {
42  struct operands o = { 0 };
43  insn_type_t type = type_of_opcode(descr, extra);
44  insn_type_descr_t *type_descr = &types[INSN_X];
45 
46  /* only use type descriptor if it has some useful data */
48  type_descr = &types[type];
49  }
50 
51  if (extra == NULL) {
52  op->type = descr->insn_type;
53  } else {
54  op->type = extra->insn_type;
55  }
56 
57  switch ((insn & INSN_OPCODE_MASK) >> INSN_OPCODE_SHIFT) {
58  case 0x00: /* l.j */
59  o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
60  op->eob = true;
61  op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
62  addr);
63  op->delay = 1;
64  break;
65  case 0x01: /* l.jal */
66  o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
67  op->eob = true;
68  op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
69  addr);
70  op->delay = 1;
71  break;
72  case 0x03: /* l.bnf */
73  o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
74  op->cond = RZ_TYPE_COND_NE;
75  op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
76  addr);
77  op->fail = addr + 8;
78  op->delay = 1;
79  break;
80  case 0x04: /* l.bf */
81  o.n = get_operand_value(insn, type_descr, INSN_OPER_N);
82  op->cond = RZ_TYPE_COND_EQ;
83  op->jump = n_oper_to_addr(o.n, get_operand_mask(type_descr, INSN_OPER_N),
84  addr);
85  op->fail = addr + 8;
86  op->delay = 1;
87  break;
88  case 0x11: /* l.jr */
89  o.rb = get_operand_value(insn, type_descr, INSN_OPER_B);
90  op->eob = true;
91  if (cpu_enable & (1 << o.rb)) {
92  op->jump = cpu[o.rb];
93  }
94  op->delay = 1;
95  break;
96  case 0x12: /* l.jalr */
97  o.rb = get_operand_value(insn, type_descr, INSN_OPER_B);
98  op->eob = true;
99  if (cpu_enable & (1 << o.rb)) {
100  op->jump = cpu[o.rb];
101  }
102  op->delay = 1;
103  break;
104  case 0x06: /* extended */
105  switch (insn & (1 << 16)) {
106  case 0: /* l.movhi */
107  o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
108  o.k = get_operand_value(insn, type_descr, INSN_OPER_K);
109  cpu[o.rd] = o.k << 16;
110  cpu_enable |= (1 << o.rd);
111  break;
112  case 1: /* l.macrc */
113  break;
114  }
115  break;
116  case 0x27: /* l.addi */
117  o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
118  o.ra = get_operand_value(insn, type_descr, INSN_OPER_A);
119  o.i = get_operand_value(insn, type_descr, INSN_OPER_I);
120  if (cpu_enable & (1 << o.ra) & cpu_enable & (1 << o.rd)) {
121  cpu[o.rd] = cpu[o.ra] | o.i;
122  cpu_enable |= (1 << o.rd);
123  op->ptr = cpu[o.rd];
124  op->direction = 8; /* reference */
125  }
126  break;
127  case 0x2a: /* l.ori */
128  o.rd = get_operand_value(insn, type_descr, INSN_OPER_D);
129  o.ra = get_operand_value(insn, type_descr, INSN_OPER_A);
130  o.i = get_operand_value(insn, type_descr, INSN_OPER_I);
131  if (cpu_enable & (1 << o.ra)) {
132  cpu[o.rd] = cpu[o.ra] | o.i;
133  cpu_enable |= (1 << o.rd);
134  op->ptr = cpu[o.rd];
135  op->direction = 8; /* reference */
136  }
137  break;
138  default:
139  /* if unknown instruction encountered, better forget state */
140  cpu_enable = 0;
141  }
142 
143  /* temporary solution to prevent using wrong register values */
145  /* FIXME: handle delay slot after branches */
146  cpu_enable = 0;
147  }
148  return 4;
149 }
150 
151 static int or1k_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask) {
152  ut32 insn, opcode;
153  ut8 opcode_idx;
154  insn_t *insn_descr;
155  insn_extra_t *extra_descr;
156 
157  /* read instruction and basic opcode value */
158  insn = rz_read_be32(data);
159  op->size = 4;
160  opcode = (insn & INSN_OPCODE_MASK);
161  opcode_idx = opcode >> INSN_OPCODE_SHIFT;
162 
163  /* make sure instruction descriptor table is not overflowed */
164  if (opcode_idx >= insns_count) {
165  return op->size;
166  }
167 
168  /* if instruction is marked as invalid finish processing now */
169  insn_descr = &or1k_insns[opcode_idx];
170  if (insn_descr->type == INSN_INVAL) {
171  return op->size;
172  }
173 
174  /* if name is null, but extra is present, it means 6 most significant bits
175  * are not enough to decode instruction */
176  if ((insn_descr->name == NULL) && (insn_descr->extra != NULL)) {
177  extra_descr = find_extra_descriptor(insn_descr->extra, insn);
178  if (extra_descr != NULL) {
179  insn_to_op(a, op, addr, insn_descr, extra_descr, insn);
180  }
181  } else {
182  /* otherwise basic descriptor is enough */
183  insn_to_op(a, op, addr, insn_descr, NULL, insn);
184  }
185 
186  return op->size;
187 }
188 
190  .name = "or1k",
191  .desc = "OpenRISC 1000",
192  .license = "LGPL3",
193  .bits = 32,
194  .arch = "or1k",
195  .esil = false,
196  .op = &or1k_op,
197 };
198 
199 #ifndef RZ_PLUGIN_INCORE
202  .data = &rz_analysis_plugin_or1k,
204 };
205 #endif
size_t len
Definition: 6502dis.c:15
#define mask()
RzAnalysisPlugin rz_analysis_plugin_or1k
static int insn_to_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, insn_t *descr, insn_extra_t *extra, ut32 insn)
Definition: analysis_or1k.c:41
static ut32 cpu[32]
Definition: analysis_or1k.c:21
RZ_API RzLibStruct rizin_plugin
static int or1k_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
static ut32 cpu_enable
Definition: analysis_or1k.c:22
static ut64 n_oper_to_addr(ut32 n, ut32 mask, ut64 addr)
Convert raw N operand to complete address.
Definition: analysis_or1k.c:34
static void sign_extend(st32 *value, ut8 bit)
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
uint8_t ut8
Definition: lh5801.h:11
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
insn_t or1k_insns[]
Definition: or1k_disas.c:219
insn_type_descr_t types[]
Definition: or1k_disas.c:7
size_t insns_count
Definition: or1k_disas.c:286
insn_extra_t * find_extra_descriptor(insn_extra_t *extra_descr, ut32 insn)
Definition: or1k_disas.c:288
static ut32 get_operand_mask(insn_type_descr_t *type_descr, insn_oper_t operand)
Definition: or1k_disas.h:152
static int is_type_descriptor_defined(insn_type_t type)
Definition: or1k_disas.h:168
static int has_type_descriptor(insn_type_t type)
Definition: or1k_disas.h:164
@ INSN_X
Definition: or1k_disas.h:55
@ INSN_INVAL
Definition: or1k_disas.h:54
static ut32 get_operand_value(ut32 insn, insn_type_descr_t *type_descr, insn_oper_t operand)
Definition: or1k_disas.h:160
@ INSN_OPER_A
Definition: or1k_disas.h:83
@ INSN_OPER_B
Definition: or1k_disas.h:84
@ INSN_OPER_I
Definition: or1k_disas.h:88
@ INSN_OPER_N
Definition: or1k_disas.h:85
@ INSN_OPER_K
Definition: or1k_disas.h:86
@ INSN_OPER_D
Definition: or1k_disas.h:87
static insn_type_t type_of_opcode(insn_t *descr, insn_extra_t *extra_descr)
Definition: or1k_disas.h:172
#define INSN_OPCODE_MASK
Definition: or1k_disas.h:10
#define INSN_OPCODE_SHIFT
Definition: or1k_disas.h:11
enum insn_type insn_type_t
RzAnalysisOpMask
Definition: rz_analysis.h:439
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
@ RZ_TYPE_COND_EQ
Equal.
Definition: rz_type.h:184
@ RZ_TYPE_COND_NE
Not equal.
Definition: rz_type.h:185
#define st64
Definition: rz_types_base.h:10
#define st32
Definition: rz_types_base.h:12
#define RZ_VERSION
Definition: rz_version.h:8
#define a(i)
Definition: sha256.c:41
insn_extra_t * extra
Definition: or1k_disas.h:118
char * name
Definition: or1k_disas.h:115
int type
Definition: or1k_disas.h:116
int insn_type
Definition: or1k_disas.h:117
const char * version
Definition: rz_analysis.h:1239
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58