Replace dlsym of swift_task_isCurrentGlobalActor with a constructor hook

Following the approach taken with the concurrency-specific type
descriptors, register a hook function for the "is current global actor"
check used for isolated conformances.
This commit is contained in:
Doug Gregor
2025-03-06 15:03:26 -08:00
parent c266a0965f
commit 6dd141ad54
13 changed files with 53 additions and 18 deletions

View File

@@ -1769,6 +1769,10 @@ namespace SpecialPointerAuthDiscriminators {
/// Isolated deinit body function pointer
const uint16_t DeinitWorkFunction = 0x8438; // = 33848
/// IsCurrentGlobalActor function used between the Swift runtime and
/// concurrency runtime.
const uint16_t IsCurrentGlobalActorFunction = 0xd1b8; // = 53688
}
/// The number of arguments that will be passed directly to a generic

View File

@@ -327,6 +327,9 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
#define __ptrauth_swift_deinit_work_function \
__ptrauth(ptrauth_key_function_pointer, 1, \
SpecialPointerAuthDiscriminators::DeinitWorkFunction)
#define __ptrauth_swift_is_global_actor_function \
__ptrauth(ptrauth_key_function_pointer, 1, \
SpecialPointerAuthDiscriminators::IsCurrentGlobalActorFunction)
#if __has_attribute(ptrauth_struct)
#define swift_ptrauth_struct(key, discriminator) \
@@ -368,6 +371,7 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
#define swift_ptrauth_sign_opaque_modify_resume_function(__fn, __buffer) (__fn)
#define __ptrauth_swift_type_layout_string
#define __ptrauth_swift_deinit_work_function
#define __ptrauth_swift_is_global_actor_function
#define swift_ptrauth_struct(key, discriminator)
#define swift_ptrauth_struct_derived(from)
#endif

View File

@@ -1057,11 +1057,20 @@ struct ConcurrencyStandardTypeDescriptors {
#include "swift/Demangling/StandardTypesMangling.def"
};
/// Register the type descriptors with standard manglings from the Concurrency
/// runtime. The passed-in struct must be immortal.
/// Function that determines whether we are executing on the given global
/// actor. The metadata is for the global actor type, and the witness table
/// is the conformance of that type to the GlobalActor protocol.
typedef bool (* SWIFT_CC(swift) IsCurrentGlobalActor)(const Metadata *, const WitnessTable *);
/// Register various concurrency-related data and hooks needed in the Swift
/// standard library / runtime. This includes type descriptors with standard
/// manglings from the Concurrency runtime as well as a hook to check whether
/// we are running on a specific global actor. Any pointers passed in here must
/// be immortal.
SWIFT_RUNTIME_STDLIB_SPI
void _swift_registerConcurrencyStandardTypeDescriptors(
const ConcurrencyStandardTypeDescriptors *descriptors);
void _swift_registerConcurrencyRuntime(
const ConcurrencyStandardTypeDescriptors *descriptors,
IsCurrentGlobalActor isCurrentGlobalActor);
/// Initialize the value witness table for a struct using the provided like type
/// as the basis for the layout.

View File

@@ -33,6 +33,11 @@
MANGLING, DESCRIPTOR_MANGLING_SUFFIX(KIND));
#include "swift/Demangling/StandardTypesMangling.def"
// Defined in Swift, redeclared here so we can register it with the runtime.
extern "C" SWIFT_CC(swift)
bool _swift_task_isCurrentGlobalActor(
const swift::Metadata *, const swift::WitnessTable *);
// Register our type descriptors with standard manglings when the concurrency
// runtime is loaded. This allows the runtime to quickly resolve those standard
// manglings.
@@ -43,5 +48,7 @@ __attribute__((constructor)) static void setupStandardConcurrencyDescriptors() {
&DESCRIPTOR_MANGLING(MANGLING, DESCRIPTOR_MANGLING_SUFFIX(KIND)),
#include "swift/Demangling/StandardTypesMangling.def"
};
_swift_registerConcurrencyStandardTypeDescriptors(&descriptors);
_swift_registerConcurrencyRuntime(
&descriptors,
&_swift_task_isCurrentGlobalActor);
}

View File

@@ -1549,8 +1549,7 @@ internal func _taskIsCurrentExecutor(
extension GlobalActor {
@available(SwiftStdlib 6.2, *)
@_silgen_name("swift_task_isCurrentGlobalActor")
@usableFromInline
@_silgen_name("_swift_task_isCurrentGlobalActor")
internal static func _taskIsCurrentGlobalActor() -> Bool {
let executor = unsafe sharedUnownedExecutor
return unsafe _taskIsCurrentExecutor(executor: executor.executor, flags: 0)

View File

@@ -1053,9 +1053,17 @@ _findContextDescriptor(Demangle::NodePointer node,
return foundContext;
}
void swift::_swift_registerConcurrencyStandardTypeDescriptors(
const ConcurrencyStandardTypeDescriptors *descriptors) {
/// Function to check whether we're currently running on the given global
/// actor.
bool (* __ptrauth_swift_is_global_actor_function SWIFT_CC(swift)
swift::_swift_task_isCurrentGlobalActorHook)(
const Metadata *, const WitnessTable *);
void swift::_swift_registerConcurrencyRuntime(
const ConcurrencyStandardTypeDescriptors *descriptors,
IsCurrentGlobalActor isCurrentGlobalActor) {
concurrencyDescriptors = descriptors;
_swift_task_isCurrentGlobalActorHook = isCurrentGlobalActor;
}
#pragma mark Protocol descriptor cache

View File

@@ -751,6 +751,13 @@ public:
id _quickLookObjectForPointer(void *value);
#endif
/// Hook function that calls into the concurrency library to check whether
/// we are currently executing the given global actor.
SWIFT_RUNTIME_LIBRARY_VISIBILITY
extern bool (* __ptrauth_swift_is_global_actor_function SWIFT_CC(swift)
_swift_task_isCurrentGlobalActorHook)(
const Metadata *, const WitnessTable *);
} // end namespace swift
#endif /* SWIFT_RUNTIME_PRIVATE_H */

View File

@@ -1190,13 +1190,11 @@ static bool _isExecutingInIsolationOfConformance(
// The concurrency library provides a function to check whether we
// are executing on the given global actor.
auto isCurrentGlobalActor = SWIFT_LAZY_CONSTANT(reinterpret_cast<bool (*)(const Metadata *, const WitnessTable *)>(
dlsym(RTLD_DEFAULT, "swift_task_isCurrentGlobalActor")));
if (!isCurrentGlobalActor)
if (!_swift_task_isCurrentGlobalActorHook)
return false;
// Check whether we are running on this global actor.
return isCurrentGlobalActor(globalActorType, globalActorWitnessTable);
return _swift_task_isCurrentGlobalActorHook(globalActorType, globalActorWitnessTable);
}
static bool _checkConformanceIsolation(

View File

@@ -997,7 +997,6 @@ _swift_task_getMainExecutor
_swift_task_hasTaskGroupStatusRecord
_swift_task_isCancelled
_swift_task_isCurrentExecutor
_swift_task_isCurrentGlobalActor
_swift_task_isOnExecutor
_swift_task_isOnExecutor_hook
_swift_task_localValueGet

View File

@@ -13415,7 +13415,7 @@ __swift_makeAnyHashableUpcastingToHashableBaseType
__swift_modifyAtReferenceWritableKeyPath_impl
__swift_modifyAtWritableKeyPath_impl
__swift_objcClassUsesNativeSwiftReferenceCounting
__swift_registerConcurrencyStandardTypeDescriptors
__swift_registerConcurrencyRuntime
__swift_release
__swift_release_n
__swift_reportFatalErrorsToDebugger

View File

@@ -13504,7 +13504,7 @@ __swift_makeAnyHashableUpcastingToHashableBaseType
__swift_modifyAtReferenceWritableKeyPath_impl
__swift_modifyAtWritableKeyPath_impl
__swift_objcClassUsesNativeSwiftReferenceCounting
__swift_registerConcurrencyStandardTypeDescriptors
__swift_registerConcurrencyRuntime
__swift_release
__swift_release_n
__swift_reportFatalErrorsToDebugger

View File

@@ -13373,7 +13373,7 @@ __swift_makeAnyHashableUpcastingToHashableBaseType
__swift_modifyAtReferenceWritableKeyPath_impl
__swift_modifyAtWritableKeyPath_impl
__swift_objcClassUsesNativeSwiftReferenceCounting
__swift_registerConcurrencyStandardTypeDescriptors
__swift_registerConcurrencyRuntime
__swift_release
__swift_release_n
__swift_reportFatalErrorsToDebugger

View File

@@ -13462,7 +13462,7 @@ __swift_makeAnyHashableUpcastingToHashableBaseType
__swift_modifyAtReferenceWritableKeyPath_impl
__swift_modifyAtWritableKeyPath_impl
__swift_objcClassUsesNativeSwiftReferenceCounting
__swift_registerConcurrencyStandardTypeDescriptors
__swift_registerConcurrencyRuntime
__swift_release
__swift_release_n
__swift_reportFatalErrorsToDebugger