From daffe8bbbbc78c847f15a25e598c445270bea67a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Sun, 21 May 2023 05:16:37 +0200 Subject: [PATCH] Fix arm64 adrp assembler (#3519) Fixed the calculation of the immediate value and more spaces, e.g. "adrp x0, 0x1234000" are allowed now. --- librz/asm/arch/arm/armass64.c | 43 ++++++++++++----------------------- test/db/asm/arm_64 | 4 +++- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/librz/asm/arch/arm/armass64.c b/librz/asm/arch/arm/armass64.c index 837ae38c52..bac4035779 100644 --- a/librz/asm/arch/arm/armass64.c +++ b/librz/asm/arch/arm/armass64.c @@ -846,41 +846,26 @@ static ut32 logical(ArmOp *op, bool invert, LogicalOp opc) { } else { return UT32_MAX; } - - ut8 flip[4]; - rz_write_le32(flip, data); - return rz_read_be32(flip); + return rz_swap_ut32(data); } -static ut32 adrp(ArmOp *op, ut64 addr, ut32 k) { //, int reg, ut64 dst) { - ut64 at = 0LL; - ut32 data = k; - if (op->operands[0].type == ARM_GPR) { - data |= encode1reg(op); - } else { +static ut32 adrp(ArmOp *op, ut64 addr) { //, int reg, ut64 dst) { + ut32 data = 0x90000000; + if (op->operands[0].type != ARM_GPR) { RZ_LOG_ERROR("assembler: arm64: adrp: invalid assembly. valid usage: adrp x0, addr\n"); return UT32_MAX; } - if (op->operands[1].type == ARM_CONSTANT) { - // XXX what about negative values? - at = op->operands[1].immediate - addr; - at /= 4; - } else { + data |= op->operands[0].reg & 0x1f; + if (op->operands[1].type != ARM_CONSTANT) { RZ_LOG_ERROR("assembler: arm64: adrp: invalid assembly. valid usage: adrp x0, addr\n"); return UT32_MAX; } - ut8 b0 = at; - ut8 b1 = (at >> 3) & 0xff; - -#if 0 - ut8 b2 = (at >> (8 + 7)) & 0xff; - data += b0 << 29; - data += b1 << 16; - data += b2 << 24; -#endif - data += b0 << 16; - data += b1 << 8; - return data; + ut64 imm = op->operands[1].immediate & ~0xfff; + imm -= addr & ~0xfff; + imm >>= 12; + data |= (imm & 3) << 29; + data |= ((imm >> 2) & rz_num_bitmask(19)) << 5; + return rz_swap_ut32(data); } static ut32 adr(ArmOp *op, int addr) { @@ -1396,8 +1381,8 @@ bool arm64ass(const char *str, ut64 addr, ut32 *op) { *op = arithmetic(&ops, 0x11); } else if (!strncmp(str, "adr x", 5)) { // w *op = adr(&ops, addr); - } else if (!strncmp(str, "adrp x", 6)) { - *op = adrp(&ops, addr, 0x00000090); + } else if (!strncmp(str, "adrp ", 5)) { + *op = adrp(&ops, addr); } else if (!strncmp(str, "neg", 3)) { *op = neg(&ops); } else if (!strcmp(str, "isb")) { diff --git a/test/db/asm/arm_64 b/test/db/asm/arm_64 index 8828604eed..36b0fb2366 100644 --- a/test/db/asm/arm_64 +++ b/test/db/asm/arm_64 @@ -42,6 +42,8 @@ a "eon w0, w13, w20" a001344a a "eon x0, x13, x20" a00134ca a "eon x0, x13, x20, ror 15" a03df4ca a "adrp x5, 0x0" 05000090 +ad "adrp x0, 0x11341000" e07fff90 0x12345678 +ad "adrp x0, 0x18343000" e0ff02d0 0x12345678 a "add x0, x1, x2" 2000028b a "add x0, xzr, x30" e0031e8b a "b 0x0" 00000014 @@ -428,7 +430,7 @@ d "add w1, w2, w2, lsl 10" 4128020b 0x0 (set x1 (cast 64 false (+ (cast 32 false d "add w1, w2, w2, lsr 12" 4130420b 0x0 (set x1 (cast 64 false (+ (cast 32 false (var x2)) (>> (cast 32 false (var x2)) (bv 6 0xc) false)))) d "add w1, w2, w2, asr 31" 417c820b 0x0 (set x1 (cast 64 false (+ (cast 32 false (var x2)) (>> (cast 32 false (var x2)) (bv 6 0x1f) (msb (cast 32 false (var x2))))))) d "adr x2, 0x10042" 02020050 0x10000 (set x2 (bv 64 0x10042)) -d "adrp x2, 0x4000" 020000b0 0x3210 (set x2 (bv 64 0x4000)) +ad "adrp x2, 0x4000" 020000b0 0x3210 (set x2 (bv 64 0x4000)) d "and x1, x2, x3" 4100038a 0x0 (set x1 (& (var x2) (var x3))) d "and w1, w2, w3" 4100030a 0x0 (set x1 (cast 64 false (& (cast 32 false (var x2)) (cast 32 false (var x3))))) d "ands x1, x2, x3" 410003ea 0x0 (seq (set x1 (& (var x2) (var x3))) (set zf (is_zero (var x1))) (set nf (msb (var x1))) (set cf false) (set vf false))