#2992·capstone

AArch64: eret*/drps/bc.<cond> decode correctly but get no instruction groups (jump/branch_relative/ret)

Author: r0ny123Created Jul 11, 2026Updated Jul 12, 2026
LabelsbugAArch64

Tested on capstone 5.0.7 (CS_ARCH_ARM64/CS_MODE_ARM, detail = True).

b.<cond> is correctly tagged with control-flow groups, but several other AArch64 instructions that are just as control-flow-relevant decode with an empty groups array:

python
import capstone
md = capstone.Cs(capstone.CS_ARCH_ARM64, capstone.CS_MODE_ARM)
md.detail = True

tests = {
    'bc.eq': bytes.fromhex('10000054'),  # FEAT_HBC hinted conditional branch
    'b.eq':  bytes.fromhex('00000054'),
    'drps':  bytes.fromhex('e003bfd6'),  # Debug Restore PState
    'eret':  bytes.fromhex('e0039fd6'),
}
for name, code in tests.items():
    for insn in md.disasm(code, 0x401000):
        groups = [insn.group_name(g) for g in insn.groups]
        print(f'{name}: mnemonic={insn.mnemonic!r} groups={groups}')

Output:

bc.eq: mnemonic='bc.eq' groups=[]
b.eq:  mnemonic='b.eq'  groups=['jump', 'branch_relative']
drps:  mnemonic='drps'  groups=[]
eret:  mnemonic='eret'  groups=[]

bc.<cond> (AARCH64_INS_BC, FEAT_HBC / ARMv8.8-9.3) shares the exact same imm19 branch-offset encoding as b.<cond> (differing only in bit 4), so it seems like a straightforward oversight that it isn't tagged jump/branch_relative the same way. eret/eretaa/eretab and drps are exception-level/debug-state control transfers (to ELR_ELx) with no operands and no groups at all — AArch64_add_cs_groups only adds AARCH64_GRP_RET for ret/retaa/retab, nothing for these.

Not sure if the missing groups on eret*/drps are deliberate (e.g. considered privileged/out-of-scope for generic CFG tooling) or just not implemented yet, but the bc.<cond> gap looks like a plain miss since its sibling b.<cond> is fully tagged. Any consumer that walks insn.groups to classify control flow (rather than a hardcoded mnemonic list) will silently treat all four as fall-through/sequential instructions, which is wrong for all of them.

Would appreciate a maintainer's read on whether:

  • bc.<cond> should get jump/branch_relative groups mirroring b.<cond>, and
  • eret*/drps are intentionally group-less, or worth a group (e.g. reusing AARCH64_GRP_RET, or a new one) given they're unconditional control transfers.

Happy to send a PR if a maintainer confirms the intended direction.

Source: capstone-engine/capstone