@@ -118,12 +118,62 @@ struct TypedExternal {
118118 template <typename T, bool Nullable = true , typename Offset = int32_t >
119119 using CompactFunctionPointer = TypedInteger<T, int32_t , Nullable>;
120120
121+ template <unsigned discriminator>
122+ struct ValueWitnessFunctionPointer {
123+ StoredPointer pointer;
124+ };
125+
121126 StoredPointer
122127 getStrippedSignedPointer (const StoredSignedPointer pointer) const {
123128 return swift_ptrauth_strip (pointer);
124129 }
125130};
126131
132+ using ExternalRuntime32 =
133+ swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<4 >>>;
134+ using ExternalRuntime64 =
135+ swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<8 >>>;
136+
137+ // Declare a specialized version of the value witness types that use a wrapper
138+ // on the functions that captures the ptrauth discriminator.
139+ template <>
140+ class TargetValueWitnessTypes <ExternalRuntime64> {
141+ public:
142+ using StoredPointer = typename ExternalRuntime64::StoredPointer;
143+
144+ #define WANT_ALL_VALUE_WITNESSES
145+ #define DATA_VALUE_WITNESS (lowerId, upperId, type )
146+ #define FUNCTION_VALUE_WITNESS (lowerId, upperId, returnType, paramTypes ) \
147+ typedef ExternalRuntime64::ValueWitnessFunctionPointer< \
148+ SpecialPointerAuthDiscriminators::upperId> \
149+ lowerId;
150+ #define MUTABLE_VALUE_TYPE TargetPointer<ExternalRuntime64, OpaqueValue>
151+ #define IMMUTABLE_VALUE_TYPE ConstTargetPointer<ExternalRuntime64, OpaqueValue>
152+ #define MUTABLE_BUFFER_TYPE TargetPointer<ExternalRuntime64, ValueBuffer>
153+ #define IMMUTABLE_BUFFER_TYPE ConstTargetPointer<ExternalRuntime64, ValueBuffer>
154+ #define TYPE_TYPE ConstTargetPointer<ExternalRuntime64, Metadata>
155+ #define SIZE_TYPE StoredSize
156+ #define INT_TYPE int
157+ #define UINT_TYPE unsigned
158+ #define VOID_TYPE void
159+ #include " swift/ABI/ValueWitness.def"
160+
161+ // Handle the data witnesses explicitly so we can use more specific
162+ // types for the flags enums.
163+ typedef size_t size;
164+ typedef size_t stride;
165+ typedef TargetValueWitnessFlags<typename ExternalRuntime64::StoredSize> flags;
166+ typedef uint32_t extraInhabitantCount;
167+ };
168+
169+ enum class PtrauthKey : int8_t {
170+ None = -1 ,
171+ IA = 0 ,
172+ IB = 1 ,
173+ DA = 2 ,
174+ DB = 3 ,
175+ };
176+
127177template <typename T>
128178inline MetadataKind getEnumeratedMetadataKind (T kind,
129179 decltype (kind.value) dummy = 0) {
@@ -189,6 +239,26 @@ class ReaderWriter;
189239
190240template <typename Runtime>
191241class ExternalGenericMetadataBuilderContext {
242+ // Structs that provide the ptrauth info for pointers to specific tyeps.
243+ template <typename Target>
244+ struct PtrauthInfo ;
245+
246+ template <>
247+ struct PtrauthInfo <const TargetValueTypeDescriptor<Runtime>> {
248+ static constexpr PtrauthKey key = PtrauthKey::DA;
249+ static constexpr bool addressDiversified = true ;
250+ static constexpr unsigned discriminator =
251+ SpecialPointerAuthDiscriminators::TypeDescriptor;
252+ };
253+
254+ template <>
255+ struct PtrauthInfo <const TargetValueWitnessTable<Runtime>> {
256+ static constexpr PtrauthKey key = PtrauthKey::DA;
257+ static constexpr bool addressDiversified = true ;
258+ static constexpr unsigned discriminator =
259+ SpecialPointerAuthDiscriminators::ValueWitnessTable;
260+ };
261+
192262 struct Atom ;
193263
194264 struct FileTarget {
@@ -208,6 +278,10 @@ class ExternalGenericMetadataBuilderContext {
208278 unsigned offset;
209279 unsigned size;
210280
281+ PtrauthKey ptrauthKey;
282+ bool addressDiversified;
283+ unsigned discriminator;
284+
211285 std::variant<FileTarget, AtomTarget> fileOrAtom;
212286 };
213287
@@ -513,7 +587,10 @@ class ExternalGenericMetadataBuilderContext {
513587 }
514588
515589 template <typename U>
516- void writePointerImpl (void *where, Buffer<U> value) {
590+ void writePointerImpl (void *where, Buffer<U> value,
591+ PtrauthKey ptrauthKey = PtrauthKey::None,
592+ bool addressDiversified = true ,
593+ unsigned discriminator = 0 ) {
517594 if (!value) {
518595 memset (where, 0 , sizeof (StoredPointer));
519596 return ;
@@ -531,6 +608,10 @@ class ExternalGenericMetadataBuilderContext {
531608
532609 target.size = sizeof (StoredPointer);
533610
611+ target.ptrauthKey = ptrauthKey;
612+ target.addressDiversified = addressDiversified;
613+ target.discriminator = discriminator;
614+
534615 if (auto *file = value.file ) {
535616 auto contents = value.section .getContents ();
536617 if (!contents) {
@@ -625,7 +706,9 @@ class ExternalGenericMetadataBuilderContext {
625706 checkPtr (where);
626707 where->SignedValue .value = ~(uintptr_t )value.ptr ;
627708
628- writePointerImpl (where, value);
709+ writePointerImpl (where, value, PtrauthInfo<U>::key,
710+ PtrauthInfo<U>::addressDiversified,
711+ PtrauthInfo<U>::discriminator);
629712 }
630713
631714 template <typename U>
@@ -639,6 +722,15 @@ class ExternalGenericMetadataBuilderContext {
639722 void writeFunctionPointer (void *where, Buffer<const char > target) {
640723 writePointer (reinterpret_cast <StoredPointer *>(where), target);
641724 }
725+
726+ template <unsigned discriminator>
727+ void writeFunctionPointer (
728+ ExternalRuntime64::ValueWitnessFunctionPointer<discriminator> *where,
729+ Buffer<const char > target) {
730+ checkPtr (where);
731+
732+ writePointerImpl (where, target, PtrauthKey::IA, true , discriminator);
733+ }
642734 };
643735
644736 ExternalGenericMetadataBuilderContext () {
@@ -669,7 +761,11 @@ class ExternalGenericMetadataBuilderContext {
669761 return allocate<T>(count * sizeof (T));
670762 }
671763
672- void setArch (const char *arch) { this ->arch = arch; }
764+ void setArch (const char *arch) {
765+ this ->arch = arch;
766+ this ->usePtrauth = this ->arch == " arm64e" ;
767+ }
768+
673769 void setNamesToBuild (const std::vector<std::string> &names) {
674770 this ->mangledNamesToBuild = names;
675771 }
@@ -736,6 +832,9 @@ class ExternalGenericMetadataBuilderContext {
736832 // The architecture being targeted.
737833 std::string arch;
738834
835+ // Does this target use pointer authentication?
836+ bool usePtrauth = false ;
837+
739838 // The readerWriter and builder helper objects.
740839 std::unique_ptr<ReaderWriter<Runtime>> readerWriter;
741840 std::unique_ptr<Builder> builder;
@@ -2152,6 +2251,14 @@ void ExternalGenericMetadataBuilderContext<Runtime>::writeAtomContentsJSON(
21522251 J.attribute (" addend" , atomTarget.offset );
21532252 J.attribute (" kind" , ptrTargetKind);
21542253 }
2254+
2255+ if (usePtrauth && targetsCursor->ptrauthKey != PtrauthKey::None) {
2256+ J.attributeObject (" authPtr" , [&] {
2257+ J.attribute (" key" , static_cast <uint8_t >(targetsCursor->ptrauthKey ));
2258+ J.attribute (" addr" , targetsCursor->addressDiversified );
2259+ J.attribute (" diversity" , targetsCursor->discriminator );
2260+ });
2261+ }
21552262 });
21562263
21572264 bufferCursor = targetsCursor->offset + targetsCursor->size ;
@@ -2311,16 +2418,11 @@ BuilderErrorOr<unsigned> getPointerWidth(std::string arch) {
23112418
23122419} // namespace swift
23132420
2314- using ExternalRuntime32 =
2315- swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<4 >>>;
2316- using ExternalRuntime64 =
2317- swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<8 >>>;
2318-
23192421struct SwiftExternalMetadataBuilder {
23202422 using Builder32 =
2321- swift::ExternalGenericMetadataBuilderContext<ExternalRuntime32>;
2423+ swift::ExternalGenericMetadataBuilderContext<swift:: ExternalRuntime32>;
23222424 using Builder64 =
2323- swift::ExternalGenericMetadataBuilderContext<ExternalRuntime64>;
2425+ swift::ExternalGenericMetadataBuilderContext<swift:: ExternalRuntime64>;
23242426
23252427 std::variant<Builder32, Builder64> context;
23262428
0 commit comments