Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Detection of ARM THUMB context switch #4555

Draft
wants to merge 5 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions librz/arch/fcn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,9 @@ static RzAnalysisBBEndCause run_basic_block_analysis(RzAnalysisTaskItem *item, R
gotoBeach(RZ_ANALYSIS_RET_END);
}
break;
case RZ_ANALYSIS_OP_TYPE_CTX_SWITCH:
analysis->bits = 16;
/* fallthrough */
case RZ_ANALYSIS_OP_TYPE_CCALL:
case RZ_ANALYSIS_OP_TYPE_CALL:
/* call dst */
Expand Down
2 changes: 2 additions & 0 deletions librz/arch/op.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ RZ_API bool rz_analysis_op_nonlinear(int t) {
switch (t) {
// call
case RZ_ANALYSIS_OP_TYPE_CALL:
case RZ_ANALYSIS_OP_TYPE_CTX_SWITCH:
case RZ_ANALYSIS_OP_TYPE_RCALL:
case RZ_ANALYSIS_OP_TYPE_ICALL:
case RZ_ANALYSIS_OP_TYPE_UCALL:
Expand Down Expand Up @@ -401,6 +402,7 @@ RZ_API char *rz_analysis_op_to_string(RzAnalysis *analysis, RzAnalysisOp *op) {
case RZ_ANALYSIS_OP_TYPE_IRCALL:
snprintf(ret, sizeof(ret), "%s()", r0);
break;
case RZ_ANALYSIS_OP_TYPE_CTX_SWITCH:
case RZ_ANALYSIS_OP_TYPE_CALL:
f = rz_analysis_get_fcn_in(analysis, op->jump, RZ_ANALYSIS_FCN_TYPE_NULL);
if (f) {
Expand Down
18 changes: 13 additions & 5 deletions librz/arch/p/analysis/analysis_arm_cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,6 @@ static void anop32(RzAnalysis *a, csh handle, RzAnalysisOp *op, cs_insn *insn, b
const ut64 addr = op->addr;
const int pcdelta = thumb ? 4 : 8;
int i;

op->cond = cond_cs2rz_32(insn->detail->arm.cc);
if (op->cond == RZ_TYPE_COND_NV) {
op->type = RZ_ANALYSIS_OP_TYPE_NOP;
Expand Down Expand Up @@ -1709,7 +1708,16 @@ jmp $$ + 4 + ( [delta] * 2 )
op->reg = cs_reg_name(handle, REGID(0));
} else {
/* blx label */
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
// Extract opcode from bytes
int byte_to_compare = (a->big_endian & CS_MODE_BIG_ENDIAN) ? 3 : 0;
// If 5th bit of opcode is 1, then encoding is A2.
// Only then can the mode switch!
// Compare to immediate bit 1 - if set, is a THUMB CTX switch
if (IMM(0) && 1 && (insn->bytes[byte_to_compare] && 8)) {
op->type = RZ_ANALYSIS_OP_TYPE_CTX_SWITCH;
} else {
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
}
op->jump = IMM(0) & UT32_MAX;
op->fail = addr + op->size;
op->hint.new_bits = (a->bits == 32) ? 16 : 32;
Expand Down Expand Up @@ -1760,7 +1768,8 @@ jmp $$ + 4 + ( [delta] * 2 )
case ARM_INS_BX:
case ARM_INS_BXJ:
/* bx reg */
op->cycles = 4;
if (op->val)
op->cycles = 4;
op->reg = cs_reg_name(handle, REGID(0));
switch (REGID(0)) {
case ARM_REG_LR:
Expand Down Expand Up @@ -1906,6 +1915,7 @@ static void set_opdir(RzAnalysisOp *op) {
case RZ_ANALYSIS_OP_TYPE_JMP:
case RZ_ANALYSIS_OP_TYPE_UJMP:
case RZ_ANALYSIS_OP_TYPE_UCALL:
case RZ_ANALYSIS_OP_TYPE_CTX_SWITCH:
op->direction = RZ_ANALYSIS_OP_DIR_EXEC;
break;
default:
Expand Down Expand Up @@ -2061,7 +2071,6 @@ static void patch_capstone_bugs(cs_insn *insn, int bits, bool big_endian) {

static int analysis_op(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
AnalysisArmCSContext *ctx = (AnalysisArmCSContext *)a->plugin_data;

cs_insn *insn = NULL;
int mode = (a->bits == 16) ? CS_MODE_THUMB : CS_MODE_ARM;
int n, ret;
Expand Down Expand Up @@ -2572,7 +2581,6 @@ static ut8 *analysis_mask(RzAnalysis *analysis, int size, const ut8 *data, ut64
if (!data) {
return NULL;
}

op = rz_analysis_op_new();
ret = malloc(size);
memset(ret, 0xff, size);
Expand Down
2 changes: 1 addition & 1 deletion librz/include/rz_analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ typedef enum {
RZ_ANALYSIS_OP_TYPE_CPL = 45, /* complement */
RZ_ANALYSIS_OP_TYPE_CRYPTO = 46,
RZ_ANALYSIS_OP_TYPE_SYNC = 47,
// RZ_ANALYSIS_OP_TYPE_DEBUG = 43, // monitor/trace/breakpoint
RZ_ANALYSIS_OP_TYPE_CTX_SWITCH = 48
#if 0
RZ_ANALYSIS_OP_TYPE_PRIV = 40, /* privileged instruction */
RZ_ANALYSIS_OP_TYPE_FPU = 41, /* floating point stuff */
Expand Down
Loading