Skip to content

Commit

Permalink
Make AArch64/ARM analysis and asm plugins Capstone v6 compatible. (#4011
Browse files Browse the repository at this point in the history
)

This commit refactors the AArch64 and partially the ARM
plugin to make it Capstone v6 compatible.
Due to the big API changes in Capstone v6 several changes
had to be made.

Because we need to be compatible to Capstone v4 and v5
many include guards are added as well.

Overview of changes done:

**ARM**

- Instruction alias were introduced. This leads to different
decoding and analysis paths taken for certain instructions.
Some alias have their IL code generated like the real
instruction now (no special handling needed anymore).
This change is responsible for many changes you'll encounter.

- The operand details of each instruction are now always the
one of the real instruction. Also for alias.
For example, if "MOV <Wd>, #<imm>" is an alias for `ORR <Wd>, WZR, #<imm>`,
the details by CS hold all three operands of "ORR".
Before, they held only the two of "MOV".

- Several bugs in variable and argument generation
were fixed. Especially the default variable width
for ARM Thumb was changed to 32bit instead of the 16bit.

**AArch64/ARM64**

The changes listed above for ARM, also apply to AArch64.

Additionally:

- Capstone v6 changed the name ARM64 now everywhere to AArch64.
To be compatible with Capstone v4/v5 AArch64 names must be wrapped
into macros which resolve the name, depending on the CS version used.

- Capstone v6 is now more consistent with
register real and alias names.
From now on we use the register alias by default.

**List squashed commit messages:**

[AArch64 CS v6 BEGIN] Change subproject config to use cs-auto-sync-aarch64 branch

Replace ARM64 with version sensitive macros.

Exclude alias if CS version >= 6

Update access to writeback member

Exclude instr alias from inclusion

Update memory operand printing to json.

Enable real instr. detail only for AArch64

Set correct arch name in meson.build for CS

Fix U/SBFM instructions and their alias.

Mark parameters with RZ_OUt/BORROW

Optimize register extension to skip some, if the width already matches.

Adapt width and lsb of U/SBFM alias instructions (ImmR and ImmS are from U/SBFM).

Fix tests correct semantic buy bad syntax

Pass alias MOV instructions to mov()

Handle CSET and CSETM alias

Fix lsl, lsr and asr by handling them as alias.

Fix mov alias.

Handle TST alias

Fix CNEG, CINV alias

Fix bfi and bfxil alias.

Fix sign extensions.

Fix compare instructions.

Fix NEG, NGC, NGCS, NEGS, MVN

Fix CINC

Fix multiply instructions.

Fix ROR

Run clang-format

Handle CMP for ESIL

Handle new position of memory disponents of post index operands.

Fix post-index operations.

Add missing writeback checks for Post and preindex

Handle UBFM and SBFM alias

Handl BFM alias

Handle CMP, CSET and CINC alias

Update meson file of for cs-aarch64 branch

Fix asm tests. Use reg alias now.

Fix condition confusion and incorrect operand usage.

Fix plf test.

Run clang-format

Use register alias in tests

Add support for fp and lr reg alias assembly.

Use reg alias in test

Rename cond tranlate functions r2 -> rz

Fix condition check which assume 0 == invalid.

Fix issues intruduced by rebase

Set CS commit to current next branch.

Rename ARM64 -> AArch64

Add missing source file to meson.build

Remove DisassemblerExtension.c file for CS v5

Update to newest capstone next branch

Bump up CS version

REVERT ME: Get Capstone v4/v5 via git clone until new tars are released.

Wrap setting of CS_DETAIL_REAL into CS version check

Add maybe-unitialized to Capstone C args.

Fix CS pre v6 build by adding guards.

Use reg alias now printed by default by CS.

Bump CS version to most recent next.

Fix build errors due to stircter alias handling in ARM.

Fix RzIL tests introduced by alias introduction to ARM.

Fix ESIL bugs introduced with ARM alias introduction.

- stackptr hasn't been set for POP and PUSH

Add support again for Thumb1 pop/push

Handle PUSHW and POPW alias

Update test case

Add more POP and PUSH alias and enrich detail for other versions of them.

Fix incorrect mem access width guesses for ARM thumb.

Set POP return info if it writes to PC

Fix tests about default var size and POP mem write direction.

Bump CS version to newest next.

Fix incorrect tests.

- TriCore: Functions were in ro section.
- Default arg width in ARM thumb is 32bit.

Revert check for a set stackptr.

stackptr is used in different ways:
1. Safes the offset from the stack frame base.
2. Is interpreted as somthing else for x86 and I cannot find out what, in a reasonably time.

Hence we cannot use it here consistently.

Remove check for non existing ARM_GRP_RET in CSv5

Fix incorrect stack offsets of variables.

'push <reg-list>' instructions for which the second register was the FP,
reset the stackptr variable to 0. This led to wrong bp offsets in the variable names.
In this case it was +0xc.

Bump CS version.

Add copy of meta-programming macros for capstone-sys build.

Update capstone-next.wrap

Use bracket-less met-programming macro to fix Windows build warnings.

Update wrap files for Capstone with branch names

Add new meta-programming macro

Add workaround for MSVC pre-processor bug.
  • Loading branch information
Rot127 committed Dec 19, 2023
1 parent 8fba9b4 commit 9b227eb
Show file tree
Hide file tree
Showing 37 changed files with 2,670 additions and 1,663 deletions.
17 changes: 17 additions & 0 deletions librz/analysis/analysis.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@ RZ_LIB_VERSION(rz_analysis);

static RzAnalysisPlugin *analysis_static_plugins[] = { RZ_ANALYSIS_STATIC_PLUGINS };

/**
* \brief Returns the default size byte width of memory access operations.
* The size is just a best guess.
*
* \param analysis The current RzAnalysis in use.
*
* \return The default width of a memory access in bytes.
*/
RZ_API ut32 rz_analysis_guessed_mem_access_width(RZ_NONNULL const RzAnalysis *analysis) {
if (analysis->bits == 16 && RZ_STR_EQ(analysis->cur->arch, "arm")) {
// Thumb access is usually 4 bytes of memory by default.
return 4;
}
// Best guess for variable size.
return analysis->bits / 8;
}

RZ_API void rz_analysis_set_limits(RzAnalysis *analysis, ut64 from, ut64 to) {
free(analysis->limit);
analysis->limit = RZ_NEW0(RzAnalysisRange);
Expand Down
31 changes: 20 additions & 11 deletions librz/analysis/arch/arm/arm_accessors64.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,30 @@

#include <capstone/capstone.h>

#define IMM64(x) (ut64)(insn->detail->arm64.operands[x].imm)
#define INSOP64(x) insn->detail->arm64.operands[x]
#define IMM64(x) (ut64)(insn->detail->CS_aarch64_.operands[x].imm)
#define INSOP64(x) insn->detail->CS_aarch64_.operands[x]

#define REGID64(x) insn->detail->arm64.operands[x].reg
#define REGBASE64(x) insn->detail->arm64.operands[x].mem.base
#define REGID64(x) insn->detail->CS_aarch64_.operands[x].reg
#define REGBASE64(x) insn->detail->CS_aarch64_.operands[x].mem.base
// s/index/base|reg/
#define HASMEMINDEX64(x) (insn->detail->arm64.operands[x].mem.index != ARM64_REG_INVALID)
#define MEMDISP64(x) (ut64) insn->detail->arm64.operands[x].mem.disp
#define ISIMM64(x) (insn->detail->arm64.operands[x].type == ARM64_OP_IMM)
#define ISREG64(x) (insn->detail->arm64.operands[x].type == ARM64_OP_REG)
#define ISMEM64(x) (insn->detail->arm64.operands[x].type == ARM64_OP_MEM)
#define HASMEMINDEX64(x) (insn->detail->CS_aarch64_.operands[x].mem.index != CS_AARCH64(_REG_INVALID))
#define MEMDISP64(x) (ut64) insn->detail->CS_aarch64_.operands[x].mem.disp
#define ISIMM64(x) (insn->detail->CS_aarch64_.operands[x].type == CS_AARCH64(_OP_IMM))
#define ISREG64(x) (insn->detail->CS_aarch64_.operands[x].type == CS_AARCH64(_OP_REG))
#define ISMEM64(x) (insn->detail->CS_aarch64_.operands[x].type == CS_AARCH64(_OP_MEM))

#define LSHIFT2_64(x) insn->detail->arm64.operands[x].shift.value
#define OPCOUNT64() insn->detail->arm64.op_count
#define LSHIFT2_64(x) insn->detail->CS_aarch64_.operands[x].shift.value
#define OPCOUNT64() insn->detail->CS_aarch64_.op_count

#if CS_NEXT_VERSION < 6
#define ISWRITEBACK64() (insn->detail->arm64.writeback == true)
#else
#define ISWRITEBACK64() (insn->detail->writeback == true)
#endif
#if CS_NEXT_VERSION < 6
#define ISPREINDEX64() (((OPCOUNT64() == 2) && (ISMEM64(1)) && (ISWRITEBACK64())) || ((OPCOUNT64() == 3) && (ISMEM64(2)) && (ISWRITEBACK64())))
#define ISPOSTINDEX64() (((OPCOUNT64() == 3) && (ISIMM64(2)) && (ISWRITEBACK64())) || ((OPCOUNT64() == 4) && (ISIMM64(3)) && (ISWRITEBACK64())))
#else
#define ISPREINDEX64() (!insn->detail->CS_aarch64_.post_index && ISWRITEBACK64())
#define ISPOSTINDEX64() (insn->detail->CS_aarch64_.post_index && ISWRITEBACK64())
#endif
3 changes: 2 additions & 1 deletion librz/analysis/arch/arm/arm_cs.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <rz_analysis.h>
#include <capstone/capstone.h>
#include "../../asm/arch/arm/aarch64_meta_macros.h"

RZ_IPI int rz_arm_cs_analysis_op_32_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, bool thumb);
RZ_IPI int rz_arm_cs_analysis_op_64_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn);
Expand All @@ -18,7 +19,7 @@ RZ_IPI const char *rz_arm32_cs_esil_prefix_cond(RzAnalysisOp *op, ARMCC_CondCode
#else
RZ_IPI const char *rz_arm32_cs_esil_prefix_cond(RzAnalysisOp *op, arm_cc cond_type);
#endif
RZ_IPI const char *rz_arm64_cs_esil_prefix_cond(RzAnalysisOp *op, arm64_cc cond_type);
RZ_IPI const char *rz_arm64_cs_esil_prefix_cond(RzAnalysisOp *op, CS_aarch64_cc() cond_type);

RZ_IPI RzILOpEffect *rz_arm_cs_32_il(csh *handle, cs_insn *insn, bool thumb);
RZ_IPI RzAnalysisILConfig *rz_arm_cs_32_il_config(bool big_endian);
Expand Down
4 changes: 4 additions & 0 deletions librz/analysis/arch/arm/arm_esil32.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,11 @@ RZ_IPI int rz_arm_cs_analysis_op_32_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 a
case ARM_INS_BKPT:
rz_strbuf_setf(&op->esil, "%d,%d,TRAP", IMM(0), IMM(0));
break;
#if CS_NEXT_VERSION < 6
case ARM_INS_NOP:
#else
case ARM_INS_HINT:
#endif
rz_strbuf_setf(&op->esil, ",");
break;
case ARM_INS_BL:
Expand Down
Loading

0 comments on commit 9b227eb

Please sign in to comment.