@@ -118,12 +118,62 @@ struct TypedExternal {
118
118
template <typename T, bool Nullable = true , typename Offset = int32_t >
119
119
using CompactFunctionPointer = TypedInteger<T, int32_t , Nullable>;
120
120
121
+ template <unsigned discriminator>
122
+ struct ValueWitnessFunctionPointer {
123
+ StoredPointer pointer;
124
+ };
125
+
121
126
StoredPointer
122
127
getStrippedSignedPointer (const StoredSignedPointer pointer) const {
123
128
return swift_ptrauth_strip (pointer);
124
129
}
125
130
};
126
131
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
+
127
177
template <typename T>
128
178
inline MetadataKind getEnumeratedMetadataKind (T kind,
129
179
decltype (kind.value) dummy = 0) {
@@ -189,6 +239,26 @@ class ReaderWriter;
189
239
190
240
template <typename Runtime>
191
241
class 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
+
192
262
struct Atom ;
193
263
194
264
struct FileTarget {
@@ -208,6 +278,10 @@ class ExternalGenericMetadataBuilderContext {
208
278
unsigned offset;
209
279
unsigned size;
210
280
281
+ PtrauthKey ptrauthKey;
282
+ bool addressDiversified;
283
+ unsigned discriminator;
284
+
211
285
std::variant<FileTarget, AtomTarget> fileOrAtom;
212
286
};
213
287
@@ -513,7 +587,10 @@ class ExternalGenericMetadataBuilderContext {
513
587
}
514
588
515
589
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 ) {
517
594
if (!value) {
518
595
memset (where, 0 , sizeof (StoredPointer));
519
596
return ;
@@ -531,6 +608,10 @@ class ExternalGenericMetadataBuilderContext {
531
608
532
609
target.size = sizeof (StoredPointer);
533
610
611
+ target.ptrauthKey = ptrauthKey;
612
+ target.addressDiversified = addressDiversified;
613
+ target.discriminator = discriminator;
614
+
534
615
if (auto *file = value.file ) {
535
616
auto contents = value.section .getContents ();
536
617
if (!contents) {
@@ -625,7 +706,9 @@ class ExternalGenericMetadataBuilderContext {
625
706
checkPtr (where);
626
707
where->SignedValue .value = ~(uintptr_t )value.ptr ;
627
708
628
- writePointerImpl (where, value);
709
+ writePointerImpl (where, value, PtrauthInfo<U>::key,
710
+ PtrauthInfo<U>::addressDiversified,
711
+ PtrauthInfo<U>::discriminator);
629
712
}
630
713
631
714
template <typename U>
@@ -639,6 +722,15 @@ class ExternalGenericMetadataBuilderContext {
639
722
void writeFunctionPointer (void *where, Buffer<const char > target) {
640
723
writePointer (reinterpret_cast <StoredPointer *>(where), target);
641
724
}
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
+ }
642
734
};
643
735
644
736
ExternalGenericMetadataBuilderContext () {
@@ -669,7 +761,11 @@ class ExternalGenericMetadataBuilderContext {
669
761
return allocate<T>(count * sizeof (T));
670
762
}
671
763
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
+
673
769
void setNamesToBuild (const std::vector<std::string> &names) {
674
770
this ->mangledNamesToBuild = names;
675
771
}
@@ -736,6 +832,9 @@ class ExternalGenericMetadataBuilderContext {
736
832
// The architecture being targeted.
737
833
std::string arch;
738
834
835
+ // Does this target use pointer authentication?
836
+ bool usePtrauth = false ;
837
+
739
838
// The readerWriter and builder helper objects.
740
839
std::unique_ptr<ReaderWriter<Runtime>> readerWriter;
741
840
std::unique_ptr<Builder> builder;
@@ -2152,6 +2251,14 @@ void ExternalGenericMetadataBuilderContext<Runtime>::writeAtomContentsJSON(
2152
2251
J.attribute (" addend" , atomTarget.offset );
2153
2252
J.attribute (" kind" , ptrTargetKind);
2154
2253
}
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
+ }
2155
2262
});
2156
2263
2157
2264
bufferCursor = targetsCursor->offset + targetsCursor->size ;
@@ -2311,16 +2418,11 @@ BuilderErrorOr<unsigned> getPointerWidth(std::string arch) {
2311
2418
2312
2419
} // namespace swift
2313
2420
2314
- using ExternalRuntime32 =
2315
- swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<4 >>>;
2316
- using ExternalRuntime64 =
2317
- swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<8 >>>;
2318
-
2319
2421
struct SwiftExternalMetadataBuilder {
2320
2422
using Builder32 =
2321
- swift::ExternalGenericMetadataBuilderContext<ExternalRuntime32>;
2423
+ swift::ExternalGenericMetadataBuilderContext<swift:: ExternalRuntime32>;
2322
2424
using Builder64 =
2323
- swift::ExternalGenericMetadataBuilderContext<ExternalRuntime64>;
2425
+ swift::ExternalGenericMetadataBuilderContext<swift:: ExternalRuntime64>;
2324
2426
2325
2427
std::variant<Builder32, Builder64> context;
2326
2428
0 commit comments