mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-23 06:14:53 +00:00
Co-authored-by: phakeobj <phakeobj@users.noreply.github.com>
This commit is contained in:
parent
46ac728d7a
commit
1dbe43d83d
@ -581,6 +581,7 @@ R_API const char *r_anal_op_family_to_string(int n) {
|
||||
case R_ANAL_OP_FAMILY_CRYPTO: return "crpt";
|
||||
case R_ANAL_OP_FAMILY_IO: return "io";
|
||||
case R_ANAL_OP_FAMILY_VIRT: return "virt";
|
||||
case R_ANAL_OP_FAMILY_MTE: return "mte";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -601,6 +602,7 @@ R_API int r_anal_op_family_from_string(const char *f) {
|
||||
{"io", R_ANAL_OP_FAMILY_IO},
|
||||
{"pac", R_ANAL_OP_FAMILY_PAC},
|
||||
{"thread", R_ANAL_OP_FAMILY_THREAD},
|
||||
{"mte", R_ANAL_OP_FAMILY_MTE},
|
||||
};
|
||||
|
||||
int i;
|
||||
|
@ -1,5 +1,129 @@
|
||||
static int hack_handle_dp_reg(ut32 insn, RAnalOp *op) {
|
||||
const bool op0 = (insn >> 30) & 0x1;
|
||||
const bool op1 = (insn >> 28) & 0x1;
|
||||
const ut8 op2 = (insn >> 21) & 0xf;
|
||||
|
||||
// Data-processing (2 source)
|
||||
if (!op0 && op1 && op2 == 6) {
|
||||
const bool sf = (insn >> 31) & 0x1;
|
||||
const bool S = (insn >> 29) & 0x1;
|
||||
const ut8 opcode = (insn >> 10) & 0x1f;
|
||||
if (sf) {
|
||||
if (!S) {
|
||||
if (opcode == 4) {
|
||||
// irg
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
return op->size = 4;
|
||||
} else if (opcode == 0) {
|
||||
// subp
|
||||
op->type = R_ANAL_OP_TYPE_SUB;
|
||||
return op->size = 4;
|
||||
} else if (opcode == 5) {
|
||||
// gmi
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
return op->size = 4;
|
||||
}
|
||||
} else if (S && opcode == 0) {
|
||||
// subps
|
||||
op->type = R_ANAL_OP_TYPE_SUB;
|
||||
return op->size = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int hack_handle_ldst(ut32 insn, RAnalOp *op) {
|
||||
const ut8 op0 = (insn >> 28) & 0xf;
|
||||
const bool op1 = (insn >> 26) & 0x1;
|
||||
ut8 op2 = (insn >> 23) & 0x3;
|
||||
const bool op3 = (insn >> 21) & 0x1;
|
||||
|
||||
// Load/store memory tags
|
||||
if (op0 == 13 && !op1 && (op2 == 2 || op2 == 3) && op3) {
|
||||
const ut8 opc = (insn >> 22) & 0x3;
|
||||
op2 = (insn >> 10) & 0x3;
|
||||
if (op2 > 0) {
|
||||
switch (opc) {
|
||||
case 0:
|
||||
// stg
|
||||
op->type = R_ANAL_OP_TYPE_STORE;
|
||||
return op->size = 4;
|
||||
case 1:
|
||||
// stzg
|
||||
op->type = R_ANAL_OP_TYPE_STORE;
|
||||
return op->size = 4;
|
||||
case 2:
|
||||
// st2g
|
||||
op->type = R_ANAL_OP_TYPE_STORE;
|
||||
return op->size = 4;
|
||||
case 3:
|
||||
// stz2g
|
||||
op->type = R_ANAL_OP_TYPE_STORE;
|
||||
return op->size = 4;
|
||||
}
|
||||
} else if (op2 == 0) {
|
||||
switch (opc) {
|
||||
case 0:
|
||||
// stzgm
|
||||
op->type = R_ANAL_OP_TYPE_STORE;
|
||||
return op->size = 4;
|
||||
case 1:
|
||||
// ldg
|
||||
op->type = R_ANAL_OP_TYPE_LOAD;
|
||||
return op->size = 4;
|
||||
case 2:
|
||||
// stgm
|
||||
op->type = R_ANAL_OP_TYPE_STORE;
|
||||
return op->size = 4;
|
||||
case 3:
|
||||
// ldgm
|
||||
op->type = R_ANAL_OP_TYPE_LOAD;
|
||||
return op->size = 4;
|
||||
}
|
||||
}
|
||||
// Load/store register pair
|
||||
} else if ((op0 & 0x3) == 2) {
|
||||
const ut8 opc = (insn >> 30) & 0x3;
|
||||
const bool V = (insn >> 26) & 0x1;
|
||||
const bool L = (insn >> 22) & 0x1;
|
||||
if (opc == 1 && !V && !L) {
|
||||
// stgp
|
||||
op->type = R_ANAL_OP_TYPE_STORE;
|
||||
return op->size = 4;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int hack_handle_dp_imm(ut32 insn, RAnalOp *op) {
|
||||
const ut8 op0 = (insn >> 23) & 0x7;
|
||||
|
||||
// Add/subtract (immediate, with tags)
|
||||
if (op0 == 3) {
|
||||
const bool sf = (insn >> 31) & 0x1;
|
||||
const bool op_ = (insn >> 30) & 0x1;
|
||||
const bool S = (insn >> 29) & 0x1;
|
||||
const bool o2 = (insn >> 2) & 0x1;
|
||||
if (sf && !S && !o2) {
|
||||
if (op_ ) {
|
||||
// subg
|
||||
op->type = R_ANAL_OP_TYPE_SUB;
|
||||
return op->size = 4;
|
||||
}
|
||||
// addg
|
||||
op->type = R_ANAL_OP_TYPE_ADD;
|
||||
return op->size = 4;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int hackyArmAnal(RAnal *a, RAnalOp *op, const ut8 *buf, int len) {
|
||||
// Hacky support for ARMv8.3
|
||||
int ret = -1;
|
||||
ut32 *insn = (ut32 *)buf;
|
||||
int insn_class = (*insn >> 25) & 0xf;
|
||||
// Hacky support for ARMv8.3 and ARMv8.5
|
||||
if (a->bits == 64 && len >= 4) {
|
||||
// xpaci // e#43c1da
|
||||
if (!memcmp (buf + 1, "\x43\xc1\xda", 3)) {
|
||||
@ -16,6 +140,36 @@ static inline int hackyArmAnal(RAnal *a, RAnalOp *op, const ut8 *buf, int len) {
|
||||
op->type = R_ANAL_OP_TYPE_RET;
|
||||
return op->size = 4;
|
||||
}
|
||||
|
||||
switch (insn_class) {
|
||||
// Data Processing -- Register
|
||||
case 5:
|
||||
case 13:
|
||||
// irg, subp, gmi, subps
|
||||
ret = hack_handle_dp_reg (*insn, op);
|
||||
break;
|
||||
// Data Processing -- Immediate
|
||||
case 8:
|
||||
case 9:
|
||||
// addg, subg
|
||||
ret = hack_handle_dp_imm (*insn, op);
|
||||
break;
|
||||
// Loads and Stores
|
||||
case 4:
|
||||
case 6:
|
||||
case 12:
|
||||
case 14:
|
||||
// stg, stzgm, ldg, stzg, st2g, stgm, stz2g, ldgm, stgp
|
||||
ret = hack_handle_ldst (*insn, op);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
op->family = R_ANAL_OP_FAMILY_MTE;
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <r_lib.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "../arch/arm/asm-arm.h"
|
||||
#include "./asm_arm_hacks.inc"
|
||||
|
||||
bool arm64ass(const char *str, ut64 addr, ut32 *op);
|
||||
static csh cd = 0;
|
||||
@ -91,6 +92,11 @@ static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
if (!buf) {
|
||||
goto beach;
|
||||
}
|
||||
int haa = hackyArmAsm (a, op, buf, len);
|
||||
if (haa > 0) {
|
||||
return haa;
|
||||
}
|
||||
|
||||
n = cs_disasm (cd, buf, R_MIN (4, len), a->pc, 1, &insn);
|
||||
if (n < 1 || insn->size < 1) {
|
||||
ret = -1;
|
||||
|
230
libr/asm/p/asm_arm_hacks.inc
Normal file
230
libr/asm/p/asm_arm_hacks.inc
Normal file
@ -0,0 +1,230 @@
|
||||
static char *hack_handle_dp_imm(ut32 insn) {
|
||||
char *buf_asm = NULL;
|
||||
char *mnemonic = NULL;
|
||||
const ut8 op0 = (insn >> 23) & 0x7;
|
||||
|
||||
// Add/subtract (immediate, with tags)
|
||||
if (op0 == 3) {
|
||||
const bool sf = (insn >> 31) & 0x1;
|
||||
const bool op = (insn >> 30) & 0x1;
|
||||
const bool S = (insn >> 29) & 0x1;
|
||||
const bool o2 = (insn >> 2) & 0x1;
|
||||
if (sf && !S && !o2) {
|
||||
if (op) {
|
||||
mnemonic = "subg";
|
||||
} else {
|
||||
mnemonic = "addg";
|
||||
}
|
||||
}
|
||||
if (mnemonic) {
|
||||
const ut8 uimm6 = ((insn >> 16) & 0x3f) << 4;
|
||||
const ut8 uimm4 = (insn >> 10) & 0xf;
|
||||
const ut8 Xn = (insn >> 5) & 0x1f;
|
||||
const ut8 Xd = (insn >> 0) & 0x1f;
|
||||
buf_asm = r_str_newf ("%s x%d, x%d, #0x%x, #0x%x",
|
||||
mnemonic, Xd, Xn, uimm6, uimm4);
|
||||
buf_asm = r_str_replace (buf_asm, "x31", "sp", 1);
|
||||
return buf_asm;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *hack_handle_dp_reg(ut32 insn) {
|
||||
char *buf_asm = NULL;
|
||||
char *mnemonic = NULL;
|
||||
const bool op0 = (insn >> 30) & 0x1;
|
||||
const bool op1 = (insn >> 28) & 0x1;
|
||||
const ut8 op2 = (insn >> 21) & 0xf;
|
||||
|
||||
// Data-processing (2 source)
|
||||
if (!op0 && op1 && op2 == 6) {
|
||||
const bool sf = (insn >> 31) & 0x1;
|
||||
const bool S = (insn >> 29) & 0x1;
|
||||
const ut8 opcode = (insn >> 10) & 0x1f;
|
||||
if (sf) {
|
||||
if (!S) {
|
||||
if (opcode == 4) {
|
||||
mnemonic = "irg";
|
||||
} else if (opcode == 0) {
|
||||
mnemonic = "subp";
|
||||
} else if (opcode == 5) {
|
||||
mnemonic = "gmi";
|
||||
}
|
||||
} else if (S && opcode == 0) {
|
||||
mnemonic = "subps";
|
||||
}
|
||||
}
|
||||
if (mnemonic) {
|
||||
const ut8 Xm = (insn >> 16) & 0x1f;
|
||||
const ut8 Xn = (insn >> 5) & 0x1f;
|
||||
const ut8 Xd = (insn >> 0) & 0x1f;
|
||||
if (Xm == 31 && !strcmp (mnemonic, "irg")) {
|
||||
// Xm is xzr, discard it
|
||||
buf_asm = r_str_newf ("%s x%d, x%d", mnemonic, Xd, Xn);
|
||||
} else if (!strcmp (mnemonic, "subps") && S == 1 && Xd == 0x1f) {
|
||||
// ccmp is an alias for subps when S == '1' && Xd == '11111'
|
||||
buf_asm = r_str_newf ("cmpp x%d, x%d", Xn, Xm);
|
||||
} else {
|
||||
buf_asm = r_str_newf ("%s x%d, x%d, x%d", mnemonic, Xd, Xn, Xm);
|
||||
}
|
||||
buf_asm = r_str_replace (buf_asm, "x31", "sp", 1);
|
||||
return buf_asm;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *hack_handle_ldst(ut32 insn) {
|
||||
char *buf_asm = NULL;
|
||||
char *mnemonic = NULL;
|
||||
bool ignore_imm9 = false;
|
||||
const ut8 op0 = (insn >> 28) & 0xf;
|
||||
const bool op1 = (insn >> 26) & 0x1;
|
||||
ut8 op2 = (insn >> 23) & 0x3;
|
||||
const bool op3 = (insn >> 21) & 0x1;
|
||||
|
||||
// Load/store memory tags
|
||||
if (op0 == 13 && !op1 && (op2 == 2 || op2 == 3) && op3) {
|
||||
const ut8 opc = (insn >> 22) & 0x3;
|
||||
const ut16 imm9 = ((insn >> 12) & 0x1ff) << 4;
|
||||
op2 = (insn >> 10) & 0x3;
|
||||
const ut8 Xn = (insn >> 5) & 0x1f;
|
||||
const ut8 Xt = (insn >> 0) & 0x1f;
|
||||
|
||||
if (op2 > 0) {
|
||||
switch (opc) {
|
||||
case 0:
|
||||
mnemonic = "stg";
|
||||
break;
|
||||
case 1:
|
||||
mnemonic = "stzg";
|
||||
break;
|
||||
case 2:
|
||||
mnemonic = "st2g";
|
||||
break;
|
||||
case 3:
|
||||
mnemonic = "stz2g";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (op2) {
|
||||
case 1:
|
||||
buf_asm = r_str_newf ("%s x%d, [x%d], #0x%x",
|
||||
mnemonic, Xt, Xn, imm9);
|
||||
break;
|
||||
case 2:
|
||||
buf_asm = r_str_newf ("%s x%d, [x%d, #0x%x]",
|
||||
mnemonic, Xt, Xn, imm9);
|
||||
break;
|
||||
case 3:
|
||||
buf_asm = r_str_newf ("%s x%d, [x%d, #0x%x]!",
|
||||
mnemonic, Xt, Xn, imm9);
|
||||
break;
|
||||
}
|
||||
buf_asm = r_str_replace (buf_asm, "x31", "sp", 1);
|
||||
return buf_asm;
|
||||
} else if (op2 == 0) {
|
||||
switch (opc) {
|
||||
case 0:
|
||||
mnemonic = "stzgm";
|
||||
ignore_imm9 = true;
|
||||
break;
|
||||
case 1:
|
||||
mnemonic = "ldg";
|
||||
break;
|
||||
case 2:
|
||||
mnemonic = "stgm";
|
||||
ignore_imm9 = true;
|
||||
break;
|
||||
case 3:
|
||||
mnemonic = "ldgm";
|
||||
ignore_imm9 = true;
|
||||
break;
|
||||
}
|
||||
if (ignore_imm9) {
|
||||
buf_asm = r_str_newf ("%s x%d, [x%d]",
|
||||
mnemonic, Xt, Xn);
|
||||
} else {
|
||||
buf_asm = r_str_newf ("%s x%d, [x%d, #0x%x]",
|
||||
mnemonic, Xt, Xn, imm9);
|
||||
}
|
||||
buf_asm = r_str_replace (buf_asm, "x31", "sp", 1);
|
||||
return buf_asm;
|
||||
}
|
||||
// Load/store register pair
|
||||
} else if ((op0 & 0x3) == 2) {
|
||||
const ut8 opc = (insn >> 30) & 0x3;
|
||||
const bool V = (insn >> 26) & 0x1;
|
||||
const bool L = (insn >> 22) & 0x1;
|
||||
|
||||
if (opc == 1 && !V && !L) {
|
||||
const ut8 imm7 = ((insn >> 15) & 0x7f) << 4;
|
||||
const ut8 Xt2 = (insn >> 10) & 0x1f;
|
||||
const ut8 Xn = (insn >> 5) & 0x1f;
|
||||
const ut8 Xt = (insn >> 0) & 0x1f;
|
||||
switch (op2) {
|
||||
case 1:
|
||||
buf_asm = r_str_newf ("stgp x%d, x%d, [x%d], #0x%x",
|
||||
Xt, Xt2, Xn, imm7);
|
||||
break;
|
||||
case 2:
|
||||
buf_asm = r_str_newf ("stgp x%d, [x%d, #0x%x]",
|
||||
Xt, Xt2, Xn, imm7);
|
||||
break;
|
||||
case 3:
|
||||
buf_asm = r_str_newf ("stgp x%d, [x%d, #0x%x]!",
|
||||
Xt, Xt2, Xn, imm7);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
buf_asm = r_str_replace (buf_asm, "x31", "sp", 1);
|
||||
return buf_asm;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int hackyArmAsm(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
char *buf_asm = NULL;
|
||||
ut32 *insn = (ut32 *)buf;
|
||||
int insn_class = (*insn >> 25) & 0xf;
|
||||
// Hacky support for ARMv8.5
|
||||
if (a->bits == 64 && len >= 4) {
|
||||
switch (insn_class) {
|
||||
// Data Processing -- Register
|
||||
case 5:
|
||||
case 13:
|
||||
// irg, subp, gmi, subps
|
||||
buf_asm = hack_handle_dp_reg (*insn);
|
||||
break;
|
||||
// Data Processing -- Immediate
|
||||
case 8:
|
||||
case 9:
|
||||
// addg, subg
|
||||
buf_asm = hack_handle_dp_imm (*insn);
|
||||
break;
|
||||
// Loads and Stores
|
||||
case 4:
|
||||
case 6:
|
||||
case 12:
|
||||
case 14:
|
||||
// stg, stzgm, ldg, stzg, st2g, stgm, stz2g, ldgm, stgp
|
||||
buf_asm = hack_handle_ldst (*insn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (buf_asm) {
|
||||
if (!a->immdisp) {
|
||||
r_str_replace_char (buf_asm, '#', 0);
|
||||
}
|
||||
r_strbuf_set (&op->buf_asm, buf_asm);
|
||||
free (buf_asm);
|
||||
return op->size = 4;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
@ -362,6 +362,7 @@ typedef enum {
|
||||
R_ANAL_OP_FAMILY_VIRT, /* virtualization instructions */
|
||||
R_ANAL_OP_FAMILY_PAC, /* pointer authentication instructions */
|
||||
R_ANAL_OP_FAMILY_IO, /* IO instructions (i.e. IN/OUT) */
|
||||
R_ANAL_OP_FAMILY_MTE, /* Memory Tagging Extension instructions */
|
||||
R_ANAL_OP_FAMILY_LAST
|
||||
} RAnalOpFamily;
|
||||
|
||||
|
@ -54,3 +54,45 @@ nth paddr vaddr bind type size lib name
|
||||
6 0x0000aa20 0x0000aa20 GLOBAL FUNC 1176 Java_o__003dc_e
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=ao mte irg addg
|
||||
FILE=bins/mach0/hello-mte
|
||||
CMDS=<<EOF
|
||||
ao@0x100007f10
|
||||
?e --
|
||||
ao@0x100007f14
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
address: 0x100007f10
|
||||
opcode: irg x8, sp, x8
|
||||
disasm: irg x8, sp, x8
|
||||
pseudo: irg x8,sp,x8
|
||||
mnemonic: irg
|
||||
mask: ffffffff
|
||||
prefix: 0
|
||||
id: 0
|
||||
bytes: e813c89a
|
||||
refptr: 0
|
||||
size: 4
|
||||
sign: false
|
||||
type: mov
|
||||
cycles: 0
|
||||
family: mte
|
||||
--
|
||||
address: 0x100007f14
|
||||
opcode: addg x9, x8, 0x20, 0x0
|
||||
disasm: addg x9, x8, 0x20, 0x0
|
||||
pseudo: addg x9,x8,0x20, 0x0
|
||||
mnemonic: addg
|
||||
mask: ffffffff
|
||||
prefix: 0
|
||||
id: 0
|
||||
bytes: 09018291
|
||||
refptr: 0
|
||||
size: 4
|
||||
sign: false
|
||||
type: add
|
||||
cycles: 0
|
||||
family: mte
|
||||
EOF
|
||||
RUN
|
||||
|
@ -266,3 +266,25 @@ a "msr SP_EL0, x3" 034118d5
|
||||
a "msr sp_el0, x3" 034118d5
|
||||
a "cbnz w3, 0x1fffd4" a3feff35
|
||||
a "cbz x3, 0x1fffe8" 43ffffb4
|
||||
d "addg x0, sp, 0x80, 0x4" e0138891
|
||||
d "subg x0, sp, 0x20, 0xf" e03f82d1
|
||||
d "irg sp, x0" 1f10df9a
|
||||
d "irg x13, x3, x7" 6d10c79a
|
||||
d "subp x13, x7, sp" ed00df9a
|
||||
d "gmi x13, x3, x7" 6d14c79a
|
||||
d "subps x13, x3, x7" 6d00c7ba
|
||||
d "cmpp sp, x13" ff03cdba
|
||||
d "stg x13, [x3], 0x0" 6d0420d9
|
||||
d "stg x13, [x3, 0x10]" 6d1820d9
|
||||
d "stg x13, [x3, 0x10]!" 6d1c20d9
|
||||
d "stzgm x12, [x0]" 0c0020d9
|
||||
d "ldg x13, [x3, 0x10]" 6d1060d9
|
||||
d "ldg x13, [x3, 0x0]" 6d0060d9
|
||||
d "stzg x13, [x3], 0x10" 6d1460d9
|
||||
d "stzg x13, [x3, 0x0]" 6d0860d9
|
||||
d "stzg x13, [x3, 0x0]!" 6d0c60d9
|
||||
d "st2g sp, [sp], 0x20" ff27a0d9
|
||||
d "stgm x0, [x1]" 2000a0d9
|
||||
d "stz2g sp, [sp], 0x50" ff57e0d9
|
||||
d "ldgm x10, [x0]" 0a00e0d9
|
||||
d "stgp x1, x3, [x3], 0x70" 618c8368
|
||||
|
Loading…
x
Reference in New Issue
Block a user