Support Dart 3.13 Single Snapshots

This commit is contained in:
pancake committed 2026-09-01 15:16:12 +02:00
1 parent 2e85b70bda
commit 3fe9dff0cc
12 files changed
+296 -76

No files matched your search

+2 -1
View File
@@ -21,9 +21,10 @@ cluster layouts next, then metadata/value restoration and profile detection.
- [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**
- [x] **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.
- Test complete and truncated combined snapshots, including partial-fill failure reporting.
- 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.
+28
View File
@@ -1425,3 +1425,31 @@ 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.
## Dart 3.13 Uses One Combined Snapshot
Dart 3.13 replaces the separate VM and isolate AOT snapshots with one full
snapshot (`kind=2`). Its exported symbols are `_kDartSnapshotData` and
`_kDartSnapshotText`. r2flutter stores those addresses in its existing isolate
slots internally so the parser APIs remain compatible, but reports a single
`Combined` snapshot and does not invent VM addresses in user-facing output.
Unknown hashes remain on the newest split-snapshot compatibility profile;
otherwise merely adding a 3.13 profile would silently reinterpret older dev
builds as combined snapshots. Exact hashes and explicit overrides are positive
evidence for the new topology, while structural selection is handled
separately.
The same release changes three cluster details independently: Class allocation
becomes a single fixed-size count, Code fill gains two leading references, and
Closure becomes variable-sized with an allocation length followed during fill
by one unsigned value, three fixed references, and that many variable
references. The Class nullable-field bitmap is omitted only for synthetic
top-level class IDs. That offset is itself versioned: `1 << 16` through Dart
2.18 and `1 << 20` from Dart 2.19 onward. Applying the newer threshold to a
2.18 snapshot, or the older threshold to 3.13, shifts subsequent fills for
ordinary high class IDs.
Keep partial cluster summaries when a fill is truncated. Earlier clusters are
still useful, while the failing cluster is marked `failed` and later clusters
remain `not_parsed`. This is more informative than rejecting the whole snapshot
and makes malformed-input behavior explicit to JSON consumers.
+3 -1
View File
@@ -12,6 +12,7 @@ typedef struct {
} DartHashEntry;
static const DartHashEntry dart_hash_entries[] = {
{ "0451907c2eaa8467e848c0067bfe8ed4", 4 }, // Dart 3.13.0
{ "0c7f1aa25fc597a7b3b9a19ed390afa1", 8 }, // Dart 2.13.0
{ "0eb277b50d6ce4069261c69150ce52c9", 4 }, // Dart 2.17.0
{ "1441d6b13b8623fa7fbf61433abebd31", 4 }, // Dart 2.17.6
@@ -36,6 +37,7 @@ static const DartHashEntry dart_hash_entries[] = {
{ "77b867742ae1ace67fbbb9a9a0d0334e", 4 }, // Dart 3.3.0
{ "77bd0a83c49bfc555a44a0740f15003a", 4 }, // Dart 2.18.0
{ "78da37fed6bf1489361a312568249f3f", 4 }, // Dart 3.11.5
{ "7a1ea3f6f5cf1089a7f6e55d7f20dbfd", 4 }, // Dart 3.14.0
{ "7a5b240780941844bae88eca5dbaa7b8", 8 }, // Dart 2.13.0
{ "7b96ef6dda75bdd1d70be8c2f7cb814e", 8 }, // Dart 2.15.0
{ "7dbbeeb8ef7b91338640dca3927636de", 4 }, // Dart 3.1.3
@@ -76,7 +78,7 @@ static const DartHashEntry dart_hash_entries[] = {
{ "fe53c4fdba846005b70514aec3840296", 8 }, // Dart 3.4.0
};
#define DART_HASH_ENTRIES_COUNT 62
#define DART_HASH_ENTRIES_COUNT 64
// Default offset arrays (identical across all known Dart versions)
#define DART_DEFAULT_EP_OFFSETS \
+11 -4
View File
@@ -77,6 +77,10 @@ typedef struct {
int code_refs;
int code_leading_refs;
bool code_has_text_offset;
bool single_snapshot;
bool class_alloc_fixed;
bool closure_variable;
bool class_top_level_cid20;
} DartVerLayout;
// Lookup Dart version from a snapshot hash (MD5)
@@ -87,15 +91,18 @@ const char *dart_version_from_hash(const char *hash);
// Returns NULL if the version string is not a dotted numeric version.
const DartVerLayout *dart_profile_from_version(const char *version);
// Pick a layout structure based on hash, with fallback to defaults
// Pick a layout structure based on hash, with fallback to a compatible baseline
// Returns a newly allocated DartVerLayout (caller must free)
// If hash is unknown, fingerprints against the newest known layout profile
// If hash is unknown, fingerprints against the newest split-snapshot profile.
DartVerLayout *dart_layout_from_hash(const char *hash);
// Newest known layout profile (used as the fingerprint baseline for unknown
// git/dev builds, whose snapshot format tracks the latest release).
// Newest known layout profile.
const DartVerLayout *dart_newest_profile(void);
// Conservative profile used until an unknown hash can be structurally probed.
// Single-snapshot mechanics require positive evidence and are not inherited.
const DartVerLayout *dart_fingerprint_profile(void);
// Human-readable name for a DartVersionSource value.
const char *dart_version_source_str(int source);
+6 -2
View File
@@ -28,7 +28,9 @@
"3.9.0": {"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}},
"3.10.0": {"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}},
"3.11.0": {"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}},
"3.12.0": {"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}}
"3.12.0": {"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}},
"3.13.0": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "OBJECT_HEADER", "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": 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": 176}},
"3.14.0": {"cws": 4, "heap_object_tag": 1, "max_alignment": 16, "it_cap": 20000, "tag_style": "OBJECT_HEADER", "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": 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": 176}}
},
"hashes": {
"8ee4ef7a67df9845fba331734198a953": "2.10.0",
@@ -92,6 +94,8 @@
"1ce86630892e2dca9a8543fdb8ed8e22": "3.10.7",
"78da37fed6bf1489361a312568249f3f": "3.11.5",
"41be3daaabd524b8aa7423bc24584957": "3.12.0",
"ace654289f5abc240509fc941453ebc5": "3.12.1"
"ace654289f5abc240509fc941453ebc5": "3.12.1",
"0451907c2eaa8467e848c0067bfe8ed4": "3.13.0",
"7a1ea3f6f5cf1089a7f6e55d7f20dbfd": "3.14.0"
}
}
+16 -2
View File
@@ -635,6 +635,17 @@ def code_layout_for_version(version):
}
def snapshot_layout_for_version(version):
parsed = parse_version(version)
modern_single = parsed >= (3, 13)
return {
"single": "true" if modern_single else "false",
"class_fixed": "true" if modern_single else "false",
"closure_variable": "true" if modern_single else "false",
"class_top_level_cid20": "true" if parsed >= (2, 19) else "false",
}
def profile_diff(existing, inferred):
diffs = []
for key in ("cws", "heap_object_tag", "max_alignment", "it_cap", "tag_style", "header_fields"):
@@ -752,11 +763,14 @@ def gen_profile_entries(offsets):
ref_encoding = ref_encoding_for_version(ver)
pool_encoding = pool_encoding_for_version(ver)
code = code_layout_for_version(ver)
snapshot = snapshot_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}, '
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 }")
f'{code["alloc"]}, {code["refs"]}, {code["leading_refs"]}, {code["has_text_offset"]}, '
f'{snapshot["single"]}, {snapshot["class_fixed"]}, {snapshot["closure_variable"]}, '
f'{snapshot["class_top_level_cid20"]} }}, // Dart {ver}')
lines.append("\t{ { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }")
lines.append("};")
return "\n".join(lines)
+2
View File
@@ -41,6 +41,8 @@ static const DartCidTable cid_tables[] = {
{ "3.10.0", { CID (ILLEGAL, 0), CID (NATIVE_POINTER, 1), CID (CLASS, 5), CID (PATCH_CLASS, 6), CID (FUNCTION, 7), CID (TYPE_PARAMETERS, 8), CID (CLOSURE_DATA, 9), CID (FFI_TRAMPOLINE_DATA, 10), CID (FIELD, 11), CID (SCRIPT, 12), CID (LIBRARY, 13), CID (NAMESPACE, 14), CID (KERNEL_PROGRAM_INFO, 15), CID (WEAK_SERIALIZATION_REFERENCE, 16), CID (WEAK_ARRAY, 17), CID (CODE, 18), CID (OBJECT_POOL, 23), CID (PC_DESCRIPTORS, 24), CID (CODE_SOURCE_MAP, 25), CID (COMPRESSED_STACK_MAPS, 26), CID (EXCEPTION_HANDLERS, 28), CID (CONTEXT, 29), CID (CONTEXT_SCOPE, 30), CID (SENTINEL, 31), CID (SINGLE_TARGET_CACHE, 32), CID (UNLINKED_CALL, 35), CID (MONOMORPHIC_SMIABLE_CALL, 33), CID (CALL_SITE_DATA, 34), CID (ICDATA, 36), CID (MEGAMORPHIC_CACHE, 37), CID (SUBTYPE_TEST_CACHE, 38), CID (LOADING_UNIT, 39), CID (LANGUAGE_ERROR, 42), CID (UNHANDLED_EXCEPTION, 43), CID (INSTANCE, 45), CID (LIBRARY_PREFIX, 46), CID (TYPE_ARGUMENTS, 47), CID (TYPE, 49), CID (FUNCTION_TYPE, 50), CID (RECORD_TYPE, 51), CID (TYPE_PARAMETER, 52), CID (CLOSURE, 57), CID (MINT, 61), CID (DOUBLE, 62), CID (FLOAT32X4, 64), CID (INT32X4, 65), CID (FLOAT64X2, 66), CID (RECORD, 67), CID (TYPED_DATA, 69), CID (EXTERNAL_TYPED_DATA, 70), CID (TYPED_DATA_VIEW, 71), CID (CAPABILITY, 74), CID (RECEIVE_PORT, 75), CID (SEND_PORT, 76), CID (STACK_TRACE, 77), CID (SUSPEND_STATE, 78), CID (REGEXP, 79), CID (WEAK_PROPERTY, 80), CID (WEAK_REFERENCE, 81), CID (FUTURE_OR, 83), CID (USER_TAG, 84), CID (TRANSFERABLE_TYPED_DATA, 85), CID (MAP, 86), CID (CONST_MAP, 87), CID (SET, 88), CID (CONST_SET, 89), CID (ARRAY, 90), CID (IMMUTABLE_ARRAY, 91), CID (GROWABLE_OBJECT_ARRAY, 92), CID (STRING, 93), CID (ONE_BYTE_STRING, 94), CID (TWO_BYTE_STRING, 95), CID (NUM_PREDEFINED_CIDS, 175) }, 112, 168, 4 },
{ "3.11.0", { CID (ILLEGAL, 0), CID (NATIVE_POINTER, 1), CID (CLASS, 5), CID (PATCH_CLASS, 6), CID (FUNCTION, 7), CID (TYPE_PARAMETERS, 8), CID (CLOSURE_DATA, 9), CID (FFI_TRAMPOLINE_DATA, 10), CID (FIELD, 11), CID (SCRIPT, 12), CID (LIBRARY, 13), CID (NAMESPACE, 14), CID (KERNEL_PROGRAM_INFO, 15), CID (WEAK_SERIALIZATION_REFERENCE, 16), CID (WEAK_ARRAY, 17), CID (CODE, 18), CID (OBJECT_POOL, 23), CID (PC_DESCRIPTORS, 24), CID (CODE_SOURCE_MAP, 25), CID (COMPRESSED_STACK_MAPS, 26), CID (EXCEPTION_HANDLERS, 28), CID (CONTEXT, 29), CID (CONTEXT_SCOPE, 30), CID (SENTINEL, 31), CID (SINGLE_TARGET_CACHE, 32), CID (UNLINKED_CALL, 35), CID (MONOMORPHIC_SMIABLE_CALL, 33), CID (CALL_SITE_DATA, 34), CID (ICDATA, 36), CID (MEGAMORPHIC_CACHE, 37), CID (SUBTYPE_TEST_CACHE, 38), CID (LOADING_UNIT, 39), CID (LANGUAGE_ERROR, 42), CID (UNHANDLED_EXCEPTION, 43), CID (INSTANCE, 45), CID (LIBRARY_PREFIX, 46), CID (TYPE_ARGUMENTS, 47), CID (TYPE, 49), CID (FUNCTION_TYPE, 50), CID (RECORD_TYPE, 51), CID (TYPE_PARAMETER, 52), CID (CLOSURE, 57), CID (MINT, 61), CID (DOUBLE, 62), CID (FLOAT32X4, 64), CID (INT32X4, 65), CID (FLOAT64X2, 66), CID (RECORD, 67), CID (TYPED_DATA, 69), CID (EXTERNAL_TYPED_DATA, 70), CID (TYPED_DATA_VIEW, 71), CID (CAPABILITY, 74), CID (RECEIVE_PORT, 75), CID (SEND_PORT, 76), CID (STACK_TRACE, 77), CID (SUSPEND_STATE, 78), CID (REGEXP, 79), CID (WEAK_PROPERTY, 80), CID (WEAK_REFERENCE, 81), CID (FUTURE_OR, 83), CID (USER_TAG, 84), CID (TRANSFERABLE_TYPED_DATA, 85), CID (MAP, 86), CID (CONST_MAP, 87), CID (SET, 88), CID (CONST_SET, 89), CID (ARRAY, 90), CID (IMMUTABLE_ARRAY, 91), CID (GROWABLE_OBJECT_ARRAY, 92), CID (STRING, 93), CID (ONE_BYTE_STRING, 94), CID (TWO_BYTE_STRING, 95), CID (NUM_PREDEFINED_CIDS, 175) }, 112, 168, 4 },
{ "3.12.0", { CID (ILLEGAL, 0), CID (NATIVE_POINTER, 1), CID (CLASS, 5), CID (PATCH_CLASS, 6), CID (FUNCTION, 7), CID (TYPE_PARAMETERS, 8), CID (CLOSURE_DATA, 9), CID (FFI_TRAMPOLINE_DATA, 10), CID (FIELD, 11), CID (SCRIPT, 12), CID (LIBRARY, 13), CID (NAMESPACE, 14), CID (KERNEL_PROGRAM_INFO, 15), CID (WEAK_SERIALIZATION_REFERENCE, 16), CID (WEAK_ARRAY, 17), CID (CODE, 18), CID (OBJECT_POOL, 23), CID (PC_DESCRIPTORS, 24), CID (CODE_SOURCE_MAP, 25), CID (COMPRESSED_STACK_MAPS, 26), CID (EXCEPTION_HANDLERS, 28), CID (CONTEXT, 29), CID (CONTEXT_SCOPE, 30), CID (SENTINEL, 31), CID (SINGLE_TARGET_CACHE, 32), CID (UNLINKED_CALL, 35), CID (MONOMORPHIC_SMIABLE_CALL, 33), CID (CALL_SITE_DATA, 34), CID (ICDATA, 36), CID (MEGAMORPHIC_CACHE, 37), CID (SUBTYPE_TEST_CACHE, 38), CID (LOADING_UNIT, 39), CID (LANGUAGE_ERROR, 42), CID (UNHANDLED_EXCEPTION, 43), CID (INSTANCE, 45), CID (LIBRARY_PREFIX, 46), CID (TYPE_ARGUMENTS, 47), CID (TYPE, 49), CID (FUNCTION_TYPE, 50), CID (RECORD_TYPE, 51), CID (TYPE_PARAMETER, 52), CID (CLOSURE, 57), CID (MINT, 61), CID (DOUBLE, 62), CID (FLOAT32X4, 64), CID (INT32X4, 65), CID (FLOAT64X2, 66), CID (RECORD, 67), CID (TYPED_DATA, 69), CID (EXTERNAL_TYPED_DATA, 70), CID (TYPED_DATA_VIEW, 71), CID (CAPABILITY, 74), CID (RECEIVE_PORT, 75), CID (SEND_PORT, 76), CID (STACK_TRACE, 77), CID (SUSPEND_STATE, 78), CID (REGEXP, 79), CID (WEAK_PROPERTY, 80), CID (WEAK_REFERENCE, 81), CID (FUTURE_OR, 83), CID (USER_TAG, 84), CID (TRANSFERABLE_TYPED_DATA, 85), CID (MAP, 86), CID (CONST_MAP, 87), CID (SET, 88), CID (CONST_SET, 89), CID (ARRAY, 90), CID (IMMUTABLE_ARRAY, 91), CID (GROWABLE_OBJECT_ARRAY, 92), CID (STRING, 93), CID (ONE_BYTE_STRING, 94), CID (TWO_BYTE_STRING, 95), CID (NUM_PREDEFINED_CIDS, 175) }, 112, 168, 4 },
{ "3.13.0", { CID (ILLEGAL, 0), CID (NATIVE_POINTER, 1), CID (CLASS, 5), CID (PATCH_CLASS, 6), CID (FUNCTION, 7), CID (TYPE_PARAMETERS, 8), CID (CLOSURE_DATA, 9), CID (FFI_TRAMPOLINE_DATA, 10), CID (FIELD, 11), CID (SCRIPT, 12), CID (LIBRARY, 13), CID (NAMESPACE, 14), CID (KERNEL_PROGRAM_INFO, 15), CID (WEAK_SERIALIZATION_REFERENCE, 16), CID (WEAK_ARRAY, 17), CID (CODE, 18), CID (OBJECT_POOL, 23), CID (PC_DESCRIPTORS, 24), CID (CODE_SOURCE_MAP, 25), CID (COMPRESSED_STACK_MAPS, 26), CID (EXCEPTION_HANDLERS, 28), CID (CONTEXT, 29), CID (CONTEXT_SCOPE, 30), CID (SENTINEL, 31), CID (SINGLE_TARGET_CACHE, 32), CID (UNLINKED_CALL, 35), CID (MONOMORPHIC_SMIABLE_CALL, 33), CID (CALL_SITE_DATA, 34), CID (ICDATA, 36), CID (MEGAMORPHIC_CACHE, 37), CID (SUBTYPE_TEST_CACHE, 38), CID (LOADING_UNIT, 39), CID (LANGUAGE_ERROR, 42), CID (UNHANDLED_EXCEPTION, 43), CID (INSTANCE, 45), CID (LIBRARY_PREFIX, 46), CID (TYPE_ARGUMENTS, 47), CID (TYPE, 49), CID (FUNCTION_TYPE, 50), CID (RECORD_TYPE, 51), CID (TYPE_PARAMETER, 52), CID (CLOSURE, 57), CID (MINT, 61), CID (DOUBLE, 62), CID (FLOAT32X4, 64), CID (INT32X4, 65), CID (FLOAT64X2, 66), CID (RECORD, 67), CID (TYPED_DATA, 69), CID (EXTERNAL_TYPED_DATA, 70), CID (TYPED_DATA_VIEW, 71), CID (CAPABILITY, 74), CID (RECEIVE_PORT, 75), CID (SEND_PORT, 76), CID (STACK_TRACE, 77), CID (SUSPEND_STATE, 78), CID (REGEXP, 79), CID (WEAK_PROPERTY, 80), CID (WEAK_REFERENCE, 81), CID (FUTURE_OR, 83), CID (USER_TAG, 84), CID (TRANSFERABLE_TYPED_DATA, 85), CID (MAP, 86), CID (CONST_MAP, 87), CID (SET, 88), CID (CONST_SET, 89), CID (ARRAY, 90), CID (IMMUTABLE_ARRAY, 91), CID (GROWABLE_OBJECT_ARRAY, 92), CID (STRING, 93), CID (ONE_BYTE_STRING, 94), CID (TWO_BYTE_STRING, 95), CID (NUM_PREDEFINED_CIDS, 176) }, 113, 169, 4 },
{ "3.14.0", { CID (ILLEGAL, 0), CID (NATIVE_POINTER, 1), CID (CLASS, 5), CID (PATCH_CLASS, 6), CID (FUNCTION, 7), CID (TYPE_PARAMETERS, 8), CID (CLOSURE_DATA, 9), CID (FFI_TRAMPOLINE_DATA, 10), CID (FIELD, 11), CID (SCRIPT, 12), CID (LIBRARY, 13), CID (NAMESPACE, 14), CID (KERNEL_PROGRAM_INFO, 15), CID (WEAK_SERIALIZATION_REFERENCE, 16), CID (WEAK_ARRAY, 17), CID (CODE, 18), CID (OBJECT_POOL, 23), CID (PC_DESCRIPTORS, 24), CID (CODE_SOURCE_MAP, 25), CID (COMPRESSED_STACK_MAPS, 26), CID (EXCEPTION_HANDLERS, 28), CID (CONTEXT, 29), CID (CONTEXT_SCOPE, 30), CID (SENTINEL, 31), CID (SINGLE_TARGET_CACHE, 32), CID (UNLINKED_CALL, 35), CID (MONOMORPHIC_SMIABLE_CALL, 33), CID (CALL_SITE_DATA, 34), CID (ICDATA, 36), CID (MEGAMORPHIC_CACHE, 37), CID (SUBTYPE_TEST_CACHE, 38), CID (LOADING_UNIT, 39), CID (LANGUAGE_ERROR, 42), CID (UNHANDLED_EXCEPTION, 43), CID (INSTANCE, 45), CID (LIBRARY_PREFIX, 46), CID (TYPE_ARGUMENTS, 47), CID (TYPE, 49), CID (FUNCTION_TYPE, 50), CID (RECORD_TYPE, 51), CID (TYPE_PARAMETER, 52), CID (CLOSURE, 57), CID (MINT, 61), CID (DOUBLE, 62), CID (FLOAT32X4, 64), CID (INT32X4, 65), CID (FLOAT64X2, 66), CID (RECORD, 67), CID (TYPED_DATA, 69), CID (EXTERNAL_TYPED_DATA, 70), CID (TYPED_DATA_VIEW, 71), CID (CAPABILITY, 74), CID (RECEIVE_PORT, 75), CID (SEND_PORT, 76), CID (STACK_TRACE, 77), CID (SUSPEND_STATE, 78), CID (REGEXP, 79), CID (WEAK_PROPERTY, 80), CID (WEAK_REFERENCE, 81), CID (FUTURE_OR, 83), CID (USER_TAG, 84), CID (TRANSFERABLE_TYPED_DATA, 85), CID (MAP, 86), CID (CONST_MAP, 87), CID (SET, 88), CID (CONST_SET, 89), CID (ARRAY, 90), CID (IMMUTABLE_ARRAY, 91), CID (GROWABLE_OBJECT_ARRAY, 92), CID (STRING, 93), CID (ONE_BYTE_STRING, 94), CID (TWO_BYTE_STRING, 95), CID (NUM_PREDEFINED_CIDS, 176) }, 113, 169, 4 },
{ NULL, { 0 }, 0, 0, 0 }
// clang-format on
};
+35 -1
View File
@@ -22,6 +22,16 @@ static bool looks_like_data_snapshot(DartCtx *ctx, ut64 base, ut64 *out_total_le
return true;
}
static bool dart_snapshot_is_single(DartCtx *ctx, ut64 base) {
DartSnapshotHeader hdr;
if (!base || !dart_snapshot_header_read (ctx, base, &hdr)) {
return false;
}
const char *version = dart_version_from_hash (hdr.hash);
const DartVerLayout *layout = version? dart_profile_from_version (version): NULL;
return layout && layout->single_snapshot;
}
static void pick_vm_iso_by_size(const ut64 *addrs, const ut64 *lens, int count, ut64 *vm_out, ut64 *iso_out) {
if (count < 1) {
return;
@@ -157,6 +167,13 @@ static void locate_instr_images_structural(DartCtx *ctx) {
if (!vm_instr || vm_instr >= data_lo || !dart_image_at (ctx, vm_instr, data_lo, &sz1)) {
return;
}
if (dart_snapshot_is_single (ctx, ctx->iso_data? ctx->iso_data: ctx->vm_data)) {
ctx->iso_instr = vm_instr;
if (ctx->verbose > 0) {
fprintf (stderr, "[r2flutter] located single instruction image structurally: snapshot_instr=0x%" PFMT64x "\n", (ut64)vm_instr);
}
return;
}
ut64 iso_instr = dart_align_up (vm_instr + sz1, DART_IMAGE_ALIGN);
if (iso_instr <= vm_instr || iso_instr >= data_lo || !dart_image_at (ctx, iso_instr, data_lo, &sz2)) {
return;
@@ -194,6 +211,8 @@ int find_snapshots(DartCtx *ctx) {
"_kDartIsolateSnapshotInstructions",
"DartIsolateSnapshotInstructions",
};
const char *single_data_names[2] = { "_kDartSnapshotData", "DartSnapshotData" };
const char *single_text_names[2] = { "_kDartSnapshotText", "DartSnapshotText" };
ut64 *outs[4] = { &ctx->vm_data, &ctx->vm_instr, &ctx->iso_data, &ctx->iso_instr };
if (core->bin) {
RVecRBinSymbol *v = r_bin_get_symbols_vec (core->bin);
@@ -216,12 +235,23 @@ int find_snapshots(DartCtx *ctx) {
*outs[idx] = rebase_bin_addr (ctx, sym->vaddr);
}
}
for (int k = 0; k < 2; k++) {
if (!strcmp (nm, single_data_names[k]) && sym->vaddr) {
ctx->iso_data = rebase_bin_addr (ctx, sym->vaddr);
}
if (!strcmp (nm, single_text_names[k]) && sym->vaddr) {
ctx->iso_instr = rebase_bin_addr (ctx, sym->vaddr);
}
}
}
}
}
if (ctx->vm_data && ctx->vm_instr && ctx->iso_data && ctx->iso_instr) {
return 0;
}
if (ctx->iso_data && ctx->iso_instr && dart_snapshot_is_single (ctx, ctx->iso_data)) {
return 0;
}
RVecRBinSection *sections = r_bin_get_sections_vec (core->bin);
ut64 found_addrs[32];
@@ -280,7 +310,11 @@ int find_snapshots(DartCtx *ctx) {
// the ones still unset so scan guesses cannot overwrite good values.
ut64 scan_vm_data = 0;
ut64 scan_iso_data = 0;
pick_vm_iso_by_size (data_addrs, data_lens, data_cnt, &scan_vm_data, &scan_iso_data);
if (data_cnt == 1 && dart_snapshot_is_single (ctx, data_addrs[0])) {
scan_iso_data = data_addrs[0];
} else {
pick_vm_iso_by_size (data_addrs, data_lens, data_cnt, &scan_vm_data, &scan_iso_data);
}
if (!ctx->vm_data) {
ctx->vm_data = scan_vm_data;
}
+60 -5
View File
@@ -19,6 +19,7 @@ typedef enum {
MODERN_ALLOC_CONTEXT_SCOPE,
MODERN_ALLOC_RECORD,
MODERN_ALLOC_TYPED_DATA,
MODERN_ALLOC_VARIABLE,
MODERN_ALLOC_INSTANCE,
MODERN_ALLOC_EMPTY,
MODERN_ALLOC_UNKNOWN,
@@ -39,6 +40,7 @@ typedef enum {
MODERN_FILL_INLINE_BYTES,
MODERN_FILL_TYPED_DATA,
MODERN_FILL_RECORD,
MODERN_FILL_CLOSURE,
MODERN_FILL_INSTANCE,
MODERN_FILL_UNKNOWN,
} ModernFillKind;
@@ -97,6 +99,7 @@ typedef struct {
bool fill_ok;
int next_field_offset_words;
ut8 *discarded_codes;
ut64 *alloc_items;
} ModernClusterMeta;
typedef struct {
@@ -258,6 +261,8 @@ static const char *modern_alloc_kind_name(ModernAllocKind kind) {
return "record";
case MODERN_ALLOC_TYPED_DATA:
return "typed_data";
case MODERN_ALLOC_VARIABLE:
return "variable";
case MODERN_ALLOC_INSTANCE:
return "instance";
case MODERN_ALLOC_EMPTY:
@@ -298,6 +303,8 @@ static const char *modern_fill_kind_name(ModernFillKind kind) {
return "typed_data";
case MODERN_FILL_RECORD:
return "record";
case MODERN_FILL_CLOSURE:
return "closure";
case MODERN_FILL_INSTANCE:
return "instance";
case MODERN_FILL_UNKNOWN:
@@ -380,6 +387,7 @@ typedef struct {
// handful of clusters. Their readers are gated on this flag; everything
// else is shared.
bool legacy_format;
bool closure_variable;
// every CID this layout defines, indexed by kind; -1 when the kind is absent
int by_kind[DART_CID_KIND_COUNT];
} ModernCidCache;
@@ -453,6 +461,7 @@ static ModernCidCache modern_cid_cache_init(const DartVerLayout *layout) {
.typed_data_internal_limit = dart_cid_typed_data_limit (layout),
.typed_data_stride = dart_cid_typed_data_stride (layout),
.legacy_format = modern_layout_is_legacy (layout),
.closure_variable = layout && layout->closure_variable,
};
for (int kind = 0; kind < DART_CID_KIND_COUNT; kind++) {
cids.by_kind[kind] = dart_cid_get (layout, (DartCidKind)kind);
@@ -603,6 +612,9 @@ static ModernAllocKind modern_alloc_kind(const ModernCidCache *cids, int compres
if (modern_cid_eq (cid, cids->double_)) {
return MODERN_ALLOC_SIMPLE;
}
if (cids->closure_variable && modern_cid_eq (cid, cids->closure)) {
return MODERN_ALLOC_VARIABLE;
}
if (modern_is_simple_alloc_cid (cids, cid)) {
return MODERN_ALLOC_SIMPLE;
}
@@ -725,15 +737,25 @@ static bool modern_skip_alloc(ClusterStream *s, const ModernCidCache *cids, int
case MODERN_ALLOC_CONTEXT_SCOPE:
case MODERN_ALLOC_RECORD:
case MODERN_ALLOC_TYPED_DATA:
case MODERN_ALLOC_VARIABLE:
if (!cs_read_unsigned (s, &count)) {
return false;
}
meta->count = count;
if (kind == MODERN_ALLOC_VARIABLE && count) {
meta->alloc_items = (ut64 *)calloc ((size_t)count, sizeof (ut64));
if (!meta->alloc_items) {
return false;
}
}
for (ut64 i = 0; i < count; i++) {
ut64 item = 0;
if (!cs_read_unsigned (s, &item)) {
return false;
}
if (meta->alloc_items) {
meta->alloc_items[i] = item;
}
modern_cluster_record_item (meta, item);
}
if ((kind == MODERN_ALLOC_TYPE_ARGUMENTS || kind == MODERN_ALLOC_RODATA) && meta->is_canonical) {
@@ -746,6 +768,10 @@ static bool modern_skip_alloc(ClusterStream *s, const ModernCidCache *cids, int
if (!cs_read_unsigned (s, &predefined)) {
return false;
}
if (s->ctx && s->ctx->layout && s->ctx->layout->class_alloc_fixed) {
meta->count = predefined;
return true;
}
if (cids->num_predefined_cids > 0 && predefined > (ut64)cids->num_predefined_cids) {
if (!cs_read_unsigned (s, &predefined)) {
return false;
@@ -950,6 +976,9 @@ static ModernFillSpec modern_get_fill_spec(const ModernCidCache *cids, int cid)
if (modern_cid_eq (cid, cids->record)) {
return modern_fill_spec_kind (MODERN_FILL_RECORD);
}
if (cids->closure_variable && modern_cid_eq (cid, cids->closure)) {
return modern_fill_spec_kind (MODERN_FILL_CLOSURE);
}
static const ModernFillSpecRule rules[] = {
{ DART_CID_PATCH_CLASS, MODERN_FILL_REFS, 2, -1, -1, 0, { 0 } },
{ DART_CID_TYPE_PARAMETERS, MODERN_FILL_REFS, 4, -1, -1, 0, { 0 } },
@@ -1249,6 +1278,24 @@ static bool modern_skip_fill_record(ClusterStream *s, const ModernClusterMeta *m
return true;
}
static bool modern_skip_fill_closure(ClusterStream *s, const ModernClusterMeta *meta) {
if (!meta->alloc_items && meta->count) {
return false;
}
for (ut64 i = 0; i < meta->count; i++) {
ut64 value = 0;
if (!cs_read_unsigned (s, &value)) {
return false;
}
for (ut64 j = 0; j < 3 + meta->alloc_items[i]; j++) {
if (!cs_read_ref_id (s, &value)) {
return false;
}
}
}
return true;
}
static bool modern_resync_fill_record(ClusterStream *s, const ModernClusterMeta *meta) {
if (meta->alloc_items_count != meta->count || !meta->count) {
return modern_skip_fill_record (s, meta);
@@ -1387,6 +1434,11 @@ static bool modern_skip_fill_object_pool(ClusterStream *s, const ModernClusterMe
return true;
}
static bool modern_class_is_top_level(const DartVerLayout *layout, ut32 cid) {
const ut32 offset = layout && layout->class_top_level_cid20? 1U << 20: 1U << 16;
return cid >= offset;
}
static bool modern_skip_fill_class(ClusterStream *s, const ModernClusterMeta *meta, const ModernFillSpec *spec) {
for (ut64 j = 0; j < meta->count; j++) {
ut32 class_id = 0;
@@ -1401,7 +1453,7 @@ static bool modern_skip_fill_class(ClusterStream *s, const ModernClusterMeta *me
return false;
}
bool is_predefined = j < meta->main_count;
bool is_top_level = class_id >= (1U << 16);
bool is_top_level = modern_class_is_top_level (s->ctx? s->ctx->layout: NULL, class_id);
if (is_predefined || !is_top_level) {
ut64 bitmap = 0;
if (!cs_read_unsigned (s, &bitmap)) {
@@ -1440,6 +1492,8 @@ static bool modern_skip_fill_by_kind(ClusterStream *s, const ModernCidCache *cid
return modern_skip_fill_typed_data (s, cids, meta);
case MODERN_FILL_RECORD:
return modern_resync_fill_record (s, meta);
case MODERN_FILL_CLOSURE:
return modern_skip_fill_closure (s, meta);
case MODERN_FILL_INSTANCE:
return modern_skip_fill_instance (s->ctx, s, meta);
case MODERN_FILL_NONE:
@@ -1862,7 +1916,7 @@ static bool modern_resolver_read_class_fill(ModernWalk *w, ClusterStream *s, con
return false;
}
bool is_predefined = j < meta->main_count;
bool is_top_level = class_id >= (1U << 16);
bool is_top_level = modern_class_is_top_level (w->ctx? w->ctx->layout: NULL, class_id);
if (is_predefined || !is_top_level) {
ut64 bitmap = 0;
if (!cs_read_unsigned (s, &bitmap)) {
@@ -2673,6 +2727,7 @@ static void modern_cluster_meta_free(ModernClusterMeta *meta, ut64 num_clusters)
}
for (ut64 i = 0; i < num_clusters; i++) {
free (meta[i].discarded_codes);
free (meta[i].alloc_items);
}
free (meta);
}
@@ -2931,7 +2986,7 @@ static bool modern_collect_class_strings(ModernPoolStringRefCollector *collector
return false;
}
bool is_predefined = i < meta->main_count;
bool is_top_level = class_id >= (1U << 16);
bool is_top_level = modern_class_is_top_level (resolver->ctx? resolver->ctx->layout: NULL, class_id);
if (is_predefined || !is_top_level) {
ut64 bitmap = 0;
if (!cs_read_unsigned (&s, &bitmap)) {
@@ -3832,7 +3887,7 @@ static bool modern_read_class_fill(ModernWalk *w, ClusterStream *s, const Modern
return false;
}
bool is_predefined = j < meta->main_count;
bool is_top_level = class_id >= (1U << 16);
bool is_top_level = modern_class_is_top_level (ctx->layout, class_id);
if (is_predefined || !is_top_level) {
ut64 bitmap = 0;
if (!cs_read_unsigned (s, &bitmap)) {
@@ -4140,7 +4195,7 @@ static bool modern_name_scan_read_class(ModernWalk *w, ClusterStream *s, const M
if (!cs_read_tagged32 (s, &class_id) || !cs_read_tagged32 (s, &tmp32) || !cs_read_tagged32 (s, &tmp32) || !cs_read_tagged32 (s, &tmp32) || !cs_read_tagged32 (s, &tmp32) || !cs_read_tagged32 (s, &tmp32) || !cs_read_tagged32 (s, &tmp32)) {
return false;
}
const bool is_top_level = class_id >= (1U << 16);
const bool is_top_level = modern_class_is_top_level (w->ctx? w->ctx->layout: NULL, class_id);
if (j < m->main_count || !is_top_level) {
ut64 bitmap = 0;
if (!cs_read_unsigned (s, &bitmap)) {
+68 -28
View File
@@ -135,10 +135,9 @@ static const DartVerLayout *load_layout_from_json(const char *hash, DartVerLayou
const char *version = dart_version_from_hash (hash);
const DartVerLayout *base_profile = version? dart_profile_from_version (version): NULL;
if (!base_profile) {
// Unknown hash: fingerprint against the newest known profile so the
// decode path (-f/-A) uses the same real layout the -H report shows,
// not a degenerate zeroed struct. cws is still refined from the flags.
base_profile = dart_newest_profile ();
// Keep discovery and decoding on the same conservative profile. A newer
// single-snapshot layout requires an exact hash or structural probing.
base_profile = dart_fingerprint_profile ();
}
memcpy (out, base_profile, sizeof (*out));
r_str_ncpy (out->hash, hash, sizeof (out->hash));
@@ -174,6 +173,10 @@ static DartVerLayout *dart_pick_layout_owned_for_ctx(DartCtx *ctx) {
return dart_layout_from_hash (dart_ctx_hash (ctx));
}
static ut64 dart_ctx_primary_data(const DartCtx *ctx) {
return ctx? (ctx->vm_data? ctx->vm_data: ctx->iso_data): 0;
}
static void extract_snapshot_hash_flags(DartCtx *ctx, ut64 vm_data) {
if (!ctx || !vm_data) {
return;
@@ -197,11 +200,12 @@ static void extract_snapshot_hash_flags(DartCtx *ctx, ut64 vm_data) {
}
static void derive_layout_from_flags(DartCtx *ctx) {
if (!ctx || !ctx->vm_data) {
const ut64 data = dart_ctx_primary_data (ctx);
if (!ctx || !data) {
return;
}
DartSnapshotHeader hdr;
if (!dart_snapshot_header_read (ctx, ctx->vm_data, &hdr)) {
if (!dart_snapshot_header_read (ctx, data, &hdr)) {
return;
}
const char *flags = hdr.flags;
@@ -230,7 +234,7 @@ static void derive_layout_from_flags(DartCtx *ctx) {
}
DartVerLayout *dart_ctx_init_layout(DartCtx *ctx, DartVerLayout *tmp) {
extract_snapshot_hash_flags (ctx, ctx->vm_data);
extract_snapshot_hash_flags (ctx, dart_ctx_primary_data (ctx));
ctx->layout = R_STR_ISEMPTY (ctx->dart_version_override)? load_layout_from_json (dart_ctx_hash (ctx), tmp): NULL;
DartVerLayout *owned = NULL;
if (!ctx->layout) {
@@ -582,7 +586,7 @@ static int prepare_header_data(DartCtx *ctx) {
if (ok != 0) {
return -1;
}
extract_snapshot_hash_flags (ctx, ctx->vm_data);
extract_snapshot_hash_flags (ctx, dart_ctx_primary_data (ctx));
ctx->layout = dart_pick_layout_owned_for_ctx (ctx);
derive_layout_from_flags (ctx);
dart_ctx_set_version_source (ctx);
@@ -615,6 +619,9 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
pj_kn (pj, "vm_instr", ctx->vm_instr);
pj_kn (pj, "iso_data", ctx->iso_data);
pj_kn (pj, "iso_instr", ctx->iso_instr);
if (ctx->layout && ctx->layout->single_snapshot) {
pj_kb (pj, "single_snapshot", true);
}
if (ctx->container_kind[0]) {
pj_k (pj, "container");
pj_o (pj);
@@ -662,24 +669,33 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
}
if (fmt == 'r') {
RStrBuf *sb = r_strbuf_new (quiet? "": "'# Dart AOT Snapshot Info\n");
const bool single = ctx->layout && ctx->layout->single_snapshot;
const ut64 data = dart_ctx_primary_data (ctx);
// Create flags for snapshot addresses
r_strbuf_appendf (sb, "'fs dart\n");
r_strbuf_appendf (sb, "'f dart.vm_data = 0x%" PFMT64x "\n", (ut64)ctx->vm_data);
r_strbuf_appendf (sb, "'f dart.vm_instr = 0x%" PFMT64x "\n", (ut64)ctx->vm_instr);
r_strbuf_appendf (sb, "'f dart.iso_data = 0x%" PFMT64x "\n", (ut64)ctx->iso_data);
r_strbuf_appendf (sb, "'f dart.iso_instr = 0x%" PFMT64x "\n", (ut64)ctx->iso_instr);
if (single) {
r_strbuf_appendf (sb, "'f dart.snapshot_data = 0x%" PFMT64x "\n", (ut64)ctx->iso_data);
r_strbuf_appendf (sb, "'f dart.snapshot_text = 0x%" PFMT64x "\n", (ut64)ctx->iso_instr);
r_strbuf_appendf (sb, "'f dart.iso_data = 0x%" PFMT64x "\n", (ut64)ctx->iso_data);
r_strbuf_appendf (sb, "'f dart.iso_instr = 0x%" PFMT64x "\n", (ut64)ctx->iso_instr);
} else {
r_strbuf_appendf (sb, "'f dart.vm_data = 0x%" PFMT64x "\n", (ut64)ctx->vm_data);
r_strbuf_appendf (sb, "'f dart.vm_instr = 0x%" PFMT64x "\n", (ut64)ctx->vm_instr);
r_strbuf_appendf (sb, "'f dart.iso_data = 0x%" PFMT64x "\n", (ut64)ctx->iso_data);
r_strbuf_appendf (sb, "'f dart.iso_instr = 0x%" PFMT64x "\n", (ut64)ctx->iso_instr);
}
if (ctx->container_kind[0]) {
r_strbuf_appendf (sb, "'f dart.container_payload = 0x%" PFMT64x "\n", (ut64)ctx->container_payload_offset);
r_strbuf_appendf (sb, "'f dart.container_payload_size = 0x%" PFMT64x "\n", (ut64)ctx->container_payload_size);
}
if (!quiet) {
// Add comments with metadata
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Dart snapshot hash: %s\n", (ut64)ctx->vm_data, ctx->snapshot_hash[0]? ctx->snapshot_hash: "(unknown)");
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Dart version: %s (%s)\n", (ut64)ctx->vm_data, version, version_source);
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Dart snapshot hash: %s\n", data, ctx->snapshot_hash[0]? ctx->snapshot_hash: "(unknown)");
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Dart version: %s (%s)\n", data, version, version_source);
if (ctx->layout) {
const DartVerLayout *l = ctx->layout;
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Tag style: %s\n", (ut64)ctx->vm_data, dart_tag_style_to_string (l->tag_style));
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Alignment: %d, CWS: %d\n", (ut64)ctx->vm_data, l->max_alignment, ctx->compressed_word_size);
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Tag style: %s\n", data, dart_tag_style_to_string (l->tag_style));
r_strbuf_appendf (sb, "'@0x%" PFMT64x "'CC Alignment: %d, CWS: %d\n", data, l->max_alignment, ctx->compressed_word_size);
}
}
return r_strbuf_drain (sb);
@@ -691,6 +707,9 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
if (ctx->layout) {
const DartVerLayout *l = ctx->layout;
r_strbuf_appendf (sb, " tag_style=%s alignment=%d", dart_tag_style_to_string (l->tag_style), l->max_alignment);
if (l->single_snapshot) {
r_strbuf_append (sb, " single_snapshot=true");
}
}
return r_strbuf_drain (sb);
}
@@ -708,10 +727,15 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
}
r_strbuf_appendf (sb, "\n## Snapshot Addresses\n");
r_strbuf_appendf (sb, "vm_data: 0x%" PFMT64x "\n", (ut64)ctx->vm_data);
r_strbuf_appendf (sb, "vm_instr: 0x%" PFMT64x "\n", (ut64)ctx->vm_instr);
r_strbuf_appendf (sb, "iso_data: 0x%" PFMT64x "\n", (ut64)ctx->iso_data);
r_strbuf_appendf (sb, "iso_instr: 0x%" PFMT64x "\n", (ut64)ctx->iso_instr);
if (ctx->layout && ctx->layout->single_snapshot) {
r_strbuf_appendf (sb, "snapshot_data: 0x%" PFMT64x "\n", (ut64)ctx->iso_data);
r_strbuf_appendf (sb, "snapshot_text: 0x%" PFMT64x "\n", (ut64)ctx->iso_instr);
} else {
r_strbuf_appendf (sb, "vm_data: 0x%" PFMT64x "\n", (ut64)ctx->vm_data);
r_strbuf_appendf (sb, "vm_instr: 0x%" PFMT64x "\n", (ut64)ctx->vm_instr);
r_strbuf_appendf (sb, "iso_data: 0x%" PFMT64x "\n", (ut64)ctx->iso_data);
r_strbuf_appendf (sb, "iso_instr: 0x%" PFMT64x "\n", (ut64)ctx->iso_instr);
}
if (ctx->container_kind[0]) {
r_strbuf_appendf (sb, "\n## Container\n");
r_strbuf_appendf (sb, "kind: %s\n", ctx->container_kind);
@@ -721,8 +745,9 @@ char *dart_pool_dump_header(DartCtx *ctx, int fmt) {
r_strbuf_appendf (sb, "macho_off: 0x%" PFMT64x "\n", (ut64)ctx->container_macho_offset);
}
ut64 addrs[2] = { ctx->vm_data, ctx->iso_data };
const char *labels[2] = { "VM", "Isolate" };
const bool single = ctx->layout && ctx->layout->single_snapshot;
ut64 addrs[2] = { single? ctx->iso_data: ctx->vm_data, single? 0: ctx->iso_data };
const char *labels[2] = { single? "Combined": "VM", "Isolate" };
for (int si = 0; si < 2; si++) {
if (!addrs[si]) {
continue;
@@ -840,6 +865,9 @@ static char *dump_header_ext_json(DartCtx *ctx, int detail) {
pj_kn (pj, "vm_instr", ctx->vm_instr);
pj_kn (pj, "iso_data", ctx->iso_data);
pj_kn (pj, "iso_instr", ctx->iso_instr);
if (ctx->layout && ctx->layout->single_snapshot) {
pj_kb (pj, "single_snapshot", true);
}
pj_ki (pj, "cws", ctx->compressed_word_size);
pj_ks (pj, "dart_version", version);
pj_ks (pj, "version_source", dart_version_source_str (ctx? ctx->version_source: DART_VERSION_SOURCE_UNKNOWN));
@@ -875,8 +903,12 @@ static char *dump_header_ext_json(DartCtx *ctx, int detail) {
pj_end (pj);
}
pj_ka (pj, "snapshots");
dump_header_snapshot_json (ctx, pj, "VM", ctx->vm_data, detail);
dump_header_snapshot_json (ctx, pj, "Isolate", ctx->iso_data, detail);
if (ctx->layout && ctx->layout->single_snapshot) {
dump_header_snapshot_json (ctx, pj, "Combined", ctx->iso_data, detail);
} else {
dump_header_snapshot_json (ctx, pj, "VM", ctx->vm_data, detail);
dump_header_snapshot_json (ctx, pj, "Isolate", ctx->iso_data, detail);
}
pj_end (pj);
pj_end (pj);
return pj_drain (pj);
@@ -970,15 +1002,23 @@ static char *dart_pool_dump_header_ext_level(DartCtx *ctx, int fmt, int detail)
char *header = dart_pool_dump_header (ctx, fmt);
RStrBuf *sb = r_strbuf_new (header? header: "");
free (header);
dump_header_ext_snapshot_r2 (ctx, sb, "VM", "vm", ctx->vm_data, detail);
dump_header_ext_snapshot_r2 (ctx, sb, "Isolate", "isolate", ctx->iso_data, detail);
if (ctx->layout && ctx->layout->single_snapshot) {
dump_header_ext_snapshot_r2 (ctx, sb, "Combined", "snapshot", ctx->iso_data, detail);
} else {
dump_header_ext_snapshot_r2 (ctx, sb, "VM", "vm", ctx->vm_data, detail);
dump_header_ext_snapshot_r2 (ctx, sb, "Isolate", "isolate", ctx->iso_data, detail);
}
return r_strbuf_drain (sb);
}
char *header = dart_pool_dump_header (ctx, fmt);
RStrBuf *sb = r_strbuf_new (header? header: "");
free (header);
dump_header_ext_snapshot_text (ctx, sb, "VM", ctx->vm_data, detail);
dump_header_ext_snapshot_text (ctx, sb, "Isolate", ctx->iso_data, detail);
if (ctx->layout && ctx->layout->single_snapshot) {
dump_header_ext_snapshot_text (ctx, sb, "Combined", ctx->iso_data, detail);
} else {
dump_header_ext_snapshot_text (ctx, sb, "VM", ctx->vm_data, detail);
dump_header_ext_snapshot_text (ctx, sb, "Isolate", ctx->iso_data, detail);
}
return r_strbuf_drain (sb);
}
+47 -32
View File
@@ -125,36 +125,42 @@ static const struct {
// Dart 3.12.x
{ "41be3daaabd524b8aa7423bc24584957", "3.12.0" },
{ "ace654289f5abc240509fc941453ebc5", "3.12.1" },
// Dart 3.13.x
{ "0451907c2eaa8467e848c0067bfe8ed4", "3.13.0" },
// Dart 3.14.x
{ "7a1ea3f6f5cf1089a7f6e55d7f20dbfd", "3.14.0" },
{ NULL, NULL }
};
// 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_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 }
{ "", "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, false, false, false, false }, // 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, false, false, false, false }, // 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, false, false, false, false }, // 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, false, false, false, false }, // 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, false, false, false, false }, // 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, false, false, false, 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, false, false, false, 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, false, false, false, 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, false, false, false, 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, false, false, false, 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // 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, false, false, false, true }, // Dart 3.12.0
{ "", "3.13.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, 2, false, true, true, true, true }, // Dart 3.13.0
{ "", "3.14.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, 2, false, true, true, true, true }, // Dart 3.14.0
{ { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
const char *dart_version_from_hash(const char *hash) {
@@ -177,6 +183,16 @@ const DartVerLayout *dart_newest_profile(void) {
return newest;
}
const DartVerLayout *dart_fingerprint_profile(void) {
const DartVerLayout *baseline = version_profiles;
for (int i = 0; version_profiles[i].dart_version; i++) {
if (!version_profiles[i].single_snapshot) {
baseline = &version_profiles[i];
}
}
return baseline;
}
const char *dart_version_source_str(int source) {
switch (source) {
case DART_VERSION_SOURCE_EXACT:
@@ -222,17 +238,16 @@ DartVerLayout *dart_layout_from_hash(const char *hash) {
}
return dvl;
}
// Unknown hash: fingerprint against the newest known profile. Snapshot
// formats (CID tables, tag style) only change at release boundaries, so an
// unlisted git/dev build almost always matches the most recent release; the
// caller still refines compressed_word_size from the feature flags.
const DartVerLayout *newest = dart_newest_profile ();
memcpy (dvl, newest, sizeof (DartVerLayout));
// A single-snapshot profile changes discovery as well as cluster framing, so
// an unknown hash must not inherit one without structural evidence. Keep the
// newest compatible split-snapshot baseline until probing selects a layout.
const DartVerLayout *baseline = dart_fingerprint_profile ();
memcpy (dvl, baseline, sizeof (DartVerLayout));
if (hash && *hash) {
r_str_ncpy (dvl->hash, hash, sizeof (dvl->hash));
}
if (G_VERBOSE > 0) {
fprintf (stderr, "[r2flutter] Unknown snapshot hash, fingerprinting as newest known profile %s (hash=%s)\n", newest->dart_version, hash? hash: "(null)");
fprintf (stderr, "[r2flutter] Unknown snapshot hash, fingerprinting as compatible profile %s (hash=%s)\n", baseline->dart_version, hash? hash: "(null)");
}
return dvl;
}
+18
View File
@@ -0,0 +1,18 @@
NAME=dart-313-single-snapshot-layout
FILE=-
CMDS=<<EOF
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-single-313.bin 50414421f5f5dcdc97000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c080808087808080808080808080808080810181
!!../bin/r2flutter -q -j -HHH -l 8 /tmp/r2flutter-single-313.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); s=d["snapshots"][0]; c={x["cid"]:x for x in s["clusters"]}; e=c[23]["object_pools"][0]["entries"][0]; print(d["dart_version"], d["single_snapshot"], d["vm_data"], d["iso_data"], len(d["snapshots"]), s["label"], s["clusters_parsed"]); print(c[5]["alloc"], c[5]["fill_status"], c[18]["fill_status"], c[57]["alloc"], c[57]["fill"], c[57]["items"]["total"], e["ref"])'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-single-314.bin 50414421f5f5dcdc97000000000000000200000000000000376131656133663666356366313038396137663665353564376632306462666470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c080808087808080808080808080808080810181
!!../bin/r2flutter -q -j -H /tmp/r2flutter-single-314.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["dart_version"], d["single_snapshot"], d["vm_data"], d["iso_data"], d["cid_table"]["num_predefined"])'
!!python3 -c 'import sys; open(sys.argv[1], "wb").write(bytes.fromhex(sys.argv[2]))' /tmp/r2flutter-single-313-truncated.bin 50414421f5f5dcdc92000000000000000200000000000000303435313930376332656161383436376538343863303036376266653865643470726f647563742061726d3634206e6f2d636f6d707265737365642d706f696e746572730082868485890020c1810040c481c0800020ce81820060c58181808080808080808080808080807022c4c4c3c0c0c0c08080808780808080808080808080
!!../bin/r2flutter -q -j -HHH -l 8 /tmp/r2flutter-single-313-truncated.bin 2>/dev/null | python3 -c 'import json,sys; d=json.load(sys.stdin); s=d["snapshots"][0]; c={x["cid"]:x for x in s["clusters"]}; print("truncated", d["dart_version"], s["label"], s["clusters_parsed"], c[57]["fill_status"], c[23]["fill_status"], c[23]["object_pool_decode"])'
!!rm -f /tmp/r2flutter-single-313.bin /tmp/r2flutter-single-314.bin /tmp/r2flutter-single-313-truncated.bin
EOF
EXPECT=<<EOF
3.13.0 True 0 4 1 Combined True
class ok ok variable closure 2 1
3.14.0 True 0 4 176
truncated 3.13.0 Combined True failed not_parsed fill_not_parsed
EOF
RUN