mirror of
https://github.com/radareorg/r2flutter.git
synced 2026-11-07 06:26:00 -10:00
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:
1 parent
f138b952c9
commit
f10d30dd6f
7 files changed
+155
-142
No files matched your search
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
Reference in new issue
Block a user