Files
pancake 238bec777f Fix arm64 jmptbl detection for multi-LEA dispatchers ##analysis
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`.
2026-04-11 11:22:26 +02:00
..
2026-04-10 01:37:12 +02:00