[GH-ISSUE #6884] [Bug] inspect-dart-aot skips PT_DYNAMIC symbols when a section table remains #4221

Closed
opened 2026-10-31 00:47:49 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 23, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/6884

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

The public inspect-dart-aot CLI refuses an authored ELF64 shared library whose retained section directory omits SHT_DYNSYM, reporting that all four _kDart*Snapshot* symbols are absent. Its unchanged PT_DYNAMIC metadata still locates those symbols: the system loader resolves all four with their exact expected bytes, and readelf --wide --headers --symbols --use-dynamic exits 0 with empty stderr and lists them.

The original library and a copy with no section table both return four sections, two agreeing hash sources, complete coverage, and package:demo/main.dart. Thus retaining otherwise usable section metadata disables an existing dynamic-table decoding path.

This is a compiled, self-authored ELF containing marker arrays in the inspector's supported header layout. It is not a production Dart snapshot or a Flutter SDK build.

Reproduction

From the prepared source checkout at the revision below, set REA_ENTRYPOINT to its absolute scripts/rea.mjs path. Save this script outside the checkout as /tmp/rea-flutter-repro.py, then run python3 /tmp/rea-flutter-repro.py "$REA_ENTRYPOINT" "$(command -v node)" with Node 24.22.1 on PATH. It requires Linux x86_64, a C compiler, Python 3, and GNU readelf. It writes only a final/ directory next to the script.

The executed script compiles inert marker arrays and one function returning 7; only that self-authored function and loader symbol resolution execute. REA's inspection remains static. It checks the original, retained-section, and absent-section variants once each in the final recorded batch.

from pathlib import Path
import ctypes, json, os, struct, subprocess, sys, zipfile

root = Path(__file__).resolve().parent / 'final'
root.mkdir(exist_ok=True)
entrypoint = Path(sys.argv[1]).resolve()
node = sys.argv[2]
hash_bytes = b'0123456789abcdef0123456789abcdef'
def snapshot(tail=b''):
    return b'\xf5\xf5\xdc\xdc' + struct.pack('<QQ', 48 + len(tail), 3) + hash_bytes + tail
exports = {
    '_kDartVmSnapshotData': snapshot(),
    '_kDartVmSnapshotInstructions': bytes(16),
    '_kDartIsolateSnapshotData': snapshot(b'\0package:demo/main.dart\0dart:core\0DemoWidget\0'),
    '_kDartIsolateSnapshotInstructions': bytes(16),
}
source = '\n'.join('const unsigned char %s[] = {%s};' % (name, ','.join(map(str, data))) for name, data in exports.items())
(root / 'demo.c').write_text(source + '\nint exported_answer(void) { return 7; }\n')
subprocess.run(['cc', '-shared', '-fPIC', '-nostdlib', '-Wl,--hash-style=both', '-o', str(root / 'original.so'), str(root / 'demo.c')], check=True)
original = (root / 'original.so').read_bytes()
assert original[:7] == b'\x7fELF\x02\x01\x01'
shoff = struct.unpack_from('<Q', original, 40)[0]
width, count, names = struct.unpack_from('<HHH', original, 58)
sections = [original[shoff + i * width:shoff + (i + 1) * width] for i in range(count)]
dynsym = next(section for section in sections if struct.unpack_from('<I', section, 4)[0] == 11)
symoff, symsize = struct.unpack_from('<QQ', dynsym, 24)
keep = {struct.unpack_from('<H', original, at + 6)[0] for at in range(symoff, symoff + symsize, 24)} - {0}
dynamic = {i for i, section in enumerate(sections) if struct.unpack_from('<I', section, 4)[0] == 6}
keep |= dynamic | {struct.unpack_from('<I', sections[i], 40)[0] for i in dynamic} | {names}
table = b''.join(section if i in keep else bytes(width) for i, section in enumerate(sections))
at = (len(original) + 7) & ~7
retained = bytearray(original + bytes(at - len(original)) + table)
struct.pack_into('<Q', retained, 40, at)
absent = bytearray(original)
struct.pack_into('<Q', absent, 40, 0)
struct.pack_into('<HH', absent, 60, 0, 0)
variants = {'original': original, 'retained-sections': retained, 'no-section-table': absent}
phoff = struct.unpack_from('<Q', original, 32)[0]
phwidth, phcount = struct.unpack_from('<HH', original, 54)
for image in variants.values():
    assert image[phoff:phoff + phwidth * phcount] == original[phoff:phoff + phwidth * phcount]
    for index in range(phcount):
        ph = phoff + index * phwidth
        if struct.unpack_from('<I', original, ph)[0] == 2:
            offset = struct.unpack_from('<Q', original, ph + 8)[0]
            size = struct.unpack_from('<Q', original, ph + 32)[0]
            assert image[offset:offset + size] == original[offset:offset + size]
home = root / 'home'
home.mkdir(exist_ok=True)
environment = dict(os.environ, HOME=str(home), TMPDIR=str(root), XDG_CONFIG_HOME=str(home / 'config'), XDG_CACHE_HOME=str(home / 'cache'))
results = []
for name, image in variants.items():
    path = root / (name + '.so')
    path.write_bytes(image)
    library = ctypes.CDLL(str(path))
    assert library.exported_answer() == 7
    assert all(bytes((ctypes.c_ubyte * len(data)).in_dll(library, symbol)) == data for symbol, data in exports.items())
    check = subprocess.run(['readelf', '--wide', '--headers', '--symbols', '--use-dynamic', str(path)], text=True, capture_output=True)
    (root / (name + '.readelf.txt')).write_text(check.stdout)
    (root / (name + '.readelf.stderr.txt')).write_text(check.stderr)
    assert check.returncode == 0 and check.stderr == ''
    assert all(symbol in check.stdout for symbol in exports)
    apk = root / (name + '.apk')
    with zipfile.ZipFile(apk, 'w') as archive:
        archive.writestr('AndroidManifest.xml', '<manifest package="example.demo"/>')
        archive.writestr('lib/x86_64/libapp.so', image)
    run = subprocess.run([node, str(entrypoint), 'inspect-dart-aot', str(apk), '--json'], env=environment, text=True, capture_output=True)
    (root / (name + '.stdout.json')).write_text(run.stdout)
    (root / (name + '.stderr.txt')).write_text(run.stderr)
    output = json.loads(run.stdout)
    value = output.get('normalized_result')
    result = {'variant': name, 'loader_exports_exact': True, 'readelf_exit': check.returncode, 'readelf_stderr': check.stderr, 'cli_exit': run.returncode, 'cli_stderr': run.stderr}
    result.update({'coverage': value['coverage'], 'sections': len(value['libapp']['sections']), 'sources': value['libapp']['snapshot_hash_sources'], 'hash': value['libapp']['snapshot_hash'], 'package_uris': value['string_pool']['package_uris']} if value else {'error_code': output['code'], 'reason': output['details']['reason']})
    results.append(result)
    print(json.dumps(result))
(root / 'results.json').write_text(json.dumps(results, indent=2))

Expected behavior

Resolve the same available dynamic symbols through PT_DYNAMIC when a retained section table does not describe them. The existing decoder already handles these exact symbols when the section table is absent. A missing section-table entry should not establish that a loader-visible symbol is missing.

The documented inspection contract locates these four symbols through the ELF dynamic symbol table. The ELF dynamic-section specification describes the program-header-owned dynamic linking metadata; runtime symbol resolution does not depend on enumerating SHT_DYNSYM section headers.

Impact and scope

The tested static inspection loses the snapshot-header facts and string projection for a loadable ELF even though its existing dynamic-table decoder can recover them. The failure is deterministic for the recorded fixture; no source artifact was modified by REA, and no REA crash occurred.

Observed scope is Linux x86_64, ELF64 little-endian, with old-style four-symbol names and authored marker bytes. Naturally distributed Flutter APKs, ELF32, other hosts, and MCP were not tested. This does not establish a production Flutter application incident or full snapshot semantic validity.

A verified workaround is to clear the section-table fields in a separate library copy and repack a disposable APK for inspection. That control recovers the same hash and URI while retaining all four exact marker exports. Keep the original artifact; the copy has a different artifact digest.

REA version

CLI output: 6.7.0. Tested source commit: d78892eb4ba41cf8746e5410b3ddf6e7f0ba524f.

Runtime and platform

Node.js v24.22.1; Linux 7.2.8-9-omarchy, x86_64; GCC 16.2.1; GNU readelf / Binutils 2.47; Python 3. No external analysis provider or Flutter installation was used.

Target and artifact context

Self-authored Linux ELF64 shared library packaged at lib/x86_64/libapp.so inside a ZIP APK with an inert manifest. Four exported byte arrays carry the supported marker header layout and a package URI. The retained directory preserves .dynstr, .text, .rodata, .dynamic, and .shstrtab at their original indexes; other entries are zero SHT_NULL slots. Dynamic-symbol section indexes still identify .text or .rodata, and .dynamic.sh_link still identifies .dynstr. No retained hash/version/relocation section header points at the omitted symbol-table slot. Program headers and PT_DYNAMIC bytes are unchanged.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Reduced observations from the final executed batch:

[
  {"variant":"original","loader_exports_exact":true,"readelf_exit":0,"readelf_stderr":"","cli_exit":0,"coverage":"complete","sections":4,"sources":2,"hash":"0123456789abcdef0123456789abcdef","package_uris":["package:demo/main.dart"]},
  {"variant":"retained-sections","loader_exports_exact":true,"readelf_exit":0,"readelf_stderr":"","cli_exit":1,"error_code":"unsupported_target"},
  {"variant":"no-section-table","loader_exports_exact":true,"readelf_exit":0,"readelf_stderr":"","cli_exit":0,"coverage":"complete","sections":4,"sources":2,"hash":"0123456789abcdef0123456789abcdef","package_uris":["package:demo/main.dart"]}
]

All three CLI calls had empty stderr. The failing result's reason was:

No recognizable Dart snapshot symbols were found: symbol _kDartVmSnapshotData is not in the dynamic symbol table; symbol _kDartVmSnapshotInstructions is not in the dynamic symbol table; symbol _kDartIsolateSnapshotData is not in the dynamic symbol table; symbol _kDartIsolateSnapshotInstructions is not in the dynamic symbol table

Each loader control returned 7 and byte-compared every exported marker array with its authored input. GNU readelf independently enumerated the same symbols, with no diagnostic. The script also compared every program header and complete PT_DYNAMIC span byte-for-byte with the original.

Typed outcome or recovery expected

Successful inspection of the supported exported header markers using the existing dynamic-table path, with the same source facts and coverage as the section-table-absent control. Do not diagnose loader-visible symbols as absent merely because their section-directory entry is unavailable.

Analysis or suspected cause

Source-derived: readElfHeader enables dynamicFallback only when both e_shoff and e_shnum are zero. readElfSymbols otherwise chooses the section-table branch, and the PT_DYNAMIC decoder is an exclusive else branch. A retained directory without SHT_DYNSYM therefore yields no symbol tables, despite a complete dynamic segment.

Additional context

Related #6792 concerns inspect-native-exports falsely claiming complete absence of exports through its separate native export parser. This report concerns inspect-dart-aot refusing inspection in src/flutter/DartElf.ts, whose dynamic-table decoder already succeeds on the full-section-absence control. Related closed #6768 concerns an ignored DT_NULL value; no such value is changed here. The new-symbol-name incompatibility in #3629 is also separate: this fixture uses the currently supported four names.

NOT_ENOUGH_INFO: the first affected version and prevalence in distributed APKs were not established. All verification finished before this draft was written; no probes were rerun afterward.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The real CLI refuses the tested loadable ELF layout and loses all AOT inspection output despite loader-visible exact exports and an existing decoder that recovers the same marker facts in the passing control. This is a bounded compatibility failure on an authored input, with no demonstrated production Flutter incident.
  • Workaround status: available
  • Workaround basis: The section-table-absent copy succeeds through the same public CLI, returning the same four sections, two sources, hash, and package URI; loader byte comparisons confirm the marker exports are preserved. Apply this only to a disposable library/APK copy and retain the original artifact and its digest.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6884 ## Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ## Area Native analysis or decompilation ## Observed behavior The public `inspect-dart-aot` CLI refuses an authored ELF64 shared library whose retained section directory omits `SHT_DYNSYM`, reporting that all four `_kDart*Snapshot*` symbols are absent. Its unchanged `PT_DYNAMIC` metadata still locates those symbols: the system loader resolves all four with their exact expected bytes, and `readelf --wide --headers --symbols --use-dynamic` exits 0 with empty stderr and lists them. The original library and a copy with no section table both return four sections, two agreeing hash sources, complete coverage, and `package:demo/main.dart`. Thus retaining otherwise usable section metadata disables an existing dynamic-table decoding path. This is a compiled, self-authored ELF containing marker arrays in the inspector's supported header layout. It is not a production Dart snapshot or a Flutter SDK build. ## Reproduction From the prepared source checkout at the revision below, set `REA_ENTRYPOINT` to its absolute `scripts/rea.mjs` path. Save this script outside the checkout as `/tmp/rea-flutter-repro.py`, then run `python3 /tmp/rea-flutter-repro.py "$REA_ENTRYPOINT" "$(command -v node)"` with Node 24.22.1 on PATH. It requires Linux x86_64, a C compiler, Python 3, and GNU readelf. It writes only a `final/` directory next to the script. The executed script compiles inert marker arrays and one function returning 7; only that self-authored function and loader symbol resolution execute. REA's inspection remains static. It checks the original, retained-section, and absent-section variants once each in the final recorded batch. ```python from pathlib import Path import ctypes, json, os, struct, subprocess, sys, zipfile root = Path(__file__).resolve().parent / 'final' root.mkdir(exist_ok=True) entrypoint = Path(sys.argv[1]).resolve() node = sys.argv[2] hash_bytes = b'0123456789abcdef0123456789abcdef' def snapshot(tail=b''): return b'\xf5\xf5\xdc\xdc' + struct.pack('<QQ', 48 + len(tail), 3) + hash_bytes + tail exports = { '_kDartVmSnapshotData': snapshot(), '_kDartVmSnapshotInstructions': bytes(16), '_kDartIsolateSnapshotData': snapshot(b'\0package:demo/main.dart\0dart:core\0DemoWidget\0'), '_kDartIsolateSnapshotInstructions': bytes(16), } source = '\n'.join('const unsigned char %s[] = {%s};' % (name, ','.join(map(str, data))) for name, data in exports.items()) (root / 'demo.c').write_text(source + '\nint exported_answer(void) { return 7; }\n') subprocess.run(['cc', '-shared', '-fPIC', '-nostdlib', '-Wl,--hash-style=both', '-o', str(root / 'original.so'), str(root / 'demo.c')], check=True) original = (root / 'original.so').read_bytes() assert original[:7] == b'\x7fELF\x02\x01\x01' shoff = struct.unpack_from('<Q', original, 40)[0] width, count, names = struct.unpack_from('<HHH', original, 58) sections = [original[shoff + i * width:shoff + (i + 1) * width] for i in range(count)] dynsym = next(section for section in sections if struct.unpack_from('<I', section, 4)[0] == 11) symoff, symsize = struct.unpack_from('<QQ', dynsym, 24) keep = {struct.unpack_from('<H', original, at + 6)[0] for at in range(symoff, symoff + symsize, 24)} - {0} dynamic = {i for i, section in enumerate(sections) if struct.unpack_from('<I', section, 4)[0] == 6} keep |= dynamic | {struct.unpack_from('<I', sections[i], 40)[0] for i in dynamic} | {names} table = b''.join(section if i in keep else bytes(width) for i, section in enumerate(sections)) at = (len(original) + 7) & ~7 retained = bytearray(original + bytes(at - len(original)) + table) struct.pack_into('<Q', retained, 40, at) absent = bytearray(original) struct.pack_into('<Q', absent, 40, 0) struct.pack_into('<HH', absent, 60, 0, 0) variants = {'original': original, 'retained-sections': retained, 'no-section-table': absent} phoff = struct.unpack_from('<Q', original, 32)[0] phwidth, phcount = struct.unpack_from('<HH', original, 54) for image in variants.values(): assert image[phoff:phoff + phwidth * phcount] == original[phoff:phoff + phwidth * phcount] for index in range(phcount): ph = phoff + index * phwidth if struct.unpack_from('<I', original, ph)[0] == 2: offset = struct.unpack_from('<Q', original, ph + 8)[0] size = struct.unpack_from('<Q', original, ph + 32)[0] assert image[offset:offset + size] == original[offset:offset + size] home = root / 'home' home.mkdir(exist_ok=True) environment = dict(os.environ, HOME=str(home), TMPDIR=str(root), XDG_CONFIG_HOME=str(home / 'config'), XDG_CACHE_HOME=str(home / 'cache')) results = [] for name, image in variants.items(): path = root / (name + '.so') path.write_bytes(image) library = ctypes.CDLL(str(path)) assert library.exported_answer() == 7 assert all(bytes((ctypes.c_ubyte * len(data)).in_dll(library, symbol)) == data for symbol, data in exports.items()) check = subprocess.run(['readelf', '--wide', '--headers', '--symbols', '--use-dynamic', str(path)], text=True, capture_output=True) (root / (name + '.readelf.txt')).write_text(check.stdout) (root / (name + '.readelf.stderr.txt')).write_text(check.stderr) assert check.returncode == 0 and check.stderr == '' assert all(symbol in check.stdout for symbol in exports) apk = root / (name + '.apk') with zipfile.ZipFile(apk, 'w') as archive: archive.writestr('AndroidManifest.xml', '<manifest package="example.demo"/>') archive.writestr('lib/x86_64/libapp.so', image) run = subprocess.run([node, str(entrypoint), 'inspect-dart-aot', str(apk), '--json'], env=environment, text=True, capture_output=True) (root / (name + '.stdout.json')).write_text(run.stdout) (root / (name + '.stderr.txt')).write_text(run.stderr) output = json.loads(run.stdout) value = output.get('normalized_result') result = {'variant': name, 'loader_exports_exact': True, 'readelf_exit': check.returncode, 'readelf_stderr': check.stderr, 'cli_exit': run.returncode, 'cli_stderr': run.stderr} result.update({'coverage': value['coverage'], 'sections': len(value['libapp']['sections']), 'sources': value['libapp']['snapshot_hash_sources'], 'hash': value['libapp']['snapshot_hash'], 'package_uris': value['string_pool']['package_uris']} if value else {'error_code': output['code'], 'reason': output['details']['reason']}) results.append(result) print(json.dumps(result)) (root / 'results.json').write_text(json.dumps(results, indent=2)) ``` ## Expected behavior Resolve the same available dynamic symbols through `PT_DYNAMIC` when a retained section table does not describe them. The existing decoder already handles these exact symbols when the section table is absent. A missing section-table entry should not establish that a loader-visible symbol is missing. The [documented inspection contract](https://github.com/morluto/rea/blob/d78892eb4ba41cf8746e5410b3ddf6e7f0ba524f/docs/flutter-analysis.md#what-the-aot-inspection-returns) locates these four symbols through the ELF dynamic symbol table. The [ELF dynamic-section specification](https://gabi.xinuos.com/elf/08-dynamic.html#dynamic-section) describes the program-header-owned dynamic linking metadata; runtime symbol resolution does not depend on enumerating `SHT_DYNSYM` section headers. ## Impact and scope The tested static inspection loses the snapshot-header facts and string projection for a loadable ELF even though its existing dynamic-table decoder can recover them. The failure is deterministic for the recorded fixture; no source artifact was modified by REA, and no REA crash occurred. Observed scope is Linux x86_64, ELF64 little-endian, with old-style four-symbol names and authored marker bytes. Naturally distributed Flutter APKs, ELF32, other hosts, and MCP were not tested. This does not establish a production Flutter application incident or full snapshot semantic validity. A verified workaround is to clear the section-table fields in a separate library copy and repack a disposable APK for inspection. That control recovers the same hash and URI while retaining all four exact marker exports. Keep the original artifact; the copy has a different artifact digest. ## REA version CLI output: `6.7.0`. Tested source commit: `d78892eb4ba41cf8746e5410b3ddf6e7f0ba524f`. ## Runtime and platform Node.js `v24.22.1`; Linux `7.2.8-9-omarchy`, x86_64; GCC `16.2.1`; GNU readelf / Binutils `2.47`; Python 3. No external analysis provider or Flutter installation was used. ## Target and artifact context Self-authored Linux ELF64 shared library packaged at `lib/x86_64/libapp.so` inside a ZIP APK with an inert manifest. Four exported byte arrays carry the supported marker header layout and a package URI. The retained directory preserves `.dynstr`, `.text`, `.rodata`, `.dynamic`, and `.shstrtab` at their original indexes; other entries are zero `SHT_NULL` slots. Dynamic-symbol section indexes still identify `.text` or `.rodata`, and `.dynamic.sh_link` still identifies `.dynstr`. No retained hash/version/relocation section header points at the omitted symbol-table slot. Program headers and `PT_DYNAMIC` bytes are unchanged. ## Interface CLI ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence Reduced observations from the final executed batch: ```json [ {"variant":"original","loader_exports_exact":true,"readelf_exit":0,"readelf_stderr":"","cli_exit":0,"coverage":"complete","sections":4,"sources":2,"hash":"0123456789abcdef0123456789abcdef","package_uris":["package:demo/main.dart"]}, {"variant":"retained-sections","loader_exports_exact":true,"readelf_exit":0,"readelf_stderr":"","cli_exit":1,"error_code":"unsupported_target"}, {"variant":"no-section-table","loader_exports_exact":true,"readelf_exit":0,"readelf_stderr":"","cli_exit":0,"coverage":"complete","sections":4,"sources":2,"hash":"0123456789abcdef0123456789abcdef","package_uris":["package:demo/main.dart"]} ] ``` All three CLI calls had empty stderr. The failing result's reason was: ```text No recognizable Dart snapshot symbols were found: symbol _kDartVmSnapshotData is not in the dynamic symbol table; symbol _kDartVmSnapshotInstructions is not in the dynamic symbol table; symbol _kDartIsolateSnapshotData is not in the dynamic symbol table; symbol _kDartIsolateSnapshotInstructions is not in the dynamic symbol table ``` Each loader control returned 7 and byte-compared every exported marker array with its authored input. GNU readelf independently enumerated the same symbols, with no diagnostic. The script also compared every program header and complete `PT_DYNAMIC` span byte-for-byte with the original. ## Typed outcome or recovery expected Successful inspection of the supported exported header markers using the existing dynamic-table path, with the same source facts and coverage as the section-table-absent control. Do not diagnose loader-visible symbols as absent merely because their section-directory entry is unavailable. ## Analysis or suspected cause Source-derived: [`readElfHeader` enables `dynamicFallback` only when both `e_shoff` and `e_shnum` are zero](https://github.com/morluto/rea/blob/d78892eb4ba41cf8746e5410b3ddf6e7f0ba524f/src/flutter/DartElf.ts#L123). [`readElfSymbols` otherwise chooses the section-table branch](https://github.com/morluto/rea/blob/d78892eb4ba41cf8746e5410b3ddf6e7f0ba524f/src/flutter/DartElf.ts#L251), and [the `PT_DYNAMIC` decoder is an exclusive `else` branch](https://github.com/morluto/rea/blob/d78892eb4ba41cf8746e5410b3ddf6e7f0ba524f/src/flutter/DartElf.ts#L312). A retained directory without `SHT_DYNSYM` therefore yields no symbol tables, despite a complete dynamic segment. ## Additional context Related [#6792](https://github.com/morluto/rea/issues/6792) concerns `inspect-native-exports` falsely claiming complete absence of exports through its separate native export parser. This report concerns `inspect-dart-aot` refusing inspection in `src/flutter/DartElf.ts`, whose dynamic-table decoder already succeeds on the full-section-absence control. Related closed [#6768](https://github.com/morluto/rea/issues/6768) concerns an ignored `DT_NULL` value; no such value is changed here. The new-symbol-name incompatibility in [#3629](https://github.com/morluto/rea/issues/3629) is also separate: this fixture uses the currently supported four names. NOT_ENOUGH_INFO: the first affected version and prevalence in distributed APKs were not established. All verification finished before this draft was written; no probes were rerun afterward. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The real CLI refuses the tested loadable ELF layout and loses all AOT inspection output despite loader-visible exact exports and an existing decoder that recovers the same marker facts in the passing control. This is a bounded compatibility failure on an authored input, with no demonstrated production Flutter incident. - Workaround status: available - Workaround basis: The section-table-absent copy succeeds through the same public CLI, returning the same four sections, two sources, hash, and package URI; loader byte comparisons confirm the marker exports are preserved. Apply this only to a disposable library/APK copy and retain the original artifact and its digest.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4221
No description provided.