diff --git a/doc/learn.md b/doc/learn.md index ff27907..7060d50 100644 --- a/doc/learn.md +++ b/doc/learn.md @@ -1685,3 +1685,23 @@ residual are all word-aligned `complete=false` strings `-O` cannot resolve either), bare indirect calls 1178 -> 1, ~150 misaligned `+0x..7` bogus comments -> 0, and 64439 slots now carry a kind/name plus xrefs. Verified on iOS (Dart 3.13/3.2.5, cws=8) and Android (w0rdle, Dart 2.18, cws=4): 0 misaligned on both. + +## Expose the ObjectPool as r2's global pointer (anal.gp) in r2flutter-A + +x27 (PP) is the only Dart reserved register with a *static* address: the +ObjectPool lives in the snapshot, so we know its base. `r2flutter -p -r` +already emitted `e anal.gp=` / `dr x27=` / `e anal.roregs=...`, but +the analysis command never set them, and the `-R` script had a dead +`dr x27=\`e anal.gp\`` that depended on an unset value. `r2flutter -A` (every +depth) now calls `r2flutter_setup_pp_gp`, which seeds `anal.gp` with the pool +base, `anal.gpseed=x27`, `anal.roregs=x27,gp,zero` and an `f PP` flag, so plain +r2 analysis/ESIL resolves `[x27, off]` pool loads consistently. + +Gotcha worth remembering: `dart_resolve_pp_info` populates the context read +cache (`ctx->rmem`) and can leave a stale layout pointer. `dart_app_new_from_core` +copies the `DartCtx` by value (`memcpy`), so resolving on the live session +context and then running the analysis double-freed that cache (SIGABRT after +"Loaded N functions"). The setup resolves on a shallow copy with its own +`rmem`/`layout` and frees only what it allocated, leaving the session context +pristine. x22 (NULL_REG) and x26 (THR) are runtime pointers with no static +address, so they are documented/annotated, never seeded as anal.gp. diff --git a/src/r2/core_flutter.c b/src/r2/core_flutter.c index c44f63d..976e2c2 100644 --- a/src/r2/core_flutter.c +++ b/src/r2/core_flutter.c @@ -394,6 +394,9 @@ static bool r2flutter_run_cmd(RCore *core, DartCtx *dctx, const R2FlutterCmd *cm if (cmd->analysis_depth >= 2) { dctx->dump_fields = 1; } + // Seed anal.gp/gpseed/roregs with the ObjectPool base for every -A depth + // so plain-r2 analysis can resolve [x27, off] pool loads. + r2flutter_setup_pp_gp (core, dctx); if (cmd->analysis_depth >= 3) { r2flutter_analysis_run (core, dctx, dctx->quiet); } else { diff --git a/src/r2/flutter_analysis.c b/src/r2/flutter_analysis.c index 184e805..707efbb 100644 --- a/src/r2/flutter_analysis.c +++ b/src/r2/flutter_analysis.c @@ -1317,6 +1317,34 @@ static void flutter_scan_functions(RCore *core, FlutterAnalModel *model, Flutter ht_up_free (seen_fcns); } +// Expose the reconstructed ObjectPool as r2's global pointer so that plain-r2 +// analysis and ESIL resolve `[x27, off]` loads to pool addresses, matching how +// `r2flutter -p -r` already wires it up. x27 (PP) is the only Dart reserved +// register with a static address; x22 (NULL_REG) and x26 (THR) are runtime +// pointers and cannot be seeded this way. +void r2flutter_setup_pp_gp(RCore *core, DartCtx *dctx) { + if (!core || !dctx) { + return; + } + // Resolve on a shallow copy: dart_resolve_pp_info populates the read cache + // (ctx->rmem) and can leave a stale layout pointer in the context. The real + // dctx is copied by value into the analysis DartApp, so polluting it here + // would double-free that cache. The copy shares heap-owned pointers with + // dctx, so we only release what we allocated into it (its own rmem). + DartCtx probe = *dctx; + probe.rmem = NULL; + probe.layout = NULL; + DartPpInfo pp = { 0 }; + if (dart_resolve_pp_info (&probe, &pp) && pp.base) { + r_config_set_i (core->config, "anal.gp", pp.base); + r_config_set (core->config, "anal.gpseed", "x27"); + r_config_set (core->config, "anal.roregs", "x27,gp,zero"); + r_flag_set (core->flags, "PP", pp.base, 1); + } + dart_pp_info_fini (&pp); + dart_read_cache_free (probe.rmem); +} + bool r2flutter_analysis_run(RCore *core, DartCtx *dctx, bool quiet) { R_RETURN_VAL_IF_FAIL (core && dctx, false); DartApp *app = dart_app_new_from_core (core, dctx); diff --git a/src/r2/flutter_analysis.h b/src/r2/flutter_analysis.h index 59f210d..bc7e07b 100644 --- a/src/r2/flutter_analysis.h +++ b/src/r2/flutter_analysis.h @@ -5,5 +5,6 @@ #include "../../include/r2flutter/dart_r2.h" bool r2flutter_analysis_run(RCore *core, DartCtx *dctx, bool quiet); +void r2flutter_setup_pp_gp(RCore *core, DartCtx *dctx); #endif diff --git a/test/db/cmd/pp-gp-register-ios b/test/db/cmd/pp-gp-register-ios new file mode 100644 index 0000000..63f4902 --- /dev/null +++ b/test/db/cmd/pp-gp-register-ios @@ -0,0 +1,17 @@ +NAME=r2-pp-gp-register-ios +FILE=bins/ios/Runner.app/Frameworks/App.framework/App +ARGS=-NN -e scr.color=0 -e bin.relocs.apply=true +CMDS=<