ArmPattern, ArmXORPattern and RuntimeArmPattern build the pattern & mask from arm64 assembly, with wildcard support. The class is constexpr, so the assembly is not in the final product (if the pattern is declared constexpr).
One instruction per line; case, indentation, spacing and ; comments don't matter, so lines pasted from IDA (LDR W8, [X8,#0x18]) or lldb (ldr w8, [x8, #0x18]) both work. lldb prints ADRP operands as page counts and branch targets as absolute addresses, and IDA prints symbols (BL _printf, #off_1000@PAGE), so wildcard those (#?).
? works for any operand: a register (?, or X?/W?/D?/Q?... to keep its kind), an immediate (#?), a shift or extend (LSL #?, ?), a condition (B.?, CSEL X0, X1, X2, ?), BTI targets (BTI ?) or a whole instruction line.
- A
?leaves open exactly the bits that operand decides. A field computed from a?and a known operand is left open too (UBFX X0, X1, #?, #8: imms is lsb + 7). - A register letter pins the width; a bare
?leaves it open, along with what depends on it (scaled offsets, bitfield immr/imms, TBZ's bit 5). Where only one width fits the other operands (LSL ?, ?, #40), that one is used. - In loads and stores a bare
?register is W or X; writeB?/H?/S?/D?/Q?for floating-point/SIMD ones. - Some wildcards can't be expressed with a mask and match more than the alias:
LSL Rd, Rn, #?matches anyUBFM(alsoLSR,UBFX...), and aliases that repeat a register (CINC X?, X?, cond,ROR X?, X?, #n) can't require the two to be the same. - Others match less, as the encoding they name:
LDR Rt, [Rn,#?]is the scaled form (writeLDURfor negative or unaligned offsets, as IDA and lldb print them), andFMOV Dd, #?the 8-bit immediate form, not#0.0(FMOVfrom the zero register).
A bad operand is an error: a compile error for ArmPattern/ArmXORPattern, a std::logic_error naming the line for RuntimeArmPattern (a trap without exceptions). That's a typo, a register that doesn't exist (X31) or doesn't fit (SP where the encoding reads the zero register, W mixed with X, D0 in an integer instruction), a value out of range or misaligned for its field, a symbol instead of a number, an unknown shift, extend or condition, and a missing or extra operand.
- Branches:
B,BL,B.cond,BR,BLR,RET,CBZ,CBNZ,TBZ,TBNZ - Exceptions and hints:
SVC,HVC,SMC,BRK,HLT,UDF,NOP,BTI - Pointer authentication:
PACIASP/PACIBSP/AUTIASP/AUTIBSP(and theZ/1716forms),RETAA,RETAB,BRAA/BRAB/BLRAA/BLRAB(andZforms),LDRAA,LDRAB,PACIA/PACIB/PACDA/PACDB/AUTIA/AUTIB/AUTDA/AUTDB(andZforms),XPACI,XPACD,XPACLRI,PACGA - Addresses and moves:
ADR,ADRP,MOV,MOVZ,MOVN,MOVK,MVN - Arithmetic:
ADD(S),SUB(S),CMP,CMN,NEG(S),ADC(S),SBC(S),NGC(S),MADD,MSUB,MUL,MNEG,SMADDL,SMSUBL,UMADDL,UMSUBL,SMULL,UMULL,SMNEGL,UMNEGL,SMULH,UMULH,SDIV,UDIV - Logical:
AND(S),ORR,EOR,TST,BIC(S),ORN,EON - Shifts and bitfields:
LSL,LSR,ASR,ROR(immediate or register),LSLV,LSRV,ASRV,RORV,UBFM,SBFM,BFM,UBFX,SBFX,BFXIL,UBFIZ,SBFIZ,BFI,EXTR,SXTB,SXTH,SXTW,UXTB,UXTH - Conditionals:
CSEL,CSINC,CSINV,CSNEG,CSET,CSETM,CINC,CINV,CNEG,CCMP,CCMN - Loads and stores:
LDR,STR,LDUR,STUR(W/X and B/H/S/D/Q registers),LDRB,LDRH,LDRSB,LDRSH,LDRSW,STRB,STRHand theirLDUR/STURforms,LDP,STP(W/X and S/D/Q),LDPSW,LDNP,STNP - Exclusive and acquire/release:
LDXR,STXR,LDAXR,STLXR,LDAR,STLR,LDAPR(and theirB/Hforms),LDXP,STXP,LDAXP,STLXP - Atomics:
CAS,SWP,LD<op>,ST<op>with<op>ADD,CLR,EOR,SET,SMAX,SMIN,UMAX,UMIN, each with theA/L/ALandB/Hsuffixes - Floating point:
FMOV(register, to/from W/X, and immediates like#1.0)
Any other mnemonic becomes a wildcard for those 4 bytes, matching any instruction (the IDA plugin asks before searching with one).
Encoded the way assemblers pick them:
MOV: register, SP, or immediate viaMOVZ/MOVN/ORR;MOV Rd, #?matchesMOVZorMOVN.CMP/CMN/TST:SUBS/ADDS/ANDSto the zero register;MVN/NEG(S)/NGC(S):ORN/SUB(S)/SBC(S)from it.LDR/STRoffsets the scaled form can't hold (negative, unaligned):LDUR/STUR.ADD/SUB/CMPimmediates that are negative or multiples of 0x1000: the opposite operation orLSL #12.BIC/BICS/ORN/EONimmediates:AND/ANDS/ORR/EORwith the inverted value.- Register
ADD/SUBwithSP: the extended (UXTX) form. CSET/CSETM/CINC/CINV/CNEG:CSINC/CSINV/CSNEGwith the inverted condition.LSL/LSR/ASRby an immediate,UBFX/UBFIZ/BFI/SXTB...:UBFM/SBFM/BFM;RORby an immediate:EXTR.MUL/MNEG/SMULL...: the multiply-add forms with the zero register;ST<op>:LD<op>into the zero register.FMOV Rd, #0.0:FMOVfrom the zero register.
At the X instruction:
B/BL,B.cond,CBZ/CBNZ,TBZ/TBNZ,LDR(literal) andADRgive their target.ADRPgives the page plus theADD/SUBand load/store offset (including floating-point loads likeLDR D0) that follow it through the same register (skipping NOPs and instructions that leave the register alone).MOVZ/MOVN,ADD/SUBimmediates and load/store offsets give the value.- Any other instruction:
find()returnsnullptr, as for no match.
/r is not used on arm64.