librz/arch: add Xtensa RzIL support (#4712)

- **Add support for rzIL**: Implement various Xtensa instructions and functionalities.
- **Instruction Set Additions**:
  - **Arithmetic and Logical Operations**: sub*, add*, and*, or*, xor*, mul*, div*, rem*, neg*, abs, addi*, addmi, addexp*, addexpm*, addx2|4|8
  - **Bitwise Operations**: srl*, sra*, sll*, andb, andbc, nsau, nsa
  - **Branching and Jumps**: b*, beq*, bne*, ball, bany, bnall, bnone, j, jx, loop*, loopgez, loopnez
  - **Data Transfer**: st*, ld*, l32*, l16*, l8ui, ssi*, ssa*, src
  - **Floating Point**: sqrt0.s, float.s, floor.s, trunc*, ueq*, ule*, ult*, ufloat*, neg.s, oeq.s, ole.s, olt.s, min, max, clamps, nex
  - **System Calls and Synchronization**: syscall, simcall, entry, isync, dsync, esync, rsync, memw
  - **Miscellaneous**: const_s, extui, extw, excw, sext, witlb, wur, rur.*, mksadj.ss, mkdadj.s, const_s
- **Testing and Patches**:
  - Implement asm tests for all
- **Miscellaneous Improvements**:
  - Update Capstone and fix ARM architecture support for building.
This commit is contained in:
billow 2024-12-26 01:55:38 +08:00 committed by GitHub
parent 4c055aaffa
commit 42302da16d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 2730 additions and 27 deletions

View file

@ -201,6 +201,9 @@ static void setup_vm_init_state(RzAnalysisILVM *vm, RZ_NULLABLE RzAnalysisILInit
rz_vector_foreach (&is->vars, v) {
rz_il_vm_set_global_var(vm->vm, v->name, rz_il_value_dup(v->val));
}
if (is->cb) {
is->cb(vm, reg);
}
}
}

View file

@ -31,6 +31,8 @@ bool xtensa_open(XtensaContext *ctx, const char *cpu, bool big_endian);
bool xtensa_disassemble(XtensaContext *self, const ut8 *buf, int len, ut64 addr);
void xtensa_disassemble_fini(XtensaContext *self);
void xtensa_analyze_op_esil(XtensaContext *ctx, RzAnalysisOp *op);
void xtensa_analyze_op_rzil(XtensaContext *ctx, RzAnalysisOp *op);
RzAnalysisILConfig *xtensa_il_config(RzAnalysis *a);
static inline cs_xtensa_op_mem *xtensa_op_mem(cs_insn *insn, unsigned int index) {
cs_xtensa_op *op = &insn->detail->xtensa.operands[index];
@ -56,12 +58,13 @@ static inline int32_t xtensa_op_l32r(cs_insn *insn, unsigned int index) {
return op->imm;
}
#define XOP(I) (ctx->insn->detail->xtensa.operands + I)
#define MEM(I) xtensa_op_mem(ctx->insn, I)
#define REGI(I) xtensa_op_reg(ctx->insn, I)
#define REGN(I) cs_reg_name(ctx->handle, (xtensa_op_reg(ctx->insn, I)))
#define IMM(I) xtensa_op_imm(ctx->insn, I)
#define L32R(I) xtensa_op_l32r(ctx->insn, I)
#define INSN_SIZE (ctx->insn->size)
#define XOP(I) (ctx->insn->detail->xtensa.operands + I)
#define MEM(I) xtensa_op_mem(ctx->insn, I)
#define REGI(I) xtensa_op_reg(ctx->insn, I)
#define REGNAME(I) cs_reg_name(ctx->handle, (I))
#define REGN(I) REGNAME(REGI((I)))
#define IMM(I) xtensa_op_imm(ctx->insn, I)
#define L32R(I) xtensa_op_l32r(ctx->insn, I)
#define INSN_SIZE (ctx->insn->size)
#endif // RZ_XTENSA_H

File diff suppressed because it is too large Load diff

View file

@ -338,6 +338,7 @@ if capstone_dep.version() == 'next'
arch_isa_sources += [
'isa/xtensa/xtensa.c',
'isa/xtensa/xtensa_esil.c',
'isa/xtensa/xtensa_il.c',
]
endif

View file

@ -58,6 +58,166 @@ static char *xtensa_get_reg_profile(RzAnalysis *analysis) {
"gpr a14 .32 60 0\n"
"gpr a15 .32 64 0\n"
"gpr f0 .64 76 0\n"
"gpr f1 .64 84 0\n"
"gpr f2 .64 92 0\n"
"gpr f3 .64 100 0\n"
"gpr f4 .64 108 0\n"
"gpr f5 .64 116 0\n"
"gpr f6 .64 124 0\n"
"gpr f7 .64 132 0\n"
"gpr f8 .64 140 0\n"
"gpr f9 .64 148 0\n"
"gpr f10 .64 156 0\n"
"gpr f11 .64 164 0\n"
"gpr f12 .64 172 0\n"
"gpr f13 .64 180 0\n"
"gpr f14 .64 188 0\n"
"gpr f15 .64 196 0\n"
"gpr b0 .1 210 0\n"
"gpr b1 .1 211 0\n"
"gpr b2 .1 212 0\n"
"gpr b3 .1 213 0\n"
"gpr b4 .1 214 0\n"
"gpr b5 .1 215 0\n"
"gpr b6 .1 216 0\n"
"gpr b7 .1 217 0\n"
"gpr b8 .1 218 0\n"
"gpr b9 .1 219 0\n"
"gpr b10 .1 220 0\n"
"gpr b11 .1 221 0\n"
"gpr b12 .1 222 0\n"
"gpr b13 .1 223 0\n"
"gpr b14 .1 224 0\n"
"gpr b15 .1 225 0\n"
/*Special Registers*/
/*0*/ "gpr lbeg .32 226 0\n"
/*1*/ "gpr lend .32 230 0\n"
/*2*/ "gpr lcount .32 234 0\n"
/*3*/ "gpr sar .32 238 0\n"
/*4*/ "gpr br .32 242 0\n"
/*5*/ "gpr litbase .32 246 0\n"
/*12*/ "gpr scompare1 .32 274 0\n"
/*16*/ "gpr acclo .32 290 0\n"
/*17*/ "gpr acchi .32 294 0\n"
/*32*/ "gpr m0 .32 354 0\n"
/*33*/ "gpr m1 .32 358 0\n"
/*34*/ "gpr m2 .32 362 0\n"
/*35*/ "gpr m3 .32 366 0\n"
/*72*/ "gpr windowbase .32 514 0\n"
/*73*/ "gpr windowstart .32 518 0\n"
/*83*/ "gpr ptevaddr .32 546 0\n"
/*90*/ "gpr rasid .32 570 0\n"
/*91*/ "gpr itlbcfg .32 574 0\n"
/*92*/ "gpr dtlbcfg .32 578 0\n"
/*95*/ "gpr eracess .32 586 0\n"
/*96*/ "gpr ibreakenable .32 590 0\n"
/*97*/ "gpr memctl .32 594 0\n"
/*99*/ "gpr atomctl .32 602 0\n"
/*104*/ "gpr ddr .32 618 0\n"
/*106*/ "gpr mepc .32 626 0\n"
/*107*/ "gpr meps .32 630 0\n"
/*108*/ "gpr mesave .32 634 0\n"
/*109*/ "gpr mesr .32 638 0\n"
/*110*/ "gpr mecr .32 642 0\n"
/*111*/ "gpr mevaddr .32 646 0\n"
/*128*/ "gpr ibreaka0 .32 690 0\n"
/*129*/ "gpr ibreaka1 .32 694 0\n"
/*144*/ "gpr dbreaka0 .32 738 0\n"
/*145*/ "gpr dbreaka1 .32 742 0\n"
/*160*/ "gpr dbreakc0 .32 786 0\n"
/*161*/ "gpr dbreakc1 .32 790 0\n"
/*177*/ "gpr epc1 .32 934 0\n"
/*178*/ "gpr epc2 .32 938 0\n"
/*179*/ "gpr epc3 .32 942 0\n"
/*180*/ "gpr epc4 .32 946 0\n"
/*181*/ "gpr epc5 .32 950 0\n"
/*182*/ "gpr epc6 .32 954 0\n"
/*183*/ "gpr epc7 .32 958 0\n"
/*192*/ "gpr depc .32 994 0\n"
/*193*/ "gpr eps1 .32 998 0\n"
/*194*/ "gpr eps2 .32 1002 0\n"
/*195*/ "gpr eps3 .32 1006 0\n"
/*196*/ "gpr eps4 .32 1010 0\n"
/*197*/ "gpr eps5 .32 1014 0\n"
/*198*/ "gpr eps6 .32 1018 0\n"
/*199*/ "gpr eps7 .32 1022 0\n"
/*209*/ "gpr excsave1 .32 1062 0\n"
/*210*/ "gpr excsave2 .32 1066 0\n"
/*211*/ "gpr excsave3 .32 1070 0\n"
/*212*/ "gpr excsave4 .32 1074 0\n"
/*213*/ "gpr excsave5 .32 1078 0\n"
/*214*/ "gpr excsave6 .32 1082 0\n"
/*215*/ "gpr excsave7 .32 1086 0\n"
/*224*/ "gpr cpenable .32 1122 0\n"
/*226*/ "gpr interrupt .32 1126 0\n"
/*227*/ "gpr intclear .32 1130 0\n"
/*228*/ "gpr intenable .32 1134 0\n"
/*230*/ "gpr ps .32 1138 0\n"
/*231*/ "gpr vecbase .32 1142 0\n"
/*232*/ "gpr exccause .32 1146 0\n"
/*233*/ "gpr debugcause .32 1150 0\n"
/*234*/ "gpr ccount .32 1154 0\n"
/*235*/ "gpr prid .32 1158 0\n"
/*236*/ "gpr icount .32 1162 0\n"
/*237*/ "gpr icountlevel .32 1166 0\n"
/*238*/ "gpr excvaddr .32 1170 0\n"
/*240*/ "gpr ccompare0 .32 1178 0\n"
/*241*/ "gpr ccompare1 .32 1182 0\n"
/*242*/ "gpr ccompare2 .32 1186 0\n"
/*244*/ "gpr misc0 .32 1190 0\n"
/*245*/ "gpr misc1 .32 1194 0\n"
/*246*/ "gpr misc2 .32 1198 0\n"
/*247*/ "gpr misc3 .32 1202 0\n"
"gpr ndepc .1 2000 0\n"
"gpr ResetVector .32 2004 0\n"
"gpr UserExceptionVector .32 2008 0\n"
"gpr KernelExceptionVector .32 2012 0\n"
"gpr DoubleExceptionVector .32 2016 0\n"
"gpr accx_0 .32 3000 0\n"
"gpr accx_1 .32 3004 0\n"
"gpr bithead .32 3008 0\n"
"gpr bitptr .32 3012 0\n"
"gpr bitsused .32 3016 0\n"
"gpr cbegin0 .32 3020 0\n"
"gpr cend0 .32 3024 0\n"
"gpr cwrap .32 3028 0\n"
"gpr cw_sd_no .32 3032 0\n"
"gpr first_ts .32 3036 0\n"
"gpr nextoffset .32 3040 0\n"
"gpr overflow .32 3044 0\n"
"gpr ovf_sar .32 3048 0\n"
"gpr sar .32 3052 0\n"
"gpr searchdone .32 3056 0\n"
"gpr tablesize .32 3060 0\n"
"gpr ts_fts_bu_bp .32 3064 0\n"
"gpr fft_bit_width .32 3068 0\n"
"gpr gpio_out .32 3072 0\n"
"gpr qacc_h_0 .32 3076 0\n"
"gpr qacc_h_1 .32 3080 0\n"
"gpr qacc_h_2 .32 3084 0\n"
"gpr qacc_h_3 .32 3088 0\n"
"gpr qacc_h_4 .32 3092 0\n"
"gpr qacc_l_0 .32 3096 0\n"
"gpr qacc_l_1 .32 3100 0\n"
"gpr qacc_l_2 .32 3104 0\n"
"gpr qacc_l_3 .32 3108 0\n"
"gpr qacc_l_4 .32 3112 0\n"
"gpr sar_byte .32 3116 0\n"
"gpr ua_state_0 .32 3120 0\n"
"gpr ua_state_1 .32 3124 0\n"
"gpr ua_state_2 .32 3128 0\n"
"gpr ua_state_3 .32 3132 0\n"
"gpr windowunderflow4 .32 3136 0\n"
"gpr windowunderflow8 .32 3140 0\n"
"gpr windowunderflow12 .32 3144 0\n"
"gpr fcr .32 4000 0\n"
"gpr fsr .32 4004 0\n"
// pc
"gpr pc .32 68 0\n"
@ -140,6 +300,11 @@ static void xop_to_rval(RzAnalysis *a, XtensaContext *ctx, cs_xtensa_op *xop, Rz
static void xtensa_analyze_op(RzAnalysis *a, RzAnalysisOp *op, XtensaContext *ctx) {
int src_count = 0;
for (int i = 0; i < ctx->insn->detail->xtensa.op_count; ++i) {
if (src_count >= RZ_ARRAY_SIZE(op->src)) {
rz_warn_if_reached();
break;
}
cs_xtensa_op *xop = XOP(i);
if (xop->access & CS_AC_WRITE) {
xop_to_rval(a, ctx, xop, &op->dst);
@ -276,7 +441,7 @@ static void xtensa_analyze_op(RzAnalysis *a, RzAnalysisOp *op, XtensaContext *ct
case XTENSA_INS_CALL8:
case XTENSA_INS_CALL12:
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
op->jump = ctx->insn->address + IMM(0);
op->jump = (ctx->insn->address + IMM(0)) & ~3;
op->fail = ctx->insn->address + ctx->insn->size;
break;
case XTENSA_INS_MOVEQZ: /* moveqz */
@ -325,6 +490,9 @@ static int xtensa_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut
goto beach;
}
op->size = ctx->insn->size;
op->id = ctx->insn->id;
op->addr = addr;
xtensa_analyze_op(analysis, op, ctx);
if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
@ -339,9 +507,9 @@ static int xtensa_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut
xtensa_analyze_op_esil(ctx, op);
}
op->size = ctx->insn->size;
op->id = ctx->insn->id;
op->addr = addr;
if (mask & RZ_ANALYSIS_OP_MASK_IL) {
xtensa_analyze_op_rzil(ctx, op);
}
xtensa_disassemble_fini(ctx);
return op->size;
@ -359,6 +527,7 @@ RzAnalysisPlugin rz_analysis_plugin_xtensa_cs = {
.bits = 8,
.op = xtensa_op,
.esil = true,
.il_config = xtensa_il_config,
.archinfo = xtensa_archinfo,
.get_reg_profile = xtensa_get_reg_profile,
.init = xtensa_init,

View file

@ -928,7 +928,7 @@ typedef struct rz_analysis_op_t {
st64 stackptr; /* stack pointer */
int refptr; /* if (0) ptr = "reference" else ptr = "load memory of refptr bytes" */
ut64 mmio_address; // mmio address
RzAnalysisValue *src[6];
RzAnalysisValue *src[8];
RzAnalysisValue *dst;
RzList /*<RzAnalysisValue *>*/ *access; /* RzAnalysisValue access information */
RzStrBuf esil;
@ -1230,6 +1230,8 @@ typedef struct rz_analysis_il_init_state_var_t {
RZ_NONNULL RzILVal *val;
} RzAnalysisILInitStateVar;
typedef void (*RzAnalysisILInitCallback)(RzAnalysisILVM *vm, RzReg *reg);
/**
* \brief Description of an initial state of an RzAnalysisILVM
*
@ -1240,6 +1242,7 @@ typedef struct rz_analysis_il_init_state_var_t {
*/
typedef struct rz_analysis_il_init_state_t {
RzVector /*<RzAnalysisILInitStateVar>*/ vars; ///< Contents of global variables
RzAnalysisILInitCallback cb; ///< Callback to run after the initial state has been set up
} RzAnalysisILInitState;
/**

323
test/db/asm/xtensa Normal file

File diff suppressed because one or more lines are too long

View file

@ -445,7 +445,7 @@ a____ 16 32 64 x86.nasm LGPL3 X86 nasm assembler
a____ 16 32 64 x86.nz LGPL3 x86 handmade assembler
_dA__ 16 xap PD XAP4 RISC (CSR)
_dA__ 32 xcore BSD Capstone XCore disassembler (by pancake)
_dAe_ 32 xtensa LGPL3 Capstone Xtensa disassembly plugin (by billow)
_dAeI 32 xtensa LGPL3 Capstone Xtensa disassembly plugin (by billow)
adA__ 8 z80 GPL3 Zilog Z80 (by condret)
EOF
RUN

View file

@ -67,18 +67,18 @@ e asm.arch=xtensa
e asm.bits=32
wx c5000022a020c00200000000000000008000000000000000000000000000000002a030c00000
aes
ar~pc
ar~a0
ar~^pc
ar~^a0
aes
aes
ar~a2
aes
ar~pc
ar~a0
ar~^pc
ar~^a0
aes
aes
ar~pc
ar~a0
ar~^pc
ar~^a0
EOF
EXPECT=<<EOF
pc = 0x00000010
@ -99,11 +99,11 @@ e asm.bits=32
wx 22a002e6320526320200000086fdff
aes
aes
ar~pc
ar~^pc
aes
ar~pc
ar~^pc
aes
ar~pc
ar~^pc
EOF
EXPECT=<<EOF
pc = 0x0000000c
@ -120,7 +120,7 @@ e asm.bits=32
wx 22a002d6920000000000000000000000060000
aes
aes
ar~pc
ar~^pc
EOF
EXPECT=<<EOF
pc = 0x00000010
@ -137,7 +137,7 @@ aes
aes
aes
aes
ar~pc
ar~^pc
EOF
EXPECT=<<EOF
pc = 0x00000010
@ -155,7 +155,7 @@ aeip
aes
aes
aes
ar~pc
ar~^pc
EOF
EXPECT=<<EOF
pc = 0x00000020
@ -172,7 +172,7 @@ s 0x10
aeip
aes
aes
ar~pc
ar~^pc
EOF
EXPECT=<<EOF
pc = 0x00000020
@ -190,7 +190,7 @@ aeip
aes
aes
aes
ar~pc
ar~^pc
EOF
EXPECT=<<EOF
pc = 0x00000020

32
test/db/rzil/xtensa Normal file
View file

@ -0,0 +1,32 @@
NAME=Testing the decryption in emulateme
FILE=bins/xtensa/emulateme.xtensa-esp32-elf
TIMEOUT=30
CMDS=<<EOF
e analysis.cpu=esp32
aaa
pdf @ main
e io.cache=1
aezi
aezsu 0x400238
ps @ obj.seckrit
EOF
EXPECT=<<EOF
; DATA XREF from entry0 @ 0x4000d1
/ int main(int argc, char **argv, char **envp);
| ; arg int argc @ a2
| ; arg char **argv @ a3
| ; arg int32_t arg6 @ a7
| 0x00400220 entry a1, 0x40
| 0x00400223 mov.n a7, a1 ; arg6
| 0x00400225 s32i.n a2, a7, 0x10 ; arg6
| 0x00400227 s32i.n a3, a7, 0x14 ; arg6
| 0x00400229 l32r a8, . 0x4000b4 ; 0x400264 ; "AnyColourYouLike"
| 0x0040022c s32i.n a8, a7, 0 ; arg6
| 0x0040022e l32i a10, a7, 0 ; arg6
| 0x00400231 call8 . -0xb4 ; sym.decrypt
| 0x00400234 movi.n a8, 0
| 0x00400236 mov.n a2, a8
\ 0x00400238 retw.n
Hello from RzIL!
EOF
RUN