Replace the fake CID enum with layout-resolved class ids

* Memoize cid table for 100x speedup in -x,-f,-c
* Fix Builtin.TypeName
This commit is contained in:
pancake committed 2026-08-11 16:38:03 +02:00
1 parent f138b952c9
commit f10d30dd6f
7 files changed
+155 -142

No files matched your search

+27 -29
View File
@@ -26,7 +26,9 @@ rank; each item states the concrete failure it causes.
| `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. |
| `897a98d` | **P1.1**: one `dart_cid_from_tags` helper now decodes `CID_INT32`, `CID_SHIFT1`, and `OBJECT_HEADER` tags for object inspection, modern and legacy cluster walks, data-image scanners, and InstructionTable discovery. This removes the duplicate decoders and fixes `CID_INT32` being treated as `OBJECT_HEADER` in two paths. |
| *(uncommitted)* | **P2.1**: deleted the legacy cluster walker — `deserialize_clusters`, `decode_class_cluster`, `decode_function_cluster`, `resolve_names`, the `DartClass`/`DartPoolFunction` types and the `DartCtx.classes`/`.functions` fields that only it wrote (244 lines). It had been running on every `-f`/`-A` alongside the modern scanner while contributing nothing: verified before removal by stubbing it out (50/50 outputs identical), and after by diffing 95 sample×action outputs against the previous commit. `decode_string_cluster`/`skip_generic_cluster`/`free_dart_string` stay — the legacy **class** parser in `dart_pool_classes.c` still uses them for CID_SHIFT1 samples. |
| `833f89a` | **P2.1**: deleted the legacy cluster walker — `deserialize_clusters`, `decode_class_cluster`, `decode_function_cluster`, `resolve_names`, the `DartClass`/`DartPoolFunction` types and the `DartCtx.classes`/`.functions` fields that only it wrote (244 lines). It had been running on every `-f`/`-A` alongside the modern scanner while contributing nothing: verified before removal by stubbing it out (50/50 outputs identical), and after by diffing 95 sample×action outputs against the previous commit. `decode_string_cluster`/`skip_generic_cluster`/`free_dart_string` stay — the legacy **class** parser in `dart_pool_classes.c` still uses them for CID_SHIFT1 samples. |
| *(uncommitted)* | **P2.2**: the fake `kXxxCid` enum is gone. Only 3 of its 28 values (`Class`, `PatchClass`, `Function`) matched any real Dart release, so the legacy class parser decoded Class/Function clusters and silently skipped String/Array/Type/Mint/Double — the ones it needed for names. Its `switch` is now an `if` chain over `LegacyClusterCids`, resolved per layout via `dart_cid_get`. The two sites that fell back to a *fabricated* id when resolution failed (`dart_pool_data_image.c`, `dart_pool_it.c`) now fail closed, and a third raw `kFieldCid` comparison was resolved the same way. `builtin_type_name` keeps working on `Type.type_class_id` — a class id packed in the type flags, not a ref despite the field name — but against real ids. The `ti->kind` discriminator, which was never a snapshot id, became `DartTypeKind`. |
| *(uncommitted)* | **Perf, found via P2.2**: `cid_table_for_layout` resolved the CID table by comparing version *strings* against every row on **every** `dart_cid_get` call, and that call sits per-object on some paths. A one-entry memo keyed on the layout pointer makes it a pointer compare. Synthetic `-x` 4862 → **37 ms** (131×), mafia `-f` 1008 → 550 ms, mafia `-c` 756 → 312 ms. Output unchanged on all 95 comparisons. This was already the dominant cost *before* P2.2 — more evidence for the P3.1 note that the double cluster walk was the wrong suspect. |
Corrections to earlier assumptions, worth remembering:
- **The CID tables are not the problem.** Flooring is exactly correct 2.10→3.12,
@@ -179,22 +181,6 @@ snapshot is the isolate, leave `vm_data = 0`) and updating that test.
## P2 — duplication, dead code, structural debt
### P2.2 Delete the fake `kXxxCid` enum
`dart_pool_parse_priv.h:20-52` hardcodes a CID set matching **no real Dart
version** (`kStringCid=72`, `kOneByteStringCid=73`, `kCodeCid=40`,
`kTypeCid=110`; real ≈ 92/94/17/48), plus `dart_pool_classes.c:51-52` adds
`kFieldCid_extract=10`, `kLibraryCid_extract=12`. Used ~35× in the legacy paths.
Worse than dead: two sites use a fake CID as the **fallback** when real
resolution fails — `dart_pool_data_image.c:161` (`resolved_function_cid >= 0?
resolved_function_cid: kFunctionCid`) and `dart_pool_it.c:152` (same shape with
`kOneByteStringCid`). Falling back to a fabricated CID silently compares against
a value wrong for every Dart version; these should fail closed instead.
**Fix:** route every consumer through `dart_cid_get(layout, …)`, make the two
fallbacks bail, and remove the enum. P2.1 removed the legacy *cluster* walker,
which cut the uses from ~35 to 27; the rest sit in the legacy **class** parser
(`dart_pool_classes.c`), which is still live for CID_SHIFT1 samples like
AuthPass, so they must be converted rather than deleted.
### P2.3 Two different "newest" baselines (introduced by `d387c0b`)
`dart_pick_layout_by_hash` now fingerprints unknown hashes to
`dart_newest_profile()` = **3.12.0**, but `cid_table_for_layout`
@@ -233,9 +219,15 @@ A single `-f`/`-A` walks the cluster stream twice and the data image 2–3 times
**This was claimed to be the biggest perf win; measured, it is not.** Removing
the whole legacy cluster walk changes runtime by ~1%, inside noise (mafia `-f`
993 → 1005 ms; AuthPass `-f` 616 → 618 ms) — it bails out early rather than
re-walking the stream. Collapsing the remaining data-image scans may still help,
but **profile before spending time here**: the real cost is elsewhere, and P3.2's
brute-force InstructionTable search is the better first suspect.
re-walking the stream.
The real cost was elsewhere, and profiling found it: `dart_cid_get` re-resolved
the CID table by version-string comparison on every call (see the status table).
Memoising it took mafia `-f` from 1008 → 550 ms and the synthetic `-x` from 4862
→ 37 ms — far more than P2.1 could ever have given. **Profile before spending
time here.** `-x` is now the slowest action by a wide margin (mafia 7.8 s,
AuthPass 6.5 s) and is the next thing worth measuring; P3.2's brute-force
InstructionTable search is the other suspect.
### P3.2 Brute-force InstructionTable header search
`dart_pool_it.c:233-330` probes `{16,0,8,12} × delta -64..64 step 4`, then scans
@@ -261,6 +253,15 @@ repeatedly. Consider a small multi-window/LRU cache and a short-read-tolerant re
## P4 — test quality (beyond the corpus gaps in P0.3)
- **The synthetic fixture used to encode the fake CID table.** `bins/synthetic/field_snapshot.bin`
was authored with the `kXxxCid` values (cluster ids 73/12/5/114/75/115/110/111/10/7,
none of them real), so the four tests covering the legacy class parser agreed
with the parser and with no real binary. P2.2 renumbered its cluster tags and
packed type-class ids to the layout it fingerprints to (~3.12), verified by the
output being unchanged; feeding the *old* fixture to the new parser now yields
1 class instead of 12, which is the regression signal that was missing.
**There is no generator for this fixture** — it is a checked-in blob, so any
future layout change means patching bytes again. Worth writing one.
- **Obfuscation-map tests are tautological**: `test/db/cmd/obf-map`,
`test/custom/obf-funcs-ios.json`, `obf-it-android.json` load a map whose keys
match nothing in the sample, so output is identical to the no-`-m` run. They
@@ -281,20 +282,17 @@ repeatedly. Consider a small multi-window/LRU cache and a short-read-tolerant re
## Suggested execution order
1. **P2.2** — the fake `kXxxCid` enum and the two fabricated-CID fallbacks.
P2.1 is done; the 27 remaining uses are in the legacy class parser, which is
still live, so convert them to `dart_cid_get` rather than deleting.
2. **P2.3** — one-liner: make the CID fallback use `dart_newest_profile()` rather
1. **P2.3** — one-liner: make the CID fallback use `dart_newest_profile()` rather
than the literal `"3.9.2"`. Maintainer priority #1.
3. **P0.2** — widen the modern decoder to uncompressed snapshots. Biggest quality
2. **P0.2** — widen the modern decoder to uncompressed snapshots. Biggest quality
win; makes most iOS/macOS samples use the good path. The RO-data half is
already implemented and the alloc phase is proven correct; what remains is
version-dependent *fill* shapes — see the P0.2 notes before starting.
4. **P0.3** — grow the corpus alongside 3 so it is actually verified, and to give
3. **P0.3** — grow the corpus alongside 2 so it is actually verified, and to give
the landed P0.1 fix an end-to-end regression test.
5. **P1.3** — shared frontend parser (fixes the `-r`/`r2 -n` AGENTS.md violations).
6. **P1.2** — arch gating.
7. **P3.2** (profile first — see the P3.1 note), remaining P2 cleanups, test
4. **P1.3** — shared frontend parser (fixes the `-r`/`r2 -n` AGENTS.md violations).
5. **P1.2** — arch gating.
6. **P3.2** (profile first — see the P3.1 note), remaining P2 cleanups, test
hardening.
`COMMIT2.md` tracks the narrower follow-ups left over from the discovery work
+17 -4
View File
@@ -140,11 +140,24 @@ static const DartCidTable *cid_table_for_version(const char *version) {
}
static const DartCidTable *cid_table_for_layout(const DartVerLayout *layout) {
const DartCidTable *table = cid_table_for_version (layout? layout->dart_version: NULL);
if (table) {
return table;
// One-entry memo. dart_cid_get is called per decoded object on some paths,
// and resolving the table means comparing version strings against every row;
// a layout's version never changes once it is picked, so caching the last
// answer turns that scan into a pointer compare.
static const DartVerLayout *memo_layout = NULL;
static const DartCidTable *memo_table = NULL;
if (layout && layout == memo_layout && memo_table) {
return memo_table;
}
return cid_table_for_version ("3.9.2");
const DartCidTable *table = cid_table_for_version (layout? layout->dart_version: NULL);
if (!table) {
table = cid_table_for_version ("3.9.2");
}
if (layout && table) {
memo_layout = layout;
memo_table = table;
}
return table;
}
const char *dart_cid_kind_name(DartCidKind kind) {
+97 -69
View File
@@ -47,10 +47,58 @@ static void dart_interface_info_free(void *p) {
}
}
typedef enum {
kFieldCid_extract = 10,
kLibraryCid_extract = 12,
} ExtraCids;
// Cluster classes the legacy (non-OBJECT_HEADER) parser knows how to decode,
// resolved for the snapshot's own layout. Absent classes resolve to -1 and then
// match nothing, which is the point: comparing against a hardcoded id silently
// decoded the wrong cluster on every release that shifted the numbering.
typedef struct {
int string;
int one_byte_string;
int two_byte_string;
int class_;
int field;
int function;
int type;
int function_type;
int type_parameter;
int type_arguments;
int array;
int immutable_array;
int library;
} LegacyClusterCids;
static LegacyClusterCids legacy_cluster_cids(const DartVerLayout *layout) {
const LegacyClusterCids lc = {
.string = dart_cid_get (layout, DART_CID_STRING),
.one_byte_string = dart_cid_get (layout, DART_CID_ONE_BYTE_STRING),
.two_byte_string = dart_cid_get (layout, DART_CID_TWO_BYTE_STRING),
.class_ = dart_cid_get (layout, DART_CID_CLASS),
.field = dart_cid_get (layout, DART_CID_FIELD),
.function = dart_cid_get (layout, DART_CID_FUNCTION),
.type = dart_cid_get (layout, DART_CID_TYPE),
.function_type = dart_cid_get (layout, DART_CID_FUNCTION_TYPE),
.type_parameter = dart_cid_get (layout, DART_CID_TYPE_PARAMETER),
.type_arguments = dart_cid_get (layout, DART_CID_TYPE_ARGUMENTS),
.array = dart_cid_get (layout, DART_CID_ARRAY),
.immutable_array = dart_cid_get (layout, DART_CID_IMMUTABLE_ARRAY),
.library = dart_cid_get (layout, DART_CID_LIBRARY),
};
return lc;
}
static inline bool legacy_cid_is(ut64 cid, int resolved) {
return resolved >= 0 && cid == (ut64)resolved;
}
// Clusters whose decoders may legitimately give up part-way (variable-length
// payloads we do not fully model); the rest are treated as stream corruption.
static bool legacy_cid_recoverable(ut64 cid, const LegacyClusterCids *lc) {
return legacy_cid_is (cid, lc->function) ||
legacy_cid_is (cid, lc->function_type) ||
legacy_cid_is (cid, lc->type_arguments) ||
legacy_cid_is (cid, lc->array) ||
legacy_cid_is (cid, lc->immutable_array);
}
#define DART_TYPE_CLASS_ID_SHIFT 3
#define DART_TYPE_CLASS_ID_MASK ((1U << 20) - 1)
@@ -415,7 +463,7 @@ static int decode_type_cluster_ext(ClusterStream *s, DartCtx *ctx, RList *type_l
for (ut64 i = 0; i < count; i++) {
DartTypeInfo *ti = R_NEW0 (DartTypeInfo);
ti->ref_id = (*ref_counter)++;
ti->kind = kTypeCid;
ti->kind = DART_TYPE_KIND_TYPE;
ut64 type_test_stub_ref = 0;
ut64 hash_ref = 0;
ut64 args_ref = 0;
@@ -451,7 +499,7 @@ static int decode_type_parameter_cluster_ext(ClusterStream *s, DartCtx *ctx, RLi
for (ut64 i = 0; i < count; i++) {
DartTypeInfo *ti = R_NEW0 (DartTypeInfo);
ti->ref_id = (*ref_counter)++;
ti->kind = kTypeParameterCid;
ti->kind = DART_TYPE_KIND_TYPE_PARAMETER;
ut64 type_test_stub_ref = 0;
ut64 hash_ref = 0;
ut64 owner_ref = 0;
@@ -518,7 +566,7 @@ static int decode_function_type_cluster_ext(ClusterStream *s, DartCtx *ctx, RLis
for (ut64 i = 0; i < count; i++) {
DartTypeInfo *ti = R_NEW0 (DartTypeInfo);
ti->ref_id = (*ref_counter)++;
ti->kind = kFunctionTypeCid;
ti->kind = DART_TYPE_KIND_FUNCTION_TYPE;
ut64 type_test_stub_ref = 0;
ut64 hash_ref = 0;
if (!cs_read_ref_id (s, &type_test_stub_ref) || !cs_read_ref_id (s, &hash_ref) || !cs_read_ref_id (s, &ti->type_parameters_ref) || !cs_read_ref_id (s, &ti->result_type_ref) || !cs_read_ref_id (s, &ti->parameter_types_ref) || !cs_read_ref_id (s, &ti->named_parameter_names_ref)) {
@@ -658,23 +706,27 @@ static char *dup_ref_string_obf(DartCtx *ctx, ut64 ref) {
return value;
}
static const char *builtin_type_name(ut64 cid) {
switch (cid) {
case kStringCid:
case kOneByteStringCid:
case kTwoByteStringCid:
// `Type.type_class_id` is a class id packed into the type's flags, not a ref, so
// it is compared against this layout's real ids.
static const char *builtin_type_name(DartCtx *ctx, ut64 cid) {
const DartVerLayout *layout = ctx? ctx->layout: NULL;
if (legacy_cid_is (cid, dart_cid_get (layout, DART_CID_STRING)) ||
legacy_cid_is (cid, dart_cid_get (layout, DART_CID_ONE_BYTE_STRING)) ||
legacy_cid_is (cid, dart_cid_get (layout, DART_CID_TWO_BYTE_STRING))) {
return "String";
case kArrayCid:
case kImmutableArrayCid:
case kGrowableObjectArrayCid:
return "List";
case kMintCid:
return "int";
case kDoubleCid:
return "double";
default:
return NULL;
}
if (legacy_cid_is (cid, dart_cid_get (layout, DART_CID_ARRAY)) ||
legacy_cid_is (cid, dart_cid_get (layout, DART_CID_IMMUTABLE_ARRAY)) ||
legacy_cid_is (cid, dart_cid_get (layout, DART_CID_GROWABLE_OBJECT_ARRAY))) {
return "List";
}
if (legacy_cid_is (cid, dart_cid_get (layout, DART_CID_MINT))) {
return "int";
}
if (legacy_cid_is (cid, dart_cid_get (layout, DART_CID_DOUBLE))) {
return "double";
}
return NULL;
}
static DartTypeInfo *find_type_by_ref(RList *type_list, ut64 ref) {
@@ -855,7 +907,7 @@ static char *resolve_type_name_depth(DartCtx *ctx, RList *class_list, RList *typ
if (R_STR_ISNOTEMPTY (ti->name)) {
return strdup (ti->name);
}
if (ti->kind == kTypeParameterCid) {
if (ti->kind == DART_TYPE_KIND_TYPE_PARAMETER) {
bool is_function_param = (ti->flags & DART_TYPE_PARAMETER_FUNCTION_FLAG) != 0;
const char *base_prefix = is_function_param? "F": "C";
const char *index_prefix = is_function_param? "Y": "X";
@@ -868,7 +920,7 @@ static char *resolve_type_name_depth(DartCtx *ctx, RList *class_list, RList *typ
}
return name;
}
if (ti->kind == kFunctionTypeCid) {
if (ti->kind == DART_TYPE_KIND_FUNCTION_TYPE) {
char *name = resolve_function_type_name (ctx, class_list, type_list, type_args_list, array_list, ti, depth);
if (name) {
ti->name = strdup (name);
@@ -876,7 +928,7 @@ static char *resolve_type_name_depth(DartCtx *ctx, RList *class_list, RList *typ
return name;
}
char *name = NULL;
const char *builtin = builtin_type_name (ti->type_class_ref);
const char *builtin = builtin_type_name (ctx, ti->type_class_ref);
if (builtin) {
name = strdup (builtin);
} else {
@@ -1319,7 +1371,7 @@ static void resolve_class_interfaces(DartCtx *ctx, RList *class_list, RList *typ
char *name = resolve_type_name (ctx, class_list, type_list, type_args_list, array_list, type_ref);
ut64 class_ref = 0;
DartTypeInfo *ti = find_type_by_ref (type_list, type_ref);
if (ti && ti->kind == kTypeCid) {
if (ti && ti->kind == DART_TYPE_KIND_TYPE) {
DartClassInfo *target_ci = find_class_by_ref (class_list, ti->type_class_ref);
if (target_ci) {
class_ref = target_ci->ref_id;
@@ -1504,6 +1556,7 @@ RList *dart_pool_extract_classes(DartCtx *ctx) {
.end = snapshot_base + sh.total_len
};
ut64 ref_counter = sh.nb + 1;
const LegacyClusterCids lc = legacy_cluster_cids (ctx->layout);
for (ut64 ci2 = 0; ci2 < sh.nc && stream.cursor < stream.end; ci2++) {
uint32_t tags = 0;
if (!cs_read_u32 (&stream, &tags)) {
@@ -1513,62 +1566,37 @@ RList *dart_pool_extract_classes(DartCtx *ctx) {
bool is_canonical = ((tags >> 1) & 1) != 0;
(void)is_canonical;
if (ctx->verbose > 1) {
fprintf (stderr, "[r2flutter] Cluster %" PRIu64 ": cid=%u (Class=%d,Field=%d,String=%d)\n", ci2, cid, kClassCid, kFieldCid_extract, kOneByteStringCid);
fprintf (stderr, "[r2flutter] Cluster %" PRIu64 ": cid=%u (Class=%d,Field=%d,String=%d)\n", ci2, cid, lc.class_, lc.field, lc.one_byte_string);
}
int rc = 0;
switch (cid) {
case kOneByteStringCid:
case kTwoByteStringCid:
case kStringCid:
if (legacy_cid_is (cid, lc.one_byte_string) || legacy_cid_is (cid, lc.two_byte_string) || legacy_cid_is (cid, lc.string)) {
rc = decode_string_cluster (&stream, ctx, &ref_counter, false);
break;
case kClassCid:
} else if (legacy_cid_is (cid, lc.class_)) {
rc = decode_class_cluster_ext (&stream, ctx, class_list, &ref_counter);
break;
case kFieldCid_extract:
} else if (legacy_cid_is (cid, lc.field)) {
rc = decode_field_cluster_ext (&stream, ctx, field_list, &ref_counter);
break;
case kFunctionCid:
} else if (legacy_cid_is (cid, lc.function)) {
rc = decode_function_cluster_ext (&stream, ctx, method_list, &ref_counter);
if (rc < 0) {
rc = 0;
skip_generic_cluster (&stream);
}
break;
case kTypeCid:
} else if (legacy_cid_is (cid, lc.type)) {
rc = decode_type_cluster_ext (&stream, ctx, type_list, &ref_counter);
break;
case kFunctionTypeCid:
} else if (legacy_cid_is (cid, lc.function_type)) {
rc = decode_function_type_cluster_ext (&stream, ctx, type_list, &ref_counter);
if (rc < 0) {
rc = 0;
skip_generic_cluster (&stream);
}
break;
case kTypeParameterCid:
} else if (legacy_cid_is (cid, lc.type_parameter)) {
rc = decode_type_parameter_cluster_ext (&stream, ctx, type_list, &ref_counter);
break;
case kTypeArgumentsCid:
} else if (legacy_cid_is (cid, lc.type_arguments)) {
rc = decode_type_arguments_cluster_ext (&stream, ctx, type_args_list, &ref_counter);
if (rc < 0) {
rc = 0;
skip_generic_cluster (&stream);
}
break;
case kArrayCid:
case kImmutableArrayCid:
} else if (legacy_cid_is (cid, lc.array) || legacy_cid_is (cid, lc.immutable_array)) {
rc = decode_array_cluster_ext (&stream, ctx, array_list, &ref_counter);
if (rc < 0) {
rc = 0;
skip_generic_cluster (&stream);
}
break;
case kLibraryCid_extract:
} else if (legacy_cid_is (cid, lc.library)) {
rc = decode_library_cluster_ext (&stream, ctx, libraries, &ref_counter);
break;
default:
} else {
skip_generic_cluster (&stream);
}
// A cluster we recognise but cannot decode is not fatal: skip its
// bytes and carry on rather than abandoning the whole snapshot.
if (rc < 0 && legacy_cid_recoverable (cid, &lc)) {
rc = 0;
skip_generic_cluster (&stream);
break;
}
if (rc < 0) {
break;
+6 -4
View File
@@ -64,7 +64,8 @@ bool read_data_image_field(DartCtx *ctx, ut64 pos, ut64 data_start, ut64 data_en
return false;
}
ut64 header = r_read_le64 (hdr);
if ((int)dart_cid_from_tags (ctx, header) != kFieldCid) {
const int cid_field = dart_cid_get (ctx->layout, DART_CID_FIELD);
if (cid_field < 0 || (int)dart_cid_from_tags (ctx, header) != cid_field) {
return false;
}
bool use_compressed = ctx->compressed_word_size == 4;
@@ -157,9 +158,10 @@ bool read_data_image_method(DartCtx *ctx, ut64 pos, ut64 data_start, ut64 data_e
if (!read_mem (ctx, pos, buf, sizeof (buf))) {
return false;
}
const int resolved_function_cid = dart_cid_get (ctx->layout, DART_CID_FUNCTION);
const int cid_function = resolved_function_cid >= 0? resolved_function_cid: kFunctionCid;
if ((int)dart_cid_from_tags (ctx, r_read_le64 (buf)) != cid_function) {
// No Function id for this layout means we cannot tell a Function object from
// anything else; report nothing rather than match against a guessed id.
const int cid_function = dart_cid_get (ctx->layout, DART_CID_FUNCTION);
if (cid_function < 0 || (int)dart_cid_from_tags (ctx, r_read_le64 (buf)) != cid_function) {
return false;
}
ut64 entry = r_read_le64 (buf + fl->entry_off);
+2 -3
View File
@@ -148,9 +148,8 @@ static bool read_it_data_header_from_string_object(DartCtx *ctx, ut64 obj_addr,
}
ut64 tags = r_read_le64 (objhdr);
const ut32 cid = dart_cid_from_tags (ctx, tags);
const int resolved_string_cid = dart_cid_get (ctx->layout, DART_CID_ONE_BYTE_STRING);
const int string_cid = resolved_string_cid >= 0? resolved_string_cid: kOneByteStringCid;
if ((int)cid != string_cid) {
const int string_cid = dart_cid_get (ctx->layout, DART_CID_ONE_BYTE_STRING);
if (string_cid < 0 || (int)cid != string_cid) {
return false;
}
ut64 len_smi = r_read_le64 (objhdr + 8);
+6 -33
View File
@@ -30,40 +30,13 @@ static inline ut32 dart_cid_from_tags(const DartCtx *ctx, ut64 tags) {
}
}
// Which flavour of type a DartTypeInfo holds. Not snapshot class ids: these
// never leave the parser, so they carry no version dependency.
typedef enum {
kIllegalCid = 0,
kClassCid = 5,
kPatchClassCid = 6,
kFunctionCid = 7,
kClosureDataCid = 8,
kFfiTrampolineDataCid = 9,
kFieldCid = 10,
kScriptCid = 11,
kLibraryCid = 12,
kNamespaceCid = 13,
kKernelProgramInfoCid = 14,
kCodeCid = 40,
kInstructionsCid = 41,
kObjectPoolCid = 45,
kCodeSourceMapCid = 49,
kPcDescriptorsCid = 50,
kStringCid = 72,
kOneByteStringCid = 73,
kTwoByteStringCid = 74,
kArrayCid = 75,
kImmutableArrayCid = 76,
kGrowableObjectArrayCid = 77,
kMintCid = 78,
kDoubleCid = 79,
kTypedDataBaseCid = 80,
kTypeCid = 110,
kFunctionTypeCid = 111,
kRecordTypeCid = 112,
kTypeParametersCid = 113,
kTypeParameterCid = 114,
kTypeArgumentsCid = 115,
kNumPredefinedCids = 128
} DartCid;
DART_TYPE_KIND_TYPE = 1,
DART_TYPE_KIND_FUNCTION_TYPE,
DART_TYPE_KIND_TYPE_PARAMETER,
} DartTypeKind;
#define DART_SNAPSHOT_MAGIC 0xdcdcf5f5
#define DART_SNAPSHOT_FIXED_SIZE (4 + 8 + 8)
Binary file not shown.