Skip to content

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

Description

@r0ny123

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    AArch64ArchbugSomething is not working as it should

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions