Fix Tricore disassembly performance (#3729)

* Try fix Tricore slow disassembly
* Fix tricore_op_set_type
This commit is contained in:
billow 2023-08-10 11:48:49 +08:00 committed by GitHub
parent 0a623e1589
commit 28ad8e943d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 59 deletions

View file

@ -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;

View file

@ -3,6 +3,10 @@
#include <capstone/tricore.h>
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;
}

View file

@ -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 /*<RzAsmTokenPattern *>*/ *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;

View file

@ -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);
}