From 22b0f64ddc2b9f165b2d4ba3a859fc881ca4383f Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Wed, 22 Apr 2026 17:19:21 +0800 Subject: [PATCH] release: 0.11.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor release superseding the planned 0.10.1: - Picks up the parallel-test SymbolIndexStore data race fix (@Mutex on demangledNodeBySymbol) — lets --no-parallel / @Suite(.serialized) be dropped again. - Picks up ABI-accurate Swift section readers — __swift5_types and __swift5_protos indirect entries are now read correctly, via the new public types TypeMetadataRecord / ProtocolRecord / RelativeDirectPointerIntPair. - Carries forward everything planned for 0.10.1: generic-context dispatch signal-11 fix, swift-demangling 0.3.0 async-API migration, version-check CI, KNOWN_ISSUES race annotations. Changelogs/0.11.0.md consolidates all of the above. --- Changelogs/0.11.0.md | 67 +++++++++++++++++++++++++++++ Sources/swift-section/Version.swift | 2 +- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 Changelogs/0.11.0.md diff --git a/Changelogs/0.11.0.md b/Changelogs/0.11.0.md new file mode 100644 index 00000000..7ed6865c --- /dev/null +++ b/Changelogs/0.11.0.md @@ -0,0 +1,67 @@ +# 0.11.0 + +## Highlights + +Minor release on top of `0.10.0`, folding in the previously-planned `0.10.1` content plus the parallel-test race fix and a set of ABI-accurate Swift section readers. + +Headline items: + +1. Fixes the parallel-test `SymbolIndexStore` data race (previously tracked in `KNOWN_ISSUES.md`) that surfaced intermittently as SIGSEGV or as `.invalidContextDescriptor` failures on CI. +2. Swift section readers now mirror the ABI in `swift/include/swift/ABI/Metadata.h` — `__swift5_types` / `__swift5_protos` indirect entries are read correctly (previously misread as direct pointers, which on cross-module binaries produced garbage context-descriptor kinds). +3. Carries forward the generic-context dispatch signal-11 fix and the `swift-demangling` 0.3.0 async-API migration originally planned for `0.10.1`. + +## Bug Fixes + +### Generic context dispatch (signal-11 crash) + +- The `ReadingContext` overload of `genericContext(in:)` introduced during the reading-context refactor was declared as a protocol extension only, with no override on `TypeContextDescriptorProtocol`. Calls through `any ContextDescriptorProtocol` therefore statically dispatched to the base implementation, which built a `TargetGenericContext` (8-byte header) even when the descriptor was a `StructDescriptor` / `ClassDescriptor` / `EnumDescriptor`. Those descriptors actually start with `TypeGenericContextDescriptorHeader` (16 bytes — two relative offsets preceding the `base` header), so the read was misaligned by 8 bytes. The misaligned bytes usually surfaced as a garbage `valueHeader.numValues` of ~`UInt32.max`, after which `readWrapperElements` walked ~4 billion fabricated `GenericValueDescriptor` slots and crashed with `EXC_BAD_ACCESS`. + - Promoted `genericContext(in:)` and `parent(in:)` to protocol requirements on `ContextDescriptorProtocol` so they participate in witness-table dispatch. + - Added matching overrides on `TypeContextDescriptorProtocol` that route through `typeGenericContext(in:)?.asGenericContext()`, mirroring the `MachOSwiftSectionRepresentableWithCache` path. + - Mirrored the new overloads on `TypeContextDescriptorWrapper` / `ValueTypeDescriptorWrapper` for API parity. + - Resolves `EXC_BAD_ACCESS` in `MultiPayloadEnumTests` and in `GenericSpecializationTests.main` via `SwiftInterfaceIndexer.indexTypes`. + +### `SymbolIndexStore` parallel-test data race + +- `Storage.demangledNodeBySymbol` was previously a plain `Dictionary` mutated by `setDemangledNode(_:for:)` without synchronization. When swift-testing ran sibling suites in parallel, two builders could concurrently hit a cache miss on the same `SymbolIndexStore.Storage`; both would insert into the dictionary, and the unsynchronized read+write corrupted its internal layout — surfacing intermittently as `NSInvalidArgumentException: -[NSTaggedPointerString objectForKey:]`, SIGSEGV in the hash lookup, or later as `.invalidContextDescriptor` when the trashed bytes were reinterpreted as context-descriptor flags. +- Fixed by guarding the dictionary with `@Mutex` (`FrameworkToolbox` / `SwiftStdlibToolbox`). The CI workaround (`--no-parallel` and `@Suite(.serialized)`) is no longer needed and has been removed. This moves the entry out of `KNOWN_ISSUES.md` "deferred". + +### `__swift5_types` / `__swift5_protos` indirect entries + +- The generic section reader was reading every entry as `RelativeDirectPointer`. Per the ABI (`swift/include/swift/ABI/Metadata.h:2720, 2766`), entries in these sections are tagged pointers — the low bits encode a `TypeReferenceKind` (for `__swift5_types`) or an indirect flag + reserved bit (for `__swift5_protos`). On a cross-module binary any entry emitted as `IndirectTypeDescriptor` (see the direct-vs-indirect decision at `lib/IRGen/GenDecl.cpp:4195-4224`) was read at the wrong offset, producing a descriptor pointer to unrelated bytes and surfacing as `.invalidContextDescriptor`. +- Readers now decode the ABI correctly: `TypeMetadataRecord` branches on `TypeReferenceKind` to pick direct / indirect resolution (and drops ObjC kinds to `nil`, matching the runtime `nullptr` fallback at `Metadata.h:2753`); `ProtocolRecord` uses `RelativeIndirectablePointerIntPair` with nullable `Optional` pointee to match `MetadataRef.h:109`. Both `MachOFile.Swift` and `MachOImage.Swift` readers now throw strictly on error and are symmetric across ends. + +## Library + +New public types for downstream section-level analysis: + +- `TypeMetadataRecord` (`Models/Type/TypeMetadataRecord.swift`) — mirrors `TargetTypeMetadataRecord`; one per entry of `__swift5_types` / `__swift5_types2`, with a `contextDescriptor(in:)` method that branches on `TypeReferenceKind`. +- `ProtocolRecord` (`Models/Protocol/ProtocolRecord.swift`) — mirrors `TargetProtocolRecord`; one per entry of `__swift5_protos`, with a `protocolDescriptor(in:)` accessor. +- `RelativeDirectPointerIntPair` / `TargetRelativeDirectPointerIntPair` / `RelativeDirectPointerIntPairProtocol` (`MachOPointers`) — mirror `swift/include/swift/Basic/RelativePointer.h:575-619`. The int-tagged direct relative pointer variant needed to express `TypeMetadataRecord`'s layout; distinct from the existing `RelativeIndirectablePointerIntPair` (low 2 bits = int value, no indirect bit). +- The shape of `MachOFile.Swift.contextDescriptors` / `protocolDescriptors` / `protocolConformanceDescriptors` is unchanged (same return types). + +## Dependencies + +- **`swift-demangling` minimum bumped to `0.3.0`**. 0.3.0 makes `Node.print`, `demangleAsNode`, and `mangleAsString` async (with stack-safe execution) and adds the `DemanglingTestingSupport` module. Call sites in `SwiftDump`, `SwiftInterface`, and the test suites have been migrated to `await` the new entry points. Downstream consumers using these public demangling APIs will need to `await` them as well. + +## CI + +- Added `GenericSpecializationTests`, `MultiPayloadEnumTests`, and `MetadataReaderDemanglingTests` to the macOS matrix filter so future regressions in the generic-context dispatch path or the section reader path surface in CI instead of as local crashes. `GenericSpecializerAPITests` was folded into `GenericSpecializationTests`, and the corresponding filter entry removed. +- `Sources/swift-section/Version.swift` is the single source of truth for the CLI version: + - `release.yml` no longer injects the version via heredoc; it fails a tagged release when `BundledVersion.value != github.ref_name`. + - A new `version-check.yml` workflow runs on every push to `main` and every PR, and fails when `Changelogs/.md` does not exist. + - The extraction shell is whitespace-tolerant and guards `grep`'s exit status so formatter changes cannot silently break the check. + - Source builds (including Homebrew's source path) now report the correct version without depending on CI injection. + +## Docs + +- Corrected MachOKit version in the `0.10.0` notes: `0.49.100` (based on upstream `0.49.0`), not `0.47.100`. +- `KNOWN_ISSUES.md` annotated recent CI runs that reproduced the `SymbolIndexStore.demangledNode` data race so its flaky, parallel-harness-only nature was easier to recognize during triage. A follow-up will move that entry to the "fixed" section once `0.11.0` has been green across a few CI runs. + +## Requirements + +- Swift 6.2+ +- Xcode 26.0+ (CI validates on Xcode 26.4 / macOS 26) + +## Known Issues + +See [KNOWN_ISSUES.md](https://github.com/MxIris-Reverse-Engineering/MachOSwiftSection/blob/0.11.0/KNOWN_ISSUES.md). The `SymbolIndexStore.demangledNode` race is resolved in this release; the SharedCache global-lock item remains deferred. diff --git a/Sources/swift-section/Version.swift b/Sources/swift-section/Version.swift index 55c0728b..e3a09db4 100644 --- a/Sources/swift-section/Version.swift +++ b/Sources/swift-section/Version.swift @@ -2,5 +2,5 @@ // When bumping: also add Changelogs/.md, then tag the release with the same string. // Verified by .github/workflows/version-check.yml (PR) and .github/workflows/release.yml (tag). enum BundledVersion { - static let value = "0.10.0" + static let value = "0.11.0" }