mirror of
https://github.com/radareorg/radare2.git
synced 2026-04-20 16:39:07 +02:00
The arm64 switch-table detection had two long-standing issues that caused missing/incorrect cases on real binaries (e.g. test/bins/elf/libarm64.so): 1. The `add Rd, Rd, #imm` handler that finalises an `adrp/add` pair blindly bumped the *most recent* leaddr, even when the add operated on a different register than the last adrp. With multiple adrp's appearing before their matching adds, the wrong leaddr got bumped and the table base resolved to a bogus address (manifesting as "switch table (0 cases)" comments). 2. The br dispatcher inferred the table/base registers by popping the last two leaddr entries instead of looking at which registers the `ldr*`/`add`/`br` actually consume. That broke patterns where the compiler emits unrelated adrp's between the dispatcher prologue and the indirect branch, or where it reassigns the same register between the load and the add (single-register dispatchers and the classic Swift `adr Rt, table; ldrsw Rl, [Rt,...]; adr Rt, base; add Rd, Rt, Rl; br Rd` shape). Fixes: * `add` now matches the destination reg back to its leaddr_pair before bumping, so multiple in-flight adrp's no longer cross-contaminate. * The br handler scans backwards from the indirect branch (skipping unrelated movs) to identify the actual `add` and `ldr*` consumed by the dispatch, then resolves the corresponding leaddr entries by matching both the register name *and* the most recent op_addr that precedes each consumer (so a single register reassigned mid-block resolves to the correct value at each use site). * When `anal->cmpval` is implausibly stale (clobbered by a previously analysed branch), the case count now falls back to walking the predecessor bb via `try_get_jmptbl_info`.