mirror of
https://github.com/radareorg/r2flutter.git
synced 2026-11-07 22:56:23 -10:00
Harden unknown-hash handling and report version provenance
- Replaces the hardcoded 'v3.9.2 defaults' fallback - Fix load_layout_from_json to use that profile on the -f/-A decode path for unknown hashes, instead of a degenerate zeroed layout (cws=0/alignment=0); - Adds a version_source field to -H, guessed layout is never exact match now
This commit is contained in:
1 parent
19d8b96fc5
commit
d387c0b15b
10 files changed
+108
-29
No files matched your search
+2
-2
@@ -17,8 +17,8 @@ instruction tables, and strings directly.
|
||||
| Mach-O details | Thin Mach-O64 and fat Mach-O/fat64; arm64 slice is preferred. LC_NOTE owner `__dart_app_snap` is detected and the embedded Dart Mach-O payload is extracted to a temporary file. |
|
||||
| Architecture | ARM64/AArch64 is the real target. Instruction-table entrypoints are based on ARM64 code offsets, PP tracking uses `x27`, and the radare2 analysis pass understands AArch64 registers/op metadata. |
|
||||
| Snapshot kind | Clustered Dart AOT snapshots with magic `0xdcdcf5f5`, 32-byte snapshot hashes, feature strings, and unsigned varint header fields. |
|
||||
| Dart layouts | In-tree profiles cover Dart `2.10.0` through `3.12.1`, roughly Flutter `1.22.x` through `3.41.x`. |
|
||||
| Unknown hashes | Falls back to hardcoded default offsets (8/24/16/32 for entry points, 56 for owner, 24/8 for names) + v3.9.2-shaped ObjectHeader defaults while reporting the Dart version as `unknown`. |
|
||||
| Dart layouts | In-tree profiles cover Dart `2.10.0` through `3.12.1`, roughly Flutter `1.22.x` through `3.41.x`. Profiles are keyed at layout-change boundaries and resolved by floor: e.g. `3.7`/`3.8` share the `3.6.0` CID layout and `3.10`–`3.12` share the `3.9.0` layout. Verified byte-for-byte against every release's `runtime/vm/class_id.h` (2.10.0–3.12.1). |
|
||||
| Unknown hashes | Git/dev builds carry an unlisted snapshot hash. r2flutter **fingerprints** them: it applies the newest known layout profile (snapshot formats only change at release boundaries, so a fresh git build matches the latest release) and refines the compressed word size from the feature flags. The Dart version is reported as `~<version>+ (fingerprint)` and `version_source` is set to `fingerprint` (vs `exact-hash` / `override`) so the result is never silently presented as an exact match. |
|
||||
| Obfuscation maps | Flutter/Dart `--save-obfuscation-map` JSON arrays are supported with `-m <file>` or `e r2flutter.mapfile=<file>` in the plugin. |
|
||||
|
||||
## Layout Profiles
|
||||
|
||||
@@ -47,6 +47,7 @@ typedef struct {
|
||||
char dart_version_override[32];
|
||||
const DartVerLayout *layout;
|
||||
int compressed_word_size;
|
||||
int version_source; // DartVersionSource: how the layout/version was chosen
|
||||
HtUP *name_by_ep;
|
||||
char **name_by_code_index;
|
||||
ut64 name_by_code_index_count;
|
||||
|
||||
@@ -19,6 +19,15 @@ typedef enum {
|
||||
DART_TAG_STYLE_OBJECT_HEADER = 2 // v3.4.3+ and known 2.18.2 exception
|
||||
} DartTagStyle;
|
||||
|
||||
// How the Dart version/layout for a snapshot was determined. Reported so users
|
||||
// can tell whether decoding rests on an exact match or a best-effort guess.
|
||||
typedef enum {
|
||||
DART_VERSION_SOURCE_EXACT = 0, // snapshot hash matched a known SDK release
|
||||
DART_VERSION_SOURCE_OVERRIDE = 1, // user forced a profile via -D
|
||||
DART_VERSION_SOURCE_FINGERPRINT = 2, // unknown hash, layout inferred from evidence
|
||||
DART_VERSION_SOURCE_UNKNOWN = 3 // no snapshot available
|
||||
} DartVersionSource;
|
||||
|
||||
// Version layout information for Dart snapshots
|
||||
// CID values are stored in dart_cid.c's cid_tables[] and accessed via dart_cid_get()
|
||||
typedef struct {
|
||||
@@ -42,9 +51,16 @@ const DartVerLayout *dart_profile_from_version(const char *version);
|
||||
|
||||
// Pick a layout structure based on hash, with fallback to defaults
|
||||
// Returns a newly allocated DartVerLayout (caller must free)
|
||||
// If hash is unknown, uses v3.9.2 defaults
|
||||
// If hash is unknown, fingerprints against the newest known layout profile
|
||||
DartVerLayout *dart_pick_layout_by_hash(const char *hash);
|
||||
|
||||
// Newest known layout profile (used as the fingerprint baseline for unknown
|
||||
// git/dev builds, whose snapshot format tracks the latest release).
|
||||
const DartVerLayout *dart_newest_profile(void);
|
||||
|
||||
// Human-readable name for a DartVersionSource value.
|
||||
const char *dart_version_source_str(int source);
|
||||
|
||||
// Free a DartVerLayout allocated by dart_pick_layout_by_hash
|
||||
void dart_ver_layout_free(DartVerLayout *layout);
|
||||
|
||||
|
||||
+52
-12
@@ -69,6 +69,37 @@ const char *dart_ctx_effective_version(DartCtx *ctx) {
|
||||
return dart_version_from_hash (dart_ctx_effective_hash (ctx));
|
||||
}
|
||||
|
||||
// Classify how the layout was determined, for honest reporting: exact hash
|
||||
// match, user override, best-effort fingerprint (unknown hash), or no snapshot.
|
||||
static void dart_ctx_set_version_source(DartCtx *ctx) {
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
if (R_STR_ISNOTEMPTY (ctx->dart_version_override)) {
|
||||
ctx->version_source = DART_VERSION_SOURCE_OVERRIDE;
|
||||
} else if (dart_version_from_hash (dart_ctx_effective_hash (ctx))) {
|
||||
ctx->version_source = DART_VERSION_SOURCE_EXACT;
|
||||
} else if (R_STR_ISNOTEMPTY (dart_ctx_effective_hash (ctx))) {
|
||||
ctx->version_source = DART_VERSION_SOURCE_FINGERPRINT;
|
||||
} else {
|
||||
ctx->version_source = DART_VERSION_SOURCE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Effective version label including a marker when the layout was fingerprinted
|
||||
// from an unknown (git/dev build) hash rather than matched exactly.
|
||||
static const char *dart_ctx_version_label(DartCtx *ctx, char *buf, size_t bufsz) {
|
||||
const char *v = dart_ctx_effective_version (ctx);
|
||||
if (v) {
|
||||
return v;
|
||||
}
|
||||
if (ctx && ctx->version_source == DART_VERSION_SOURCE_FINGERPRINT && ctx->layout && ctx->layout->dart_version) {
|
||||
snprintf (buf, bufsz, "~%s+ (fingerprint)", ctx->layout->dart_version);
|
||||
return buf;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static const char *dart_tag_style_names[] = {
|
||||
"CID_INT32", // DART_TAG_STYLE_CID_INT32 = 0
|
||||
"CID_SHIFT1", // DART_TAG_STYLE_CID_SHIFT1 = 1
|
||||
@@ -103,12 +134,13 @@ static const DartVerLayout *load_layout_from_json(const char *hash, DartVerLayou
|
||||
}
|
||||
const char *version = dart_version_from_hash (hash);
|
||||
const DartVerLayout *base_profile = version? dart_profile_from_version (version): NULL;
|
||||
if (base_profile) {
|
||||
memcpy (out, base_profile, sizeof (*out));
|
||||
} else {
|
||||
memset (out, 0, sizeof (*out));
|
||||
out->tag_style = DART_TAG_STYLE_OBJECT_HEADER;
|
||||
if (!base_profile) {
|
||||
// Unknown hash: fingerprint against the newest known profile so the
|
||||
// decode path (-f/-A) uses the same real layout the -H report shows,
|
||||
// not a degenerate zeroed struct. cws is still refined from the flags.
|
||||
base_profile = dart_newest_profile ();
|
||||
}
|
||||
memcpy (out, base_profile, sizeof (*out));
|
||||
r_str_ncpy (out->hash, hash, sizeof (out->hash));
|
||||
for (int i = 0; i < DART_HASH_ENTRIES_COUNT; i++) {
|
||||
if (!strcmp (dart_hash_entries[i].hash, hash)) {
|
||||
@@ -206,6 +238,7 @@ DartVerLayout *dart_ctx_init_layout(DartCtx *ctx, DartVerLayout *tmp) {
|
||||
ctx->layout = owned;
|
||||
}
|
||||
derive_layout_from_flags (ctx);
|
||||
dart_ctx_set_version_source (ctx);
|
||||
return owned;
|
||||
}
|
||||
|
||||
@@ -583,6 +616,7 @@ static int prepare_header_data(DartCtx *ctx) {
|
||||
extract_snapshot_hash_flags (ctx, ctx->vm_data);
|
||||
ctx->layout = dart_pick_layout_owned_for_ctx (ctx);
|
||||
derive_layout_from_flags (ctx);
|
||||
dart_ctx_set_version_source (ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -594,7 +628,9 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
|
||||
return fmt == 'r'? strdup ("# Error: Dart snapshots not found\n"): strdup ("Error: Dart snapshots not found\n");
|
||||
}
|
||||
const bool quiet = ctx && ctx->quiet;
|
||||
const char *version = dart_ctx_effective_version (ctx);
|
||||
char vbuf[48];
|
||||
const char *version = dart_ctx_version_label (ctx, vbuf, sizeof (vbuf));
|
||||
const char *version_source = dart_version_source_str (ctx? ctx->version_source: DART_VERSION_SOURCE_UNKNOWN);
|
||||
if (fmt == 'j') {
|
||||
ut64 header_addr = ctx->iso_data? ctx->iso_data: ctx->vm_data;
|
||||
DartSnapshotHeader sh = { 0 };
|
||||
@@ -630,7 +666,8 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
|
||||
pj_kn (pj, "total", sh.total_len);
|
||||
pj_end (pj);
|
||||
pj_ki (pj, "cws", ctx->compressed_word_size);
|
||||
pj_ks (pj, "dart_version", version? version: "unknown");
|
||||
pj_ks (pj, "dart_version", version);
|
||||
pj_ks (pj, "version_source", version_source);
|
||||
if (ctx->layout) {
|
||||
const DartVerLayout *l = ctx->layout;
|
||||
pj_ks (pj, "tag_style", dart_tag_style_to_string (l->tag_style));
|
||||
@@ -669,7 +706,7 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
|
||||
if (!quiet) {
|
||||
// Add comments with metadata
|
||||
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Dart snapshot hash: %s\n", (ut64)ctx->vm_data, ctx->snapshot_hash[0]? ctx->snapshot_hash: "(unknown)");
|
||||
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Dart version: %s\n", (ut64)ctx->vm_data, version? version: "unknown");
|
||||
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Dart version: %s (%s)\n", (ut64)ctx->vm_data, version, version_source);
|
||||
if (ctx->layout) {
|
||||
const DartVerLayout *l = ctx->layout;
|
||||
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Tag style: %s\n", (ut64)ctx->vm_data, dart_tag_style_to_string (l->tag_style));
|
||||
@@ -681,7 +718,7 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
|
||||
|
||||
RStrBuf *sb = r_strbuf_new ("");
|
||||
if (quiet) {
|
||||
r_strbuf_appendf (sb, "snapshot_hash=%s dart_version=%s vm_data=0x%" PFMT64x " vm_instr=0x%" PFMT64x " iso_data=0x%" PFMT64x " iso_instr=0x%" PFMT64x " cws=%d", ctx->snapshot_hash[0]? ctx->snapshot_hash: "(unknown)", version? version: "unknown", (ut64)ctx->vm_data, (ut64)ctx->vm_instr, (ut64)ctx->iso_data, (ut64)ctx->iso_instr, ctx->compressed_word_size);
|
||||
r_strbuf_appendf (sb, "snapshot_hash=%s dart_version=%s version_source=%s vm_data=0x%" PFMT64x " vm_instr=0x%" PFMT64x " iso_data=0x%" PFMT64x " iso_instr=0x%" PFMT64x " cws=%d", ctx->snapshot_hash[0]? ctx->snapshot_hash: "(unknown)", version, version_source, (ut64)ctx->vm_data, (ut64)ctx->vm_instr, (ut64)ctx->iso_data, (ut64)ctx->iso_instr, ctx->compressed_word_size);
|
||||
if (ctx->layout) {
|
||||
const DartVerLayout *l = ctx->layout;
|
||||
r_strbuf_appendf (sb, " tag_style=%s alignment=%d", dart_tag_style_to_string (l->tag_style), l->max_alignment);
|
||||
@@ -690,7 +727,8 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
|
||||
}
|
||||
r_strbuf_appendf (sb, "# Dart AOT Snapshot Header\n\n");
|
||||
r_strbuf_appendf (sb, "snapshot_hash: %s\n", ctx->snapshot_hash[0]? ctx->snapshot_hash: "(unknown)");
|
||||
r_strbuf_appendf (sb, "dart_version: %s\n", version? version: "unknown");
|
||||
r_strbuf_appendf (sb, "dart_version: %s\n", version);
|
||||
r_strbuf_appendf (sb, "version_source: %s\n", version_source);
|
||||
if (ctx->layout) {
|
||||
const DartVerLayout *l = ctx->layout;
|
||||
r_strbuf_appendf (sb, "tag_style: %s\n", dart_tag_style_to_string_verbose (l->tag_style));
|
||||
@@ -811,7 +849,8 @@ static void dump_header_snapshot_json(DartCtx *ctx, PJ *pj, const char *label, u
|
||||
}
|
||||
|
||||
static char *dump_header_ext_json(DartCtx *ctx, int detail) {
|
||||
const char *version = dart_ctx_effective_version (ctx);
|
||||
char vbuf[48];
|
||||
const char *version = dart_ctx_version_label (ctx, vbuf, sizeof (vbuf));
|
||||
DartSnapshotHeader iso = { 0 };
|
||||
if (ctx->iso_data) {
|
||||
dart_snapshot_header_read (ctx, ctx->iso_data, &iso);
|
||||
@@ -828,7 +867,8 @@ static char *dump_header_ext_json(DartCtx *ctx, int detail) {
|
||||
pj_kn (pj, "iso_data", ctx->iso_data);
|
||||
pj_kn (pj, "iso_instr", ctx->iso_instr);
|
||||
pj_ki (pj, "cws", ctx->compressed_word_size);
|
||||
pj_ks (pj, "dart_version", version? version: "unknown");
|
||||
pj_ks (pj, "dart_version", version);
|
||||
pj_ks (pj, "version_source", dart_version_source_str (ctx? ctx->version_source: DART_VERSION_SOURCE_UNKNOWN));
|
||||
pj_ki (pj, "detail", detail);
|
||||
if (ctx->container_kind[0]) {
|
||||
pj_k (pj, "container");
|
||||
|
||||
+31
-9
@@ -163,6 +163,27 @@ const char *dart_version_from_hash(const char *hash) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const DartVerLayout *dart_newest_profile(void) {
|
||||
const DartVerLayout *newest = version_profiles;
|
||||
for (int i = 0; version_profiles[i].dart_version; i++) {
|
||||
newest = &version_profiles[i];
|
||||
}
|
||||
return newest;
|
||||
}
|
||||
|
||||
const char *dart_version_source_str(int source) {
|
||||
switch (source) {
|
||||
case DART_VERSION_SOURCE_EXACT:
|
||||
return "exact-hash";
|
||||
case DART_VERSION_SOURCE_OVERRIDE:
|
||||
return "override";
|
||||
case DART_VERSION_SOURCE_FINGERPRINT:
|
||||
return "fingerprint";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const DartVerLayout *dart_profile_from_version(const char *version) {
|
||||
if (!version) {
|
||||
return NULL;
|
||||
@@ -195,16 +216,17 @@ DartVerLayout *dart_pick_layout_by_hash(const char *hash) {
|
||||
}
|
||||
return dvl;
|
||||
}
|
||||
// Default to v3.9.2 layout for unknown hashes
|
||||
dvl->compressed_word_size = 4;
|
||||
dvl->heap_object_tag = 1;
|
||||
dvl->max_alignment = 16;
|
||||
dvl->it_cap = 20000;
|
||||
dvl->tag_style = DART_TAG_STYLE_OBJECT_HEADER;
|
||||
dvl->header_fields = 5;
|
||||
dvl->dart_version = "unknown";
|
||||
// Unknown hash: fingerprint against the newest known profile. Snapshot
|
||||
// formats (CID tables, tag style) only change at release boundaries, so an
|
||||
// unlisted git/dev build almost always matches the most recent release; the
|
||||
// caller still refines compressed_word_size from the feature flags.
|
||||
const DartVerLayout *newest = dart_newest_profile ();
|
||||
memcpy (dvl, newest, sizeof (DartVerLayout));
|
||||
if (hash && *hash) {
|
||||
r_str_ncpy (dvl->hash, hash, sizeof (dvl->hash));
|
||||
}
|
||||
if (G_VERBOSE > 0) {
|
||||
fprintf (stderr, "[r2flutter] Unknown snapshot hash, using v3.9.2 defaults (hash=%s)\n", hash? hash: "(null)");
|
||||
fprintf (stderr, "[r2flutter] Unknown snapshot hash, fingerprinting as newest known profile %s (hash=%s)\n", newest->dart_version, hash? hash: "(null)");
|
||||
}
|
||||
return dvl;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ CMDS=<<EOF
|
||||
!!../bin/r2flutter -j -H bins/android/first 2>/dev/null
|
||||
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","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}}
|
||||
{"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}}
|
||||
EOF
|
||||
RUN
|
||||
@@ -4,6 +4,6 @@ CMDS=<<EOF
|
||||
!!../bin/r2flutter -j -H bins/ios/AuthPass.app
|
||||
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","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}}
|
||||
{"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}}
|
||||
EOF
|
||||
RUN
|
||||
@@ -4,6 +4,6 @@ CMDS=<<EOF
|
||||
!!../bin/r2flutter -j -H bins/ios/Runner.app 2>/dev/null
|
||||
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","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}}
|
||||
{"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}}
|
||||
EOF
|
||||
RUN
|
||||
@@ -4,6 +4,6 @@ CMDS=<<EOF
|
||||
!!../bin/r2flutter -j -H bins/android/mafia 2>/dev/null
|
||||
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","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}}
|
||||
{"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}}
|
||||
EOF
|
||||
RUN
|
||||
@@ -4,6 +4,6 @@ CMDS=<<EOF
|
||||
!!../bin/r2flutter -j -D 830f4f59e7969c70b595182826435c19 -H bins/android/first 2>/dev/null
|
||||
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","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}}
|
||||
{"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}}
|
||||
EOF
|
||||
RUN
|
||||
Reference in new issue
Block a user