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>
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+
146271RzAnalysisPlugin 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
0 commit comments