Update all tests to use commands instead of !! oneliners

This commit is contained in:
pancake committed 2026-09-03 18:09:11 +02:00
1 parent 14c1847177
commit 5d86dff9fa
61 files changed
+915 -514

No files matched your search

+1 -1
View File
@@ -21,7 +21,7 @@ rank; each item states the concrete failure it causes.
| `d387c0b` | Unknown-hash **fingerprinting** replaces the blind hardcoded "v3.9.2 defaults" (`dart_newest_profile()` auto-tracks the profile table). `-H` reports **`version_source`** (`exact-hash`/`override`/`fingerprint`/`unknown`) and labels guessed layouts `~<ver>+ (fingerprint)`. Report and decode paths now share the same layout (previously decode used a degenerate zeroed struct). Test: `header-fingerprint`. |
| `2391781` | Explicit **3.7/3.8/3.10/3.11/3.12 CID + layout profiles** (parsed from each release's real `class_id.h`). Also **verified**: the floored tables were already byte-for-byte correct for *every* release 2.10.0–3.12.1, so no CID value changed — the rows are explicit coverage + a regression anchor. |
| `cd6b655` | Discovery hardening: removed the **bogus instruction-blob classification** (only data snapshots carry magic `0xf5f5dcdc`; a stray hit could poison `iso_instr`); symbol-derived addresses are no longer clobbered by scan guesses; `vaddr==0` duplicates can't erase a good address; magic hits deduped; Mach-O segments skipped. |
| `0716a95` | **Structural instruction-image location** for symbol-less Mach-O: `vm_instr` = first executable section, `iso_instr = align_up(vm_instr + ImageSize, 64)` from the Dart Image header, with cross-checks that fall back to `0` rather than emit junk. Verified on stripped Runner (`0x4000`/`0xe700`, full 7671 IT entries) and AuthPass (`0x5a80`/`0xfdc0`). Adds `scripts/strip_macho_symbols.py` + `discovery-stripped-ios`. |
| `0716a95` | **Structural instruction-image location** for symbol-less Mach-O: `vm_instr` = first executable section, `iso_instr = align_up(vm_instr + ImageSize, 64)` from the Dart Image header, with cross-checks that fall back to `0` rather than emit junk. Verified on stripped Runner (`0x4000`/`0xe700`, full 7671 IT entries) and AuthPass (`0x5a80`/`0xfdc0`). The `discovery-stripped-ios` test clones the mapped thin slice with `o:`, clears symbol/export metadata with `wv4`, and reloads it with `ooi`. |
| `d11ebc3` | **P0.1**: `modern_get_fill_spec`'s fallback `rules[]` is keyed by `DartCidKind` and resolved through a per-layout `by_kind[]` table built once in `modern_cid_cache_init`, instead of literal 3.6-era CIDs. Fixes a whole-block off-by-one on 3.2–3.5 layouts (36 CIDs from `SENTINEL` upward got the neighbouring class's ref/scalar layout) and `MonomorphicSmiableCall`/`UnlinkedCall` on 3.9+, where the two swapped places. Abstract classes that never form a cluster (`CallSiteData`, `AbstractType`, `TypedDataBase`) no longer claim a spec. |
| `33bb19b` | **P2.5**: one shared cluster walker (`ModernWalk`) replaces the five hand-rolled tag→cid→alloc→fill loops. Consumers register readers in a `DartCidKind`-keyed table and the walker skips every class they don't claim, so tag decoding, alloc/fill skipping, `start_ref` bookkeeping and the inline-string decision each exist **once** (were 4–5× each). `modern_walk_fill_recorded` serves the resolver, which reads each cluster from its own recorded offset. Verified behaviour-preserving: output byte-identical on 5 samples × 21 actions. |
| `e9fa905` | **Part of P0.2**: the read-only-data rule (`modern_walk_is_rodata`) — the six classes Dart moves into the data image when pointer compression is off (exactly `Serializer::ReadOnlyObjectType`) now correctly emit no fill records. Inert until the gate opens; see P0.2 for what still blocks it. |
+35
View File
@@ -1531,3 +1531,38 @@ version/hash overrides and exact known hashes also bypass the probe, preserving
deterministic user control and fast known-version behavior. Verbose mode reports
candidate validity, scores, the selected range start, or the reason the parser
kept the fingerprint fallback.
## Keep Snapshot Fixtures Inside radare2
Small serialized snapshots can live directly in r2r records as `malloc://`
files populated with `wx`. For tests derived from real binaries, `o: $s` makes
an in-memory copy of the current file; subsequent `wx` or `wv8` commands mutate
that copy without touching the fixture on disk. Open real inputs with `-n` when
the test depends on physical offsets, and patch every occurrence that the old
whole-file replacement changed.
`o:` copies from the current seek, so seek to `0` before cloning a complete
mapped image. It creates and selects the malloc descriptor before filling its
bytes; after changing executable metadata, use `ooi` to parse the completed
in-memory image again. Plain `ob` only lists or selects an existing bin object
and leaves a clone without section or symbol information. For fat Mach-O, a
normal bin load maps the selected thin slice at virtual address zero, which
lets the stripped-discovery test clone and patch the slice without a temporary
file or a Python Mach-O rewriter.
r2r starts radare2 with `-NN` and `R2_NOPLUGINS=1`, so core-plugin tests must
load the local `core_flutter` library explicitly with `L`. Tests try the native
`.dylib` and `.so` names to remain portable. JSON-path (`~{path}`) and gron
(`~{=}`) filters replace most Python extraction pipelines and keep expected
output focused. Empty command output followed by `~{=}` exposed a radare2
console bug: the empty-buffer guard covered JSON formatting but not gron mode,
allowing `r_json_parsedup` to receive NULL. The guard and its `cons_grep`
regression test live in the sibling radare2 tree.
On macOS, a core plugin built with `-undefined dynamic_lookup` must resolve
radare2 APIs from the host process. Linking `R2_LIBS` as well can load a second
installation's `libr_*` dylibs when their install names point at another
prefix. The ABI number can still match while host structures cross library
instances, producing hangs or crashes in parser-heavy commands. The Darwin
plugin target therefore leaves radare2 symbols unresolved; Linux continues to
link the libraries reported by `r2 -H R2_LIBS`.
-10
View File
@@ -1,10 +0,0 @@
#!/bin/sh
# Strip the iOS Runner App snapshot and verify structural instruction
# discovery still works without symbols. Run from the test/ directory.
A=bins/ios/Runner.app/Frameworks/App.framework/App
T=$(mktemp)
if python3 ../scripts/strip_macho_symbols.py "$A" "$T" > /dev/null 2>&1; then
printf "kdart=%s\n" "$(r2 -qc "is~kDart" "$T" 2> /dev/null | grep -c kDart)"
../bin/r2flutter -q -H "$T" 2> /dev/null | grep -oE "vm_instr=\S+ iso_data=\S+ iso_instr=\S+"
fi
rm -f "$T"
-71
View File
@@ -1,71 +0,0 @@
#!/usr/bin/env python3
"""Write a copy of a Mach-O with its symbol table and dyld export trie removed.
Used to build symbol-less test fixtures: the four kDart*Snapshot* symbols are
external/global and load-bearing (the Flutter engine looks them up at runtime),
so strip(1)/llvm-strip cannot remove them. This neutralises LC_SYMTAB (nsyms=0),
LC_DYLD_INFO[_ONLY] (export_off/size=0) and LC_DYLD_EXPORTS_TRIE (datasize=0) in
every arm64 slice (or the thin Mach-O), which makes r2 report no symbols while
leaving the snapshot bytes intact. This exercises r2flutter's symbol-less
discovery path (structural instruction-image location).
Usage: strip_macho_symbols.py <input> <output>
"""
import struct, shutil, sys
CPU_ARM64 = 0x0100000C
def patch_macho(d, base):
is64 = struct.unpack_from('<I', d, base)[0] == 0xfeedfacf
ncmds = struct.unpack_from('<I', d, base + 16)[0]
off = base + (32 if is64 else 28)
acted = False
for _ in range(ncmds):
cmd, cmdsize = struct.unpack_from('<II', d, off)
c = cmd & ~0x80000000
if cmd == 0x2: # LC_SYMTAB -> nsyms = 0
struct.pack_into('<I', d, off + 12, 0)
acted = True
elif c == 0x22: # LC_DYLD_INFO[_ONLY] -> export_off/size = 0
struct.pack_into('<II', d, off + 40, 0, 0)
acted = True
elif c == 0x33: # LC_DYLD_EXPORTS_TRIE -> datasize = 0
struct.pack_into('<I', d, off + 12, 0)
acted = True
off += cmdsize
return acted
def main(src, dst):
shutil.copy(src, dst)
d = bytearray(open(dst, 'rb').read())
magic = struct.unpack_from('>I', d, 0)[0]
ok = False
if magic in (0xcafebabe, 0xcafebabf): # fat
b64 = magic == 0xcafebabf
nfat = struct.unpack_from('>I', d, 4)[0]
ao = 8
for _ in range(nfat):
if b64:
ct, _cs, offset, _sz, _al, _res = struct.unpack_from('>IIQQII', d, ao)
ao += 32
else:
ct, _cs, offset, _sz, _al = struct.unpack_from('>IIIII', d, ao)
ao += 20
if ct == CPU_ARM64:
ok = patch_macho(d, offset) or ok
else:
ok = patch_macho(d, 0)
if not ok:
print("no symbol/export commands found to strip", file=sys.stderr)
return 1
open(dst, 'wb').write(d)
return 0
if __name__ == "__main__":
if len(sys.argv) != 3:
print(__doc__)
sys.exit(2)
sys.exit(main(sys.argv[1], sys.argv[2]))
+1 -1
View File
@@ -269,7 +269,7 @@ static char *dart_signature_to_afs_proto(const char *fname, const char *sig) {
if (!lp) {
return NULL;
}
char *ret = r_str_ndup (sig, (int)(lp - sig));
char *ret = r_str_ndup (sig, (int) (lp - sig));
if (R_STR_ISEMPTY (ret)) {
free (ret);
return NULL;
+10 -10
View File
@@ -903,7 +903,7 @@ static ModernFillSpec modern_get_fill_spec(const ModernCidCache *cids, int cid)
}
if (modern_cid_eq (cid, cids->function)) {
// AOT Function::ReadFill: ReadFromTo (4 refs: name, owner, signature,
// data) + ReadUnsigned(code_index) + Read<uint32_t> kind_tag. On Dart 2.x
// data) + ReadUnsigned (code_index) + Read<uint32_t> kind_tag. On Dart 2.x
// kind_tag is a Dart tagged varint, so read it as such; the token-position
// word is only present with a non-product gen_snapshot (released Flutter
// apps omit it). Newer snapshots keep the previous decoding.
@@ -1048,9 +1048,9 @@ static ModernFillSpec modern_get_fill_spec(const ModernCidCache *cids, int cid)
static const ModernFillSpecRule legacy_rules[] = {
// PatchClass::to_snapshot stops at script_ in AOT: 3 refs, no scalars.
{ DART_CID_PATCH_CLASS, MODERN_FILL_REFS, 3, -1, -1, 0, { 0 } },
// FfiTrampolineData: ReadFromTo (4) + ReadUnsigned(callback_id).
// FfiTrampolineData: ReadFromTo (4) + ReadUnsigned (callback_id).
{ DART_CID_FFI_TRAMPOLINE_DATA, MODERN_FILL_REFS, 4, -1, -1, 1, { MODERN_SCALAR_UNSIGNED } },
// Type: ReadFromTo (3) + ReadUnsigned(type_class_id) + Read<uint8_t>.
// Type: ReadFromTo (3) + ReadUnsigned (type_class_id) + Read<uint8_t>.
{ DART_CID_TYPE, MODERN_FILL_REFS, 3, -1, -1, 2, { MODERN_SCALAR_UNSIGNED, MODERN_SCALAR_UINT8 } },
// TypeParameter: ReadFromTo (3) + Read<int32_t> + 3x Read<uint8_t>.
{ DART_CID_TYPE_PARAMETER, MODERN_FILL_REFS, 3, -1, -1, 4, { MODERN_SCALAR_TAGGED32, MODERN_SCALAR_UINT8, MODERN_SCALAR_UINT8, MODERN_SCALAR_UINT8 } },
@@ -4707,10 +4707,10 @@ typedef struct {
ut64 *code_owner_ref_by_index;
int *code_owner_cid_by_index;
// Signature recovery: FunctionType graph captured during the fill walk.
ut64 *function_sig_ref; // function ref -> its FunctionType ref (signature)
ut64 *ftype_result_ref; // FunctionType ref -> result_type object ref
ut32 *ftype_packed; // FunctionType ref -> packed_parameter_counts
ut64 *type_class_id; // Type ref -> declared class id (cid), 0 if absent
ut64 *function_sig_ref; // function ref -> its FunctionType ref (signature)
ut64 *ftype_result_ref; // FunctionType ref -> result_type object ref
ut32 *ftype_packed; // FunctionType ref -> packed_parameter_counts
ut64 *type_class_id; // Type ref -> declared class id (cid), 0 if absent
HtUP *classname_ref_by_cid; // class cid -> class name string ref
ut64 refs_count;
ut64 itlen;
@@ -4767,7 +4767,7 @@ static bool modern_name_scan_read_class(ModernWalk *w, ClusterStream *s, const M
// Map real class ids (not synthetic top-level ids) to their name so
// a Type's declared class id can be resolved to a class name.
if (!is_top_level && class_id && name_ref && name_ref < u->refs_count && u->classname_ref_by_cid && !ht_up_find (u->classname_ref_by_cid, class_id, NULL)) {
ht_up_insert (u->classname_ref_by_cid, class_id, (void *)(uintptr_t)name_ref);
ht_up_insert (u->classname_ref_by_cid, class_id, (void *) (uintptr_t)name_ref);
}
}
}
@@ -4839,7 +4839,7 @@ static bool modern_name_scan_read_function_type(ModernWalk *w, ClusterStream *s,
return true;
}
// Type::ReadFill: 3 refs then (legacy) ReadUnsigned(type_class_id) + uint8, or
// Type::ReadFill: 3 refs then (legacy) ReadUnsigned (type_class_id) + uint8, or
// (3.x) a single packed flags word carrying the class id at bit 3. Capture the
// declared class id so a return/param Type can be mapped to a class name.
static bool modern_name_scan_read_type(ModernWalk *w, ClusterStream *s, const ModernClusterMeta *m) {
@@ -5042,7 +5042,7 @@ static const char *modern_sig_type_name(const ModernNameScanWalk *u, const Moder
return "Set";
}
if (u->classname_ref_by_cid) {
ut64 name_ref = (ut64)(uintptr_t)ht_up_find (u->classname_ref_by_cid, cid, NULL);
ut64 name_ref = (ut64) (uintptr_t)ht_up_find (u->classname_ref_by_cid, cid, NULL);
if (name_ref && name_ref < u->refs_count && R_STR_ISNOTEMPTY (u->strings_by_ref[name_ref])) {
return u->strings_by_ref[name_ref];
}
+5 -2
View File
@@ -7,7 +7,7 @@ R2_LIBS ?= $(shell r2 -H R2_LIBS 2>/dev/null)
R2_PLUGDIR ?= $(shell r2 -H R2_USER_PLUGINS)
CFLAGS += $(R2_CFLAGS)
LDFLAGS += $(R2_LDFLAGS)
LDLIBS += $(R2_LIBS)
R2_PLUGIN_LIBS = $(R2_LIBS)
DEPFLAGS = -MMD -MP
# Detect platform for shared library extension
@@ -15,6 +15,9 @@ UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
EXT_SO = dylib
LDFLAGS += -dynamiclib -undefined dynamic_lookup
# Resolve radare2 symbols from the host. Linking a second installation's
# libr_* dylibs into a core plugin corrupts ABI-compatible host structures.
R2_PLUGIN_LIBS =
else
EXT_SO = so
LDFLAGS += -shared
@@ -34,7 +37,7 @@ R2FLUTTER_LIB_TARGET = build/libr2flutter.a
all: $(CORE_PLUGIN)
$(CORE_PLUGIN): $(CORE_OBJ) $(R2FLUTTER_LIB)
$(CC) $(LDFLAGS) -o $@ $(CORE_OBJ) $(R2FLUTTER_LIB) $(LDLIBS)
$(CC) $(LDFLAGS) -o $@ $(CORE_OBJ) $(R2FLUTTER_LIB) $(R2_PLUGIN_LIBS) $(LDLIBS)
core_flutter.o: core_flutter.c
$(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
+22 -17
View File
@@ -69,18 +69,18 @@ static void r2flutter_subcmd_help(RCore *core, char action) {
switch (action) {
case 'i':
r_cons_printf (core->cons,
"Usage: r2flutter -i[j*] dump instruction table entries\n"
"Usage: r2flutter -i[jr*] dump instruction table entries\n"
"| -i plain text output\n"
"| -ie dump Dart code entrypoint; with -* mark instruction snapshots as dword arrays\n"
"| -ij JSON output\n"
"| -i* r2 commands output\n");
"| -ir, -i* r2 commands output\n");
break;
case 'e':
r_cons_printf (core->cons,
"Usage: r2flutter -ie[j*] dump Dart code entrypoint\n"
"Usage: r2flutter -ie[jr*] dump Dart code entrypoint\n"
"| -ie plain text output\n"
"| -iej JSON output\n"
"| -ie* r2 commands output; mark instruction snapshots as dword arrays\n");
"| -ier, -ie* r2 commands output; mark instruction snapshots as dword arrays\n");
break;
default:
r2flutter_help (core);
@@ -90,30 +90,31 @@ static void r2flutter_subcmd_help(RCore *core, char action) {
static void r2flutter_help(RCore *core) {
r_cons_printf (core->cons,
"Usage: r2flutter [j*] <action>\n"
"Usage: r2flutter [qjr*] <action>\n"
"| r2flutter -A[AA] analyze dart snapshot and apply flags/comments\n"
"| r2flutter -c[j*] dump classes\n"
"| r2flutter -c[jr*] dump classes\n"
"| r2flutter -C apply Dart classes, fields, methods and types\n"
"| r2flutter -D prof override Dart snapshot profile by hash or version\n"
"| r2flutter -f[j*] dump recovered functions\n"
"| r2flutter -E[jr*] dump Dart code entrypoint\n"
"| r2flutter -f[jr*] dump recovered functions\n"
"| r2flutter -H[HH] dump Dart AOT snapshot header info\n"
"| r2flutter -i[j*] dump instruction table entries\n"
"| r2flutter -ie[j*] dump Dart code entrypoint; with -* mark instruction snapshots as dword arrays\n"
"| r2flutter -i[jr*] dump instruction table entries\n"
"| r2flutter -ie[jr*] dump Dart code entrypoint; with -r/-* mark instruction snapshots as dword arrays\n"
"| r2flutter -l N limit function/instruction-table/xref output\n"
"| r2flutter -m file load Flutter obfuscation map JSON\n"
"| r2flutter -n use heuristic name-pool fallback; names may be wrong\n"
"| r2flutter -O spec decode a tagged pointer, PP slot, or snapshot ref:N\n"
"| r2flutter -p[j*] print reconstructed ObjectPool PP value\n"
"| r2flutter -p[jr*] print reconstructed ObjectPool PP value\n"
"| r2flutter -R dump full radare2 script (like standalone -R)\n"
"| r2flutter -S[j*] dump best-effort recovered SBOM/components\n"
"| r2flutter -T[j*] dump string-based type names\n"
"| r2flutter -x[j*] dump metadata/data-image xrefs; with -z, include string refs/ax in -*\n"
"| r2flutter -z[j*] dump reliable ObjectPool-referenced strings\n"
"| r2flutter -zz[j*] dump all fuzzy/carved strings (-xzz includes refs/ax in -*)\n"
"| r2flutter -S[jr*] dump best-effort recovered SBOM/components\n"
"| r2flutter -T[jr*] dump string-based type names\n"
"| r2flutter -x[jr*] dump metadata/data-image xrefs; with -z, include string refs/ax in -r/-*\n"
"| r2flutter -z[jr*] dump reliable ObjectPool-referenced strings\n"
"| r2flutter -zz[jr*] dump all fuzzy/carved strings (-xzz includes refs/ax in -r/-*)\n"
"| r2flutter -h show this help\n"
"| r2flutter -v increase parser verbosity\n"
"| r2flutter -V show version\n"
"Modifiers: j=json, *=r2 commands\n");
"Modifiers: q=quiet, j=json, r/*=r2 commands\n");
}
static bool r2flutter_analyze(RCore *core, DartCtx *dctx, int quiet) {
@@ -231,6 +232,9 @@ static bool r2flutter_parse_cmd(const char *args, DartCtx *dctx, R2FlutterCmd *c
case 'c':
cmd->action = flag;
break;
case 'E':
cmd->action = 'e';
break;
case 'C':
cmd->action = flag;
break;
@@ -322,6 +326,7 @@ static bool r2flutter_parse_cmd(const char *args, DartCtx *dctx, R2FlutterCmd *c
case 'q':
dctx->quiet = 1;
break;
case 'r':
case '*':
cmd->fmt = 'r';
break;
@@ -428,7 +433,7 @@ static bool r2flutter_run_cmd(RCore *core, DartCtx *dctx, const R2FlutterCmd *cm
r2flutter_dump_r2script (core, dctx);
return true;
case 'S':
out = dart_pool_dump_sbom (dctx, NULL, cmd->fmt);
out = dart_pool_dump_sbom (dctx, core->io && core->io->desc? core->io->desc->name: NULL, cmd->fmt);
break;
case 'z':
out = cmd->string_depth >= 2? dart_pool_dump_strings_fuzzy (dctx, cmd->fmt): dart_pool_dump_strings (dctx, cmd->fmt);
+30 -11
View File
@@ -1,17 +1,36 @@
NAME=serialized-class-layout-metadata
FILE=-
FILE=malloc://0x94
CMDS=<<EOF
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-class-metadata.bin 50414421f5f5dcdc8c000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730086828180800020c182818080808080808280838080807022c4c4c3c2c1c0c08584808080808080858086808080070040c0c5c4c0c0c0c0
!!../bin/r2flutter -q -j -c /tmp/r2flutter-class-metadata.bin 2>/dev/null | python3 -c 'import json,sys; a,b=json.load(sys.stdin); la=a["layout"]; lb=b["layout"]; print(a["ref"], a["class_id"], a["library"]["ref"], a["super"]["type_ref"], la["instance_size"], la["next_field_offset"], la["type_arg_offset"], la["field_bitmap"]); print(b["ref"], b["class_id"], b["library"]["ref"], b["super"]["type_ref"], lb["instance_size"], lb["next_field_offset"], "field_bitmap" in lb, b["flags"]["toplevel"])'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-class-metadata-truncated.bin 50414421f5f5dcdc74000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730086818180800020c181818080808080808280838080807022c4c4c3c2c1c0c0
!!../bin/r2flutter -q -j -c /tmp/r2flutter-class-metadata-truncated.bin 2>/dev/null | python3 -c 'import json,sys; print("truncated_classes", len(json.load(sys.stdin)))'
!!../bin/r2flutter -q -j -HHH /tmp/r2flutter-class-metadata-truncated.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print("truncated_fill", d["snapshots"][0]["clusters"][0]["fill_status"])'
!!rm -f /tmp/r2flutter-class-metadata.bin /tmp/r2flutter-class-metadata-truncated.bin
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
wx 50414421f5f5dcdc8c000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730086828180800020c182818080808080808280838080807022c4c4c3c2c1c0c08584808080808080858086808080070040c0c5c4c0c0c0c0
r2flutter -q -j -c~{=}ref,class_id,layout.,flags.toplevel
o malloc://0x7c
wx 50414421f5f5dcdc74000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730086818180800020c181818080808080808280838080807022c4c4c3c2c1c0c0
r2flutter -q -j -c
r2flutter -q -j -HHH~{snapshots[0].clusters[0].fill_status}
EOF
EXPECT=<<EOF
7 70000 2 3 32 24 16 5
8 1048583 5 6 40 32 False True
truncated_classes 0
truncated_fill failed
json[0].ref = 7;
json[0].class_id = 70000;
json[0].library.ref = 2;
json[0].super.type_ref = 3;
json[0].layout.instance_size = 32;
json[0].layout.next_field_offset = 24;
json[0].layout.type_params = 1;
json[0].layout.type_arg_offset = 16;
json[0].layout.field_bitmap = 5;
json[0].flags.toplevel = false;
json[1].ref = 8;
json[1].class_id = 1048583;
json[1].library.ref = 5;
json[1].super.type_ref = 6;
json[1].layout.instance_size = 40;
json[1].layout.next_field_offset = 32;
json[1].layout.type_params = 0;
json[1].layout.type_arg_offset = 0;
json[1].flags.toplevel = true;
[]
failed
EOF
RUN
+8 -4
View File
@@ -1,7 +1,9 @@
NAME=r2-classes-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -r -c bins/android/first 2>/dev/null | sed -n '1,7p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -c~:0..7
EOF
EXPECT=<<EOF
# Dart classes extracted from snapshot
@@ -15,9 +17,11 @@ EOF
RUN
NAME=text-classes-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -c bins/android/first 2>/dev/null | head -6
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -c~:0..6
EOF
EXPECT=<<EOF
class _Uint16List (size=0)
+8 -4
View File
@@ -1,7 +1,9 @@
NAME=text-classes-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -c bins/ios/Runner.app 2>/dev/null | sed -n '1,6p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -c~:0..6
EOF
EXPECT=<<EOF
class Pointer (size=32)
@@ -14,9 +16,11 @@ EOF
RUN
NAME=r2-classes-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -r -c bins/ios/Runner.app 2>/dev/null | head -7
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -c~:0..7
EOF
EXPECT=<<EOF
# Dart classes extracted from snapshot
+23 -8
View File
@@ -1,6 +1,10 @@
NAME=text-classes-mafia
FILE=-
CMDS=!!../bin/r2flutter -c bins/android/mafia 2>/dev/null | head -6
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -c~:0..6
EOF
EXPECT=<<EOF
class Pointer (size=32)
methods:
@@ -12,17 +16,28 @@ EOF
RUN
NAME=text-classes-mafia-modern-members
FILE=-
CMDS=!!../bin/r2flutter -c bins/android/mafia 2>/dev/null | awk '/class _RawReceivePort@1026248/{raw=1} raw && /_portMap@1026248 static final/{field=1} /firstMatch/{method=1} END { print "field=" field + 0; print "method=" method + 0 }'
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -c~?&_RawReceivePort@1026248,size=32
r2flutter -c~?_portMap@1026248
r2flutter -c~?firstMatch
EOF
EXPECT=<<EOF
field=1
method=1
1
1
1
EOF
RUN
NAME=r2-classes-mafia
FILE=-
CMDS=!!../bin/r2flutter -r -c bins/android/mafia 2>/dev/null | head -7
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -c~:0..7
EOF
EXPECT=<<EOF
# Dart classes extracted from snapshot
# class Pointer (size=32)
+20 -11
View File
@@ -1,17 +1,26 @@
NAME=versioned-code-cluster-layouts
FILE=-
FILE=malloc://0x75
CMDS=<<EOF
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-code-212.bin 50414421f5f5dcdc6d000000000000000300000000000000356239373239326232356630613731353631336237613238653037333466373770726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008284818187ce8180d1818184878080808080808081002c82
!!../bin/r2flutter -q -HHH -l 3 /tmp/r2flutter-code-212.bin 2>/dev/null | python3 -c 'import sys; lines=list(sys.stdin); code=next(x for x in lines if "alloc=code" in x); pool=next(x for x in lines if "bits=" in x); print("2.12", next(x for x in code.split() if x.startswith("fill_status=")), next(x for x in pool.split() if x.startswith("ref=")))'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-code-215.bin 50414421f5f5dcdc6e000000000000000300000000000000323464396434313163326639306338666265383930376639396538396434623070726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008284828785e281c080ea818184878080808080808081002c82
!!../bin/r2flutter -q -HHH -l 3 /tmp/r2flutter-code-215.bin 2>/dev/null | python3 -c 'import sys; lines=list(sys.stdin); code=next(x for x in lines if "alloc=code" in x); pool=next(x for x in lines if "bits=" in x); print("2.15", next(x for x in code.split() if x.startswith("fill_status=")), next(x for x in pool.split() if x.startswith("ref=")))'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-code-217.bin 50414421f5f5dcdc6d000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e7465727300828482878589e281c080ea81818780808080808081002c82
!!../bin/r2flutter -q -HHH -l 3 /tmp/r2flutter-code-217.bin 2>/dev/null | python3 -c 'import sys; lines=list(sys.stdin); code=next(x for x in lines if "alloc=code" in x); pool=next(x for x in lines if "bits=" in x); print("2.17", next(x for x in code.split() if x.startswith("fill_status=")), next(x for x in pool.split() if x.startswith("ref=")))'
!!rm -f /tmp/r2flutter-code-212.bin /tmp/r2flutter-code-215.bin /tmp/r2flutter-code-217.bin
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
wx 50414421f5f5dcdc6d000000000000000300000000000000356239373239326232356630613731353631336237613238653037333466373770726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008284818187ce8180d1818184878080808080808081002c82
r2flutter -q -HHH -l 3~alloc=code:0
r2flutter -q -HHH -l 3~bits=:0
o malloc://0x76
wx 50414421f5f5dcdc6e000000000000000300000000000000323464396434313163326639306338666265383930376639396538396434623070726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008284828785e281c080ea818184878080808080808081002c82
r2flutter -q -HHH -l 3~alloc=code:0
r2flutter -q -HHH -l 3~bits=:0
o malloc://0x75
wx 50414421f5f5dcdc6d000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e7465727300828482878589e281c080ea81818780808080808081002c82
r2flutter -q -HHH -l 3~alloc=code:0
r2flutter -q -HHH -l 3~bits=:0
EOF
EXPECT=<<EOF
2.12 fill_status=ok ref=300
2.15 fill_status=ok ref=300
2.17 fill_status=ok ref=300
0 cid=14 alloc=code fill=code count=1 refs=3..4 flags=canonical alloc=0x63..0x65 fill=0x68..0x71 fill_status=ok main=1
[0] pool_off=0xf pp_off=0x10 bits=0x00 type=tagged_object patch=patchable behavior=snapshotable stream=0x72 value=0x73 ref=300 resolved_kind=out_of_range
0 cid=17 alloc=code fill=code count=1 refs=3..4 flags=- alloc=0x63..0x66 fill=0x69..0x72 fill_status=ok main=1
[0] pool_off=0xf pp_off=0x10 bits=0x00 type=tagged_object patch=patchable behavior=snapshotable stream=0x73 value=0x74 ref=300 resolved_kind=out_of_range
0 cid=17 alloc=code fill=code count=1 refs=3..4 flags=- alloc=0x64..0x67 fill=0x6a..0x71 fill_status=ok main=1
[0] pool_off=0xf pp_off=0x10 bits=0x00 type=tagged_object patch=patchable behavior=snapshotable stream=0x72 value=0x73 ref=300 resolved_kind=out_of_range
EOF
RUN
+15 -4
View File
@@ -1,10 +1,21 @@
NAME=discovery-stripped-ios-structural-instr
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!sh ../scripts/discovery_stripped_ios.sh
s 0
o: 0x321920
wv4 0 @ 0x298
wv4 0 @ 0x29c
wv4 0 @ 0x2ac
ooi
is~?kDart
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -H~{=}vm_instr,iso_data,iso_instr
EOF
EXPECT=<<EOF
kdart=0
vm_instr=0x4000 iso_data=0x1b9600 iso_instr=0xe700
0
json.vm_instr = 16384;
json.iso_data = 1807872;
json.iso_instr = 59136;
EOF
RUN
+12 -6
View File
@@ -1,7 +1,9 @@
NAME=entrypoint-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -qE bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -qE
EOF
EXPECT=<<EOF
0xe768
@@ -9,9 +11,11 @@ EOF
RUN
NAME=json-entrypoint-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -jE bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -jE
EOF
EXPECT=<<EOF
{"entrypoint":59240,"index":0,"code_index":0,"kind":"code","name":"method.PointerEvent.get:radiusMinor","vm_instr":16384,"vm_instr_size":42736,"iso_instr":59136,"iso_instr_size":1712608}
@@ -19,9 +23,11 @@ EOF
RUN
NAME=r2-entrypoint-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -rE bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -rE
EOF
EXPECT=<<EOF
# Dart AOT entrypoint and instruction snapshot data
+53 -29
View File
@@ -1,7 +1,9 @@
NAME=text-fields-synthetic
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!../bin/r2flutter -c bins/synthetic/field_snapshot.bin 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -c
EOF
EXPECT=<<EOF
class TestClass implements TestInterface (size=48)
@@ -20,9 +22,11 @@ EOF
RUN
NAME=json-fields-synthetic
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!../bin/r2flutter -j -c bins/synthetic/field_snapshot.bin 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -c
EOF
EXPECT=<<EOF
[{"ref":12,"name":"TestClass","library":{"ref":11,"name":"package:test"},"interfaces":[{"ref":23,"class_ref":13,"name":"TestInterface"}],"layout":{"instance_size":48,"type_params":1,"type_arg_offset":0},"flags":{"abstract":false,"enum":false,"mixin":false,"toplevel":false},"fields":[{"name":"fieldA","type":"int","offset":16,"flags":{"static":false,"final":false,"const":false,"late":false}},{"name":"items","type":"List<int>","offset":24,"flags":{"static":false,"final":false,"const":false,"late":false}},{"name":"genericItems","type":"List<X0>","offset":32,"flags":{"static":false,"final":false,"const":false,"late":false}},{"name":"callback","type":"(int) => String","offset":40,"flags":{"static":false,"final":false,"const":false,"late":false}}],"methods":[{"name":"compute","entry":0,"owner":"TestClass","signature":"(int) => String","kind_tag":0,"kind":"RegularFunction"}]},{"ref":13,"name":"TestInterface","library":{"ref":11,"name":"package:test"},"layout":{"instance_size":0,"type_params":0,"type_arg_offset":0},"flags":{"abstract":false,"enum":false,"mixin":false,"toplevel":false}}]
@@ -30,9 +34,11 @@ EOF
RUN
NAME=strings-fields-synthetic
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!../bin/r2flutter -zz bins/synthetic/field_snapshot.bin 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -zz
EOF
EXPECT=<<EOF
0x00000018 74 :app "00000000000000000000000000000000product arm64 macos no-compressed-pointers"
@@ -49,9 +55,11 @@ EOF
RUN
NAME=json-strings-fields-synthetic
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!../bin/r2flutter -j -xzz bins/synthetic/field_snapshot.bin 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -xzz
EOF
EXPECT=<<EOF
[{"ref":0,"len":74,"value":"00000000000000000000000000000000product arm64 macos no-compressed-pointers","category":"app","two_byte":false,"canonical":true,"addr":24},{"ref":1,"len":9,"value":"TestClass","category":"lib","two_byte":false,"canonical":true,"addr":110,"refs":[{"obj":12,"type":"class","kind":"class.name","name":"TestClass"}]},{"ref":2,"len":12,"value":"package:test","category":"lib","two_byte":false,"canonical":true,"addr":120,"refs":[{"obj":11,"type":"library","kind":"library.name","name":"package:test"}]},{"ref":3,"len":6,"value":"fieldA","category":"lib","two_byte":false,"canonical":true,"addr":133,"refs":[{"obj":25,"type":"field","kind":"field.name","name":"TestClass.fieldA"}]},{"ref":4,"len":5,"value":"items","category":"lib","two_byte":false,"canonical":true,"addr":144,"refs":[{"obj":26,"type":"field","kind":"field.name","name":"TestClass.items"}]},{"ref":5,"len":12,"value":"genericItems","category":"lib","two_byte":false,"canonical":true,"addr":150,"refs":[{"obj":27,"type":"field","kind":"field.name","name":"TestClass.genericItems"}]},{"ref":6,"len":8,"value":"callback","category":"lib","two_byte":false,"canonical":true,"addr":163,"refs":[{"obj":28,"type":"field","kind":"field.name","name":"TestClass.callback"}]},{"ref":7,"len":7,"value":"compute","category":"lib","two_byte":false,"canonical":true,"addr":172,"refs":[{"obj":29,"type":"function","kind":"method.name","name":"TestClass.compute"}]},{"ref":8,"len":13,"value":"TestInterface","category":"lib","two_byte":false,"canonical":true,"addr":180,"refs":[{"obj":12,"type":"class","kind":"class.interface","name":"TestClass"},{"obj":13,"type":"class","kind":"class.name","name":"TestInterface"}]}]
@@ -59,9 +67,11 @@ EOF
RUN
NAME=xrefs-fields-synthetic
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!../bin/r2flutter -x bins/synthetic/field_snapshot.bin 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -x
EOF
EXPECT=<<EOF
metadata class.name class TestClass [ref=12] -> string TestClass [ref=2] @ 0x6e
@@ -95,43 +105,57 @@ L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -C
e bin.lang
ic | sed 's, dart , ? ,g'
ic
t dart_TestClass
EOF
EXPECT=<<EOF
dart
0x00000000 [0x00000000 - 0x00000000] 0 ? class 0 dart_TestClass :: dart_TestInterface
0x00000000 ? method 0 compute
0x00000010 ? field 0 fieldA
0x00000018 ? field 1 items
0x00000020 ? field 2 genericItems
0x00000028 ? field 3 callback
0x00000000 [0x00000000 - 0x00000000] 0 ? class 1 dart_TestInterface
0x00000000 [0x00000000 - 0x00000000] 0 dart class 0 dart_TestClass :: dart_TestInterface
0x00000000 dart method 0 compute
0x00000010 dart field 0 fieldA
0x00000018 dart field 1 items
0x00000020 dart field 2 genericItems
0x00000028 dart field 3 callback
0x00000000 [0x00000000 - 0x00000000] 0 dart class 1 dart_TestInterface
pf [16].qppp fieldA items genericItems callback
EOF
RUN
NAME=r2-fields-synthetic-safe-type-script
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!../bin/r2flutter -r -c bins/synthetic/field_snapshot.bin 2>/dev/null | awk 'BEGIN { td = 0; bad = 0 } /^"td struct dart_TestClass \{ uint8_t _pad0\[0x10\]; int64_t fieldA; void \* items; void \* genericItems; void \* callback; \};"$/ { td = 1 } /^af @/ || /^afc / || /td struct\.dart/ || /\(int\) => String callback @/ { bad = 1 } END { print "td=" td; print "bad=" bad }'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -c~?td struct dart_TestClass
r2flutter -r -c~?^af
r2flutter -r -c~?struct.dart
r2flutter -r -c~?callback
EOF
EXPECT=<<EOF
td=1
bad=0
1
0
0
3
EOF
RUN
NAME=r2-plugin-C-fields-synthetic
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -q -i \"\$p\" -qc \"r2flutter -C\" -qc ic -qc \"t dart_TestClass\" bins/synthetic/field_snapshot.bin 2>/dev/null" | awk '/class .* dart_TestClass( :: dart_TestInterface)?$/ { cls = 1 } /class .* dart_TestClass :: dart_TestInterface$/ { super = 1 } /method.* compute$/ { method = 1 } /field.* fieldA$/ { field = 1 } /^pf \[16\]\.qppp fieldA items genericItems callback$/ { type = 1 } END { print "class=" cls + 0; print "super=" super + 0; print "method=" method + 0; print "field=" field + 0; print "type=" type + 0 }'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -C
ic~?&class,dart_TestClass
ic~?&dart_TestClass,dart_TestInterface
ic~?&method,compute
ic~?&field,fieldA
t dart_TestClass~?fieldA items genericItems callback
EOF
EXPECT=<<EOF
class=1
super=1
method=1
field=1
type=1
1
1
1
1
1
EOF
RUN
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=text-funcs-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -l 3 bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -l 3
EOF
EXPECT=<<EOF
0x66768 Object.noSuchMethod
+9 -5
View File
@@ -1,7 +1,9 @@
NAME=text-funcs-authpass
FILE=-
FILE=bins/ios/AuthPass.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -f -l 3 bins/ios/AuthPass.app
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -l 3
EOF
EXPECT=<<EOF
0xfe28 method._HashMap_3220832.addAll
@@ -11,11 +13,13 @@ EOF
RUN
NAME=json-funcs-authpass
FILE=-
FILE=bins/ios/AuthPass.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -j -f -l 3 bins/ios/AuthPass.app
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -f -l 3
EOF
EXPECT=<<EOF
[{"addr":65064,"name":"method._HashMap_3220832.addAll"},{"addr":65236,"name":"method._HashMap_3220832.dyn:forEach"},{"addr":65360,"name":"method.MapBase.dyn:map"}]
[{"addr":65064,"name":"method._HashMap_3220832.addAll","signature":"dynamic(_HashMap@3220832)"},{"addr":65236,"name":"method._HashMap_3220832.dyn:forEach","signature":"dynamic(_HashMap@3220832,dynamic)"},{"addr":65360,"name":"method.MapBase.dyn:map","signature":"dynamic(MapBase,dynamic)"}]
EOF
RUN
+8 -6
View File
@@ -1,12 +1,14 @@
NAME=text-funcs-authpass-semantic
FILE=-
FILE=bins/ios/AuthPass.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -q -f bins/ios/AuthPass.app 2>/dev/null | awk '/method\._RawSecureSocket_.*\._secureHandshake_/ { print "handshake=" $1; next } /method\._SecureFilterImpl_.*\.registerBadCertificateCallback$/ { print "register=" $1; next } /method\._SecureFilterImpl_.*\._registerBadCertificateCallback_/ { print "register_impl=" $1; next } /method\._RawSecureSocket_.*\._onBadCertificateWrapper_/ { print "wrapper=" $1; next }'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -f~_secureHandshake_,registerBadCertificateCallback,_registerBadCertificateCallback_,_onBadCertificateWrapper_
EOF
EXPECT=<<EOF
handshake=0x31749c
register=0x3194ec
register_impl=0x31954c
wrapper=0x3199d4
0x31749c method._RawSecureSocket_14069316._secureHandshake_14069316
0x3194ec method._SecureFilterImpl_14069316.registerBadCertificateCallback
0x31954c method._SecureFilterImpl_14069316._registerBadCertificateCallback_14069316
0x3199d4 method._RawSecureSocket_14069316._onBadCertificateWrapper_14069316
EOF
RUN
+9 -5
View File
@@ -1,17 +1,21 @@
NAME=json-funcs-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -j -f -l 3 bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -f -l 3
EOF
EXPECT=<<EOF
[{"addr":59240,"name":"method.PointerEvent.get:radiusMinor"},{"addr":59248,"name":"func.0000e770"},{"addr":59296,"name":"method.PointerEvent.get:distance"}]
[{"addr":59240,"name":"method.PointerEvent.get:radiusMinor","signature":"dynamic(PointerEvent)"},{"addr":59248,"name":"func.0000e770"},{"addr":59296,"name":"method.PointerEvent.get:distance","signature":"dynamic(PointerEvent)"}]
EOF
RUN
NAME=r2-funcs-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -r -f -l 2 bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -f -l 2
EOF
EXPECT=<<EOF
f method.PointerEvent.get:radiusMinor = 0xe768
+33 -17
View File
@@ -1,7 +1,9 @@
NAME=text-funcs-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -l 3 bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -l 3
EOF
EXPECT=<<EOF
0x5b69c0 method.DateTime.compareTo
@@ -11,9 +13,11 @@ EOF
RUN
NAME=r2-funcs-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -r -f -l 2 bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -f -l 2
EOF
EXPECT=<<EOF
f method.DateTime.compareTo = 0x5b69c0
@@ -24,9 +28,11 @@ EOF
RUN
NAME=quiet-r2-funcs-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -qrf -l 2 bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -qrf -l 2
EOF
EXPECT=<<EOF
f method.DateTime.compareTo = 0x5b69c0
@@ -35,12 +41,14 @@ EOF
RUN
NAME=json-funcs-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -j -f -l 3 bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -f -l 3
EOF
EXPECT=<<EOF
[{"addr":5990848,"name":"method.DateTime.compareTo"},{"addr":5991076,"name":"method.Duration.compareTo"},{"addr":5991268,"name":"method.Duration.dyn:_"}]
[{"addr":5990848,"name":"method.DateTime.compareTo","signature":"dynamic(DateTime)"},{"addr":5991076,"name":"method.Duration.compareTo","signature":"dynamic(Duration)"},{"addr":5991268,"name":"method.Duration.dyn:_","signature":"dynamic(Duration,dynamic)"}]
EOF
RUN
@@ -48,9 +56,11 @@ RUN
# stub.Allocate<ClassName>Stub, not shifted into a neighboring method name by
# the name-pool fallback. 0x5b6bf4 is the AllocateDurationStub in this fixture.
NAME=funcs-mafia-allocate-stub
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -q bins/android/mafia 2>/dev/null | grep -E '^0x5b6bf4 '
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -q~0x5b6bf4
EOF
EXPECT=<<EOF
0x5b6bf4 stub.AllocateDurationStub
@@ -60,9 +70,11 @@ RUN
# The same address must NOT appear under any method.fn_* fallback name, which
# was the bug before the Code-owner-cid fix.
NAME=funcs-mafia-allocate-stub-not-fallback
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -q bins/android/mafia 2>/dev/null | grep -c '^0x5b6bf4 method.fn_'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -q~?&0x5b6bf4,method.fn_
EOF
EXPECT=<<EOF
0
@@ -72,9 +84,11 @@ RUN
# Type-test stubs (Code owner is an AbstractType) must be synthesized as
# stub.typetest_* rather than pulling from the name pool.
NAME=funcs-mafia-typetest-stub-present
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -q bins/android/mafia 2>/dev/null | grep -c ' stub.typetest_'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -q~?stub.typetest_
EOF
EXPECT=<<EOF
1277
@@ -85,9 +99,11 @@ RUN
# the count is 4096; if it drops noticeably (e.g. back to zero) the owner-cid
# lookup has regressed.
NAME=funcs-mafia-allocate-stub-count
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -q bins/android/mafia 2>/dev/null | grep -c ' stub.Allocate'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -q~?stub.Allocate
EOF
EXPECT=<<EOF
4096
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=text-funcs-mafia-closure
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -q bins/android/mafia 2>/dev/null | grep -E '0x5b72b0|0x5b74cc'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -q~0x5b72b0,0x5b74cc
EOF
EXPECT=<<EOF
0x5b72b0 method.FlutterError._anon_closure
+12 -6
View File
@@ -1,7 +1,9 @@
NAME=funcs-mafia-name-pool-window
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -q -n -l 6 bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -q -n -l 6
EOF
EXPECT=<<EOF
0x5b69c0 method.DateTime.compareTo
@@ -14,15 +16,19 @@ EOF
RUN
NAME=funcs-mafia-name-pool-stub-counts
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -q -n bins/android/mafia 2>/dev/null | awk '$1=="0x5b6bf4" || $1=="0x5b6f6c" || $1=="0x5bb750" {print} / stub\.Allocate/ {alloc++} / stub\.typetest_/ {type++} END {print "alloc=" alloc; print "typetest=" type}'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -q -n~0x5b6bf4,0x5b6f6c,0x5bb750
r2flutter -f -q -n~?stub.Allocate
r2flutter -f -q -n~?stub.typetest_
EOF
EXPECT=<<EOF
0x5b6bf4 stub.AllocateDurationStub
0x5b6f6c stub.typetest_13
0x5bb750 stub.AllocateStringBufferStub
alloc=4096
typetest=1277
4096
1277
EOF
RUN
+4 -3
View File
@@ -1,7 +1,9 @@
NAME=funcs-mafia-vm-symbol-operators
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -f -q bins/android/mafia 2>/dev/null | awk '$1=="0xe11f60" || $1=="0xe1205c" || $1=="0xe12174" || $1=="0xe12220" || $1=="0xe122a8" {print} $1=="0xe12220" || $1=="0xe122a8" {names[$2]=1} END {n=0; for (name in names) {n++} print "unique_greaterthan=" n}'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -f -q~0xe11f60,0xe1205c,0xe12174,0xe12220,0xe122a8
EOF
EXPECT=<<EOF
0xe11f60 method._Double_0150898.op_add
@@ -9,6 +11,5 @@ EXPECT=<<EOF
0xe12174 method._Double_0150898.op_gt
0xe12220 method._Double_0150898._greaterThan_0150898
0xe122a8 method._IntegerImplementation_0150898.op_gt
unique_greaterthan=2
EOF
RUN
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=json-header-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -j -H bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -H
EOF
EXPECT=<<EOF
{"kind":3,"hash":"f91b8b03bf7f30a5e983fd19b23d978d","vm_data":512,"vm_instr":327680,"iso_data":36544,"iso_instr":419584,"cluster":{"base":1154,"objs":11342,"clusters":47,"it_len":1311,"it_off":64,"total":91657},"cws":8,"dart_version":"2.18.2","version_source":"exact-hash","tag_style":"OBJECT_HEADER","alignment":16,"header_fields":5,"it_capacity":20000,"cid_table":{"cid_class":5,"cid_function":7,"cid_code":18,"cid_string":93,"cid_one_byte_string":94,"cid_two_byte_string":95,"cid_array":90,"cid_mint":61,"cid_object_pool":23,"num_predefined":175}}
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=json-header-authpass
FILE=-
FILE=bins/ios/AuthPass.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -j -H bins/ios/AuthPass.app
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -H
EOF
EXPECT=<<EOF
{"kind":3,"hash":"f71c76320d35b65f1164dbaa6d95fe09","vm_data":7333504,"vm_instr":23168,"iso_data":7368576,"iso_instr":64960,"cluster":{"base":1129,"objs":277373,"clusters":1044,"it_len":37092,"it_off":64,"total":3159106},"cws":8,"dart_version":"3.2.5","version_source":"exact-hash","tag_style":"CID_SHIFT1","alignment":16,"header_fields":5,"it_capacity":20000,"cid_table":{"cid_class":5,"cid_function":7,"cid_code":18,"cid_string":92,"cid_one_byte_string":93,"cid_two_byte_string":94,"cid_array":89,"cid_mint":60,"cid_object_pool":22,"num_predefined":176}}
+6 -4
View File
@@ -1,12 +1,14 @@
NAME=header-deep-macos
FILE=-
FILE=bins/macos/hello/hello.aot
CMDS=<<EOF
!!../bin/r2flutter -q -HHH -l 36 bins/macos/hello/hello.aot 2>/dev/null | grep -Eo '^( detail: object_pool_entries| 34 cid=23 alloc=object_pool fill=object_pool count=1| object_pool ref=9145 index=0 length=1380)'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -HHH -l 36~object_pool_entries,34 cid=23,object_pool ref=9145
EOF
EXPECT=<<EOF
detail: object_pool_entries
detail: object_pool_entries
34 cid=23 alloc=object_pool fill=object_pool count=1
object_pool ref=9145 index=0 length=1380
34 cid=23 alloc=object_pool fill=object_pool count=1 refs=9145..9146 flags=- alloc=0x5ee7b..0x5ee7e fill=0x6e81a..0x6f56e fill_status=ok items=count:1,first:1380,min:1380,max:1380,total:1380
object_pool ref=9145 index=0 length=1380 stream=0x6e81a
EOF
RUN
+6 -4
View File
@@ -1,16 +1,18 @@
NAME=header-extended-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -HH -l 1 bins/ios/Runner.app 2>/dev/null | grep -Eo '^(## (VM|Isolate) Clusters| columns:.*| 0 cid=92 alloc=rodata fill=none count=[0-9]+| \.\.\. [0-9]+ clusters omitted by -l)'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -HH -l 1~VM Clusters,Isolate Clusters,columns,0 cid=92,clusters omitted
EOF
EXPECT=<<EOF
## VM Clusters
columns: idx cid alloc fill count refs flags alloc_range fill_range extras
0 cid=92 alloc=rodata fill=none count=884
0 cid=92 alloc=rodata fill=none count=884 refs=97..981 flags=canonical,immutable alloc=0x1b09d9..0x1b10c6 fill=0x1b118b..0x1b118b fill_status=ok items=count:884,first:91,min:1,max:91,total:2018
... 5 clusters omitted by -l
## Isolate Clusters
columns: idx cid alloc fill count refs flags alloc_range fill_range extras
0 cid=92 alloc=rodata fill=none count=8589
0 cid=92 alloc=rodata fill=none count=8589 refs=1157..9746 flags=canonical,immutable alloc=0x1b96dc..0x1bd9fd fill=0x1c8d24..0x1c8d24 fill_status=ok items=count:8589,first:12413,min:2,max:12413,total:36811
... 334 clusters omitted by -l
EOF
RUN
+7 -3
View File
@@ -1,9 +1,13 @@
NAME=header-fingerprint-unknown-hash
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -j -D ffffffffffffffffffffffffffffffff -H bins/android/first 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print("version=%s source=%s tag=%s" % (d["dart_version"], d["version_source"], d["tag_style"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -D ffffffffffffffffffffffffffffffff -H~{=}dart_version,version_source,tag_style
EOF
EXPECT=<<EOF
version=~3.12.0+ (fingerprint) source=fingerprint tag=OBJECT_HEADER
json.dart_version = "~3.12.0+ (fingerprint)";
json.version_source = "fingerprint";
json.tag_style = "OBJECT_HEADER";
EOF
RUN
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=json-header-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -j -H bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -H
EOF
EXPECT=<<EOF
{"kind":3,"hash":"d20a1be77c3d3c41b2a5accaee1ce549","vm_data":1771776,"vm_instr":16384,"iso_data":1807872,"iso_instr":59136,"cluster":{"base":1156,"objs":51434,"clusters":335,"it_len":7670,"it_off":64,"total":536223},"cws":8,"dart_version":"3.4.3","version_source":"exact-hash","tag_style":"OBJECT_HEADER","alignment":16,"header_fields":5,"it_capacity":20000,"cid_table":{"cid_class":5,"cid_function":7,"cid_code":18,"cid_string":92,"cid_one_byte_string":93,"cid_two_byte_string":94,"cid_array":89,"cid_mint":60,"cid_object_pool":22,"num_predefined":174}}
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=json-header-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -j -H bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -H
EOF
EXPECT=<<EOF
{"kind":3,"hash":"97ff04a728735e6b6b098bdf983faaba","vm_data":832,"vm_instr":5898240,"iso_data":19072,"iso_instr":5990720,"cluster":{"base":1177,"objs":237774,"clusters":1105,"it_len":37258,"it_off":64,"total":4871502},"cws":4,"dart_version":"3.9.2","version_source":"exact-hash","tag_style":"OBJECT_HEADER","alignment":64,"header_fields":5,"it_capacity":20000,"cid_table":{"cid_class":5,"cid_function":7,"cid_code":18,"cid_string":93,"cid_one_byte_string":94,"cid_two_byte_string":95,"cid_array":90,"cid_mint":61,"cid_object_pool":23,"num_predefined":175}}
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=header-markdown
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -H bins/android/first 2>/dev/null | grep -E '^(#{1,2} |={3,}|-{3,})'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -H~Dart AOT Snapshot Header,Snapshot Addresses,VM Snapshot,Isolate Snapshot,Class IDs
EOF
EXPECT=<<EOF
# Dart AOT Snapshot Header
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=header-override-profile
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -j -D 830f4f59e7969c70b595182826435c19 -H bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -D 830f4f59e7969c70b595182826435c19 -H
EOF
EXPECT=<<EOF
{"kind":3,"hash":"830f4f59e7969c70b595182826435c19","vm_data":512,"vm_instr":327680,"iso_data":36544,"iso_instr":419584,"cluster":{"base":1154,"objs":11342,"clusters":47,"it_len":1311,"it_off":64,"total":91657},"cws":8,"dart_version":"3.8.1","version_source":"exact-hash","tag_style":"OBJECT_HEADER","alignment":16,"header_fields":5,"it_capacity":20000,"cid_table":{"cid_class":5,"cid_function":7,"cid_code":18,"cid_string":93,"cid_one_byte_string":94,"cid_two_byte_string":95,"cid_array":90,"cid_mint":61,"cid_object_pool":23,"num_predefined":175}}
+26 -11
View File
@@ -1,17 +1,32 @@
NAME=version-specific-snapshot-headers
FILE=-
FILE=malloc://0x62
CMDS=<<EOF
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-header-210.bin 50414421f5f5dcdc5a000000000000000300000000000000386565346566376136376466393834356662613333313733343139386139353370726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008283818780
!!../bin/r2flutter -j -H /tmp/r2flutter-header-210.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); c=d["cluster"]; print(d["dart_version"], c["clusters"], c["it_len"], c["it_off"], d["header_fields"])'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-header-212.bin 50414421f5f5dcdc5b000000000000000300000000000000356239373239326232356630613731353631336237613238653037333466373770726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e7465727300828381828780
!!../bin/r2flutter -j -H /tmp/r2flutter-header-212.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); c=d["cluster"]; print(d["dart_version"], c["clusters"], c["it_len"], c["it_off"], d["header_fields"])'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-header-217.bin 50414421f5f5dcdc5c000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082838187858980
!!../bin/r2flutter -j -H /tmp/r2flutter-header-217.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); c=d["cluster"]; print(d["dart_version"], c["clusters"], c["it_len"], c["it_off"], d["header_fields"])'
!!rm -f /tmp/r2flutter-header-210.bin /tmp/r2flutter-header-212.bin /tmp/r2flutter-header-217.bin
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
wx 50414421f5f5dcdc5a000000000000000300000000000000386565346566376136376466393834356662613333313733343139386139353370726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008283818780
r2flutter -q -j -H~{=}cluster.clusters,cluster.it_len,cluster.it_off,dart_version,header_fields
o malloc://0x63
wx 50414421f5f5dcdc5b000000000000000300000000000000356239373239326232356630613731353631336237613238653037333466373770726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e7465727300828381828780
r2flutter -q -j -H~{=}cluster.clusters,cluster.it_len,cluster.it_off,dart_version,header_fields
o malloc://0x64
wx 50414421f5f5dcdc5c000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082838187858980
r2flutter -q -j -H~{=}cluster.clusters,cluster.it_len,cluster.it_off,dart_version,header_fields
EOF
EXPECT=<<EOF
2.10.0 1 0 0 4
2.12.0 3 0 0 5
2.17.6 1 5 9 6
json.cluster.clusters = 1;
json.cluster.it_len = 0;
json.cluster.it_off = 0;
json.dart_version = "2.10.0";
json.header_fields = 4;
json.cluster.clusters = 3;
json.cluster.it_len = 0;
json.cluster.it_off = 0;
json.dart_version = "2.12.0";
json.header_fields = 5;
json.cluster.clusters = 1;
json.cluster.it_len = 5;
json.cluster.it_off = 9;
json.dart_version = "2.17.6";
json.header_fields = 6;
EOF
RUN
+12 -6
View File
@@ -1,7 +1,9 @@
NAME=dump-it-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -l 3 -i bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -l 3 -i
EOF
EXPECT=<<EOF
# length=1311 first_entry_with_code=0 canonical_stack_map_entries_offset=25731
@@ -12,9 +14,11 @@ EOF
RUN
NAME=json-it-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -j -l 2 -i bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -l 2 -i
EOF
EXPECT=<<EOF
{"length":1311,"first_entry_with_code":0,"canonical_stack_map_entries_offset":25731,"entries":[{"index":0,"code_index":0,"address":419688,"pc_offset":104,"stack_map_offset":11487,"kind":"code","name":"Object.noSuchMethod"},{"index":1,"code_index":1,"address":419732,"pc_offset":148,"stack_map_offset":10504,"kind":"code","name":"new NoSuchMethodError"}]}
@@ -22,9 +26,11 @@ EOF
RUN
NAME=r2-it-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -r -l 2 -i bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -l 2 -i
EOF
EXPECT=<<EOF
# Dart InstructionTable entries
+12 -6
View File
@@ -1,7 +1,9 @@
NAME=dump-it-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -l 3 -i bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -l 3 -i
EOF
EXPECT=<<EOF
# length=7670 first_entry_with_code=0 canonical_stack_map_entries_offset=160751
@@ -12,9 +14,11 @@ EOF
RUN
NAME=json-it-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -j -l 2 -i bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -l 2 -i
EOF
EXPECT=<<EOF
{"length":7670,"first_entry_with_code":0,"canonical_stack_map_entries_offset":160751,"entries":[{"index":0,"code_index":0,"address":59240,"pc_offset":104,"stack_map_offset":61376,"kind":"code","name":"method.PointerEvent.get:radiusMinor"},{"index":1,"code_index":1,"address":59248,"pc_offset":112,"stack_map_offset":61376,"kind":"code","name":"func.0000e770"}]}
@@ -22,9 +26,11 @@ EOF
RUN
NAME=r2-it-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -r -l 2 -i bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -l 2 -i
EOF
EXPECT=<<EOF
# Dart InstructionTable entries
+12 -6
View File
@@ -1,7 +1,9 @@
NAME=dump-it-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -l 3 -i bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -l 3 -i
EOF
EXPECT=<<EOF
# length=37258 first_entry_with_code=0 canonical_stack_map_entries_offset=827131
@@ -12,9 +14,11 @@ EOF
RUN
NAME=json-it-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -j -l 2 -i bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -l 2 -i
EOF
EXPECT=<<EOF
{"length":37258,"first_entry_with_code":0,"canonical_stack_map_entries_offset":827131,"entries":[{"index":0,"code_index":0,"address":5990848,"pc_offset":128,"stack_map_offset":762000,"kind":"code","name":"method.DateTime.compareTo"},{"index":1,"code_index":1,"address":5991076,"pc_offset":356,"stack_map_offset":762043,"kind":"code","name":"method.Duration.compareTo"}]}
@@ -22,9 +26,11 @@ EOF
RUN
NAME=r2-it-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -r -l 2 -i bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -l 2 -i
EOF
EXPECT=<<EOF
# Dart InstructionTable entries
+51 -21
View File
@@ -1,28 +1,58 @@
NAME=unknown-hash-structural-layout-probe
FILE=-
FILE=bins/android/mafia/libapp.so
ARGS=-n
CMDS=<<EOF
!!python3 -c 'import sys; b=open(sys.argv[1], "rb").read().replace(b"97ff04a728735e6b6b098bdf983faaba", b"a"*32); open(sys.argv[2], "wb").write(b)' bins/android/mafia/libapp.so /tmp/r2flutter-probe-android.bin
!!../bin/r2flutter -q -j -H /tmp/r2flutter-probe-android.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["dart_version"], d["version_source"], d["cid_table"]["num_predefined"], d["cluster"]["clusters"])'
!!python3 -c 'import sys; b=open(sys.argv[1], "rb").read().replace(b"d20a1be77c3d3c41b2a5accaee1ce549", b"b"*32); open(sys.argv[2], "wb").write(b)' bins/ios/Runner.app/Frameworks/App.framework/App /tmp/r2flutter-probe-ios.bin
!!../bin/r2flutter -q -j -H /tmp/r2flutter-probe-ios.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["dart_version"], d["version_source"], d["cid_table"]["num_predefined"], d["cluster"]["clusters"])'
!!python3 -c 'import sys; b=bytes.fromhex(sys.argv[2]).replace(b"0451907c2eaa8467e848c0067bfe8ed4", b"c"*32); open(sys.argv[1], "wb").write(b)' /tmp/r2flutter-probe-single.bin 50414421f5f5dcdc97000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c080808087808080808080808080808080810181
!!../bin/r2flutter -q -j -H /tmp/r2flutter-probe-single.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["dart_version"], d["version_source"], d["single_snapshot"], d["vm_data"], d["iso_data"], d["cluster"]["clusters"])'
!!python3 -c 'import sys; b=bytes.fromhex(sys.argv[2]).replace(b"1441d6b13b8623fa7fbf61433abebd31", b"d"*32); open(sys.argv[1], "wb").write(b)' /tmp/r2flutter-probe-legacy.bin 50414421f5f5dcdc6d000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e7465727300828482878589e281c080ea81818780808080808081002c82
!!../bin/r2flutter -q -j -H /tmp/r2flutter-probe-legacy.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["dart_version"], d["version_source"], d["header_fields"], d["cid_table"]["cid_code"])'
!!../bin/r2flutter -q -j -D 2.17.0 -H /tmp/r2flutter-probe-legacy.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["dart_version"], d["version_source"])'
!!python3 -c 'import sys; b=bytes.fromhex(sys.argv[2]).replace(b"1441d6b13b8623fa7fbf61433abebd31", b"e"*32); open(sys.argv[1], "wb").write(b)' /tmp/r2flutter-probe-incomplete.bin 50414421f5f5dcdc5c000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082838187858980
!!../bin/r2flutter -q -j -H /tmp/r2flutter-probe-incomplete.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["version_source"], d["tag_style"])'
!!python3 -c 'import sys; b=bytearray(open(sys.argv[1], "rb").read()); b[8:16]=(4096).to_bytes(8, "little"); open(sys.argv[2], "wb").write(b)' /tmp/r2flutter-probe-incomplete.bin /tmp/r2flutter-probe-bad-length.bin
!!../bin/r2flutter -q -j -H /tmp/r2flutter-probe-bad-length.bin 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin)["error"])'
!!rm -f /tmp/r2flutter-probe-android.bin /tmp/r2flutter-probe-ios.bin /tmp/r2flutter-probe-single.bin /tmp/r2flutter-probe-legacy.bin /tmp/r2flutter-probe-incomplete.bin /tmp/r2flutter-probe-bad-length.bin
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
o: $s
wx 6161616161616161616161616161616161616161616161616161616161616161 @ 0x354
wx 6161616161616161616161616161616161616161616161616161616161616161 @ 0x4a94
r2flutter -q -j -H~{=}cluster.clusters,dart_version,version_source,num_predefined
on bins/ios/Runner.app/Frameworks/App.framework/App
s 0
o: $s
wx 6262626262626262626262626262626262626262626262626262626262626262 @ 0x1b4914
wx 6262626262626262626262626262626262626262626262626262626262626262 @ 0x1bd614
r2flutter -q -j -H~{=}cluster.clusters,dart_version,version_source,num_predefined
o malloc://0x9f
wx 50414421f5f5dcdc97000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c080808087808080808080808080808080810181
wx 6363636363636363636363636363636363636363636363636363636363636363 @ 0x18
r2flutter -q -j -H~{=}cluster.clusters,dart_version,version_source,single_snapshot,vm_data,iso_data
o malloc://0x75
wx 50414421f5f5dcdc6d000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e7465727300828482878589e281c080ea81818780808080808081002c82
wx 6464646464646464646464646464646464646464646464646464646464646464 @ 0x18
r2flutter -q -j -H~{=}dart_version,version_source,header_fields,cid_code
r2flutter -q -j -D 2.17.0 -H~{=}dart_version,version_source
o malloc://0x64
wx 50414421f5f5dcdc5c000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082838187858980
wx 6565656565656565656565656565656565656565656565656565656565656565 @ 0x18
r2flutter -q -j -H~{=}version_source,tag_style
wv8 4096 @ 8
r2flutter -q -j -H~{error}
EOF
EXPECT=<<EOF
~3.9.0+ (structural-probe) structural-probe 175 1105
~3.4.0+ (structural-probe) structural-probe 174 335
~3.13.0+ (structural-probe) structural-probe True 0 4 4
~2.17.0+ (structural-probe) structural-probe 6 17
2.17.0 override
fingerprint OBJECT_HEADER
json.cluster.clusters = 1105;
json.dart_version = "~3.9.0+ (structural-probe)";
json.version_source = "structural-probe";
json.cid_table.num_predefined = 175;
json.cluster.clusters = 335;
json.dart_version = "~3.4.0+ (structural-probe)";
json.version_source = "structural-probe";
json.cid_table.num_predefined = 174;
json.vm_data = 0;
json.iso_data = 4;
json.single_snapshot = true;
json.cluster.clusters = 4;
json.dart_version = "~3.13.0+ (structural-probe)";
json.version_source = "structural-probe";
json.dart_version = "~2.17.0+ (structural-probe)";
json.version_source = "structural-probe";
json.header_fields = 6;
json.cid_table.cid_code = 17;
json.dart_version = "2.17.0";
json.version_source = "override";
json.version_source = "fingerprint";
json.tag_style = "OBJECT_HEADER";
Dart snapshots not found
EOF
RUN
+9 -5
View File
@@ -1,17 +1,21 @@
NAME=obf-funcs-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -j -f -l 3 -m custom/obf-map.txt bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -f -l 3 -m custom/obf-map.txt
EOF
EXPECT=<<EOF
[{"addr":59240,"name":"method.PointerEvent.get:radiusMinor"},{"addr":59248,"name":"func.0000e770"},{"addr":59296,"name":"method.PointerEvent.get:distance"}]
[{"addr":59240,"name":"method.PointerEvent.get:radiusMinor","signature":"dynamic(PointerEvent)"},{"addr":59248,"name":"func.0000e770"},{"addr":59296,"name":"method.PointerEvent.get:distance","signature":"dynamic(PointerEvent)"}]
EOF
RUN
NAME=obf-it-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -i -l 2 -m custom/obf-map.txt bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -i -l 2 -m custom/obf-map.txt
EOF
EXPECT=<<EOF
# length=1311 first_entry_with_code=0 canonical_stack_map_entries_offset=25731
+35 -8
View File
@@ -1,27 +1,54 @@
NAME=object-inspect-tagged-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -j -O 0x1651 bins/android/first 2>/dev/null | python3 -c 'import json, sys; j = json.load (sys.stdin); o = j["value"]["object"]; s = o["string"]; print ("%s addr=0x%x cid=%d len=%d value=%s" % (j["kind"], o["addr"], o["cid"], s["length"], s["value"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -j -O 0x1651~{=}kind,value.object.addr,value.object.cid,value.object.string.length,value.object.string.value
EOF
EXPECT=<<EOF
object addr=0x1650 cid=93 len=11 value=_Uint16List
json.kind = "object";
json.value.kind = "object";
json.value.object.addr = 5712;
json.value.object.cid = 93;
json.value.object.cid_name = "String";
json.value.object.string.length_raw = 22;
json.value.object.string.length = 11;
json.value.object.string.value_truncated = false;
json.value.object.string.value = "_Uint16List";
json.value.candidates[0].kind = "tagged_heap";
json.value.candidates[1].kind = "raw_address";
EOF
RUN
NAME=object-inspect-pp-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -j -O pp+0x68 bins/android/mafia 2>/dev/null | python3 -c 'import json, sys; j = json.load (sys.stdin); p = j["pp_slot"]; v = j["value"]; s = j["snapshot"]; print ("%s index=%d type=%s kind=%s cid=%d name=%s decoded=%s snapshot=%s:%s" % (j["kind"], p["entry_index"], p["type"], p["resolved_kind"], p["resolved_cid"], p["resolved_name"], v["decoded"], s["kind"], s["value"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -j -O pp+0x68~{=}kind,pp_slot.entry_index,pp_slot.type,pp_slot.resolved_kind,pp_slot.resolved_cid,pp_slot.resolved_name,value.decoded,snapshot.kind,snapshot.value
EOF
EXPECT=<<EOF
object_pool_ref index=11 type=tagged_object kind=string cid=93 name=getCallbackHandle decoded=False snapshot=string:getCallbackHandle
json.kind = "object_pool_ref";
json.pp_slot.entry_index = 11;
json.pp_slot.type = "tagged_object";
json.pp_slot.resolved_kind = "string";
json.pp_slot.resolved_name = "getCallbackHandle";
json.pp_slot.resolved_cid = 93;
json.value.decoded = false;
json.value.kind = "object_pool_ref";
json.value.candidates[0].kind = "raw_address";
json.value.candidates[1].kind = "compressed_data_image";
json.snapshot.kind = "string";
json.snapshot.value = "getCallbackHandle";
EOF
RUN
NAME=object-inspect-plugin-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -q -i \"\$p\" -qc \"r2flutter -q -O 0x1651\" bins/android/first/libapp.so 2>/dev/null"
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -O 0x1651
EOF
EXPECT=<<EOF
_Uint16List
+10 -8
View File
@@ -1,14 +1,16 @@
NAME=versioned-object-pool-entry-bits
FILE=-
FILE=malloc://0x69
CMDS=<<EOF
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-pool-300.bin 50414421f5f5dcdc61000000000000000300000000000000636535643337636632366561346661616335343363643231366633623936643170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008283818589ec8181818002ac
!!../bin/r2flutter -q -HHH -l 1 /tmp/r2flutter-pool-300.bin 2>/dev/null | python3 -c 'import sys; line=next(x for x in sys.stdin if "bits=" in x); print("3.0", *(x for x in line.split() if x.startswith(("bits=", "type=", "patch=", "behavior=", "ref="))))'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-pool-320.bin 50414421f5f5dcdc61000000000000000300000000000000396436333632323636623738653431393866373834646131613238666438326270726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008283818589ec8181818102ac
!!../bin/r2flutter -q -HHH -l 1 /tmp/r2flutter-pool-320.bin 2>/dev/null | python3 -c 'import sys; line=next(x for x in sys.stdin if "bits=" in x); print("3.2", *(x for x in line.split() if x.startswith(("bits=", "type=", "patch=", "behavior=", "ref="))))'
!!rm -f /tmp/r2flutter-pool-300.bin /tmp/r2flutter-pool-320.bin
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
wx 50414421f5f5dcdc61000000000000000300000000000000636535643337636632366561346661616335343363643231366633623936643170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008283818589ec8181818002ac
r2flutter -q -HHH -l 1~bits=:0
o malloc://0x69
wx 50414421f5f5dcdc61000000000000000300000000000000396436333632323636623738653431393866373834646131613238666438326270726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e74657273008283818589ec8181818102ac
r2flutter -q -HHH -l 1~bits=:0
EOF
EXPECT=<<EOF
3.0 bits=0x80 type=tagged_object patch=not_patchable behavior=snapshotable ref=300
3.2 bits=0x81 type=tagged_object patch=not_patchable behavior=snapshotable ref=300
[0] pool_off=0xf pp_off=0x10 bits=0x80 type=tagged_object patch=not_patchable behavior=snapshotable stream=0x66 value=0x67 ref=300 resolved_kind=out_of_range
[0] pool_off=0xf pp_off=0x10 bits=0x81 type=tagged_object patch=not_patchable behavior=snapshotable stream=0x66 value=0x67 ref=300 resolved_kind=out_of_range
EOF
RUN
+11 -3
View File
@@ -1,9 +1,17 @@
NAME=object-pool-resolve-android
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -j -HHH -l 1100 bins/android/mafia 2>/dev/null | python3 -c 'import json, sys; j = json.load (sys.stdin); iso = next (s for s in j["snapshots"] if s["label"] == "Isolate"); pool = next (p for c in iso["clusters"] for p in c.get ("object_pools", [])); e11 = pool["entries"][11]; e12 = pool["entries"][12]; print ("pool=%d len=%d e11=%s:%d:%s e12=%s:%d:%d:%s" % (pool["ref"], pool["length"], e11["resolved_kind"], e11["resolved_cid"], e11["resolved_name"], e12["resolved_kind"], e12["resolved_cid"], e12["resolved_code_index"], e12["resolved_name"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -j -HHH -l 1100~{snapshots[1].clusters[1088].object_pools[0].ref}
r2flutter -q -j -HHH -l 1100~{snapshots[1].clusters[1088].object_pools[0].length}
r2flutter -q -j -HHH -l 1100~{snapshots[1].clusters[1088].object_pools[0].entries[11]}
r2flutter -q -j -HHH -l 1100~{snapshots[1].clusters[1088].object_pools[0].entries[12]}
EOF
EXPECT=<<EOF
pool=195985 len=46569 e11=string:93:getCallbackHandle e12=function:7:37188:method._anonymous_closure_
195985
46569
{"index":11,"pool_offset":103,"pp_offset":104,"stream_offset":3690871,"value_offset":3690872,"bits":17,"type":"tagged_object","patch":"not_patchable","behavior":"snapshotable","ref":17080,"resolved_kind":"string","resolved_name":"getCallbackHandle","resolved_cid":93}
{"index":12,"pool_offset":111,"pp_offset":112,"stream_offset":3690875,"value_offset":3690876,"bits":17,"type":"tagged_object","patch":"not_patchable","behavior":"snapshotable","ref":152807,"resolved_kind":"function","resolved_name":"method._anonymous_closure_","resolved_cid":7,"resolved_code_index":37188}
EOF
RUN
+59 -14
View File
@@ -1,7 +1,9 @@
NAME=pp-android
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -p bins/android/mafia 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -p
EOF
EXPECT=<<EOF
vaddr=0x385154 paddr=0x385154
@@ -9,33 +11,57 @@ EOF
RUN
NAME=pp-json-android
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -j -p bins/android/mafia 2>/dev/null | python3 -c 'import json, sys; j = json.load (sys.stdin); print ("base=%d vaddr=%d paddr=%d kind=%s cluster=%d pool=%d length=%d size=%d word=%d source_paddr=%d" % (j["base"], j["vaddr"], j["paddr"], j["kind"], j["cluster_index"], j["pool_ref"], j["length"], j["size"], j["word_size"], j["source_addr"]["paddr"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -j -p~{=}base,vaddr,paddr,kind,cluster_index,pool_ref,length,size,word_size,source_addr.paddr
EOF
EXPECT=<<EOF
base=3690836 vaddr=3690836 paddr=3690836 kind=synthetic cluster=1088 pool=195985 length=46569 size=419144 word=8 source_paddr=3690836
json.base = 3690836;
json.vaddr = 3690836;
json.paddr = 3690836;
json.kind = "synthetic";
json.pp_addr.vaddr = 3690836;
json.pp_addr.paddr = 3690836;
json.source_addr.vaddr = 3690836;
json.source_addr.paddr = 3690836;
json.snapshot_base = 19072;
json.data_image_base = 4890624;
json.cluster_index = 1088;
json.pool_ref = 195985;
json.length = 46569;
json.size = 419144;
json.word_size = 8;
EOF
RUN
NAME=pp-r2-android
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -r -p bins/android/mafia 2>/dev/null | grep -E '^(o malloc://|e anal[.]gp=|dr anal[.]roregs=|dr x27=|f PP =|f dart[.]pp )'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -r -p~malloc://,anal.gp,anal.roregs,x27=,PP =,dart.pp
EOF
EXPECT=<<EOF
o malloc://0x66548 0x385154 rw
e anal.gp=0x385154
e anal.roregs=
dr x27=0x385154
e anal.roregs=x27,gp,zero
f PP = 0x385154
f dart.pp 0x66548 @ 0x385154
f dart.pp.entries 0x5af48 @ 0x385164
f dart.pp.entry_bits 0xb5e9 @ 0x3e00ac
EOF
RUN
NAME=pp-plugin-android
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -q -i \"\$p\" -qc \"r2flutter -q -p\" bins/android/mafia/libapp.so 2>/dev/null"
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -p
EOF
EXPECT=<<EOF
vaddr=0x385154 paddr=0x385154
@@ -43,9 +69,12 @@ EOF
RUN
NAME=pp-plugin-rebased-android
FILE=-
FILE=bins/android/mafia/libapp.so
ARGS=-B 0x70000000
CMDS=<<EOF
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -B 0x70000000 -q -i \"\$p\" -qc \"r2flutter -q -p\" bins/android/mafia/libapp.so 2>/dev/null"
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -p
EOF
EXPECT=<<EOF
vaddr=0x70385154 paddr=0x385154
@@ -53,11 +82,27 @@ EOF
RUN
NAME=pp-json-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -q -j -p bins/ios/Runner.app 2>/dev/null | python3 -c 'import json, sys; j = json.load (sys.stdin); print ("base=%d vaddr=%d paddr=%d kind=%s cluster=%d pool=%d length=%d size=%d word=%d source_paddr=%d" % (j["base"], j["vaddr"], j["paddr"], j["kind"], j["cluster_index"], j["pool_ref"], j["length"], j["size"], j["word_size"], j["source_addr"]["paddr"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -j -p~{=}base,vaddr,paddr,kind,cluster_index,pool_ref,length,size,word_size,source_addr.paddr
EOF
EXPECT=<<EOF
base=2282193 vaddr=2282193 paddr=2282193 kind=synthetic cluster=320 pool=41741 length=8435 size=75936 word=8 source_paddr=2282193
json.base = 2282193;
json.vaddr = 2282193;
json.paddr = 2282193;
json.kind = "synthetic";
json.pp_addr.vaddr = 2282193;
json.pp_addr.paddr = 2282193;
json.source_addr.vaddr = 2265809;
json.source_addr.paddr = 2282193;
json.snapshot_base = 1807872;
json.data_image_base = 2344128;
json.cluster_index = 320;
json.pool_ref = 41741;
json.length = 8435;
json.size = 75936;
json.word_size = 8;
EOF
RUN
+11 -5
View File
@@ -1,17 +1,23 @@
NAME=r2script-method-order
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<CMDS_END
!!../bin/r2flutter -R bins/ios/Runner.app 2>/dev/null | perl -ne 'if (/^f method\..* = 0x([0-9a-fA-F]+)/) { $v = hex ($1); if (defined $p && $v < $p) { print "UNSORTED\n"; exit 1; } $p = $v; $count++; } END { if ($count > 0) { print "OK\n"; } else { print "NO_METHODS\n"; exit 1; } }'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -R~^f method.:0..3
CMDS_END
EXPECT=<<EXPECT_END
OK
f method.PointerEvent.get:radiusMinor = 0xe768
f method.func.0000e770 = 0xe770
f method.PointerEvent.get:distance = 0xe7a0
EXPECT_END
RUN
NAME=r2script-pp-scan-skipped
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<CMDS_END
!!../bin/r2flutter -R bins/android/mafia 2>/dev/null | tail -4 | head -3
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -R~:-3..0
CMDS_END
EXPECT=<<EXPECT_END
dr x27=`e anal.gp`
+6 -5
View File
@@ -1,11 +1,12 @@
NAME=versioned-snapshot-reference-codec
FILE=-
FILE=malloc://0x6a
CMDS=<<EOF
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-ref-217.bin 50414421f5f5dcdc62000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e7465727300828381878589ea818181002c82
!!../bin/r2flutter -q -HHH -l 1 /tmp/r2flutter-ref-217.bin 2>/dev/null | python3 -c 'import sys; print(next(line.strip() for line in sys.stdin if "bits=" in line))'
!!rm -f /tmp/r2flutter-ref-217.bin
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
wx 50414421f5f5dcdc62000000000000000300000000000000313434316436623133623836323366613766626636313433336162656264333170726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e7465727300828381878589ea818181002c82
r2flutter -q -HHH -l 1~bits=:0
EOF
EXPECT=<<EOF
[0] pool_off=0xf pp_off=0x10 bits=0x00 type=tagged_object patch=patchable behavior=snapshotable stream=0x67 value=0x68 ref=300 resolved_kind=out_of_range
[0] pool_off=0xf pp_off=0x10 bits=0x00 type=tagged_object patch=patchable behavior=snapshotable stream=0x67 value=0x68 ref=300 resolved_kind=out_of_range
EOF
RUN
+8 -4
View File
@@ -1,7 +1,9 @@
NAME=sbom-synthetic
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!../bin/r2flutter -S bins/synthetic/field_snapshot.bin 2>/dev/null | sed -n '1,8p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -S~:0..8
EOF
EXPECT=<<EOF
# Dart/Flutter Recovered Components
@@ -16,9 +18,11 @@ EOF
RUN
NAME=json-sbom-synthetic
FILE=-
FILE=bins/synthetic/field_snapshot.bin
CMDS=<<EOF
!!../bin/r2flutter -jS bins/synthetic/field_snapshot.bin 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -jS
EOF
EXPECT=<<EOF
{"format":"r2flutter-recovered-sbom","complete":false,"note":"Best-effort component report. Dart package versions are null unless explicit packaged metadata is present.","input":"bins/synthetic/field_snapshot.bin","snapshot":{"hash":"00000000000000000000000000000000","dart_version":"unknown","vm_data":4,"iso_data":4},"count":2,"components":[{"type":"dart-package","name":"test","version":null,"confidence":90,"occurrences":3,"source":"library_cluster","evidence":"package:test"},{"type":"runtime","name":"dart-sdk","version":null,"confidence":70,"occurrences":1,"source":"snapshot_header","evidence":"snapshot_hash=00000000000000000000000000000000"}]}
+56 -12
View File
@@ -1,18 +1,62 @@
NAME=dart-313-single-snapshot-layout
FILE=-
FILE=malloc://0x9f
CMDS=<<EOF
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-single-313.bin 50414421f5f5dcdc97000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c080808087808080808080808080808080810181
!!../bin/r2flutter -q -j -HHH -l 8 /tmp/r2flutter-single-313.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); s=d["snapshots"][0]; c={x["cid"]:x for x in s["clusters"]}; e=c[23]["object_pools"][0]["entries"][0]; print(d["dart_version"], d["single_snapshot"], d["vm_data"], d["iso_data"], len(d["snapshots"]), s["label"], s["clusters_parsed"]); print(c[5]["alloc"], c[5]["fill_status"], c[18]["fill_status"], c[57]["alloc"], c[57]["fill"], c[57]["items"]["total"], e["ref"])'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-single-314.bin 50414421f5f5dcdc97000000000000000200000000000000376131656133663666356366313038396137663665353564376632306462666470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c080808087808080808080808080808080810181
!!../bin/r2flutter -q -j -H /tmp/r2flutter-single-314.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["dart_version"], d["single_snapshot"], d["vm_data"], d["iso_data"], d["cid_table"]["num_predefined"])'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-single-313-truncated.bin 50414421f5f5dcdc92000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c08080808780808080808080808080
!!../bin/r2flutter -q -j -HHH -l 8 /tmp/r2flutter-single-313-truncated.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); s=d["snapshots"][0]; c={x["cid"]:x for x in s["clusters"]}; print("truncated", d["dart_version"], s["label"], s["clusters_parsed"], c[57]["fill_status"], c[23]["fill_status"], c[23]["object_pool_decode"])'
!!rm -f /tmp/r2flutter-single-313.bin /tmp/r2flutter-single-314.bin /tmp/r2flutter-single-313-truncated.bin
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
wx 50414421f5f5dcdc97000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c080808087808080808080808080808080810181
r2flutter -q -j -HHH -l 8~{dart_version}
r2flutter -q -j -HHH -l 8~{single_snapshot}
r2flutter -q -j -HHH -l 8~{vm_data}
r2flutter -q -j -HHH -l 8~{iso_data}
r2flutter -q -j -HHH -l 8~{snapshots[0].label}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters_parsed}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[0].alloc}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[0].fill_status}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[1].fill_status}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[2].alloc}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[2].fill}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[2].items.total}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[3].object_pools[0].entries[0].ref}
o malloc://0x9f
wx 50414421f5f5dcdc97000000000000000200000000000000376131656133663666356366313038396137663665353564376632306462666470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c080808087808080808080808080808080810181
r2flutter -q -j -H~{dart_version}
r2flutter -q -j -H~{single_snapshot}
r2flutter -q -j -H~{vm_data}
r2flutter -q -j -H~{iso_data}
r2flutter -q -j -H~{cid_table.num_predefined}
o malloc://0x9a
wx 50414421f5f5dcdc92000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c08080808780808080808080808080
r2flutter -q -j -HHH -l 8~{dart_version}
r2flutter -q -j -HHH -l 8~{snapshots[0].label}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters_parsed}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[2].fill_status}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[3].fill_status}
r2flutter -q -j -HHH -l 8~{snapshots[0].clusters[3].object_pool_decode}
EOF
EXPECT=<<EOF
3.13.0 True 0 4 1 Combined True
class ok ok variable closure 2 1
3.14.0 True 0 4 176
truncated 3.13.0 Combined True failed not_parsed fill_not_parsed
3.13.0
true
0
4
Combined
true
class
ok
ok
variable
closure
2
1
3.14.0
true
0
4
176
3.13.0
Combined
true
failed
not_parsed
fill_not_parsed
EOF
RUN
+89 -23
View File
@@ -1,43 +1,109 @@
NAME=snapshot-value-graph-android
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -j -O ref:158145 bins/android/mafia 2>/dev/null | python3 -c 'import json,sys; s=json.load(sys.stdin)["snapshot"]; d=s["fields"][2]["value"]; a=d["elements"]; i=a[1]["value"]; f=i["fields"]; print("%s cid=%d complete=%s data=%s len=%d pair=%s:%s(%s) fields=%s,%s,%s"%(s["kind"],s["cid"],s["complete"],d["kind"],d["length"],a[0]["value"]["value"],i["kind"],i["name"],f[0]["value"],f[1]["value"],f[2]["value"]["value"]))'
!!../bin/r2flutter -q -j -O ref:160785 bins/android/mafia 2>/dev/null | python3 -c 'import json,sys; s=json.load(sys.stdin)["snapshot"]; print("%s cid=%d complete=%s data=%s"%(s["kind"],s["cid"],s["complete"],s["fields"][2]["value"]["kind"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -j -O ref:158145~{snapshot.kind}
r2flutter -q -j -O ref:158145~{snapshot.cid}
r2flutter -q -j -O ref:158145~{snapshot.complete}
r2flutter -q -j -O ref:158145~{snapshot.fields[2].value.kind}
r2flutter -q -j -O ref:158145~{snapshot.fields[2].value.length}
r2flutter -q -j -O ref:158145~{snapshot.fields[2].value.elements[0].value.value}
r2flutter -q -j -O ref:158145~{snapshot.fields[2].value.elements[1].value.kind}
r2flutter -q -j -O ref:158145~{snapshot.fields[2].value.elements[1].value.name}
r2flutter -q -j -O ref:158145~{snapshot.fields[2].value.elements[1].value.fields[0].value}
r2flutter -q -j -O ref:158145~{snapshot.fields[2].value.elements[1].value.fields[1].value}
r2flutter -q -j -O ref:158145~{snapshot.fields[2].value.elements[1].value.fields[2].value.value}
r2flutter -q -j -O ref:160785~{snapshot.kind}
r2flutter -q -j -O ref:160785~{snapshot.cid}
r2flutter -q -j -O ref:160785~{snapshot.complete}
r2flutter -q -j -O ref:160785~{snapshot.fields[2].value.kind}
EOF
EXPECT=<<EOF
map cid=87 complete=True data=array len=48 pair=129:instance(SemanticsAction) fields=1,0,tap
set cid=89 complete=True data=array
map
87
true
array
48
129
instance
SemanticsAction
1
0
tap
set
89
true
array
EOF
RUN
NAME=snapshot-value-graph-ios-rodata
FILE=-
FILE=bins/ios/AuthPass.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -q -j -O ref:209553 bins/ios/AuthPass.app/Frameworks/App.framework/App 2>/dev/null | python3 -c 'import json,sys; s=json.load(sys.stdin)["snapshot"]; a=s["fields"][2]["value"]["elements"]; print("%s cid=%d complete=%s strings=%s/%s"%(s["kind"],s["cid"],s["complete"],a[0]["value"]["value"],a[1]["value"]["value"]))'
!!../bin/r2flutter -q -j -O ref:211161 bins/ios/AuthPass.app/Frameworks/App.framework/App 2>/dev/null | python3 -c 'import json,sys; s=json.load(sys.stdin)["snapshot"]; print("%s cid=%d complete=%s data=%s"%(s["kind"],s["cid"],s["complete"],s["fields"][2]["value"]["kind"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -j -O ref:209553~{=}~snapshot.kind,snapshot.cid,snapshot.complete,cancel,Cancel
r2flutter -q -j -O ref:211161~{=}~snapshot.kind,snapshot.cid,snapshot.complete,"array"
EOF
EXPECT=<<EOF
map cid=86 complete=True strings=cancel/Cancel
set cid=88 complete=True data=array
json.snapshot.kind = "map";
json.snapshot.complete = true;
json.snapshot.cid = 86;
json.snapshot.fields[2].value.elements[0].value.value = "cancel";
json.snapshot.fields[2].value.elements[1].value.value = "Cancel";
json.snapshot.kind = "set";
json.snapshot.complete = true;
json.snapshot.cid = 88;
json.snapshot.fields[2].value.kind = "array";
EOF
RUN
NAME=snapshot-value-graph-bounds-and-truncation
FILE=-
FILE=malloc://0x6b
CMDS=<<EOF
!!python3 -c 'import sys; open(sys.argv[1],"wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-value-map.bin 50414421f5f5dcdc63000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082818180800060d5818080808080
!!python3 -c 'import sys; open(sys.argv[1],"wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-value-map-truncated.bin 50414421f5f5dcdc62000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082818180800060d58180808080
!!python3 -c 'import sys; open(sys.argv[1],"wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-value-cycle.bin 50414421f5f5dcdc62000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082818180800040d68181818083
!!../bin/r2flutter -q -j -O ref:3 /tmp/r2flutter-value-map.bin 2>/dev/null | python3 -c 'import json,sys; s=json.load(sys.stdin)["snapshot"]; print("valid",s["kind"],s["complete"],[(x["name"],x["value"]["kind"]) for x in s["fields"]])'
!!../bin/r2flutter -q -j -O ref:3 /tmp/r2flutter-value-cycle.bin 2>/dev/null | python3 -c 'import json,sys; s=json.load(sys.stdin)["snapshot"]; v=s["elements"][0]["value"]; print("cycle",s["kind"],s["complete"],s["length"],v["kind"],v["cycle"])'
!!../bin/r2flutter -q -j -O ref:3 /tmp/r2flutter-value-map-truncated.bin 2>/dev/null | python3 -c 'import json,sys; s=json.load(sys.stdin)["snapshot"]; print("truncated",s["kind"],s["complete"],"fields" in s)'
!!../bin/r2flutter -q -j -O ref:99 /tmp/r2flutter-value-map.bin 2>/dev/null | python3 -c 'import json,sys; s=json.load(sys.stdin)["snapshot"]; print("invalid",s["kind"],s["complete"])'
!!rm -f /tmp/r2flutter-value-map.bin /tmp/r2flutter-value-map-truncated.bin /tmp/r2flutter-value-cycle.bin
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
wx 50414421f5f5dcdc63000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082818180800060d5818080808080
r2flutter -q -j -O ref:3~{=}snapshot.kind,snapshot.complete,.name,.value.kind
o malloc://0x6a
wx 50414421f5f5dcdc62000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082818180800040d68181818083
r2flutter -q -j -O ref:3~{snapshot.kind}
r2flutter -q -j -O ref:3~{snapshot.complete}
r2flutter -q -j -O ref:3~{snapshot.length}
r2flutter -q -j -O ref:3~{snapshot.elements[0].value.kind}
r2flutter -q -j -O ref:3~{snapshot.elements[0].value.cycle}
o malloc://0x6a
wx 50414421f5f5dcdc62000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082818180800060d58180808080
r2flutter -q -j -O ref:3~{snapshot.kind}
r2flutter -q -j -O ref:3~{snapshot.complete}
o malloc://0x6b
wx 50414421f5f5dcdc63000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082818180800060d5818080808080
r2flutter -q -j -O ref:99~{snapshot.kind}
r2flutter -q -j -O ref:99~{snapshot.complete}
EOF
EXPECT=<<EOF
valid map True [('type_arguments', 'null'), ('hash_mask', 'null'), ('data', 'null'), ('used_data', 'null'), ('deleted_keys', 'null')]
cycle array True 1 array True
truncated map False False
invalid out_of_range False
json.value.kind = "snapshot_ref";
json.snapshot.kind = "map";
json.snapshot.complete = true;
json.snapshot.fields[0].name = "type_arguments";
json.snapshot.fields[0].value.kind = "null";
json.snapshot.fields[1].name = "hash_mask";
json.snapshot.fields[1].value.kind = "null";
json.snapshot.fields[2].name = "data";
json.snapshot.fields[2].value.kind = "null";
json.snapshot.fields[3].name = "used_data";
json.snapshot.fields[3].value.kind = "null";
json.snapshot.fields[4].name = "deleted_keys";
json.snapshot.fields[4].value.kind = "null";
array
true
1
array
true
map
false
out_of_range
false
EOF
RUN
+16 -8
View File
@@ -1,7 +1,9 @@
NAME=text-strings-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -zz bins/android/first 2>/dev/null | sed -n '1,6p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -zz~:0..6
EOF
EXPECT=<<EOF
0x00000214 165 :app "f91b8b03bf7f30a5e983fd19b23d978dproduct no-code_comments no-dwarf_stack_traces_mode no-lazy_dispatchers dedup_instructions no-tsan arm64 linux no-compressed-pointers"
@@ -14,9 +16,11 @@ EOF
RUN
NAME=verbose-text-strings-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -vzz bins/android/first 2>/dev/null | sed -n '1p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -vzz~:0
EOF
EXPECT=<<EOF
0x00000214 165 :app "f91b8b03bf7f30a5e983fd19b23d978dproduct no-code_comments no-dwarf_stack_traces_mode no-lazy_dispatchers dedup_instructions no-tsan arm64 linux no-compressed-pointers"
@@ -24,9 +28,11 @@ EOF
RUN
NAME=r2-strings-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -r -zz bins/android/first 2>/dev/null | head -7
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -zz~:0..7
EOF
EXPECT=<<EOF
# Dart Strings
@@ -40,9 +46,11 @@ EOF
RUN
NAME=quiet-r2-strings-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -qrzz bins/android/first 2>/dev/null | head -6
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -qrzz~:0..6
EOF
EXPECT=<<EOF
iz+ 0x00000214 165
+25 -13
View File
@@ -1,7 +1,9 @@
NAME=text-strings-android-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -zz bins/android/mafia 2>/dev/null | sed -n '1,14p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -zz~:0..14
EOF
EXPECT=<<EOF
0x00000354 167 :app "97ff04a728735e6b6b098bdf983faabaproduct no-code_comments no-dwarf_stack_traces_mode dedup_instructions no-tsan no-msan no-shared_data arm64 android compressed-pointers"
@@ -22,9 +24,11 @@ EOF
RUN
NAME=text-strings-xrefs-android-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -xzz bins/android/mafia 2>/dev/null | sed -n '1,14p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -xzz~:0..14
EOF
EXPECT=<<EOF
0x00000354 167 :app "97ff04a728735e6b6b098bdf983faabaproduct no-code_comments no-dwarf_stack_traces_mode dedup_instructions no-tsan no-msan no-shared_data arm64 android compressed-pointers"
@@ -45,19 +49,23 @@ EOF
RUN
NAME=json-strings-objectpool-android-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -j -xz bins/android/mafia 2>/dev/null | python3 -c 'import json, sys; a = json.load (sys.stdin); e = next (s for s in a if s["value"] == "useShouldInterceptRequest"); r = e["refs"][0]; print ("count=%d value=%s addr=0x%x kind=%s ref=%d name=%s" % (len (a), e["value"], e["addr"], r["kind"], r["obj"], r["name"]))'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -j -xz~{[0]}
EOF
EXPECT=<<EOF
count=10630 value=useShouldInterceptRequest addr=0x49d81 kind=object_pool.entry ref=195985 name=pool=195985 index=0 entry=44440 pp_off=0x56cd0
{"ref":10404,"len":25,"value":"useShouldInterceptRequest","category":"lib","two_byte":false,"canonical":true,"addr":302465,"refs":[{"obj":195985,"type":"other","kind":"object_pool.entry","name":"pool=195985 index=0 entry=44440 pp_off=0x56cd0"}]}
EOF
RUN
NAME=quiet-strings-objectpool-android-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -z bins/android/mafia 2>/dev/null | sed -n '1,3p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -z~:0..3
EOF
EXPECT=<<EOF
useShouldInterceptRequest
@@ -67,9 +75,11 @@ EOF
RUN
NAME=r2-string-xrefs-objectpool-android-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -q -r -x -z bins/android/mafia 2>/dev/null | sed -n '1,4p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -q -r -x -z~:0..4
EOF
EXPECT=<<EOF
iz+ 0x00049d81 25
@@ -80,9 +90,11 @@ EOF
RUN
NAME=plugin-quiet-strings-objectpool-android-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -q -i \"\$p\" -qc \"r2flutter -qz\" -qc q bins/android/mafia/libapp.so 2>/dev/null | sed -n '1,3p'"
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -qz~:0..3
EOF
EXPECT=<<EOF
useShouldInterceptRequest
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=r2-strings-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -r -zz bins/ios/Runner.app 2>/dev/null | sed -n '1,7p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -zz~:0..7
EOF
EXPECT=<<EOF
# Dart Strings
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=r2-strings-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -r -zz bins/android/mafia 2>/dev/null | head -7
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -zz~:0..7
EOF
EXPECT=<<EOF
# Dart Strings
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=text-types-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -T bins/android/first 2>/dev/null | sed -n '1,6p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -T~:0..6
EOF
EXPECT=<<EOF
class _Uint16List (size=0)
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=text-types-enum-android
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -T bins/android/mafia 2>/dev/null | grep '^enum AppLifecycleState {'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -T~^enum AppLifecycleState
EOF
EXPECT=<<EOF
enum AppLifecycleState { detached, hidden, inactive, paused, resumed }
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=text-types-enum-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -T bins/ios/Runner.app 2>/dev/null | grep '^enum AppLifecycleState {'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -T~^enum AppLifecycleState
EOF
EXPECT=<<EOF
enum AppLifecycleState { detached, hidden, inactive, paused, resumed }
+4 -2
View File
@@ -1,7 +1,9 @@
NAME=r2-types-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -r -T bins/ios/Runner.app 2>/dev/null | sed -n '1,7p'
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -T~:0..7
EOF
EXPECT=<<EOF
# Dart classes extracted from snapshot
+8 -4
View File
@@ -1,7 +1,9 @@
NAME=text-types-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -T bins/android/mafia 2>/dev/null | head -6
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -T~:0..6
EOF
EXPECT=<<EOF
class Pointer (size=32)
@@ -14,9 +16,11 @@ EOF
RUN
NAME=r2-types-mafia
FILE=-
FILE=bins/android/mafia/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -r -T bins/android/mafia 2>/dev/null | head -7
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -T~:0..7
EOF
EXPECT=<<EOF
# Dart classes extracted from snapshot
+12 -6
View File
@@ -1,7 +1,9 @@
NAME=text-xrefs-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -l 4 -x bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -l 4 -x
EOF
EXPECT=<<EOF
scan class.name class _Uint16List -> string _Uint16List @ 0x1660
@@ -12,9 +14,11 @@ EOF
RUN
NAME=json-xrefs-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -j -l 3 -x bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -l 3 -x
EOF
EXPECT=<<EOF
[{"kind":"class.name","origin":"scan","src":{"type":"class","name":"_Uint16List"},"dst":{"type":"string","name":"_Uint16List","addr":5728}},{"kind":"class.name","origin":"scan","src":{"type":"class","name":"_ExternalInt64Array"},"dst":{"type":"string","name":"_ExternalInt64Array","addr":5760}},{"kind":"class.name","origin":"scan","src":{"type":"class","name":"FutureOr"},"dst":{"type":"string","name":"FutureOr","addr":5840}}]
@@ -22,9 +26,11 @@ EOF
RUN
NAME=r2-xrefs-android
FILE=-
FILE=bins/android/first/libapp.so
CMDS=<<EOF
!!../bin/r2flutter -r -l 2 -x bins/android/first 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -l 2 -x
EOF
EXPECT=<<EOF
# Dart xrefs
+15 -9
View File
@@ -1,35 +1,41 @@
NAME=text-xrefs-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -l 4 -x bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -l 4 -x
EOF
EXPECT=<<EOF
metadata class.name class Pointer [ref=36652] -> string Pointer [ref=151] @ 0x1b24d0
metadata class.library class Pointer [ref=36652] -> library library#41733 [ref=41733]
metadata method.owner method Pointer.get:hashCode [ref=31064] -> class Pointer [ref=36652]
metadata method.name method Pointer.get:hashCode [ref=31064] -> string get:hashCode [ref=7217] @ 0x2b0230
metadata method.signature method Pointer.get:hashCode [ref=31064] -> type type#1 [ref=1]
EOF
RUN
NAME=json-xrefs-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -j -l 3 -x bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -j -l 3 -x
EOF
EXPECT=<<EOF
[{"kind":"class.name","origin":"metadata","src":{"type":"class","name":"Pointer","ref":36652},"dst":{"type":"string","name":"Pointer","ref":151,"addr":1778896}},{"kind":"method.owner","origin":"metadata","src":{"type":"method","name":"Pointer.get:hashCode","ref":31064},"dst":{"type":"class","name":"Pointer","ref":36652}},{"kind":"method.name","origin":"metadata","src":{"type":"method","name":"Pointer.get:hashCode","ref":31064},"dst":{"type":"string","name":"get:hashCode","ref":7217,"addr":2818608}}]
[{"kind":"class.name","origin":"metadata","src":{"type":"class","name":"Pointer","ref":36652},"dst":{"type":"string","name":"Pointer","ref":151,"addr":1778896}},{"kind":"class.library","origin":"metadata","src":{"type":"class","name":"Pointer","ref":36652},"dst":{"type":"library","name":"library#41733","ref":41733}},{"kind":"method.owner","origin":"metadata","src":{"type":"method","name":"Pointer.get:hashCode","ref":31064},"dst":{"type":"class","name":"Pointer","ref":36652}}]
EOF
RUN
NAME=r2-xrefs-ios
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!../bin/r2flutter -r -l 2 -x bins/ios/Runner.app 2>/dev/null
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -r -l 2 -x
EOF
EXPECT=<<EOF
# Dart xrefs
# metadata class.name class Pointer [ref=36652] -> string Pointer [ref=151] @ 0x1b24d0
'@0x1b24d0'CCu base64:UG9pbnRlcg==
# metadata method.owner method Pointer.get:hashCode [ref=31064] -> class Pointer [ref=36652]
# metadata class.library class Pointer [ref=36652] -> library library#41733 [ref=41733]
EOF
RUN
+7 -3
View File
@@ -1,7 +1,11 @@
NAME=compstr
FILE=-
FILE=bins/ios/Runner.app/Frameworks/App.framework/App
CMDS=<<EOF
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -q -i \"\$p\" -qc \"r2flutter -jzz\" bins/ios/Runner.app/Frameworks/App.framework/App 2>/dev/null" | head -c 200
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -jzz~{[0]}
EOF
EXPECT=<<EOF
{"ref":568,"len":186,"value":"d20a1be77c3d3c41b2a5accaee1ce549product no-code_comments no-dwarf_stack_traces_mode no-lazy_dispatchers dedup_instructions no-tsan no-asserts arm64 ios no-compressed-pointers null-safety","category":"app","two_byte":false,"canonical":true,"addr":1771796}
EOF
EXPECT=[{"ref":568,"len":186,"value":"d20a1be77c3d3c41b2a5accaee1ce549product no-code_comments no-dwarf_stack_traces_mode no-lazy_dispatchers dedup_instructions no-tsan no-asserts arm64 ios no-compressed-poi
RUN
+32 -64
View File
@@ -1,95 +1,63 @@
NAME=help
FILE=-
CMDS=<<EOF
!!../bin/r2flutter -h
L ../src/r2/core_flutter.dylib
L ../src/r2/core_flutter.so
r2flutter -h
?e ===
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -q -i \"\$p\" -qc \"r2flutter -h\" -"
?e ===
!!../bin/r2flutter | sed -n '1p'
?e ===
!!sh -c "p=../src/r2/core_flutter.dylib; [ -f \"\$p\" ] || p=../src/r2/core_flutter.so; r2 -NN -q -i \"\$p\" -qc r2flutter -"
r2flutter
EOF
EXPECT=<<EOF
Usage: ../bin/r2flutter [-jrv*] <libapp_path_or_dir>
Modifiers:
-h Show help
-j Output in JSON format
-n Heuristic fallback for unknown functions; may assign wrong names
-q Compact output; suppress non-essential detail
-r Output r2 commands for the selected action
-v Verbose (stderr debug info)
-vv More verbose (dump headers)
-V Show version
Actions:
-A[AA] Analyze Dart snapshot and apply flags/comments
-c[jr*] Print extracted class information
-f[jr*] Print all extracted functions (addr name)
-H[HH] Print Dart AOT snapshot header info
-i[jr*] Print instruction table entries (-ii same as -i)
-ie[jr*], -E[jr*] Print Dart code entrypoint
-O <addr|pp+off> Decode Dart tagged/object pointer or ObjectPool PP slot
-p[jr*] Print reconstructed ObjectPool PP value
-R Print radare2 script for snapshot analysis
-S[jr*] Print best-effort recovered SBOM/components
-T[jr*] Print string-based type names
-x[jr*] Print metadata/data-image xrefs; with -z, include string refs/ax in -r
-z[jr*] Print reliable ObjectPool-referenced strings (-q prints values only)
-zz[jr*] Print all fuzzy/carved extracted strings (-xzz includes refs/ax in -r)
Options:
-D <hash|version> Override Dart snapshot profile for analysis
-l <N> Limit output to N items
-m <file> Load Flutter obfuscation map JSON
===
Usage: r2flutter [j*] <action>
Usage: r2flutter [qjr*] <action>
| r2flutter -A[AA] analyze dart snapshot and apply flags/comments
| r2flutter -c[j*] dump classes
| r2flutter -c[jr*] dump classes
| r2flutter -C apply Dart classes, fields, methods and types
| r2flutter -D prof override Dart snapshot profile by hash or version
| r2flutter -f[j*] dump recovered functions
| r2flutter -E[jr*] dump Dart code entrypoint
| r2flutter -f[jr*] dump recovered functions
| r2flutter -H[HH] dump Dart AOT snapshot header info
| r2flutter -i[j*] dump instruction table entries
| r2flutter -ie[j*] dump Dart code entrypoint; with -* mark instruction snapshots as dword arrays
| r2flutter -i[jr*] dump instruction table entries
| r2flutter -ie[jr*] dump Dart code entrypoint; with -r/-* mark instruction snapshots as dword arrays
| r2flutter -l N limit function/instruction-table/xref output
| r2flutter -m file load Flutter obfuscation map JSON
| r2flutter -n use heuristic name-pool fallback; names may be wrong
| r2flutter -O addr decode Dart tagged/object pointer or ObjectPool PP slot
| r2flutter -p[j*] print reconstructed ObjectPool PP value
| r2flutter -O spec decode a tagged pointer, PP slot, or snapshot ref:N
| r2flutter -p[jr*] print reconstructed ObjectPool PP value
| r2flutter -R dump full radare2 script (like standalone -R)
| r2flutter -S[j*] dump best-effort recovered SBOM/components
| r2flutter -T[j*] dump string-based type names
| r2flutter -x[j*] dump metadata/data-image xrefs; with -z, include string refs/ax in -*
| r2flutter -z[j*] dump reliable ObjectPool-referenced strings
| r2flutter -zz[j*] dump all fuzzy/carved strings (-xzz includes refs/ax in -*)
| r2flutter -S[jr*] dump best-effort recovered SBOM/components
| r2flutter -T[jr*] dump string-based type names
| r2flutter -x[jr*] dump metadata/data-image xrefs; with -z, include string refs/ax in -r/-*
| r2flutter -z[jr*] dump reliable ObjectPool-referenced strings
| r2flutter -zz[jr*] dump all fuzzy/carved strings (-xzz includes refs/ax in -r/-*)
| r2flutter -h show this help
| r2flutter -v increase parser verbosity
| r2flutter -V show version
Modifiers: j=json, *=r2 commands
Modifiers: q=quiet, j=json, r/*=r2 commands
===
Usage: ../bin/r2flutter [-jrv*] <libapp_path_or_dir>
===
Usage: r2flutter [j*] <action>
Usage: r2flutter [qjr*] <action>
| r2flutter -A[AA] analyze dart snapshot and apply flags/comments
| r2flutter -c[j*] dump classes
| r2flutter -c[jr*] dump classes
| r2flutter -C apply Dart classes, fields, methods and types
| r2flutter -D prof override Dart snapshot profile by hash or version
| r2flutter -f[j*] dump recovered functions
| r2flutter -E[jr*] dump Dart code entrypoint
| r2flutter -f[jr*] dump recovered functions
| r2flutter -H[HH] dump Dart AOT snapshot header info
| r2flutter -i[j*] dump instruction table entries
| r2flutter -ie[j*] dump Dart code entrypoint; with -* mark instruction snapshots as dword arrays
| r2flutter -i[jr*] dump instruction table entries
| r2flutter -ie[jr*] dump Dart code entrypoint; with -r/-* mark instruction snapshots as dword arrays
| r2flutter -l N limit function/instruction-table/xref output
| r2flutter -m file load Flutter obfuscation map JSON
| r2flutter -n use heuristic name-pool fallback; names may be wrong
| r2flutter -O addr decode Dart tagged/object pointer or ObjectPool PP slot
| r2flutter -p[j*] print reconstructed ObjectPool PP value
| r2flutter -O spec decode a tagged pointer, PP slot, or snapshot ref:N
| r2flutter -p[jr*] print reconstructed ObjectPool PP value
| r2flutter -R dump full radare2 script (like standalone -R)
| r2flutter -S[j*] dump best-effort recovered SBOM/components
| r2flutter -T[j*] dump string-based type names
| r2flutter -x[j*] dump metadata/data-image xrefs; with -z, include string refs/ax in -*
| r2flutter -z[j*] dump reliable ObjectPool-referenced strings
| r2flutter -zz[j*] dump all fuzzy/carved strings (-xzz includes refs/ax in -*)
| r2flutter -S[jr*] dump best-effort recovered SBOM/components
| r2flutter -T[jr*] dump string-based type names
| r2flutter -x[jr*] dump metadata/data-image xrefs; with -z, include string refs/ax in -r/-*
| r2flutter -z[jr*] dump reliable ObjectPool-referenced strings
| r2flutter -zz[jr*] dump all fuzzy/carved strings (-xzz includes refs/ax in -r/-*)
| r2flutter -h show this help
| r2flutter -v increase parser verbosity
| r2flutter -V show version
Modifiers: j=json, *=r2 commands
Modifiers: q=quiet, j=json, r/*=r2 commands
EOF
RUN