diff --git a/librz/analysis/p/analysis_tricore_cs.c b/librz/analysis/p/analysis_tricore_cs.c index 4bcdee2111..d05e9b1a22 100644 --- a/librz/analysis/p/analysis_tricore_cs.c +++ b/librz/analysis/p/analysis_tricore_cs.c @@ -96,24 +96,13 @@ rz_analysis_tricore_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *da return -1; } - static csh handle = 0; - static cs_mode omode = CS_MODE_TRICORE_162; - cs_insn *insn; - cs_mode mode = tricore_cpu_to_cs_mode(a->cpu); - if (mode != omode) { - cs_close(&handle); - handle = 0; - omode = mode; - } - - cs_err err = cs_open(CS_ARCH_TRICORE, mode, &handle); - if (err) { - RZ_LOG_ERROR("Failed on cs_open() with error returned: %u\n", err); + csh handle = tricore_setup_cs_handle(a->cpu, NULL); + if (handle == 0) { return -1; } - cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); op->size = 2; + cs_insn *insn = NULL; ut32 count = cs_disasm(handle, (const ut8 *)data, len, addr, 1, &insn); if (count <= 0) { op->type = RZ_ANALYSIS_OP_TYPE_ILL; @@ -414,10 +403,16 @@ static void tricore_op_set_type(RzAnalysisOp *op, csh h, cs_insn *insn) { case TRICORE_INS_ADDS_BU: case TRICORE_INS_ADDS_U: { op->type = RZ_ANALYSIS_OP_TYPE_ADD; - if (insn->detail->tricore.op_count == 2) { + if (tricore_op_count(insn) >= 2) { cs_tricore_op *op1 = tricore_get_op(insn, 1); if (op1->type == TRICORE_OP_IMM) { op->val = op1->imm; + + cs_tricore_op *op0 = tricore_get_op(insn, 0); + if (op0->type == TRICORE_OP_REG && op0->reg == TRICORE_REG_SP) { + op->stackop = RZ_ANALYSIS_STACK_INC; + op->stackptr = op1->imm; + } } } break; @@ -788,14 +783,16 @@ static void tricore_op_set_type(RzAnalysisOp *op, csh h, cs_insn *insn) { case TRICORE_INS_MSUBMS_U: { op->type = RZ_ANALYSIS_OP_TYPE_SUB; cs_tricore_op *op0 = tricore_get_op(insn, 0); - if (op0->type == TRICORE_OP_REG && op0->reg == TRICORE_REG_SP) { - op->stackop = RZ_ANALYSIS_STACK_INC; - op->stackptr = -tricore_get_op_imm(insn, 1); - } - if (insn->detail->tricore.op_count == 2) { + if (tricore_op_count(insn) >= 2) { cs_tricore_op *op1 = tricore_get_op(insn, 1); if (op1->type == TRICORE_OP_IMM) { op->val = op1->imm; + + cs_tricore_op *op1 = tricore_get_op(insn, 1); + if (op0->type == TRICORE_OP_REG && op0->reg == TRICORE_REG_SP) { + op->stackop = RZ_ANALYSIS_STACK_INC; + op->stackptr = -op1->imm; + } } } break; diff --git a/librz/asm/arch/tricore/tricore.inc b/librz/asm/arch/tricore/tricore.inc index 55a849852c..aaf22fb45c 100644 --- a/librz/asm/arch/tricore/tricore.inc +++ b/librz/asm/arch/tricore/tricore.inc @@ -3,6 +3,10 @@ #include +static inline ut8 tricore_op_count(cs_insn *insn) { + return insn->detail->tricore.op_count; +} + static inline cs_mode tricore_cpu_to_cs_mode(const char *cpu_type) { if (RZ_STR_ISNOTEMPTY(cpu_type)) { if (!strcmp(cpu_type, "generic")) { @@ -25,8 +29,9 @@ static inline cs_mode tricore_cpu_to_cs_mode(const char *cpu_type) { } static inline cs_tricore_op *tricore_get_op(cs_insn *insn, int idx) { - if (idx >= insn->detail->tricore.op_count) { - rz_warn_if_reached(); + if (idx >= tricore_op_count(insn)) { + RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\"\n", + idx, tricore_op_count(insn), insn->mnemonic, insn->op_str); return NULL; } return &insn->detail->tricore.operands[idx]; @@ -35,7 +40,8 @@ static inline cs_tricore_op *tricore_get_op(cs_insn *insn, int idx) { static inline const char *tricore_get_op_regname(csh h, cs_insn *insn, int idx) { cs_tricore_op *op = tricore_get_op(insn, idx); if (op->type != TRICORE_OP_REG) { - rz_warn_if_reached(); + RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\" [reg]\n", + idx, tricore_op_count(insn), insn->mnemonic, insn->op_str); return NULL; } return cs_reg_name(h, op->reg); @@ -44,12 +50,32 @@ static inline const char *tricore_get_op_regname(csh h, cs_insn *insn, int idx) static inline st32 tricore_get_op_imm(cs_insn *insn, int idx) { cs_tricore_op *op = tricore_get_op(insn, idx); if (op->type != TRICORE_OP_IMM) { - rz_warn_if_reached(); + RZ_LOG_WARN("Failed to get operand%d [%d]: \"%s %s\" [imm]\n", + idx, tricore_op_count(insn), insn->mnemonic, insn->op_str); return 0; } return op->imm; } -static inline ut8 tricore_op_count(cs_insn *insn) { - return insn->detail->tricore.op_count; +static inline csh tricore_setup_cs_handle(const char *cpu, const char *features) { + static csh handle = 0; + static cs_mode omode = CS_MODE_TRICORE_162; + + cs_mode mode = tricore_cpu_to_cs_mode(cpu); + if (mode != omode) { + cs_close(&handle); + handle = 0; + omode = mode; + } + + if (handle == 0) { + cs_err err = cs_open(CS_ARCH_TRICORE, mode, &handle); + if (err) { + RZ_LOG_ERROR("Failed on cs_open() with error returned: %u\n", err); + return 0; + } + cs_option(handle, CS_OPT_DETAIL, + RZ_STR_ISNOTEMPTY(features) || features == NULL ? CS_OPT_ON : CS_OPT_OFF); + } + return handle; } diff --git a/librz/asm/p/asm_tricore_cs.c b/librz/asm/p/asm_tricore_cs.c index e3b55759eb..6dabebbe63 100644 --- a/librz/asm/p/asm_tricore_cs.c +++ b/librz/asm/p/asm_tricore_cs.c @@ -33,32 +33,22 @@ static int disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) { return -1; } - csh handle; - cs_insn *insn; - cs_mode mode = tricore_cpu_to_cs_mode(a->cpu); - cs_err err = cs_open(CS_ARCH_TRICORE, mode, &handle); - if (err) { - RZ_LOG_ERROR("Failed on cs_open() with error returned: %u\n", err); + csh handle = tricore_setup_cs_handle(a->cpu, a->features); + if (handle == 0) { return -1; } - cs_option(handle, CS_OPT_DETAIL, RZ_STR_ISNOTEMPTY(a->features) ? CS_OPT_ON : CS_OPT_OFF); + cs_insn *insn = NULL; unsigned count = cs_disasm(handle, buf, len, a->pc, 1, &insn); if (count <= 0) { - cs_close(&handle); return -1; } + op->size = insn->size; char *asmstr = rz_str_newf("%s%s%s", insn->mnemonic, RZ_STR_ISNOTEMPTY(insn->op_str) ? " " : "", insn->op_str); rz_asm_op_set_asm(op, asmstr); - op->size = insn->size; - - RzAsmTriCoreState *state = get_state(); - op->asm_toks = rz_asm_tokenize_asm_regex(&op->buf_asm, state->token_patterns); - free(asmstr); - cs_close(&handle); cs_free(insn, count); return op->size; } @@ -84,12 +74,12 @@ static RZ_OWN RzPVector /**/ *get_token_patterns() { TOKEN(NUMBER, "(0x[[:digit:]abcdef]+)"); + TOKEN(MNEMONIC, "([[:alpha:]]+[[:alnum:]\\.]*[[:alnum:]]+)|([[:alpha:]]+)"); + TOKEN(REGISTER, "([adep][[:digit:]]{1,2})|(sp|psw|pcxi|pc|fcx|lcx|isp|icr|pipn|biv|btv)"); TOKEN(SEPARATOR, "([[:blank:]]+)|([,;#\\(\\)\\{\\}:])"); - TOKEN(MNEMONIC, "([[:alpha:]]+[[:alnum:]\\.]*[[:alnum:]]+)|([[:alpha:]]+)"); - TOKEN(NUMBER, "([[:digit:]]+)"); return pvec; diff --git a/librz/core/disasm.c b/librz/core/disasm.c index 6a96202079..3e244c409e 100644 --- a/librz/core/disasm.c +++ b/librz/core/disasm.c @@ -4913,24 +4913,8 @@ static bool set_jump_realname(RzDisasmState *ds, ut64 addr, const char **kw, con * \param op RzAsmOp instance */ void rz_asm_op_tricore_fixup(RzAsmOp *op, RzAsmTriCoreState *state) { - if (!op->asm_toks) { - return; - } char *asmstr = rz_asm_op_get_asm(op); - - RzAsmToken *token = NULL; - rz_vector_foreach(op->asm_toks->tokens, token) { - char *p = asmstr + token->start; - if (token->type != RZ_ASM_TOKEN_SEPARATOR || - rz_str_cmp("#", p, token->len) != 0) { - continue; - } - - for (size_t i = 0; i < token->len; i++) { - *p = -1; - } - } - rz_str_remove_char(asmstr, -1); + rz_str_remove_char(asmstr, '#'); rz_asm_op_set_asm(op, asmstr); op->asm_toks = rz_asm_tokenize_asm_regex(&op->buf_asm, state->token_patterns); }