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.
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 emptygroupsarray:Output:
bc.<cond>(AARCH64_INS_BC, FEAT_HBC / ARMv8.8-9.3) shares the exact same imm19 branch-offset encoding asb.<cond>(differing only in bit 4), so it seems like a straightforward oversight that it isn't taggedjump/branch_relativethe same way.eret/eretaa/eretabanddrpsare exception-level/debug-state control transfers (toELR_ELx) with no operands and no groups at all —AArch64_add_cs_groupsonly addsAARCH64_GRP_RETforret/retaa/retab, nothing for these.Not sure if the missing groups on
eret*/drpsare deliberate (e.g. considered privileged/out-of-scope for generic CFG tooling) or just not implemented yet, but thebc.<cond>gap looks like a plain miss since its siblingb.<cond>is fully tagged. Any consumer that walksinsn.groupsto 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 getjump/branch_relativegroups mirroringb.<cond>, anderet*/drpsare intentionally group-less, or worth a group (e.g. reusingAARCH64_GRP_RET, or a new one) given they're unconditional control transfers.Happy to send a PR if a maintainer confirms the intended direction.