diff --git a/doc/dae-todo.md b/doc/dae-todo.md new file mode 100644 index 0000000..ab3378f --- /dev/null +++ b/doc/dae-todo.md @@ -0,0 +1,37 @@ +# DAE Gap Implementation TODO + +This roadmap tracks the high-confidence Dart AOT format and restoration gaps +identified by comparing `third_party/dae` with r2flutter. IDs are stable so an +item can be selected by name in follow-up work. + +Items are ordered by dependency: stream framing and codecs first, versioned +cluster layouts next, then metadata/value restoration and profile detection. + +- [x] **R2F-DAE-001 — Parse version-specific snapshot headers** + - Read the profile-defined header field count and semantics. + - Preserve canonical-cluster and field-table fields where present. + - Commit: `Parse Version-Specific Snapshot Headers` +- [ ] **R2F-DAE-002 — Add versioned snapshot reference decoding** + - Use unsigned LEB128 references through Dart 2.17. + - Use the `ReadRefId` +128 encoding from Dart 2.18 onward. + - Commit: `Add Versioned Snapshot Reference Decoding` +- [ ] **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** + - 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** + - Add hashes/CIDs and merged VM/isolate snapshot handling. + - Add the alternate symbols and 3.13 Class, Code, and Closure layouts. + - Commit: `Support Dart 3.13 Single Snapshots` +- [ ] **R2F-DAE-006 — Retain serialized class layout metadata** + - Keep class ID, library/super references, next-field offset, and bitmap. + - Commit: `Retain Serialized Class Layout Metadata` +- [ ] **R2F-DAE-007 — Retain snapshot object value graph** + - Preserve Instance, Array, Map, and Set values by object reference. + - Expose bounded recursive values through the object inspector. + - Commit: `Retain Snapshot Object Value Graph` +- [ ] **R2F-DAE-008 — Probe snapshot layouts for unknown hashes** + - Validate candidate layouts structurally instead of selecting the newest. + - Commit: `Probe Snapshot Layouts for Unknown Hashes` diff --git a/doc/learn.md b/doc/learn.md index 0e88007..f2b90c5 100644 --- a/doc/learn.md +++ b/doc/learn.md @@ -1367,3 +1367,17 @@ field declarations as `'@0x'ic+Class..field ` rather than an `offset=0x` attribute (or a trailing `@` modifier). This keeps the address separate from `ic+`'s metadata arguments and works for both script emission and direct core-command application. +## Snapshot Header Fields Are Versioned Data + +The clustered header after the feature string is not a stable five-value +tuple. Dart 2.10 writes four fields; 2.12-2.13 add a separate canonical-cluster +count; 2.14-2.15 carry a field-table length but no instruction-table data +offset; 2.16-2.17 write six fields; and 2.18+ use the modern five-field +`num_base_objects`, `num_objects`, `num_clusters`, `instructions_table_len`, +`instructions_table_rodata_offset` layout. + +The parser must select the ordered header schema from the snapshot hash before +locating the first allocation cluster. Treating every header as the modern +five-field form consumes a cluster byte on 2.10, starts before the final header +field on 2.16-2.17, and mistakes the canonical-cluster count for the total on +2.12-2.13. diff --git a/include/r2flutter/dart_offsets.h b/include/r2flutter/dart_offsets.h index 96e5524..8e2ead7 100644 --- a/include/r2flutter/dart_offsets.h +++ b/include/r2flutter/dart_offsets.h @@ -27,6 +27,7 @@ static const DartHashEntry dart_hash_entries[] = { { "41be3daaabd524b8aa7423bc24584957", 4 }, // Dart 3.12.0 { "501ef5cbd64ca70b6b42672346af6a8a", 4 }, // Dart 2.19.0 { "5191d02bb1d36a9f8609aa7495894e76", 4 }, // Dart 3.1.0 + { "5b97292b25f0a715613b7a28e0734f77", 8 }, // Dart 2.12.0 { "6093345773c65683f60c20c8e62cbe4a", 8 }, // Dart 2.16.0 { "617d044d9faa87a98c29f8aad5d2f220", 4 }, // Dart 3.0.3 { "659a72e41e3276e882709901c27de33d", 8 }, // Dart 2.14.0 @@ -75,7 +76,7 @@ static const DartHashEntry dart_hash_entries[] = { { "fe53c4fdba846005b70514aec3840296", 8 }, // Dart 3.4.0 }; -#define DART_HASH_ENTRIES_COUNT 61 +#define DART_HASH_ENTRIES_COUNT 62 // Default offset arrays (identical across all known Dart versions) #define DART_DEFAULT_EP_OFFSETS \ diff --git a/include/r2flutter/dart_version.h b/include/r2flutter/dart_version.h index a1a969a..de4657b 100644 --- a/include/r2flutter/dart_version.h +++ b/include/r2flutter/dart_version.h @@ -19,6 +19,16 @@ typedef enum { DART_TAG_STYLE_OBJECT_HEADER = 2 // v3.4.3+ and known 2.18.2 exception } DartTagStyle; +// Ordered fields following the snapshot feature string. The field count alone +// is insufficient because the meaning of the five-field layouts changed. +typedef enum { + DART_HEADER_STYLE_MODERN = 0, // nb, no, nc, itlen, itdata (2.18+) + DART_HEADER_STYLE_210, // nb, no, nc, field_table_len + DART_HEADER_STYLE_212, // nb, no, canonical_nc, nc, field_table_len + DART_HEADER_STYLE_214, // nb, no, nc, field_table_len, itlen + DART_HEADER_STYLE_216 // nb, no, nc, field_table_len, itlen, itdata +} DartHeaderStyle; + // 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 { @@ -39,6 +49,7 @@ typedef struct { ut64 it_cap; DartTagStyle tag_style; int header_fields; + DartHeaderStyle header_style; } DartVerLayout; // Lookup Dart version from a snapshot hash (MD5) diff --git a/offsets.json b/offsets.json index 78ca14a..bb69b8e 100644 --- a/offsets.json +++ b/offsets.json @@ -6,15 +6,15 @@ }, "profiles": { "2.10.0": {"cws": 8, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_INT32", "header_fields": 4, "typed_data_internal_base": 108, "typed_data_internal_limit": 150, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "CLASS": 4, "PATCH_CLASS": 5, "FUNCTION": 6, "CLOSURE_DATA": 7, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 77, "CODE": 16, "OBJECT_POOL": 20, "PC_DESCRIPTORS": 21, "CODE_SOURCE_MAP": 22, "COMPRESSED_STACK_MAPS": 23, "EXCEPTION_HANDLERS": 25, "CONTEXT": 26, "CONTEXT_SCOPE": 27, "SINGLE_TARGET_CACHE": 29, "UNLINKED_CALL": 30, "MONOMORPHIC_SMIABLE_CALL": 31, "CALL_SITE_DATA": 32, "ICDATA": 33, "MEGAMORPHIC_CACHE": 34, "SUBTYPE_TEST_CACHE": 35, "LOADING_UNIT": 36, "LANGUAGE_ERROR": 39, "UNHANDLED_EXCEPTION": 40, "INSTANCE": 42, "LIBRARY_PREFIX": 43, "TYPE_ARGUMENTS": 44, "TYPE": 46, "TYPE_REF": 47, "TYPE_PARAMETER": 48, "CLOSURE": 49, "MINT": 53, "DOUBLE": 54, "FLOAT32X4": 57, "INT32X4": 58, "FLOAT64X2": 59, "TYPED_DATA": 61, "EXTERNAL_TYPED_DATA": 62, "TYPED_DATA_VIEW": 63, "CAPABILITY": 66, "RECEIVE_PORT": 67, "SEND_PORT": 68, "STACK_TRACE": 69, "REGEXP": 70, "WEAK_PROPERTY": 71, "FUTURE_OR": 74, "USER_TAG": 75, "TRANSFERABLE_TYPED_DATA": 76, "ARRAY": 78, "IMMUTABLE_ARRAY": 79, "GROWABLE_OBJECT_ARRAY": 56, "STRING": 80, "ONE_BYTE_STRING": 81, "TWO_BYTE_STRING": 82, "NUM_PREDEFINED_CIDS": 156}}, - "2.12.0": {"cws": 8, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_INT32", "header_fields": 4, "typed_data_internal_base": 100, "typed_data_internal_limit": 142, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "CLASS": 4, "PATCH_CLASS": 5, "FUNCTION": 6, "CLOSURE_DATA": 7, "FFI_TRAMPOLINE_DATA": 8, "FIELD": 9, "SCRIPT": 10, "LIBRARY": 11, "NAMESPACE": 12, "KERNEL_PROGRAM_INFO": 13, "WEAK_SERIALIZATION_REFERENCE": 74, "CODE": 14, "OBJECT_POOL": 17, "PC_DESCRIPTORS": 18, "CODE_SOURCE_MAP": 19, "COMPRESSED_STACK_MAPS": 20, "EXCEPTION_HANDLERS": 22, "CONTEXT": 23, "CONTEXT_SCOPE": 24, "SINGLE_TARGET_CACHE": 25, "UNLINKED_CALL": 26, "MONOMORPHIC_SMIABLE_CALL": 27, "CALL_SITE_DATA": 28, "ICDATA": 29, "MEGAMORPHIC_CACHE": 30, "SUBTYPE_TEST_CACHE": 31, "LOADING_UNIT": 32, "LANGUAGE_ERROR": 35, "UNHANDLED_EXCEPTION": 36, "INSTANCE": 38, "LIBRARY_PREFIX": 39, "TYPE_ARGUMENTS": 40, "TYPE": 42, "FUNCTION_TYPE": 43, "TYPE_REF": 44, "TYPE_PARAMETER": 45, "CLOSURE": 46, "MINT": 50, "DOUBLE": 51, "FLOAT32X4": 54, "INT32X4": 55, "FLOAT64X2": 56, "TYPED_DATA": 58, "EXTERNAL_TYPED_DATA": 59, "TYPED_DATA_VIEW": 60, "CAPABILITY": 63, "RECEIVE_PORT": 64, "SEND_PORT": 65, "STACK_TRACE": 66, "REGEXP": 67, "WEAK_PROPERTY": 68, "FUTURE_OR": 71, "USER_TAG": 72, "TRANSFERABLE_TYPED_DATA": 73, "ARRAY": 75, "IMMUTABLE_ARRAY": 76, "GROWABLE_OBJECT_ARRAY": 53, "STRING": 77, "ONE_BYTE_STRING": 78, "TWO_BYTE_STRING": 79, "NUM_PREDEFINED_CIDS": 148}}, + "2.12.0": {"cws": 8, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_INT32", "header_fields": 5, "typed_data_internal_base": 100, "typed_data_internal_limit": 142, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "CLASS": 4, "PATCH_CLASS": 5, "FUNCTION": 6, "CLOSURE_DATA": 7, "FFI_TRAMPOLINE_DATA": 8, "FIELD": 9, "SCRIPT": 10, "LIBRARY": 11, "NAMESPACE": 12, "KERNEL_PROGRAM_INFO": 13, "WEAK_SERIALIZATION_REFERENCE": 74, "CODE": 14, "OBJECT_POOL": 17, "PC_DESCRIPTORS": 18, "CODE_SOURCE_MAP": 19, "COMPRESSED_STACK_MAPS": 20, "EXCEPTION_HANDLERS": 22, "CONTEXT": 23, "CONTEXT_SCOPE": 24, "SINGLE_TARGET_CACHE": 25, "UNLINKED_CALL": 26, "MONOMORPHIC_SMIABLE_CALL": 27, "CALL_SITE_DATA": 28, "ICDATA": 29, "MEGAMORPHIC_CACHE": 30, "SUBTYPE_TEST_CACHE": 31, "LOADING_UNIT": 32, "LANGUAGE_ERROR": 35, "UNHANDLED_EXCEPTION": 36, "INSTANCE": 38, "LIBRARY_PREFIX": 39, "TYPE_ARGUMENTS": 40, "TYPE": 42, "FUNCTION_TYPE": 43, "TYPE_REF": 44, "TYPE_PARAMETER": 45, "CLOSURE": 46, "MINT": 50, "DOUBLE": 51, "FLOAT32X4": 54, "INT32X4": 55, "FLOAT64X2": 56, "TYPED_DATA": 58, "EXTERNAL_TYPED_DATA": 59, "TYPED_DATA_VIEW": 60, "CAPABILITY": 63, "RECEIVE_PORT": 64, "SEND_PORT": 65, "STACK_TRACE": 66, "REGEXP": 67, "WEAK_PROPERTY": 68, "FUTURE_OR": 71, "USER_TAG": 72, "TRANSFERABLE_TYPED_DATA": 73, "ARRAY": 75, "IMMUTABLE_ARRAY": 76, "GROWABLE_OBJECT_ARRAY": 53, "STRING": 77, "ONE_BYTE_STRING": 78, "TWO_BYTE_STRING": 79, "NUM_PREDEFINED_CIDS": 148}}, "2.13.0": {"cws": 8, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_INT32", "header_fields": 5, "typed_data_internal_base": 100, "typed_data_internal_limit": 142, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "CLASS": 4, "PATCH_CLASS": 5, "FUNCTION": 6, "CLOSURE_DATA": 7, "FFI_TRAMPOLINE_DATA": 8, "FIELD": 9, "SCRIPT": 10, "LIBRARY": 11, "NAMESPACE": 12, "KERNEL_PROGRAM_INFO": 13, "WEAK_SERIALIZATION_REFERENCE": 14, "CODE": 15, "OBJECT_POOL": 18, "PC_DESCRIPTORS": 19, "CODE_SOURCE_MAP": 20, "COMPRESSED_STACK_MAPS": 21, "EXCEPTION_HANDLERS": 23, "CONTEXT": 24, "CONTEXT_SCOPE": 25, "SINGLE_TARGET_CACHE": 26, "UNLINKED_CALL": 27, "MONOMORPHIC_SMIABLE_CALL": 28, "CALL_SITE_DATA": 29, "ICDATA": 30, "MEGAMORPHIC_CACHE": 31, "SUBTYPE_TEST_CACHE": 32, "LOADING_UNIT": 33, "LANGUAGE_ERROR": 36, "UNHANDLED_EXCEPTION": 37, "INSTANCE": 39, "LIBRARY_PREFIX": 40, "TYPE_ARGUMENTS": 41, "TYPE": 43, "FUNCTION_TYPE": 44, "TYPE_REF": 45, "TYPE_PARAMETER": 46, "CLOSURE": 47, "MINT": 51, "DOUBLE": 52, "FLOAT32X4": 55, "INT32X4": 56, "FLOAT64X2": 57, "TYPED_DATA": 59, "EXTERNAL_TYPED_DATA": 60, "TYPED_DATA_VIEW": 61, "CAPABILITY": 64, "RECEIVE_PORT": 65, "SEND_PORT": 66, "STACK_TRACE": 67, "REGEXP": 68, "WEAK_PROPERTY": 69, "FUTURE_OR": 72, "USER_TAG": 73, "TRANSFERABLE_TYPED_DATA": 74, "ARRAY": 75, "IMMUTABLE_ARRAY": 76, "GROWABLE_OBJECT_ARRAY": 54, "STRING": 77, "ONE_BYTE_STRING": 78, "TWO_BYTE_STRING": 79, "NUM_PREDEFINED_CIDS": 148}}, "2.14.0": {"cws": 8, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 104, "typed_data_internal_limit": 146, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "CLASS": 4, "PATCH_CLASS": 5, "FUNCTION": 6, "TYPE_PARAMETERS": 7, "CLOSURE_DATA": 8, "FFI_TRAMPOLINE_DATA": 9, "FIELD": 10, "SCRIPT": 11, "LIBRARY": 12, "NAMESPACE": 13, "KERNEL_PROGRAM_INFO": 14, "WEAK_SERIALIZATION_REFERENCE": 15, "CODE": 16, "OBJECT_POOL": 20, "PC_DESCRIPTORS": 21, "CODE_SOURCE_MAP": 22, "COMPRESSED_STACK_MAPS": 23, "EXCEPTION_HANDLERS": 25, "CONTEXT": 26, "CONTEXT_SCOPE": 27, "SENTINEL": 28, "SINGLE_TARGET_CACHE": 29, "UNLINKED_CALL": 30, "MONOMORPHIC_SMIABLE_CALL": 31, "CALL_SITE_DATA": 32, "ICDATA": 33, "MEGAMORPHIC_CACHE": 34, "SUBTYPE_TEST_CACHE": 35, "LOADING_UNIT": 36, "LANGUAGE_ERROR": 39, "UNHANDLED_EXCEPTION": 40, "INSTANCE": 42, "LIBRARY_PREFIX": 43, "TYPE_ARGUMENTS": 44, "TYPE": 46, "FUNCTION_TYPE": 47, "TYPE_REF": 48, "TYPE_PARAMETER": 49, "CLOSURE": 50, "MINT": 54, "DOUBLE": 55, "FLOAT32X4": 58, "INT32X4": 59, "FLOAT64X2": 60, "TYPED_DATA": 62, "EXTERNAL_TYPED_DATA": 63, "TYPED_DATA_VIEW": 64, "CAPABILITY": 67, "RECEIVE_PORT": 68, "SEND_PORT": 69, "STACK_TRACE": 70, "REGEXP": 71, "WEAK_PROPERTY": 72, "FUTURE_OR": 74, "USER_TAG": 75, "TRANSFERABLE_TYPED_DATA": 76, "ARRAY": 79, "IMMUTABLE_ARRAY": 80, "GROWABLE_OBJECT_ARRAY": 57, "STRING": 81, "ONE_BYTE_STRING": 82, "TWO_BYTE_STRING": 83, "NUM_PREDEFINED_CIDS": 152}}, "2.15.0": {"cws": 8, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 106, "typed_data_internal_limit": 148, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "CODE": 17, "OBJECT_POOL": 21, "PC_DESCRIPTORS": 22, "CODE_SOURCE_MAP": 23, "COMPRESSED_STACK_MAPS": 24, "EXCEPTION_HANDLERS": 26, "CONTEXT": 27, "CONTEXT_SCOPE": 28, "SENTINEL": 29, "SINGLE_TARGET_CACHE": 30, "UNLINKED_CALL": 31, "MONOMORPHIC_SMIABLE_CALL": 32, "CALL_SITE_DATA": 33, "ICDATA": 34, "MEGAMORPHIC_CACHE": 35, "SUBTYPE_TEST_CACHE": 36, "LOADING_UNIT": 37, "LANGUAGE_ERROR": 40, "UNHANDLED_EXCEPTION": 41, "INSTANCE": 43, "LIBRARY_PREFIX": 44, "TYPE_ARGUMENTS": 45, "TYPE": 47, "FUNCTION_TYPE": 48, "TYPE_REF": 49, "TYPE_PARAMETER": 50, "CLOSURE": 51, "MINT": 55, "DOUBLE": 56, "FLOAT32X4": 58, "INT32X4": 59, "FLOAT64X2": 60, "TYPED_DATA": 62, "EXTERNAL_TYPED_DATA": 63, "TYPED_DATA_VIEW": 64, "CAPABILITY": 67, "RECEIVE_PORT": 68, "SEND_PORT": 69, "STACK_TRACE": 70, "REGEXP": 71, "WEAK_PROPERTY": 72, "FUTURE_OR": 74, "USER_TAG": 75, "TRANSFERABLE_TYPED_DATA": 76, "ARRAY": 81, "IMMUTABLE_ARRAY": 82, "GROWABLE_OBJECT_ARRAY": 83, "STRING": 84, "ONE_BYTE_STRING": 85, "TWO_BYTE_STRING": 86, "NUM_PREDEFINED_CIDS": 154}}, "2.16.0": {"cws": 8, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 6, "typed_data_internal_base": 106, "typed_data_internal_limit": 148, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "CODE": 17, "OBJECT_POOL": 21, "PC_DESCRIPTORS": 22, "CODE_SOURCE_MAP": 23, "COMPRESSED_STACK_MAPS": 24, "EXCEPTION_HANDLERS": 26, "CONTEXT": 27, "CONTEXT_SCOPE": 28, "SENTINEL": 29, "SINGLE_TARGET_CACHE": 30, "UNLINKED_CALL": 31, "MONOMORPHIC_SMIABLE_CALL": 32, "CALL_SITE_DATA": 33, "ICDATA": 34, "MEGAMORPHIC_CACHE": 35, "SUBTYPE_TEST_CACHE": 36, "LOADING_UNIT": 37, "LANGUAGE_ERROR": 40, "UNHANDLED_EXCEPTION": 41, "INSTANCE": 43, "LIBRARY_PREFIX": 44, "TYPE_ARGUMENTS": 45, "TYPE": 47, "FUNCTION_TYPE": 48, "TYPE_REF": 49, "TYPE_PARAMETER": 50, "CLOSURE": 51, "MINT": 55, "DOUBLE": 56, "FLOAT32X4": 58, "INT32X4": 59, "FLOAT64X2": 60, "TYPED_DATA": 62, "EXTERNAL_TYPED_DATA": 63, "TYPED_DATA_VIEW": 64, "CAPABILITY": 67, "RECEIVE_PORT": 68, "SEND_PORT": 69, "STACK_TRACE": 70, "REGEXP": 71, "WEAK_PROPERTY": 72, "FUTURE_OR": 74, "USER_TAG": 75, "TRANSFERABLE_TYPED_DATA": 76, "ARRAY": 81, "IMMUTABLE_ARRAY": 82, "GROWABLE_OBJECT_ARRAY": 83, "STRING": 84, "ONE_BYTE_STRING": 85, "TWO_BYTE_STRING": 86, "NUM_PREDEFINED_CIDS": 154}}, "2.17.0": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 6, "typed_data_internal_base": 110, "typed_data_internal_limit": 152, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "CODE": 17, "OBJECT_POOL": 21, "PC_DESCRIPTORS": 22, "CODE_SOURCE_MAP": 23, "COMPRESSED_STACK_MAPS": 24, "EXCEPTION_HANDLERS": 26, "CONTEXT": 27, "CONTEXT_SCOPE": 28, "SENTINEL": 29, "SINGLE_TARGET_CACHE": 30, "UNLINKED_CALL": 31, "MONOMORPHIC_SMIABLE_CALL": 32, "CALL_SITE_DATA": 33, "ICDATA": 34, "MEGAMORPHIC_CACHE": 35, "SUBTYPE_TEST_CACHE": 36, "LOADING_UNIT": 37, "LANGUAGE_ERROR": 40, "UNHANDLED_EXCEPTION": 41, "INSTANCE": 43, "LIBRARY_PREFIX": 44, "TYPE_ARGUMENTS": 45, "TYPE": 47, "FUNCTION_TYPE": 52, "TYPE_REF": 53, "TYPE_PARAMETER": 54, "CLOSURE": 55, "MINT": 59, "DOUBLE": 60, "FLOAT32X4": 62, "INT32X4": 63, "FLOAT64X2": 64, "TYPED_DATA": 66, "EXTERNAL_TYPED_DATA": 67, "TYPED_DATA_VIEW": 68, "CAPABILITY": 71, "RECEIVE_PORT": 72, "SEND_PORT": 73, "STACK_TRACE": 74, "REGEXP": 75, "WEAK_PROPERTY": 76, "WEAK_REFERENCE": 77, "FUTURE_OR": 79, "USER_TAG": 80, "TRANSFERABLE_TYPED_DATA": 81, "ARRAY": 86, "IMMUTABLE_ARRAY": 87, "GROWABLE_OBJECT_ARRAY": 88, "STRING": 89, "ONE_BYTE_STRING": 90, "TWO_BYTE_STRING": 91, "NUM_PREDEFINED_CIDS": 158}}, - "2.18.0": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 111, "typed_data_internal_limit": 153, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "CODE": 17, "OBJECT_POOL": 21, "PC_DESCRIPTORS": 22, "CODE_SOURCE_MAP": 23, "COMPRESSED_STACK_MAPS": 24, "EXCEPTION_HANDLERS": 26, "CONTEXT": 27, "CONTEXT_SCOPE": 28, "SENTINEL": 29, "SINGLE_TARGET_CACHE": 30, "UNLINKED_CALL": 31, "MONOMORPHIC_SMIABLE_CALL": 32, "CALL_SITE_DATA": 33, "ICDATA": 34, "MEGAMORPHIC_CACHE": 35, "SUBTYPE_TEST_CACHE": 36, "LOADING_UNIT": 37, "LANGUAGE_ERROR": 40, "UNHANDLED_EXCEPTION": 41, "INSTANCE": 43, "LIBRARY_PREFIX": 44, "TYPE_ARGUMENTS": 45, "TYPE": 47, "FUNCTION_TYPE": 52, "TYPE_REF": 53, "TYPE_PARAMETER": 54, "CLOSURE": 55, "MINT": 59, "DOUBLE": 60, "FLOAT32X4": 62, "INT32X4": 63, "FLOAT64X2": 64, "TYPED_DATA": 66, "EXTERNAL_TYPED_DATA": 67, "TYPED_DATA_VIEW": 68, "CAPABILITY": 71, "RECEIVE_PORT": 72, "SEND_PORT": 73, "STACK_TRACE": 74, "SUSPEND_STATE": 75, "REGEXP": 76, "WEAK_PROPERTY": 77, "WEAK_REFERENCE": 78, "FUTURE_OR": 80, "USER_TAG": 81, "TRANSFERABLE_TYPED_DATA": 82, "ARRAY": 87, "IMMUTABLE_ARRAY": 88, "GROWABLE_OBJECT_ARRAY": 89, "STRING": 90, "ONE_BYTE_STRING": 91, "TWO_BYTE_STRING": 92, "NUM_PREDEFINED_CIDS": 159}}, + "2.18.0": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 111, "typed_data_internal_limit": 153, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "CODE": 17, "OBJECT_POOL": 21, "PC_DESCRIPTORS": 22, "CODE_SOURCE_MAP": 23, "COMPRESSED_STACK_MAPS": 24, "EXCEPTION_HANDLERS": 26, "CONTEXT": 27, "CONTEXT_SCOPE": 28, "SENTINEL": 29, "SINGLE_TARGET_CACHE": 30, "UNLINKED_CALL": 31, "MONOMORPHIC_SMIABLE_CALL": 32, "CALL_SITE_DATA": 33, "ICDATA": 34, "MEGAMORPHIC_CACHE": 35, "SUBTYPE_TEST_CACHE": 36, "LOADING_UNIT": 37, "LANGUAGE_ERROR": 40, "UNHANDLED_EXCEPTION": 41, "INSTANCE": 43, "LIBRARY_PREFIX": 44, "TYPE_ARGUMENTS": 45, "TYPE": 47, "FUNCTION_TYPE": 52, "TYPE_REF": 53, "TYPE_PARAMETER": 54, "CLOSURE": 55, "MINT": 59, "DOUBLE": 60, "FLOAT32X4": 62, "INT32X4": 63, "FLOAT64X2": 64, "TYPED_DATA": 66, "EXTERNAL_TYPED_DATA": 67, "TYPED_DATA_VIEW": 68, "CAPABILITY": 71, "RECEIVE_PORT": 72, "SEND_PORT": 73, "STACK_TRACE": 74, "SUSPEND_STATE": 75, "REGEXP": 76, "WEAK_PROPERTY": 77, "WEAK_REFERENCE": 78, "FUTURE_OR": 80, "USER_TAG": 81, "TRANSFERABLE_TYPED_DATA": 82, "MAP": 83, "CONST_MAP": 84, "SET": 85, "CONST_SET": 86, "ARRAY": 87, "IMMUTABLE_ARRAY": 88, "GROWABLE_OBJECT_ARRAY": 89, "STRING": 90, "ONE_BYTE_STRING": 91, "TWO_BYTE_STRING": 92, "NUM_PREDEFINED_CIDS": 159}}, "2.18.2": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "OBJECT_HEADER", "header_fields": 5, "typed_data_internal_base": 112, "typed_data_internal_limit": 168, "typed_data_stride": 4, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "WEAK_ARRAY": 17, "CODE": 18, "OBJECT_POOL": 23, "PC_DESCRIPTORS": 24, "CODE_SOURCE_MAP": 25, "COMPRESSED_STACK_MAPS": 26, "EXCEPTION_HANDLERS": 28, "CONTEXT": 29, "CONTEXT_SCOPE": 30, "SENTINEL": 31, "SINGLE_TARGET_CACHE": 32, "UNLINKED_CALL": 35, "MONOMORPHIC_SMIABLE_CALL": 33, "CALL_SITE_DATA": 34, "ICDATA": 36, "MEGAMORPHIC_CACHE": 37, "SUBTYPE_TEST_CACHE": 38, "LOADING_UNIT": 39, "LANGUAGE_ERROR": 42, "UNHANDLED_EXCEPTION": 43, "INSTANCE": 45, "LIBRARY_PREFIX": 46, "TYPE_ARGUMENTS": 47, "TYPE": 49, "FUNCTION_TYPE": 50, "RECORD_TYPE": 51, "TYPE_PARAMETER": 52, "CLOSURE": 57, "MINT": 61, "DOUBLE": 62, "FLOAT32X4": 64, "INT32X4": 65, "FLOAT64X2": 66, "RECORD": 67, "TYPED_DATA": 69, "EXTERNAL_TYPED_DATA": 70, "TYPED_DATA_VIEW": 71, "CAPABILITY": 74, "RECEIVE_PORT": 75, "SEND_PORT": 76, "STACK_TRACE": 77, "SUSPEND_STATE": 78, "REGEXP": 79, "WEAK_PROPERTY": 80, "WEAK_REFERENCE": 81, "FUTURE_OR": 83, "USER_TAG": 84, "TRANSFERABLE_TYPED_DATA": 85, "MAP": 86, "CONST_MAP": 87, "SET": 88, "CONST_SET": 89, "ARRAY": 90, "IMMUTABLE_ARRAY": 91, "GROWABLE_OBJECT_ARRAY": 92, "STRING": 93, "ONE_BYTE_STRING": 94, "TWO_BYTE_STRING": 95, "NUM_PREDEFINED_CIDS": 175}, "note": "Uses fallback CIDs from 3.9.2 for the in-tree Flutter engine snapshot; not standalone Dart SDK 2.18.2 CIDs."}, - "2.18.3": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 111, "typed_data_internal_limit": 153, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "CODE": 17, "OBJECT_POOL": 21, "PC_DESCRIPTORS": 22, "CODE_SOURCE_MAP": 23, "COMPRESSED_STACK_MAPS": 24, "EXCEPTION_HANDLERS": 26, "CONTEXT": 27, "CONTEXT_SCOPE": 28, "SENTINEL": 29, "SINGLE_TARGET_CACHE": 30, "UNLINKED_CALL": 31, "MONOMORPHIC_SMIABLE_CALL": 32, "CALL_SITE_DATA": 33, "ICDATA": 34, "MEGAMORPHIC_CACHE": 35, "SUBTYPE_TEST_CACHE": 36, "LOADING_UNIT": 37, "LANGUAGE_ERROR": 40, "UNHANDLED_EXCEPTION": 41, "INSTANCE": 43, "LIBRARY_PREFIX": 44, "TYPE_ARGUMENTS": 45, "TYPE": 47, "FUNCTION_TYPE": 52, "TYPE_REF": 53, "TYPE_PARAMETER": 54, "CLOSURE": 55, "MINT": 59, "DOUBLE": 60, "FLOAT32X4": 62, "INT32X4": 63, "FLOAT64X2": 64, "TYPED_DATA": 66, "EXTERNAL_TYPED_DATA": 67, "TYPED_DATA_VIEW": 68, "CAPABILITY": 71, "RECEIVE_PORT": 72, "SEND_PORT": 73, "STACK_TRACE": 74, "SUSPEND_STATE": 75, "REGEXP": 76, "WEAK_PROPERTY": 77, "WEAK_REFERENCE": 78, "FUTURE_OR": 80, "USER_TAG": 81, "TRANSFERABLE_TYPED_DATA": 82, "ARRAY": 87, "IMMUTABLE_ARRAY": 88, "GROWABLE_OBJECT_ARRAY": 89, "STRING": 90, "ONE_BYTE_STRING": 91, "TWO_BYTE_STRING": 92, "NUM_PREDEFINED_CIDS": 159}}, + "2.18.3": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 111, "typed_data_internal_limit": 153, "typed_data_stride": 3, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "CODE": 17, "OBJECT_POOL": 21, "PC_DESCRIPTORS": 22, "CODE_SOURCE_MAP": 23, "COMPRESSED_STACK_MAPS": 24, "EXCEPTION_HANDLERS": 26, "CONTEXT": 27, "CONTEXT_SCOPE": 28, "SENTINEL": 29, "SINGLE_TARGET_CACHE": 30, "UNLINKED_CALL": 31, "MONOMORPHIC_SMIABLE_CALL": 32, "CALL_SITE_DATA": 33, "ICDATA": 34, "MEGAMORPHIC_CACHE": 35, "SUBTYPE_TEST_CACHE": 36, "LOADING_UNIT": 37, "LANGUAGE_ERROR": 40, "UNHANDLED_EXCEPTION": 41, "INSTANCE": 43, "LIBRARY_PREFIX": 44, "TYPE_ARGUMENTS": 45, "TYPE": 47, "FUNCTION_TYPE": 52, "TYPE_REF": 53, "TYPE_PARAMETER": 54, "CLOSURE": 55, "MINT": 59, "DOUBLE": 60, "FLOAT32X4": 62, "INT32X4": 63, "FLOAT64X2": 64, "TYPED_DATA": 66, "EXTERNAL_TYPED_DATA": 67, "TYPED_DATA_VIEW": 68, "CAPABILITY": 71, "RECEIVE_PORT": 72, "SEND_PORT": 73, "STACK_TRACE": 74, "SUSPEND_STATE": 75, "REGEXP": 76, "WEAK_PROPERTY": 77, "WEAK_REFERENCE": 78, "FUTURE_OR": 80, "USER_TAG": 81, "TRANSFERABLE_TYPED_DATA": 82, "MAP": 83, "CONST_MAP": 84, "SET": 85, "CONST_SET": 86, "ARRAY": 87, "IMMUTABLE_ARRAY": 88, "GROWABLE_OBJECT_ARRAY": 89, "STRING": 90, "ONE_BYTE_STRING": 91, "TWO_BYTE_STRING": 92, "NUM_PREDEFINED_CIDS": 159}}, "2.19.0": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 113, "typed_data_internal_limit": 169, "typed_data_stride": 4, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "CODE": 17, "OBJECT_POOL": 21, "PC_DESCRIPTORS": 22, "CODE_SOURCE_MAP": 23, "COMPRESSED_STACK_MAPS": 24, "EXCEPTION_HANDLERS": 26, "CONTEXT": 27, "CONTEXT_SCOPE": 28, "SENTINEL": 29, "SINGLE_TARGET_CACHE": 30, "UNLINKED_CALL": 31, "MONOMORPHIC_SMIABLE_CALL": 32, "CALL_SITE_DATA": 33, "ICDATA": 34, "MEGAMORPHIC_CACHE": 35, "SUBTYPE_TEST_CACHE": 36, "LOADING_UNIT": 37, "LANGUAGE_ERROR": 40, "UNHANDLED_EXCEPTION": 41, "INSTANCE": 43, "LIBRARY_PREFIX": 44, "TYPE_ARGUMENTS": 45, "TYPE": 47, "FUNCTION_TYPE": 48, "RECORD_TYPE": 49, "TYPE_REF": 50, "TYPE_PARAMETER": 51, "CLOSURE": 56, "MINT": 60, "DOUBLE": 61, "FLOAT32X4": 63, "INT32X4": 64, "FLOAT64X2": 65, "RECORD": 66, "TYPED_DATA": 68, "EXTERNAL_TYPED_DATA": 69, "TYPED_DATA_VIEW": 70, "CAPABILITY": 73, "RECEIVE_PORT": 74, "SEND_PORT": 75, "STACK_TRACE": 76, "SUSPEND_STATE": 77, "REGEXP": 78, "WEAK_PROPERTY": 79, "WEAK_REFERENCE": 80, "FUTURE_OR": 82, "USER_TAG": 83, "TRANSFERABLE_TYPED_DATA": 84, "MAP": 85, "CONST_MAP": 86, "SET": 87, "CONST_SET": 88, "ARRAY": 89, "IMMUTABLE_ARRAY": 90, "GROWABLE_OBJECT_ARRAY": 91, "STRING": 92, "ONE_BYTE_STRING": 93, "TWO_BYTE_STRING": 94, "NUM_PREDEFINED_CIDS": 176}}, "3.0.0": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 114, "typed_data_internal_limit": 170, "typed_data_stride": 4, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "WEAK_ARRAY": 17, "CODE": 18, "OBJECT_POOL": 22, "PC_DESCRIPTORS": 23, "CODE_SOURCE_MAP": 24, "COMPRESSED_STACK_MAPS": 25, "EXCEPTION_HANDLERS": 27, "CONTEXT": 28, "CONTEXT_SCOPE": 29, "SENTINEL": 30, "SINGLE_TARGET_CACHE": 31, "UNLINKED_CALL": 32, "MONOMORPHIC_SMIABLE_CALL": 33, "CALL_SITE_DATA": 34, "ICDATA": 35, "MEGAMORPHIC_CACHE": 36, "SUBTYPE_TEST_CACHE": 37, "LOADING_UNIT": 38, "LANGUAGE_ERROR": 41, "UNHANDLED_EXCEPTION": 42, "INSTANCE": 44, "LIBRARY_PREFIX": 45, "TYPE_ARGUMENTS": 46, "TYPE": 48, "FUNCTION_TYPE": 49, "RECORD_TYPE": 50, "TYPE_REF": 51, "TYPE_PARAMETER": 52, "CLOSURE": 57, "MINT": 61, "DOUBLE": 62, "FLOAT32X4": 64, "INT32X4": 65, "FLOAT64X2": 66, "RECORD": 67, "TYPED_DATA": 69, "EXTERNAL_TYPED_DATA": 70, "TYPED_DATA_VIEW": 71, "CAPABILITY": 74, "RECEIVE_PORT": 75, "SEND_PORT": 76, "STACK_TRACE": 77, "SUSPEND_STATE": 78, "REGEXP": 79, "WEAK_PROPERTY": 80, "WEAK_REFERENCE": 81, "FUTURE_OR": 83, "USER_TAG": 84, "TRANSFERABLE_TYPED_DATA": 85, "MAP": 86, "CONST_MAP": 87, "SET": 88, "CONST_SET": 89, "ARRAY": 90, "IMMUTABLE_ARRAY": 91, "GROWABLE_OBJECT_ARRAY": 92, "STRING": 93, "ONE_BYTE_STRING": 94, "TWO_BYTE_STRING": 95, "NUM_PREDEFINED_CIDS": 177}}, "3.1.0": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "CID_SHIFT1", "header_fields": 5, "typed_data_internal_base": 113, "typed_data_internal_limit": 169, "typed_data_stride": 4, "cids": {"ILLEGAL": 0, "NATIVE_POINTER": 1, "CLASS": 5, "PATCH_CLASS": 6, "FUNCTION": 7, "TYPE_PARAMETERS": 8, "CLOSURE_DATA": 9, "FFI_TRAMPOLINE_DATA": 10, "FIELD": 11, "SCRIPT": 12, "LIBRARY": 13, "NAMESPACE": 14, "KERNEL_PROGRAM_INFO": 15, "WEAK_SERIALIZATION_REFERENCE": 16, "WEAK_ARRAY": 17, "CODE": 18, "OBJECT_POOL": 22, "PC_DESCRIPTORS": 23, "CODE_SOURCE_MAP": 24, "COMPRESSED_STACK_MAPS": 25, "EXCEPTION_HANDLERS": 27, "CONTEXT": 28, "CONTEXT_SCOPE": 29, "SENTINEL": 30, "SINGLE_TARGET_CACHE": 31, "UNLINKED_CALL": 32, "MONOMORPHIC_SMIABLE_CALL": 33, "CALL_SITE_DATA": 34, "ICDATA": 35, "MEGAMORPHIC_CACHE": 36, "SUBTYPE_TEST_CACHE": 37, "LOADING_UNIT": 38, "LANGUAGE_ERROR": 41, "UNHANDLED_EXCEPTION": 42, "INSTANCE": 44, "LIBRARY_PREFIX": 45, "TYPE_ARGUMENTS": 46, "TYPE": 48, "FUNCTION_TYPE": 49, "RECORD_TYPE": 50, "TYPE_PARAMETER": 51, "CLOSURE": 56, "MINT": 60, "DOUBLE": 61, "FLOAT32X4": 63, "INT32X4": 64, "FLOAT64X2": 65, "RECORD": 66, "TYPED_DATA": 68, "EXTERNAL_TYPED_DATA": 69, "TYPED_DATA_VIEW": 70, "CAPABILITY": 73, "RECEIVE_PORT": 74, "SEND_PORT": 75, "STACK_TRACE": 76, "SUSPEND_STATE": 77, "REGEXP": 78, "WEAK_PROPERTY": 79, "WEAK_REFERENCE": 80, "FUTURE_OR": 82, "USER_TAG": 83, "TRANSFERABLE_TYPED_DATA": 84, "MAP": 85, "CONST_MAP": 86, "SET": 87, "CONST_SET": 88, "ARRAY": 89, "IMMUTABLE_ARRAY": 90, "GROWABLE_OBJECT_ARRAY": 91, "STRING": 92, "ONE_BYTE_STRING": 93, "TWO_BYTE_STRING": 94, "NUM_PREDEFINED_CIDS": 176}}, @@ -33,6 +33,7 @@ "hashes": { "8ee4ef7a67df9845fba331734198a953": "2.10.0", "d979fa911b038a8682e98cc8c8569261": "2.10.0", + "5b97292b25f0a715613b7a28e0734f77": "2.12.0", "e036be9d5df68283e1a043e348fa7ff4": "2.12.0", "0c7f1aa25fc597a7b3b9a19ed390afa1": "2.13.0", "34f6eec64e9371856eaaa278ccf56538": "2.13.0", diff --git a/scripts/update-dart-version b/scripts/update-dart-version index 2462df9..10c920b 100755 --- a/scripts/update-dart-version +++ b/scripts/update-dart-version @@ -52,6 +52,14 @@ TAG_STYLE_NAMES = { "OBJECT_HEADER": "DART_TAG_STYLE_OBJECT_HEADER", } +HEADER_STYLE_NAMES = { + "modern": "DART_HEADER_STYLE_MODERN", + "2.10": "DART_HEADER_STYLE_210", + "2.12": "DART_HEADER_STYLE_212", + "2.14": "DART_HEADER_STYLE_214", + "2.16": "DART_HEADER_STYLE_216", +} + TAG_STYLE_VALUES = {v: k for k, v in TAG_STYLE_NAMES.items()} CID_KIND_TO_CLASS_NAME = [ @@ -555,7 +563,7 @@ def infer_profile_for_version(version): tag_style = "CID_INT32" if (2, 16) <= ver_tuple < (2, 18): hdr = 6 - elif ver_tuple >= (2, 13): + elif ver_tuple >= (2, 12): hdr = 5 else: hdr = 4 @@ -573,6 +581,19 @@ def infer_profile_for_version(version): } +def header_style_for_version(version): + ver_tuple = parse_version(version) + if ver_tuple < (2, 12): + return HEADER_STYLE_NAMES["2.10"] + if ver_tuple < (2, 14): + return HEADER_STYLE_NAMES["2.12"] + if ver_tuple < (2, 16): + return HEADER_STYLE_NAMES["2.14"] + if ver_tuple < (2, 18): + return HEADER_STYLE_NAMES["2.16"] + return HEADER_STYLE_NAMES["modern"] + + def profile_diff(existing, inferred): diffs = [] for key in ("cws", "heap_object_tag", "max_alignment", "it_cap", "tag_style", "header_fields"): @@ -686,10 +707,11 @@ def gen_profile_entries(offsets): for ver in sorted(profiles.keys(), key=parse_version): v = profiles[ver] tag_name = TAG_STYLE_NAMES.get(v["tag_style"], "0") + header_style = header_style_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"]} }}, // Dart {ver}') - lines.append("\t{ { 0 }, NULL, 0, 0, 0, 0, 0, 0 }") + f'{v["header_fields"]}, {header_style} }}, // Dart {ver}') + lines.append("\t{ { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0 }") lines.append("};") return "\n".join(lines) @@ -728,11 +750,14 @@ def gen_dart_offsets_h(offsets): lines.append(f"#define DART_HASH_ENTRIES_COUNT {len(hashes)}") lines.append("") lines.append("// Default offset arrays (identical across all known Dart versions)") - lines.append(f"#define DART_DEFAULT_EP_OFFSETS {{ {', '.join(str(x) for x in ep)} }}") + lines.append("#define DART_DEFAULT_EP_OFFSETS \\") + lines.append(f"\t{{ {', '.join(str(x) for x in ep)} }}") lines.append(f"#define DART_DEFAULT_EP_OFFSETS_COUNT {len(ep)}") - lines.append(f"#define DART_DEFAULT_OWNER_OFFSETS {{ {', '.join(str(x) for x in owner)} }}") + lines.append("#define DART_DEFAULT_OWNER_OFFSETS \\") + lines.append(f"\t{{ {', '.join(str(x) for x in owner)} }}") lines.append(f"#define DART_DEFAULT_OWNER_OFFSETS_COUNT {len(owner)}") - lines.append(f"#define DART_DEFAULT_NAME_OFFSETS {{ {', '.join(str(x) for x in name)} }}") + lines.append("#define DART_DEFAULT_NAME_OFFSETS \\") + lines.append(f"\t{{ {', '.join(str(x) for x in name)} }}") lines.append(f"#define DART_DEFAULT_NAME_OFFSETS_COUNT {len(name)}") lines.append("") lines.append("#endif // R2C_DART_OFFSETS_H") diff --git a/src/lib/dart_pool_parse.c b/src/lib/dart_pool_parse.c index a09a22f..d27dccb 100644 --- a/src/lib/dart_pool_parse.c +++ b/src/lib/dart_pool_parse.c @@ -783,6 +783,12 @@ static void dump_header_snapshot_json(DartCtx *ctx, PJ *pj, const char *label, u pj_kn (pj, "base_objects", sh.nb); pj_kn (pj, "objects", sh.no); pj_kn (pj, "clusters_count", sh.nc); + if (sh.ncc) { + pj_kn (pj, "canonical_clusters_count", sh.ncc); + } + if (sh.field_table_len) { + pj_kn (pj, "field_table_len", sh.field_table_len); + } pj_kn (pj, "it_length", sh.itlen); pj_kn (pj, "it_data_off", sh.itdata); pj_kn (pj, "cluster_start", sh.cluster_start); diff --git a/src/lib/dart_pool_parse_priv.h b/src/lib/dart_pool_parse_priv.h index 15241a0..9d8f398 100644 --- a/src/lib/dart_pool_parse_priv.h +++ b/src/lib/dart_pool_parse_priv.h @@ -62,6 +62,8 @@ typedef struct { ut64 nb; ut64 no; ut64 nc; + ut64 ncc; + ut64 field_table_len; ut64 itlen; ut64 itdata; ut64 cluster_start; @@ -225,7 +227,7 @@ bool dart_read_unsigned_at(DartCtx *ctx, ut64 addr, ut64 *out_val, ut64 *out_nex bool dart_read_unsigned_buf(const ut8 *buf, ut64 size, ut64 pos, ut64 *out_val, ut64 *out_next); char *dart_utf16le_to_utf8(const ut8 *buf, ut64 size); bool dart_snapshot_header_read(DartCtx *ctx, ut64 base, DartSnapshotHeader *out); -bool dart_snapshot_header_read_buf(const ut8 *buf, ut64 size, DartSnapshotHeader *out); +bool dart_snapshot_header_read_buf(const ut8 *buf, ut64 size, const DartVerLayout *layout, DartSnapshotHeader *out); DartVerLayout *dart_ctx_init_layout(DartCtx *ctx, DartVerLayout *tmp); void dart_ctx_fini_layout(DartCtx *ctx, DartVerLayout *owned); int find_snapshots(DartCtx *ctx); diff --git a/src/lib/dart_pool_snapshot.c b/src/lib/dart_pool_snapshot.c index 23cc1a8..0d149eb 100644 --- a/src/lib/dart_pool_snapshot.c +++ b/src/lib/dart_pool_snapshot.c @@ -140,6 +140,70 @@ char *dart_utf16le_to_utf8(const ut8 *buf, ut64 size) { return out; } +static const DartVerLayout *dart_snapshot_header_layout(DartCtx *ctx, const char *hash) { + if (ctx && ctx->layout) { + return ctx->layout; + } + if (ctx && R_STR_ISNOTEMPTY (ctx->dart_version_override)) { + const DartVerLayout *layout = dart_profile_from_version (ctx->dart_version_override); + if (layout) { + return layout; + } + } + const char *version = dart_version_from_hash (hash); + const DartVerLayout *layout = version? dart_profile_from_version (version): NULL; + return layout? layout: dart_newest_profile (); +} + +static bool dart_snapshot_header_set_fields(DartSnapshotHeader *out, const DartVerLayout *layout, const ut64 *fields, int count) { + if (!out || !layout || !fields || count != layout->header_fields) { + return false; + } + switch (layout->header_style) { + case DART_HEADER_STYLE_210: + out->nb = fields[0]; + out->no = fields[1]; + out->nc = fields[2]; + out->field_table_len = fields[3]; + break; + case DART_HEADER_STYLE_212: + if (UT64_MAX - fields[2] < fields[3]) { + return false; + } + out->nb = fields[0]; + out->no = fields[1]; + out->ncc = fields[2]; + out->nc = fields[2] + fields[3]; + out->field_table_len = fields[4]; + break; + case DART_HEADER_STYLE_214: + out->nb = fields[0]; + out->no = fields[1]; + out->nc = fields[2]; + out->field_table_len = fields[3]; + out->itlen = fields[4]; + break; + case DART_HEADER_STYLE_216: + out->nb = fields[0]; + out->no = fields[1]; + out->nc = fields[2]; + out->field_table_len = fields[3]; + out->itlen = fields[4]; + out->itdata = fields[5]; + break; + case DART_HEADER_STYLE_MODERN: + out->nb = fields[0]; + out->no = fields[1]; + out->nc = fields[2]; + out->itlen = fields[3]; + out->itdata = fields[4]; + break; + default: + return false; + } + return true; +} + bool dart_snapshot_header_read(DartCtx *ctx, ut64 base, DartSnapshotHeader *out) { if (!ctx || !out) { return false; @@ -181,20 +245,18 @@ bool dart_snapshot_header_read(DartCtx *ctx, ut64 base, DartSnapshotHeader *out) } out->flags[tocopy] = '\0'; cursor += (ut64)scanned + 1; + const DartVerLayout *layout = dart_snapshot_header_layout (ctx, out->hash); + if (!layout || layout->header_fields < 4 || layout->header_fields > 6) { + return false; + } ut64 next = cursor; - if (!dart_read_unsigned_at (ctx, next, &out->nb, &next)) { - return false; + ut64 fields[6] = { 0 }; + for (int i = 0; i < layout->header_fields; i++) { + if (!dart_read_unsigned_at (ctx, next, &fields[i], &next)) { + return false; + } } - if (!dart_read_unsigned_at (ctx, next, &out->no, &next)) { - return false; - } - if (!dart_read_unsigned_at (ctx, next, &out->nc, &next)) { - return false; - } - if (!dart_read_unsigned_at (ctx, next, &out->itlen, &next)) { - return false; - } - if (!dart_read_unsigned_at (ctx, next, &out->itdata, &next)) { + if (!dart_snapshot_header_set_fields (out, layout, fields, layout->header_fields)) { return false; } out->cluster_start = next; @@ -202,7 +264,7 @@ bool dart_snapshot_header_read(DartCtx *ctx, ut64 base, DartSnapshotHeader *out) return true; } -bool dart_snapshot_header_read_buf(const ut8 *buf, ut64 size, DartSnapshotHeader *out) { +bool dart_snapshot_header_read_buf(const ut8 *buf, ut64 size, const DartVerLayout *layout, DartSnapshotHeader *out) { if (!buf || !out || size < DART_SNAPSHOT_FIXED_SIZE + DART_SNAPSHOT_HASH_SIZE + 1) { return false; } @@ -236,20 +298,20 @@ bool dart_snapshot_header_read_buf(const ut8 *buf, ut64 size, DartSnapshotHeader } out->flags[tocopy] = '\0'; cursor += (ut64)scanned + 1; + if (!layout) { + layout = dart_snapshot_header_layout (NULL, out->hash); + } + if (!layout || layout->header_fields < 4 || layout->header_fields > 6) { + return false; + } ut64 next = cursor; - if (!dart_read_unsigned_buf (buf, size, next, &out->nb, &next)) { - return false; + ut64 fields[6] = { 0 }; + for (int i = 0; i < layout->header_fields; i++) { + if (!dart_read_unsigned_buf (buf, size, next, &fields[i], &next)) { + return false; + } } - if (!dart_read_unsigned_buf (buf, size, next, &out->no, &next)) { - return false; - } - if (!dart_read_unsigned_buf (buf, size, next, &out->nc, &next)) { - return false; - } - if (!dart_read_unsigned_buf (buf, size, next, &out->itlen, &next)) { - return false; - } - if (!dart_read_unsigned_buf (buf, size, next, &out->itdata, &next)) { + if (!dart_snapshot_header_set_fields (out, layout, fields, layout->header_fields)) { return false; } if (next >= out->total_len) { diff --git a/src/lib/dart_pool_strings.c b/src/lib/dart_pool_strings.c index 2737b2b..0de0b37 100644 --- a/src/lib/dart_pool_strings.c +++ b/src/lib/dart_pool_strings.c @@ -410,7 +410,7 @@ static void scan_packed_strings_from_snapshot(DartCtx *ctx, ut64 snapshot_base, return; } DartSnapshotHeader hdr; - if (!dart_snapshot_header_read_buf (buf, total_len, &hdr)) { + if (!dart_snapshot_header_read_buf (buf, total_len, ctx->layout, &hdr)) { free (buf); return; } diff --git a/src/lib/dart_version.c b/src/lib/dart_version.c index fc54de7..7d8103e 100644 --- a/src/lib/dart_version.c +++ b/src/lib/dart_version.c @@ -45,6 +45,7 @@ static const struct { { "8ee4ef7a67df9845fba331734198a953", "2.10.0" }, { "d979fa911b038a8682e98cc8c8569261", "2.10.0" }, // Dart 2.12.x + { "5b97292b25f0a715613b7a28e0734f77", "2.12.0" }, { "e036be9d5df68283e1a043e348fa7ff4", "2.12.0" }, // Dart 2.13.x { "0c7f1aa25fc597a7b3b9a19ed390afa1", "2.13.0" }, @@ -129,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 2.10.0 - { "", "2.12.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 4 }, // Dart 2.12.0 - { "", "2.13.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 5 }, // Dart 2.13.0 - { "", "2.14.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 2.14.0 - { "", "2.15.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 2.15.0 - { "", "2.16.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 6 }, // Dart 2.16.0 - { "", "2.17.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 6 }, // Dart 2.17.0 - { "", "2.18.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 2.18.0 - { "", "2.18.2", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 2.18.2 - { "", "2.18.3", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 2.18.3 - { "", "2.19.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 2.19.0 - { "", "3.0.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 3.0.0 - { "", "3.1.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 3.1.0 - { "", "3.2.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 3.2.0 - { "", "3.3.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5 }, // Dart 3.3.0 - { "", "3.4.0", 8, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.4.0 - { "", "3.5.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.5.0 - { "", "3.6.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.6.0 - { "", "3.7.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.7.0 - { "", "3.8.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.8.0 - { "", "3.9.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.9.0 - { "", "3.10.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.10.0 - { "", "3.11.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.11.0 - { "", "3.12.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5 }, // Dart 3.12.0 - { { 0 }, NULL, 0, 0, 0, 0, 0, 0 } + { "", "2.10.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 4, DART_HEADER_STYLE_210 }, // Dart 2.10.0 + { "", "2.12.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 5, DART_HEADER_STYLE_212 }, // Dart 2.12.0 + { "", "2.13.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_INT32, 5, DART_HEADER_STYLE_212 }, // Dart 2.13.0 + { "", "2.14.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_214 }, // Dart 2.14.0 + { "", "2.15.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_214 }, // Dart 2.15.0 + { "", "2.16.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 6, DART_HEADER_STYLE_216 }, // Dart 2.16.0 + { "", "2.17.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 6, DART_HEADER_STYLE_216 }, // Dart 2.17.0 + { "", "2.18.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN }, // Dart 2.18.0 + { "", "2.18.2", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 2.18.2 + { "", "2.18.3", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN }, // Dart 2.18.3 + { "", "2.19.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN }, // Dart 2.19.0 + { "", "3.0.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.0.0 + { "", "3.1.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.1.0 + { "", "3.2.0", 8, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.2.0 + { "", "3.3.0", 4, 1, 16, 20000, DART_TAG_STYLE_CID_SHIFT1, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.3.0 + { "", "3.4.0", 8, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.4.0 + { "", "3.5.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.5.0 + { "", "3.6.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.6.0 + { "", "3.7.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.7.0 + { "", "3.8.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.8.0 + { "", "3.9.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.9.0 + { "", "3.10.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.10.0 + { "", "3.11.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.11.0 + { "", "3.12.0", 4, 1, 16, 20000, DART_TAG_STYLE_OBJECT_HEADER, 5, DART_HEADER_STYLE_MODERN }, // Dart 3.12.0 + { { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0 } }; const char *dart_version_from_hash(const char *hash) { diff --git a/test/db/cmd/header-versioned b/test/db/cmd/header-versioned new file mode 100644 index 0000000..a0ed8c7 --- /dev/null +++ b/test/db/cmd/header-versioned @@ -0,0 +1,17 @@ +NAME=version-specific-snapshot-headers +FILE=- +CMDS=</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 +EOF +EXPECT=<