diff --git a/doc/dae-todo.md b/doc/dae-todo.md index e02c495..a432570 100644 --- a/doc/dae-todo.md +++ b/doc/dae-todo.md @@ -18,7 +18,7 @@ cluster layouts next, then metadata/value restoration and profile detection. - [x] **R2F-DAE-003 — Handle versioned ObjectPool entry bits** - Model low-seven-bit, swapped low-seven-bit, and modern bitfield eras. - Commit: `Handle Versioned ObjectPool Entry Bits` -- [ ] **R2F-DAE-004 — Parse versioned Code cluster layouts** +- [x] **R2F-DAE-004 — Parse versioned Code cluster layouts** - Profile Code reference counts, text-offset deltas, and leading refs. - Commit: `Parse Versioned Code Cluster Layouts` - [ ] **R2F-DAE-005 — Support Dart 3.13 single snapshots** diff --git a/doc/learn.md b/doc/learn.md index b4f8e07..cb1e56d 100644 --- a/doc/learn.md +++ b/doc/learn.md @@ -1407,3 +1407,21 @@ that bit width but swaps those two type values. Dart 3.3 and later use the modern layout: a four-bit type, bit 4 patchability, and bits 5-7 snapshot behavior. A broad Dart-2-versus-Dart-3 check therefore misdecodes 3.0-3.2 and may skip a serialized payload, shifting every following pool entry. + +## Code Cluster Framing Has Independent Transitions + +Code allocation and fill cannot be keyed only to a broad legacy flag. Dart +2.10-2.13 allocation writes the main count followed directly by the deferred +count. Dart 2.14 and later add a state word for every main and deferred Code. + +The fill has seven object references through Dart 2.16 and six from Dart 2.17 +onward. Dart 2.10-2.15 also put an instruction text-offset delta before each +main Code's payload info. Dart 3.13 adds two cluster-level references before +the per-Code records. These fields are profiled separately so a format change +in one dimension does not imply a change in another. + +r2flutter keeps its existing normalized Code and instruction-table model. The +profile is applied while framing the Code stream and while recovering Code +owners; DAE's Dart 2.18 negative fill adjustment is intentionally not copied, +because it compensates for drift in DAE's own generic fill walker rather than +a serialized SDK field. diff --git a/include/r2flutter/dart_version.h b/include/r2flutter/dart_version.h index e048ecf..0952f39 100644 --- a/include/r2flutter/dart_version.h +++ b/include/r2flutter/dart_version.h @@ -45,6 +45,11 @@ typedef enum { DART_POOL_ENCODING_LOW7_SWAPPED // type[0..6], patch[7], immediate=0, tagged=1 } DartPoolEncoding; +typedef enum { + DART_CODE_ALLOC_STATE_DEFERRED = 0, // count, state words, deferred count/state words + DART_CODE_ALLOC_DEFERRED_ONLY // count, deferred count +} DartCodeAlloc; + // 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 { @@ -68,6 +73,10 @@ typedef struct { DartHeaderStyle header_style; DartRefEncoding ref_encoding; DartPoolEncoding pool_encoding; + DartCodeAlloc code_alloc; + int code_refs; + int code_leading_refs; + bool code_has_text_offset; } DartVerLayout; // Lookup Dart version from a snapshot hash (MD5) diff --git a/scripts/update-dart-version b/scripts/update-dart-version index c005bd0..593110d 100755 --- a/scripts/update-dart-version +++ b/scripts/update-dart-version @@ -71,6 +71,11 @@ POOL_ENCODING_NAMES = { "low7_swapped": "DART_POOL_ENCODING_LOW7_SWAPPED", } +CODE_ALLOC_NAMES = { + "state_deferred": "DART_CODE_ALLOC_STATE_DEFERRED", + "deferred_only": "DART_CODE_ALLOC_DEFERRED_ONLY", +} + TAG_STYLE_VALUES = {v: k for k, v in TAG_STYLE_NAMES.items()} CID_KIND_TO_CLASS_NAME = [ @@ -620,6 +625,16 @@ def pool_encoding_for_version(version): return POOL_ENCODING_NAMES["modern"] +def code_layout_for_version(version): + ver_tuple = parse_version(version) + return { + "alloc": CODE_ALLOC_NAMES["deferred_only" if ver_tuple < (2, 14) else "state_deferred"], + "refs": 7 if ver_tuple < (2, 17) else 6, + "leading_refs": 2 if ver_tuple >= (3, 13) else 0, + "has_text_offset": "true" if ver_tuple < (2, 16) else "false", + } + + def profile_diff(existing, inferred): diffs = [] for key in ("cws", "heap_object_tag", "max_alignment", "it_cap", "tag_style", "header_fields"): @@ -736,10 +751,12 @@ def gen_profile_entries(offsets): header_style = header_style_for_version(ver) ref_encoding = ref_encoding_for_version(ver) pool_encoding = pool_encoding_for_version(ver) + code = code_layout_for_version(ver) lines.append(f'\t{{ "", "{ver}", {v["cws"]}, {v["heap_object_tag"]}, ' f'{v["max_alignment"]}, {v["it_cap"]}, {tag_name}, ' - f'{v["header_fields"]}, {header_style}, {ref_encoding}, {pool_encoding} }}, // Dart {ver}') - lines.append("\t{ { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0 }") + f'{v["header_fields"]}, {header_style}, {ref_encoding}, {pool_encoding}, ' + f'{code["alloc"]}, {code["refs"]}, {code["leading_refs"]}, {code["has_text_offset"]} }}, // Dart {ver}') + lines.append("\t{ { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }") lines.append("};") return "\n".join(lines) diff --git a/src/lib/dart_pool_modern.c b/src/lib/dart_pool_modern.c index c74d73a..f0cfbb4 100644 --- a/src/lib/dart_pool_modern.c +++ b/src/lib/dart_pool_modern.c @@ -771,6 +771,15 @@ static bool modern_skip_alloc(ClusterStream *s, const ModernCidCache *cids, int return false; } meta->main_count = count; + DartCodeAlloc encoding = s->ctx && s->ctx->layout? s->ctx->layout->code_alloc: DART_CODE_ALLOC_STATE_DEFERRED; + if (encoding == DART_CODE_ALLOC_DEFERRED_ONLY) { + ut64 deferred = 0; + if (!cs_read_unsigned (s, &deferred)) { + return false; + } + meta->count = count + deferred; + return true; + } meta->discarded_codes = (ut8 *)calloc ((size_t)count + 1, 1); for (ut64 i = 0; i < count; i++) { ut32 state_bits = 0; @@ -1325,10 +1334,23 @@ static bool modern_skip_fill_instance(DartCtx *ctx, ClusterStream *s, const Mode } static bool modern_skip_fill_code(ClusterStream *s, const ModernClusterMeta *meta) { - const int num_refs = 6; + const DartVerLayout *layout = s && s->ctx? s->ctx->layout: NULL; + const int num_refs = layout && layout->code_refs > 0? layout->code_refs: 6; + const int leading_refs = layout? layout->code_leading_refs: 0; + ut64 ref = 0; + for (int i = 0; i < leading_refs; i++) { + if (!cs_read_ref_id (s, &ref)) { + return false; + } + } for (ut64 i = 0; i < meta->count; i++) { - ut64 ref = 0; if (i < meta->main_count) { + if (layout && layout->code_has_text_offset) { + ut64 text_offset_delta = 0; + if (!cs_read_unsigned (s, &text_offset_delta)) { + return false; + } + } ut64 payload = 0; if (!cs_read_unsigned (s, &payload)) { return false; @@ -4252,11 +4274,25 @@ static int modern_name_scan_owner_cid(const ModernWalk *w, ut64 owner_ref) { static bool modern_name_scan_read_code(ModernWalk *w, ClusterStream *s, const ModernClusterMeta *m) { ModernNameScanWalk *u = (ModernNameScanWalk *)w->user; + const DartVerLayout *layout = w && w->ctx? w->ctx->layout: NULL; + const int num_refs = layout && layout->code_refs > 0? layout->code_refs: 6; + const int leading_refs = layout? layout->code_leading_refs: 0; + ut64 tmp_ref = 0; + for (int i = 0; i < leading_refs; i++) { + if (!cs_read_ref_id (s, &tmp_ref)) { + return false; + } + } for (ut64 j = 0; j < m->count; j++) { ut64 owner_ref = 0; - ut64 tmp_ref = 0; ut64 slot = UT64_MAX; if (j < m->main_count) { + if (layout && layout->code_has_text_offset) { + ut64 text_offset_delta = 0; + if (!cs_read_unsigned (s, &text_offset_delta)) { + return false; + } + } ut64 payload = 0; if (!cs_read_unsigned (s, &payload)) { return false; @@ -4269,7 +4305,7 @@ static bool modern_name_scan_read_code(ModernWalk *w, ClusterStream *s, const Mo continue; } } - for (int k = 0; k < 6; k++) { + for (int k = 0; k < num_refs; k++) { if (!cs_read_ref_id (s, &tmp_ref)) { return false; } diff --git a/src/lib/dart_version.c b/src/lib/dart_version.c index e079476..fe58b90 100644 --- a/src/lib/dart_version.c +++ b/src/lib/dart_version.c @@ -130,31 +130,31 @@ static const struct { // Range-start version profiles. CID tables are generated in dart_cid.c. static const DartVerLayout version_profiles[] = { - { "", "2.10.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 4, DART_HEADER_STYLE_210, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7 }, // Dart 2.10.0 - { "", "2.12.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 5, DART_HEADER_STYLE_212, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7 }, // Dart 2.12.0 - { "", "2.13.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 5, DART_HEADER_STYLE_212, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7 }, // Dart 2.13.0 - { "", "2.14.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_214, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7 }, // Dart 2.14.0 - { "", "2.15.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_214, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7 }, // Dart 2.15.0 - { "", "2.16.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 6, DART_HEADER_STYLE_216, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7 }, // Dart 2.16.0 - { "", "2.17.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 6, DART_HEADER_STYLE_216, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7 }, // Dart 2.17.0 - { "", "2.18.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7 }, // Dart 2.18.0 - { "", "2.18.2", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7 }, // Dart 2.18.2 - { "", "2.18.3", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7 }, // Dart 2.18.3 - { "", "2.19.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7 }, // Dart 2.19.0 - { "", "3.0.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7 }, // Dart 3.0.0 - { "", "3.1.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7 }, // Dart 3.1.0 - { "", "3.2.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7_SWAPPED }, // Dart 3.2.0 - { "", "3.3.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.3.0 - { "", "3.4.0", 8, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.4.0 - { "", "3.5.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.5.0 - { "", "3.6.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.6.0 - { "", "3.7.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.7.0 - { "", "3.8.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.8.0 - { "", "3.9.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.9.0 - { "", "3.10.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.10.0 - { "", "3.11.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.11.0 - { "", "3.12.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN }, // Dart 3.12.0 - { { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + { "", "2.10.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 4, DART_HEADER_STYLE_210, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_DEFERRED_ONLY, 7, 0, true }, // Dart 2.10.0 + { "", "2.12.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 5, DART_HEADER_STYLE_212, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_DEFERRED_ONLY, 7, 0, true }, // Dart 2.12.0 + { "", "2.13.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 5, DART_HEADER_STYLE_212, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_DEFERRED_ONLY, 7, 0, true }, // Dart 2.13.0 + { "", "2.14.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_214, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 7, 0, true }, // Dart 2.14.0 + { "", "2.15.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_214, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 7, 0, true }, // Dart 2.15.0 + { "", "2.16.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 6, DART_HEADER_STYLE_216, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 7, 0, false }, // Dart 2.16.0 + { "", "2.17.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 6, DART_HEADER_STYLE_216, DART_REF_ENCODING_UNSIGNED, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 2.17.0 + { "", "2.18.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 2.18.0 + { "", "2.18.2", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 2.18.2 + { "", "2.18.3", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 2.18.3 + { "", "2.19.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 2.19.0 + { "", "3.0.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.0.0 + { "", "3.1.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.1.0 + { "", "3.2.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_LOW7_SWAPPED, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.2.0 + { "", "3.3.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.3.0 + { "", "3.4.0", 8, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.4.0 + { "", "3.5.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.5.0 + { "", "3.6.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.6.0 + { "", "3.7.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.7.0 + { "", "3.8.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.8.0 + { "", "3.9.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.9.0 + { "", "3.10.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.10.0 + { "", "3.11.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.11.0 + { "", "3.12.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN, DART_REF_ENCODING_REF_ID128, DART_POOL_ENCODING_MODERN, DART_CODE_ALLOC_STATE_DEFERRED, 6, 0, false }, // Dart 3.12.0 + { { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; const char *dart_version_from_hash(const char *hash) { diff --git a/test/db/cmd/code-cluster-layouts b/test/db/cmd/code-cluster-layouts new file mode 100644 index 0000000..fd48096 --- /dev/null +++ b/test/db/cmd/code-cluster-layouts @@ -0,0 +1,17 @@ +NAME=versioned-code-cluster-layouts +FILE=- +CMDS=</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 +EOF +EXPECT=<