Skip to content

Commit 0c45176

Browse files
authored
librz/arch: add xcore support (#5617)
* Add proper xcore support * Add check on nullptr for language
1 parent 728b7be commit 0c45176

File tree

5 files changed

+421
-48
lines changed

5 files changed

+421
-48
lines changed

librz/arch/p/analysis/analysis_xcore_cs.c

Lines changed: 173 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-FileCopyrightText: 2014-2017 pancake <pancake@nopcode.org>
1+
// SPDX-FileCopyrightText: 2025 deroad <deroad@kumo.xn--q9jyb4c>
22
// SPDX-License-Identifier: LGPL-3.0-only
33

44
#include <rz_analysis.h>
@@ -8,7 +8,52 @@
88

99
#define INSOP(n) insn->detail->xcore.operands[n]
1010

11-
static void opex(RzStrBuf *buf, csh handle, cs_insn *insn) {
11+
static char *xcore_get_reg_profile(RzAnalysis *analysis) {
12+
const char *p =
13+
"=PC pc\n"
14+
"=SP dp\n"
15+
"=BP sp\n"
16+
"=SR sr\n"
17+
"=SN r0\n"
18+
"=A0 r4\n"
19+
"=A1 r5\n"
20+
"=A2 r6\n"
21+
"=A3 r7\n"
22+
"=A4 r8\n"
23+
"=A5 r9\n"
24+
"=A6 r10\n"
25+
"gpr r0 .32 0 0\n"
26+
"gpr r1 .32 4 0\n"
27+
"gpr r2 .32 8 0\n"
28+
"gpr r3 .32 12 0\n"
29+
"gpr r4 .32 16 0\n"
30+
"gpr r5 .32 20 0\n"
31+
"gpr r6 .32 24 0\n"
32+
"gpr r7 .32 28 0\n"
33+
"gpr r8 .32 32 0\n"
34+
"gpr r9 .32 36 0\n"
35+
"gpr r10 .32 40 0\n"
36+
"gpr r11 .32 44 0\n"
37+
"gpr cp .32 48 0\n" // constant pool pointer
38+
"gpr dp .32 52 0\n" // data pointer
39+
"gpr sp .32 56 0\n" // stack pointer
40+
"gpr lr .32 60 0\n" // link register
41+
"gpr pc .32 64 0\n" // program counter
42+
"gpr sr .32 68 0\n" // status register
43+
"gpr spc .32 72 0\n" // saved pc
44+
"gpr ssr .32 76 0\n" // saved status
45+
"gpr et .32 80 0\n" // exception type
46+
"gpr ed .32 84 0\n" // exception data
47+
"gpr sed .32 88 0\n" // saved exception data
48+
"gpr kep .32 92 0\n" // kernel entry pointer
49+
"gpr ksp .32 96 0\n" // kernel stack pointer
50+
"gpr id .32 100 0\n" // thread id
51+
"";
52+
53+
return rz_str_dup(p);
54+
}
55+
56+
static void xcore_opex(RzStrBuf *buf, csh handle, cs_insn *insn) {
1257
int i;
1358
PJ *pj = pj_new();
1459
if (!pj) {
@@ -69,9 +114,6 @@ static int analyze_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf
69114
cs_insn *insn;
70115
int mode, n, ret;
71116
mode = CS_MODE_BIG_ENDIAN;
72-
if (!strcmp(a->cpu, "v9")) {
73-
mode |= CS_MODE_V9;
74-
}
75117
if (mode != ctx->omode) {
76118
if (ctx->handle) {
77119
cs_close(&ctx->handle);
@@ -86,52 +128,118 @@ static int analyze_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf
86128
}
87129
cs_option(ctx->handle, CS_OPT_DETAIL, CS_OPT_ON);
88130
}
89-
// capstone-next
131+
90132
n = cs_disasm(ctx->handle, (const ut8 *)buf, len, addr, 1, &insn);
91133
if (n < 1) {
92134
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
93-
} else {
94-
if (mask & RZ_ANALYSIS_OP_MASK_OPEX) {
95-
opex(&op->opex, ctx->handle, insn);
96-
}
97-
op->size = insn->size;
98-
op->id = insn->id;
99-
switch (insn->id) {
100-
case XCORE_INS_DRET:
101-
case XCORE_INS_KRET:
102-
case XCORE_INS_RETSP:
103-
op->type = RZ_ANALYSIS_OP_TYPE_RET;
104-
break;
105-
case XCORE_INS_DCALL:
106-
case XCORE_INS_KCALL:
107-
case XCORE_INS_ECALLF:
108-
case XCORE_INS_ECALLT:
109-
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
110-
op->jump = INSOP(0).imm;
111-
break;
112-
/* ??? */
113-
case XCORE_INS_BL:
114-
case XCORE_INS_BLA:
115-
case XCORE_INS_BLAT:
116-
case XCORE_INS_BT:
117-
case XCORE_INS_BF:
118-
case XCORE_INS_BU:
119-
case XCORE_INS_BRU:
120-
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
121-
op->jump = INSOP(0).imm;
122-
break;
123-
case XCORE_INS_SUB:
124-
case XCORE_INS_LSUB:
125-
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
126-
break;
127-
case XCORE_INS_ADD:
128-
case XCORE_INS_LADD:
129-
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
130-
break;
135+
if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
136+
op->mnemonic = strdup("invalid");
131137
}
132-
cs_free(insn, n);
138+
return -1;
133139
}
134-
// cs_close (&handle);
140+
141+
if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
142+
op->mnemonic = rz_str_newf("%s%s%s", insn->mnemonic, insn->op_str[0] ? " " : "", insn->op_str);
143+
}
144+
145+
if (mask & RZ_ANALYSIS_OP_MASK_OPEX) {
146+
xcore_opex(&op->opex, ctx->handle, insn);
147+
}
148+
149+
op->size = insn->size;
150+
op->id = insn->id;
151+
switch (insn->id) {
152+
case XCORE_INS_BAU: /* Branch absolute unconditional register */
153+
op->type = RZ_ANALYSIS_OP_TYPE_RJMP;
154+
op->fail = addr + op->size;
155+
break;
156+
case XCORE_INS_BLA: /* Branch and link absolute via register */
157+
op->type = RZ_ANALYSIS_OP_TYPE_RCALL;
158+
op->fail = addr + op->size;
159+
break;
160+
case XCORE_INS_BLAT: /* Branch and link absolute via table */
161+
op->type = RZ_ANALYSIS_OP_TYPE_MEM | RZ_ANALYSIS_OP_TYPE_UCALL;
162+
op->fail = addr + op->size;
163+
break;
164+
case XCORE_INS_BL:
165+
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
166+
op->jump = addr + (st64)(INSOP(0).imm * op->size);
167+
op->fail = addr + op->size;
168+
break;
169+
case XCORE_INS_BF:
170+
/* fall-thru */
171+
case XCORE_INS_BT:
172+
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
173+
op->jump = addr + (st64)(INSOP(1).imm * op->size);
174+
op->fail = addr + op->size;
175+
break;
176+
case XCORE_INS_BU:
177+
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
178+
op->jump = addr + (st64)(INSOP(0).imm * op->size);
179+
break;
180+
case XCORE_INS_BRU:
181+
op->type = RZ_ANALYSIS_OP_TYPE_RJMP;
182+
break;
183+
case XCORE_INS_DCALL:
184+
op->type = RZ_ANALYSIS_OP_TYPE_UCALL;
185+
break;
186+
case XCORE_INS_DRET:
187+
op->type = RZ_ANALYSIS_OP_TYPE_RET;
188+
break;
189+
case XCORE_INS_ECALLF:
190+
op->type = RZ_ANALYSIS_OP_TYPE_UCCALL;
191+
op->fail = addr + op->size;
192+
break;
193+
case XCORE_INS_ECALLT:
194+
op->type = RZ_ANALYSIS_OP_TYPE_UCCALL;
195+
op->fail = addr + op->size;
196+
break;
197+
case XCORE_INS_EQ: /* Compare if equal */
198+
/* fall-thru */
199+
case XCORE_INS_LSS: /* Compare if less than (signed) */
200+
/* fall-thru */
201+
case XCORE_INS_LSU: /* Compare if less than (unsigned) */
202+
op->type = RZ_ANALYSIS_OP_TYPE_CMP;
203+
break;
204+
case XCORE_INS_KCALL: /* kernel call */
205+
op->type = RZ_ANALYSIS_OP_TYPE_RCALL;
206+
break;
207+
case XCORE_INS_KRET:
208+
op->type = RZ_ANALYSIS_OP_TYPE_RET;
209+
break;
210+
case XCORE_INS_LD16S:
211+
/* fall-thru */
212+
case XCORE_INS_LD8U:
213+
/* fall-thru */
214+
case XCORE_INS_LDA16:
215+
/* fall-thru */
216+
case XCORE_INS_LDAW:
217+
/* fall-thru */
218+
case XCORE_INS_LDW:
219+
/* fall-thru */
220+
case XCORE_INS_ST16:
221+
/* fall-thru */
222+
case XCORE_INS_ST8:
223+
/* fall-thru */
224+
case XCORE_INS_STW:
225+
op->type = RZ_ANALYSIS_OP_TYPE_MEM | RZ_ANALYSIS_OP_TYPE_MOV;
226+
break;
227+
case XCORE_INS_LDAP:
228+
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
229+
op->ptr = op->val = addr + (st64)(INSOP(0).imm * op->size);
230+
break;
231+
case XCORE_INS_LDC:
232+
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
233+
op->val = (st64)INSOP(0).imm;
234+
break;
235+
case XCORE_INS_RETSP:
236+
op->type = RZ_ANALYSIS_OP_TYPE_RET;
237+
break;
238+
default:
239+
break;
240+
}
241+
cs_free(insn, n);
242+
135243
return op->size;
136244
}
137245

@@ -143,6 +251,23 @@ static bool xcore_fini(void *user) {
143251
return true;
144252
}
145253

254+
static int xcore_archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
255+
switch (query) {
256+
case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE:
257+
return 2;
258+
case RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE:
259+
return 4;
260+
case RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN:
261+
return 2;
262+
case RZ_ANALYSIS_ARCHINFO_DATA_ALIGN:
263+
return 1;
264+
case RZ_ANALYSIS_ARCHINFO_CAN_USE_POINTERS:
265+
return true;
266+
default:
267+
return -1;
268+
}
269+
}
270+
146271
RzAnalysisPlugin rz_analysis_plugin_xcore_cs = {
147272
.name = "xcore",
148273
.desc = "Capstone XCORE analysis",
@@ -153,7 +278,8 @@ RzAnalysisPlugin rz_analysis_plugin_xcore_cs = {
153278
.op = &analyze_op,
154279
.init = xcore_init,
155280
.fini = xcore_fini,
156-
//.set_reg_profile = &set_reg_profile,
281+
.archinfo = xcore_archinfo,
282+
.get_reg_profile = &xcore_get_reg_profile,
157283
};
158284

159285
#ifndef RZ_PLUGIN_INCORE

librz/arch/p/asm/asm_xcore_cs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ RzAsmPlugin rz_asm_plugin_xcore_cs = {
6161
.license = "BSD",
6262
.author = "pancake",
6363
.arch = "xcore",
64+
.cpus = "",
6465
.bits = 32,
6566
.endian = RZ_SYS_ENDIAN_LITTLE | RZ_SYS_ENDIAN_BIG,
6667
.init = &xcore_asm_init,

librz/bin/bin_demangle.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ RZ_API RZ_OWN char *rz_bin_demangle(RZ_NULLABLE RzBin *bin, RZ_NULLABLE const ch
110110
break;
111111
}
112112

113-
if (!bin) {
113+
if (!bin || RZ_STR_ISEMPTY(language)) {
114114
return NULL;
115115
}
116116

librz/bin/format/elf/elf_info.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ static const struct arch_translation arch_translation_table[] = {
369369
{ EM_U16_U8CORE, "u16_u8core" },
370370
{ EM_TACHYUM, "tachyum" },
371371
{ EM_56800EF, "56800ef" },
372+
{ EM_XCORE, "xcore" },
372373
};
373374

374375
static const struct ver_flags_translation ver_flags_translation_table[] = {

0 commit comments

Comments
 (0)