[IRGen] ObjC metadata and block PAC signing for arm64e#88114
Draft
oskarwirga wants to merge 4 commits intoswiftlang:mainfrom
Draft
[IRGen] ObjC metadata and block PAC signing for arm64e#88114oskarwirga wants to merge 4 commits intoswiftlang:mainfrom
oskarwirga wants to merge 4 commits intoswiftlang:mainfrom
Conversation
Sign isa, superclass, and class_ro pointers in class/metaclass metadata using ObjCIsaPointers (DA, disc 0x6AE1), ObjCSuperPointers (DA, disc 0xB5AB), and ObjCClassROPointers (DA, disc 0) schemas respectively. On arm64e, the ObjC runtime expects these pointers to be signed. Without signing, loading a Swift class that inherits from NSObject (or any ObjC class) causes a ptrauth failure when the runtime tries to authenticate the isa or superclass pointer during class realization. Key changes: - Change ObjCClassStructTy layout to use OpaquePtrTy for the class_ro field (matching Clang's ClassnfABITy) to enable addSignedPointer. - Sign metaclass isa, class isa (metaclass pointer), superclass, and class_ro pointers with appropriate ptrauth schemas. - Move type descriptor signing to the singleton metadata access call site to avoid double-signing when the runtime passes pre-signed descriptors to generic instantiation functions. - Add isProtocolRequirementDescriptor() and isValueWitnessTable() predicates to LinkEntity for use by later patches. addSignedPointer with an empty schema falls back to an unsigned add, so non-arm64e targets are completely unaffected.
On arm64e, the ObjC runtime signs isa pointers stored in object headers using the DA key with address diversity and discriminator 0x6AE1. When Swift loads the isa for vtable dispatch (IsaEncoding::Pointer path), the raw load returns a PAC-signed pointer that must be authenticated before use as a metadata base address. Use the PointerAuthInfo/emitPointerAuthAuth abstraction layer to authenticate the isa pointer against the ObjCIsaPointers schema, matching the pattern used in GenFunc.cpp for block isa signing. For the ObjC isa encoding path, bypass the swift_isaMask inline masking approach when the ObjCIsaPointers schema is active and use object_getClass() instead. The mask-based extraction doesn't handle PAC bits, producing a corrupted metadata pointer that crashes on subsequent access.
Only sign method list pointers for class and category metadata, not protocol metadata. The ObjC runtime's fixupProtocolMethodList uses plain ldr (no auth) on protocol method lists, while fixupMethodList authenticates class method lists with autda. Add a !isBuildingProtocol() guard to the method list pointer signing code path. Without this guard, Swift-emitted @objc protocol metadata has signed method list pointers that the runtime attempts to dereference without authentication, causing EXC_BAD_ACCESS during protocol fixup at image load time. Also switch the metaclass metadata builder in GenClass.cpp from using ConstantStruct::get to ConstantInitBuilder, which enables proper ptrauth signing of isa, superclass, and class_ro pointers in the metaclass struct on arm64e (matching the GenMeta.cpp approach).
Swift IRGen's emitBlockHeader stored __NSConcreteStackBlock as the block's isa without ptrauth signing. On arm64e, objc_msgSend authenticates all isa pointers with autda(DA, blend(addr, 0x6AE1)). An unsigned isa causes EXC_BAD_ACCESS (code=261) -- the canonical PAC authentication failure. Sign the isa using the ObjCIsaPointers schema (DA key, disc 0x6AE1, address-diversified), matching Clang's EmitPointerAuthObjCISA behavior in CGObjC.cpp. This fixes crashes when Swift @convention(block) closures with captures are passed to ObjC APIs that subsequently send messages to the block.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Discriminator values come from Apple's objc-ptrauth.h. addSignedPointer with an empty schema falls back to unsigned add, so non-arm64e targets are unaffected.
Test plan
@swift-ci Please smoke test