mirror of
https://github.com/radareorg/r2flutter.git
synced 2026-11-07 06:26:00 -10:00
Expose the ObjectPool as anal.gp in r2flutter-A
x27/PP is the only Dart reserved register with a static address (the pool is in the snapshot). r2flutter -A now 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 - matching what -p -r already set up. Resolution runs on a shallow DartCtx copy so the per-command read cache (ctx->rmem) is not shared into the analysis DartApp and double-freed.
This commit is contained in:
1 parent
a6fc7e4829
commit
5651efc492
5 files changed
+69
No files matched your search
@@ -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=<base>` / `dr x27=<base>` / `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.
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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=<<EOF2
|
||||
L ../src/r2/core_flutter.so
|
||||
L ../src/r2/core_flutter.dylib
|
||||
r2flutter -A
|
||||
e anal.gp
|
||||
e anal.gpseed
|
||||
f~ PP[0]
|
||||
EOF2
|
||||
EXPECT=<<EOF2
|
||||
0x0022d2d1
|
||||
x27
|
||||
0x0022d2d1
|
||||
EOF2
|
||||
RUN
|
||||
Reference in new issue
Block a user