mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Wasm][Runtime] Interpret absolute function pointer in runtime structures
When SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER is enabled, relative direct pointers whose pointees are functions will be turned into absolute pointer at compile-time.
This commit is contained in:
62
include/swift/ABI/CompactFunctionPointer.h
Normal file
62
include/swift/ABI/CompactFunctionPointer.h
Normal file
@@ -0,0 +1,62 @@
|
||||
//===--- CompactFunctionPointer.h - Compact Function Pointers ---*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift's runtime structures often use relative function pointers to reduce the
|
||||
// size of metadata and also to minimize load-time overhead in PIC.
|
||||
// This file defines pointer types whose size and interface are compatible with
|
||||
// the relative pointer types for targets that do not support relative references
|
||||
// to code from data.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_ABI_COMPACTFUNCTIONPOINTER_H
|
||||
#define SWIFT_ABI_COMPACTFUNCTIONPOINTER_H
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// A compact unconditional absolute function pointer that can fit in a 32-bit
|
||||
/// integer.
|
||||
/// As a trade-off compared to relative pointers, this has load-time overhead in PIC
|
||||
/// and is only available on 32-bit targets.
|
||||
template <typename T>
|
||||
class AbsoluteFunctionPointer {
|
||||
T *Pointer;
|
||||
static_assert(sizeof(T *) == sizeof(int32_t),
|
||||
"Function pointer must be 32-bit when using compact absolute pointer");
|
||||
|
||||
public:
|
||||
using PointerTy = T *;
|
||||
|
||||
PointerTy get() const & { return Pointer; }
|
||||
|
||||
operator PointerTy() const & { return this->get(); }
|
||||
|
||||
bool isNull() const & { return Pointer == nullptr; }
|
||||
|
||||
/// Resolve a pointer from a `base` pointer and a value loaded from `base`.
|
||||
template <typename BasePtrTy, typename Value>
|
||||
static PointerTy resolve(BasePtrTy *base, Value value) {
|
||||
return reinterpret_cast<PointerTy>(value);
|
||||
}
|
||||
|
||||
template <typename... ArgTy>
|
||||
typename std::result_of<T *(ArgTy...)>::type operator()(ArgTy... arg) const {
|
||||
static_assert(std::is_function<T>::value,
|
||||
"T must be an explicit function type");
|
||||
return this->get()(std::forward<ArgTy>(arg)...);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO(katei): Add another pointer structure for 64-bit targets and for efficiency on PIC
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_ABI_COMPACTFUNCTIONPOINTER_H
|
||||
@@ -241,7 +241,7 @@ template <class AsyncSignature>
|
||||
class AsyncFunctionPointer {
|
||||
public:
|
||||
/// The function to run.
|
||||
RelativeDirectPointer<AsyncFunctionType<AsyncSignature>,
|
||||
TargetCompactFunctionPointer<InProcess, AsyncFunctionType<AsyncSignature>,
|
||||
/*nullable*/ false,
|
||||
int32_t> Function;
|
||||
|
||||
|
||||
@@ -506,9 +506,20 @@ struct TargetMethodDescriptor {
|
||||
MethodDescriptorFlags Flags;
|
||||
|
||||
/// The method implementation.
|
||||
TargetRelativeDirectPointer<Runtime, void> Impl;
|
||||
union {
|
||||
TargetCompactFunctionPointer<Runtime, void> Impl;
|
||||
TargetRelativeDirectPointer<Runtime, void> AsyncImpl;
|
||||
};
|
||||
|
||||
// TODO: add method types or anything else needed for reflection.
|
||||
|
||||
void *getImpl() const {
|
||||
if (Flags.isAsync()) {
|
||||
return AsyncImpl.get();
|
||||
} else {
|
||||
return Impl.get();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using MethodDescriptor = TargetMethodDescriptor<InProcess>;
|
||||
@@ -578,7 +589,20 @@ struct TargetMethodOverrideDescriptor {
|
||||
TargetRelativeMethodDescriptorPointer<Runtime> Method;
|
||||
|
||||
/// The implementation of the override.
|
||||
TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> Impl;
|
||||
union {
|
||||
TargetCompactFunctionPointer<Runtime, void, /*nullable*/ true> Impl;
|
||||
TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> AsyncImpl;
|
||||
};
|
||||
|
||||
void *getImpl() const {
|
||||
auto *baseMethod = Method.get();
|
||||
assert(baseMethod && "no base method");
|
||||
if (baseMethod->Flags.isAsync()) {
|
||||
return AsyncImpl.get();
|
||||
} else {
|
||||
return Impl.get();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Header for a class vtable override descriptor. This is a variable-sized
|
||||
@@ -1523,7 +1547,18 @@ struct TargetProtocolRequirement {
|
||||
// TODO: name, type
|
||||
|
||||
/// The optional default implementation of the protocol.
|
||||
RelativeDirectPointer<void, /*nullable*/ true> DefaultImplementation;
|
||||
union {
|
||||
TargetCompactFunctionPointer<Runtime, void, /*nullable*/ true> DefaultFuncImplementation;
|
||||
TargetRelativeDirectPointer<Runtime, void, /*nullable*/ true> DefaultImplementation;
|
||||
};
|
||||
|
||||
void *getDefaultImplementation() const {
|
||||
if (Flags.isFunctionImpl()) {
|
||||
return DefaultFuncImplementation.get();
|
||||
} else {
|
||||
return DefaultImplementation.get();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using ProtocolRequirement = TargetProtocolRequirement<InProcess>;
|
||||
@@ -2170,7 +2205,18 @@ using GenericBoxHeapMetadata = TargetGenericBoxHeapMetadata<InProcess>;
|
||||
template <typename Runtime>
|
||||
struct TargetResilientWitness {
|
||||
TargetRelativeProtocolRequirementPointer<Runtime> Requirement;
|
||||
RelativeDirectPointer<void> Witness;
|
||||
union {
|
||||
TargetRelativeDirectPointer<Runtime, void> Impl;
|
||||
TargetCompactFunctionPointer<Runtime, void> FuncImpl;
|
||||
};
|
||||
|
||||
void *getWitness(ProtocolRequirementFlags flags) const {
|
||||
if (flags.isFunctionImpl()) {
|
||||
return FuncImpl.get();
|
||||
} else {
|
||||
return Impl.get();
|
||||
}
|
||||
}
|
||||
};
|
||||
using ResilientWitness = TargetResilientWitness<InProcess>;
|
||||
|
||||
@@ -2233,10 +2279,13 @@ struct TargetGenericWitnessTable {
|
||||
uint16_t WitnessTablePrivateSizeInWordsAndRequiresInstantiation;
|
||||
|
||||
/// The instantiation function, which is called after the template is copied.
|
||||
RelativeDirectPointer<void(TargetWitnessTable<Runtime> *instantiatedTable,
|
||||
const TargetMetadata<Runtime> *type,
|
||||
const void * const *instantiationArgs),
|
||||
/*nullable*/ true> Instantiator;
|
||||
TargetCompactFunctionPointer<
|
||||
Runtime,
|
||||
void(TargetWitnessTable<Runtime> *instantiatedTable,
|
||||
const TargetMetadata<Runtime> *type,
|
||||
const void *const *instantiationArgs),
|
||||
/*nullable*/ true>
|
||||
Instantiator;
|
||||
|
||||
using PrivateDataType = void *[swift::NumGenericMetadataPrivateDataWords];
|
||||
|
||||
@@ -2968,12 +3017,12 @@ using MetadataCompleter =
|
||||
template <typename Runtime>
|
||||
struct TargetGenericMetadataPattern {
|
||||
/// The function to call to instantiate the template.
|
||||
TargetRelativeDirectPointer<Runtime, MetadataInstantiator>
|
||||
TargetCompactFunctionPointer<Runtime, MetadataInstantiator>
|
||||
InstantiationFunction;
|
||||
|
||||
/// The function to call to complete the instantiation. If this is null,
|
||||
/// the instantiation function must always generate complete metadata.
|
||||
TargetRelativeDirectPointer<Runtime, MetadataCompleter, /*nullable*/ true>
|
||||
TargetCompactFunctionPointer<Runtime, MetadataCompleter, /*nullable*/ true>
|
||||
CompletionFunction;
|
||||
|
||||
/// Flags describing the layout of this instantiation pattern.
|
||||
@@ -3080,10 +3129,10 @@ struct TargetGenericClassMetadataPattern final :
|
||||
using TargetGenericMetadataPattern<Runtime>::PatternFlags;
|
||||
|
||||
/// The heap-destructor function.
|
||||
TargetRelativeDirectPointer<Runtime, HeapObjectDestroyer> Destroy;
|
||||
TargetCompactFunctionPointer<Runtime, HeapObjectDestroyer> Destroy;
|
||||
|
||||
/// The ivar-destructor function.
|
||||
TargetRelativeDirectPointer<Runtime, ClassIVarDestroyer, /*nullable*/ true>
|
||||
TargetCompactFunctionPointer<Runtime, ClassIVarDestroyer, /*nullable*/ true>
|
||||
IVarDestroyer;
|
||||
|
||||
/// The class flags.
|
||||
@@ -3284,7 +3333,7 @@ private:
|
||||
template <typename Runtime>
|
||||
struct TargetForeignMetadataInitialization {
|
||||
/// The completion function. The pattern will always be null.
|
||||
TargetRelativeDirectPointer<Runtime, MetadataCompleter, /*nullable*/ true>
|
||||
TargetCompactFunctionPointer<Runtime, MetadataCompleter, /*nullable*/ true>
|
||||
CompletionFunction;
|
||||
};
|
||||
|
||||
@@ -3329,14 +3378,14 @@ struct TargetResilientClassMetadataPattern {
|
||||
///
|
||||
/// If this is null, the runtime instead calls swift_relocateClassMetadata(),
|
||||
/// passing in the class descriptor and this pattern.
|
||||
TargetRelativeDirectPointer<Runtime, MetadataRelocator, /*nullable*/ true>
|
||||
TargetCompactFunctionPointer<Runtime, MetadataRelocator, /*nullable*/ true>
|
||||
RelocationFunction;
|
||||
|
||||
/// The heap-destructor function.
|
||||
TargetRelativeDirectPointer<Runtime, HeapObjectDestroyer> Destroy;
|
||||
TargetCompactFunctionPointer<Runtime, HeapObjectDestroyer> Destroy;
|
||||
|
||||
/// The ivar-destructor function.
|
||||
TargetRelativeDirectPointer<Runtime, ClassIVarDestroyer, /*nullable*/ true>
|
||||
TargetCompactFunctionPointer<Runtime, ClassIVarDestroyer, /*nullable*/ true>
|
||||
IVarDestroyer;
|
||||
|
||||
/// The class flags.
|
||||
@@ -3380,7 +3429,7 @@ struct TargetSingletonMetadataInitialization {
|
||||
|
||||
/// The completion function. The pattern will always be null, even
|
||||
/// for a resilient class.
|
||||
TargetRelativeDirectPointer<Runtime, MetadataCompleter>
|
||||
TargetCompactFunctionPointer<Runtime, MetadataCompleter>
|
||||
CompletionFunction;
|
||||
|
||||
bool hasResilientClassPattern(
|
||||
@@ -3409,7 +3458,7 @@ struct TargetCanonicalSpecializedMetadatasListEntry {
|
||||
|
||||
template <typename Runtime>
|
||||
struct TargetCanonicalSpecializedMetadataAccessorsListEntry {
|
||||
TargetRelativeDirectPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false> accessor;
|
||||
TargetCompactFunctionPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false> accessor;
|
||||
};
|
||||
|
||||
template <typename Runtime>
|
||||
@@ -3429,7 +3478,7 @@ public:
|
||||
/// The function type here is a stand-in. You should use getAccessFunction()
|
||||
/// to wrap the function pointer in an accessor that uses the proper calling
|
||||
/// convention for a given number of arguments.
|
||||
TargetRelativeDirectPointer<Runtime, MetadataResponse(...),
|
||||
TargetCompactFunctionPointer<Runtime, MetadataResponse(...),
|
||||
/*Nullable*/ true> AccessFunctionPtr;
|
||||
|
||||
/// A pointer to the field descriptor for the type, if any.
|
||||
@@ -3694,7 +3743,7 @@ public:
|
||||
using MetadataListEntry =
|
||||
TargetCanonicalSpecializedMetadatasListEntry<Runtime>;
|
||||
using MetadataAccessor =
|
||||
TargetRelativeDirectPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false>;
|
||||
TargetCompactFunctionPointer<Runtime, MetadataResponse(MetadataRequest), /*Nullable*/ false>;
|
||||
using MetadataAccessorListEntry =
|
||||
TargetCanonicalSpecializedMetadataAccessorsListEntry<Runtime>;
|
||||
using MetadataCachingOnceToken =
|
||||
@@ -4495,12 +4544,23 @@ class DynamicReplacementDescriptor {
|
||||
DynamicReplacementKey *
|
||||
__ptrauth_swift_dynamic_replacement_key>>
|
||||
replacedFunctionKey;
|
||||
RelativeDirectPointer<void, false> replacementFunction;
|
||||
union {
|
||||
TargetCompactFunctionPointer<InProcess, void, false> replacementFunction;
|
||||
TargetRelativeDirectPointer<InProcess, void, false> replacementAsyncFunction;
|
||||
};
|
||||
RelativeDirectPointer<DynamicReplacementChainEntry, false> chainEntry;
|
||||
uint32_t flags;
|
||||
|
||||
enum : uint32_t { EnableChainingMask = 0x1 };
|
||||
|
||||
void *getReplacementFunction() const {
|
||||
if (replacedFunctionKey->isAsync()) {
|
||||
return replacementAsyncFunction.get();
|
||||
} else {
|
||||
return replacementFunction.get();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/// Enable this replacement by changing the function's replacement chain's
|
||||
/// root entry.
|
||||
|
||||
@@ -611,6 +611,21 @@ public:
|
||||
|
||||
int_type getIntValue() const { return Value; }
|
||||
|
||||
/// Is the method implementation is represented as a native function pointer?
|
||||
bool isFunctionImpl() const {
|
||||
switch (getKind()) {
|
||||
case ProtocolRequirementFlags::Kind::Method:
|
||||
case ProtocolRequirementFlags::Kind::Init:
|
||||
case ProtocolRequirementFlags::Kind::Getter:
|
||||
case ProtocolRequirementFlags::Kind::Setter:
|
||||
case ProtocolRequirementFlags::Kind::ReadCoroutine:
|
||||
case ProtocolRequirementFlags::Kind::ModifyCoroutine:
|
||||
return !isAsync();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum : uintptr_t {
|
||||
/// Bit used to indicate that an associated type witness is a pointer to
|
||||
/// a mangled name (vs. a pointer to metadata).
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "swift/Runtime/Config.h"
|
||||
#include "swift/Basic/RelativePointer.h"
|
||||
#include "swift/ABI/CompactFunctionPointer.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
@@ -101,6 +102,14 @@ struct InProcess {
|
||||
template <typename T, bool Nullable = true>
|
||||
using RelativeDirectPointer = RelativeDirectPointer<T, Nullable>;
|
||||
|
||||
template <typename T, bool Nullable = true, typename Offset = int32_t>
|
||||
#if SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER
|
||||
using CompactFunctionPointer = AbsoluteFunctionPointer<T>;
|
||||
#else
|
||||
using CompactFunctionPointer =
|
||||
swift::RelativeDirectPointer<T, Nullable, Offset>;
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
T *getStrippedSignedPointer(const T *pointer) const {
|
||||
return swift_ptrauth_strip(pointer);
|
||||
@@ -163,6 +172,9 @@ struct External {
|
||||
template <typename T, bool Nullable = true>
|
||||
using RelativeDirectPointer = int32_t;
|
||||
|
||||
template <typename T, bool Nullable = true, typename Offset = int32_t>
|
||||
using CompactFunctionPointer = int32_t;
|
||||
|
||||
StoredPointer getStrippedSignedPointer(const StoredSignedPointer pointer) const {
|
||||
return swift_ptrauth_strip(pointer);
|
||||
}
|
||||
@@ -191,6 +203,12 @@ template <typename Runtime, typename Pointee, bool Nullable = true>
|
||||
using TargetRelativeIndirectablePointer
|
||||
= typename Runtime::template RelativeIndirectablePointer<Pointee,Nullable>;
|
||||
|
||||
template <typename Runtime, typename Pointee, bool Nullable = true,
|
||||
typename Offset = int32_t>
|
||||
using TargetCompactFunctionPointer =
|
||||
typename Runtime::template CompactFunctionPointer<Pointee, Nullable,
|
||||
Offset>;
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
|
||||
@@ -386,6 +386,10 @@ public:
|
||||
/// position-independent constant data.
|
||||
template<typename T, bool Nullable, typename Offset>
|
||||
class RelativeDirectPointerImpl {
|
||||
#if SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER
|
||||
static_assert(!std::is_function<T>::value,
|
||||
"relative direct function pointer should not be used under absolute function pointer mode");
|
||||
#endif
|
||||
private:
|
||||
/// The relative offset of the function's entry point from *this.
|
||||
Offset RelativeOffset;
|
||||
@@ -454,19 +458,25 @@ public:
|
||||
|
||||
/// Apply the offset to a parameter, instead of `this`.
|
||||
PointerTy getRelative(void *base) const & {
|
||||
// Check for null.
|
||||
if (Nullable && RelativeOffset == 0)
|
||||
return nullptr;
|
||||
|
||||
// The value is addressed relative to `base`.
|
||||
uintptr_t absolute = detail::applyRelativeOffset(base, RelativeOffset);
|
||||
return reinterpret_cast<PointerTy>(absolute);
|
||||
return resolve(base, RelativeOffset);
|
||||
}
|
||||
|
||||
/// A zero relative offset encodes a null reference.
|
||||
bool isNull() const & {
|
||||
return RelativeOffset == 0;
|
||||
}
|
||||
|
||||
/// Resolve a pointer from a `base` pointer and a value loaded from `base`.
|
||||
template<typename BasePtrTy>
|
||||
static PointerTy resolve(BasePtrTy *base, Offset value) {
|
||||
// Check for null.
|
||||
if (Nullable && value == 0)
|
||||
return nullptr;
|
||||
|
||||
// The value is addressed relative to `base`.
|
||||
uintptr_t absolute = detail::applyRelativeOffset(base, value);
|
||||
return reinterpret_cast<PointerTy>(absolute);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, bool Nullable = true, typename Offset = int32_t,
|
||||
@@ -502,6 +512,7 @@ public:
|
||||
}
|
||||
|
||||
using super::isNull;
|
||||
using super::resolve;
|
||||
};
|
||||
|
||||
/// A specialization of RelativeDirectPointer for function pointers,
|
||||
@@ -548,6 +559,7 @@ public:
|
||||
}
|
||||
|
||||
using super::isNull;
|
||||
using super::resolve;
|
||||
};
|
||||
|
||||
/// A direct relative reference to an aligned object, with an additional
|
||||
|
||||
@@ -248,6 +248,16 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
|
||||
#define SWIFT_VFORMAT(fmt)
|
||||
#endif
|
||||
|
||||
/// Should we use absolute function pointers instead of relative ones?
|
||||
/// WebAssembly target uses it by default.
|
||||
#ifndef SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER
|
||||
# if defined(__wasm__)
|
||||
# define SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER 1
|
||||
# else
|
||||
# define SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Pointer authentication.
|
||||
#if __has_feature(ptrauth_calls)
|
||||
#define SWIFT_PTRAUTH 1
|
||||
|
||||
@@ -302,6 +302,10 @@ function(_add_target_variant_c_compile_flags)
|
||||
list(APPEND result "-DSWIFT_OBJC_INTEROP=0")
|
||||
endif()
|
||||
|
||||
if(SWIFT_STDLIB_COMPACT_ABSOLUTE_FUNCTION_POINTER)
|
||||
list(APPEND result "-DSWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER=1")
|
||||
endif()
|
||||
|
||||
if(SWIFT_STDLIB_STABLE_ABI)
|
||||
list(APPEND result "-DSWIFT_LIBRARY_EVOLUTION=1")
|
||||
else()
|
||||
|
||||
@@ -73,6 +73,10 @@ option(SWIFT_STDLIB_STABLE_ABI
|
||||
"Should stdlib be built with stable ABI (library evolution, resilience)."
|
||||
"${SWIFT_STDLIB_STABLE_ABI_default}")
|
||||
|
||||
option(SWIFT_STDLIB_COMPACT_ABSOLUTE_FUNCTION_POINTER
|
||||
"Force compact function pointer to always be absolute mainly for WebAssembly"
|
||||
FALSE)
|
||||
|
||||
option(SWIFT_ENABLE_MODULE_INTERFACES
|
||||
"Generate .swiftinterface files alongside .swiftmodule files"
|
||||
"${SWIFT_STDLIB_STABLE_ABI}")
|
||||
|
||||
@@ -269,6 +269,10 @@ function(_add_target_variant_swift_compile_flags
|
||||
list(APPEND result "-D" "INTERNAL_CHECKS_ENABLED")
|
||||
endif()
|
||||
|
||||
if(SWIFT_STDLIB_COMPACT_ABSOLUTE_FUNCTION_POINTER)
|
||||
list(APPEND result "-D" "SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER")
|
||||
endif()
|
||||
|
||||
if(SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY)
|
||||
list(APPEND result "-D" "SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY")
|
||||
endif()
|
||||
|
||||
@@ -2615,7 +2615,7 @@ internal func _resolveKeyPathGenericArgReference(
|
||||
var offset: Int32 = 0
|
||||
_memcpy(dest: &offset, src: pointerReference, size: 4)
|
||||
|
||||
let accessorPtrRaw = _resolveRelativeAddress(pointerReference, offset)
|
||||
let accessorPtrRaw = _resolveCompactFunctionPointer(pointerReference, offset)
|
||||
let accessorPtrSigned =
|
||||
_PtrAuth.sign(pointer: accessorPtrRaw,
|
||||
key: .processIndependentCode,
|
||||
@@ -2714,6 +2714,16 @@ internal func _resolveRelativeIndirectableAddress(_ base: UnsafeRawPointer,
|
||||
}
|
||||
return _resolveRelativeAddress(base, offset)
|
||||
}
|
||||
|
||||
internal func _resolveCompactFunctionPointer(_ base: UnsafeRawPointer, _ offset: Int32)
|
||||
-> UnsafeRawPointer {
|
||||
#if SWIFT_COMPACT_ABSOLUTE_FUNCTION_POINTER
|
||||
return UnsafeRawPointer(bitPattern: Int(offset)).unsafelyUnwrapped
|
||||
#else
|
||||
return _resolveRelativeAddress(base, offset)
|
||||
#endif
|
||||
}
|
||||
|
||||
internal func _loadRelativeAddress<T>(at: UnsafeRawPointer,
|
||||
fromByteOffset: Int = 0,
|
||||
as: T.Type) -> T {
|
||||
@@ -2780,12 +2790,12 @@ internal func _walkKeyPathPattern<W: KeyPathPatternVisitor>(
|
||||
let idValue = _pop(from: &componentBuffer, as: Int32.self)
|
||||
let getterBase = componentBuffer.baseAddress.unsafelyUnwrapped
|
||||
let getterRef = _pop(from: &componentBuffer, as: Int32.self)
|
||||
let getter = _resolveRelativeAddress(getterBase, getterRef)
|
||||
let getter = _resolveCompactFunctionPointer(getterBase, getterRef)
|
||||
let setter: UnsafeRawPointer?
|
||||
if header.isComputedSettable {
|
||||
let setterBase = componentBuffer.baseAddress.unsafelyUnwrapped
|
||||
let setterRef = _pop(from: &componentBuffer, as: Int32.self)
|
||||
setter = _resolveRelativeAddress(setterBase, setterRef)
|
||||
setter = _resolveCompactFunctionPointer(setterBase, setterRef)
|
||||
} else {
|
||||
setter = nil
|
||||
}
|
||||
@@ -2799,7 +2809,7 @@ internal func _walkKeyPathPattern<W: KeyPathPatternVisitor>(
|
||||
if header.hasComputedArguments {
|
||||
let getLayoutBase = componentBuffer.baseAddress.unsafelyUnwrapped
|
||||
let getLayoutRef = _pop(from: &componentBuffer, as: Int32.self)
|
||||
let getLayoutRaw = _resolveRelativeAddress(getLayoutBase, getLayoutRef)
|
||||
let getLayoutRaw = _resolveCompactFunctionPointer(getLayoutBase, getLayoutRef)
|
||||
let getLayoutSigned = _PtrAuth.sign(pointer: getLayoutRaw,
|
||||
key: .processIndependentCode,
|
||||
discriminator: _PtrAuth.discriminator(for: KeyPathComputedArgumentLayoutFn.self))
|
||||
@@ -2817,8 +2827,8 @@ internal func _walkKeyPathPattern<W: KeyPathPatternVisitor>(
|
||||
|
||||
let initializerBase = componentBuffer.baseAddress.unsafelyUnwrapped
|
||||
let initializerRef = _pop(from: &componentBuffer, as: Int32.self)
|
||||
let initializerRaw = _resolveRelativeAddress(initializerBase,
|
||||
initializerRef)
|
||||
let initializerRaw = _resolveCompactFunctionPointer(initializerBase,
|
||||
initializerRef)
|
||||
let initializerSigned = _PtrAuth.sign(pointer: initializerRaw,
|
||||
key: .processIndependentCode,
|
||||
discriminator: _PtrAuth.discriminator(for: KeyPathComputedArgumentInitializerFn.self))
|
||||
|
||||
@@ -2762,7 +2762,7 @@ static void initClassVTable(ClassMetadata *self) {
|
||||
for (unsigned i = 0, e = vtable->VTableSize; i < e; ++i) {
|
||||
auto &methodDescription = descriptors[i];
|
||||
swift_ptrauth_init_code_or_data(
|
||||
&classWords[vtableOffset + i], methodDescription.Impl.get(),
|
||||
&classWords[vtableOffset + i], methodDescription.getImpl(),
|
||||
methodDescription.Flags.getExtraDiscriminator(),
|
||||
!methodDescription.Flags.isAsync());
|
||||
}
|
||||
@@ -2802,9 +2802,8 @@ static void initClassVTable(ClassMetadata *self) {
|
||||
auto baseVTable = baseClass->getVTableDescriptor();
|
||||
auto offset = (baseVTable->getVTableOffset(baseClass) +
|
||||
(baseMethod - baseClassMethods.data()));
|
||||
|
||||
swift_ptrauth_init_code_or_data(&classWords[offset],
|
||||
descriptor.Impl.get(),
|
||||
descriptor.getImpl(),
|
||||
baseMethod->Flags.getExtraDiscriminator(),
|
||||
!baseMethod->Flags.isAsync());
|
||||
}
|
||||
@@ -5139,7 +5138,7 @@ static void initializeResilientWitnessTable(
|
||||
|
||||
auto &reqt = requirements[reqDescriptor - requirements.begin()];
|
||||
// This is an unsigned pointer formed from a relative address.
|
||||
void *impl = witness.Witness.get();
|
||||
void *impl = witness.getWitness(reqt.Flags);
|
||||
initProtocolWitness(&table[witnessIndex], impl, reqt);
|
||||
}
|
||||
|
||||
@@ -5153,7 +5152,7 @@ static void initializeResilientWitnessTable(
|
||||
auto &reqt = requirements[i];
|
||||
if (!table[witnessIndex]) {
|
||||
// This is an unsigned pointer formed from a relative address.
|
||||
void *impl = reqt.DefaultImplementation.get();
|
||||
void *impl = reqt.getDefaultImplementation();
|
||||
initProtocolWitness(&table[witnessIndex], impl, reqt);
|
||||
}
|
||||
|
||||
@@ -5622,7 +5621,7 @@ static const WitnessTable *swift_getAssociatedConformanceWitnessSlowImpl(
|
||||
// Resolve the relative reference to the witness function.
|
||||
int32_t offset;
|
||||
memcpy(&offset, mangledName.data() + 1, 4);
|
||||
uintptr_t ptr = detail::applyRelativeOffset(mangledName.data() + 1, offset);
|
||||
void *ptr = TargetCompactFunctionPointer<InProcess, void>::resolve(mangledName.data() + 1, offset);
|
||||
|
||||
// Call the witness function.
|
||||
AssociatedWitnessTableAccessFunction *witnessFn;
|
||||
|
||||
@@ -76,7 +76,16 @@ static uintptr_t resolveSymbolicReferenceOffset(SymbolicReferenceKind kind,
|
||||
Directness isIndirect,
|
||||
int32_t offset,
|
||||
const void *base) {
|
||||
auto ptr = detail::applyRelativeOffset(base, offset);
|
||||
uintptr_t ptr;
|
||||
// Function references may be resolved differently than other data references.
|
||||
switch (kind) {
|
||||
case SymbolicReferenceKind::AccessorFunctionReference:
|
||||
ptr = (uintptr_t)TargetCompactFunctionPointer<InProcess, void>::resolve(base, offset);
|
||||
break;
|
||||
default:
|
||||
ptr = detail::applyRelativeOffset(base, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
// Indirect references may be authenticated in a way appropriate for the
|
||||
// referent.
|
||||
@@ -2600,10 +2609,10 @@ void DynamicReplacementDescriptor::enableReplacement() const {
|
||||
|
||||
// Link the replacement entry.
|
||||
chainRoot->next = chainEntry.get();
|
||||
// chainRoot->implementationFunction = replacementFunction.get();
|
||||
// chainRoot->implementationFunction = getReplacementFunction();
|
||||
swift_ptrauth_init_code_or_data(
|
||||
reinterpret_cast<void **>(&chainRoot->implementationFunction),
|
||||
reinterpret_cast<void *>(replacementFunction.get()),
|
||||
reinterpret_cast<void *>(getReplacementFunction()),
|
||||
replacedFunctionKey->getExtraDiscriminator(),
|
||||
!replacedFunctionKey->isAsync());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user