@@ -117,12 +117,62 @@ struct TypedExternal {
117
117
template <typename T, bool Nullable = true , typename Offset = int32_t >
118
118
using CompactFunctionPointer = TypedInteger<T, int32_t , Nullable>;
119
119
120
+ template <unsigned discriminator>
121
+ struct ValueWitnessFunctionPointer {
122
+ StoredPointer pointer;
123
+ };
124
+
120
125
StoredPointer
121
126
getStrippedSignedPointer (const StoredSignedPointer pointer) const {
122
127
return swift_ptrauth_strip (pointer);
123
128
}
124
129
};
125
130
131
+ using ExternalRuntime32 =
132
+ swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<4 >>>;
133
+ using ExternalRuntime64 =
134
+ swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<8 >>>;
135
+
136
+ // Declare a specialized version of the value witness types that use a wrapper
137
+ // on the functions that captures the ptrauth discriminator.
138
+ template <>
139
+ class TargetValueWitnessTypes <ExternalRuntime64> {
140
+ public:
141
+ using StoredPointer = typename ExternalRuntime64::StoredPointer;
142
+
143
+ #define WANT_ALL_VALUE_WITNESSES
144
+ #define DATA_VALUE_WITNESS (lowerId, upperId, type )
145
+ #define FUNCTION_VALUE_WITNESS (lowerId, upperId, returnType, paramTypes ) \
146
+ typedef ExternalRuntime64::ValueWitnessFunctionPointer< \
147
+ SpecialPointerAuthDiscriminators::upperId> \
148
+ lowerId;
149
+ #define MUTABLE_VALUE_TYPE TargetPointer<ExternalRuntime64, OpaqueValue>
150
+ #define IMMUTABLE_VALUE_TYPE ConstTargetPointer<ExternalRuntime64, OpaqueValue>
151
+ #define MUTABLE_BUFFER_TYPE TargetPointer<ExternalRuntime64, ValueBuffer>
152
+ #define IMMUTABLE_BUFFER_TYPE ConstTargetPointer<ExternalRuntime64, ValueBuffer>
153
+ #define TYPE_TYPE ConstTargetPointer<ExternalRuntime64, Metadata>
154
+ #define SIZE_TYPE StoredSize
155
+ #define INT_TYPE int
156
+ #define UINT_TYPE unsigned
157
+ #define VOID_TYPE void
158
+ #include " swift/ABI/ValueWitness.def"
159
+
160
+ // Handle the data witnesses explicitly so we can use more specific
161
+ // types for the flags enums.
162
+ typedef size_t size;
163
+ typedef size_t stride;
164
+ typedef TargetValueWitnessFlags<typename ExternalRuntime64::StoredSize> flags;
165
+ typedef uint32_t extraInhabitantCount;
166
+ };
167
+
168
+ enum class PtrauthKey : int8_t {
169
+ None = -1 ,
170
+ IA = 0 ,
171
+ IB = 1 ,
172
+ DA = 2 ,
173
+ DB = 3 ,
174
+ };
175
+
126
176
template <typename T>
127
177
inline MetadataKind getEnumeratedMetadataKind (T kind,
128
178
decltype (kind.value) dummy = 0) {
@@ -188,6 +238,26 @@ class ReaderWriter;
188
238
189
239
template <typename Runtime>
190
240
class ExternalGenericMetadataBuilderContext {
241
+ // Structs that provide the ptrauth info for pointers to specific tyeps.
242
+ template <typename Target>
243
+ struct PtrauthInfo ;
244
+
245
+ template <>
246
+ struct PtrauthInfo <const TargetValueTypeDescriptor<Runtime>> {
247
+ static constexpr PtrauthKey key = PtrauthKey::DA;
248
+ static constexpr bool addressDiversified = true ;
249
+ static constexpr unsigned discriminator =
250
+ SpecialPointerAuthDiscriminators::TypeDescriptor;
251
+ };
252
+
253
+ template <>
254
+ struct PtrauthInfo <const TargetValueWitnessTable<Runtime>> {
255
+ static constexpr PtrauthKey key = PtrauthKey::DA;
256
+ static constexpr bool addressDiversified = true ;
257
+ static constexpr unsigned discriminator =
258
+ SpecialPointerAuthDiscriminators::ValueWitnessTable;
259
+ };
260
+
191
261
struct Atom ;
192
262
193
263
struct FileTarget {
@@ -207,6 +277,10 @@ class ExternalGenericMetadataBuilderContext {
207
277
unsigned offset;
208
278
unsigned size;
209
279
280
+ PtrauthKey ptrauthKey;
281
+ bool addressDiversified;
282
+ unsigned discriminator;
283
+
210
284
std::variant<FileTarget, AtomTarget> fileOrAtom;
211
285
};
212
286
@@ -512,7 +586,10 @@ class ExternalGenericMetadataBuilderContext {
512
586
}
513
587
514
588
template <typename U>
515
- void writePointerImpl (void *where, Buffer<U> value) {
589
+ void writePointerImpl (void *where, Buffer<U> value,
590
+ PtrauthKey ptrauthKey = PtrauthKey::None,
591
+ bool addressDiversified = true ,
592
+ unsigned discriminator = 0 ) {
516
593
if (!value) {
517
594
memset (where, 0 , sizeof (StoredPointer));
518
595
return ;
@@ -530,6 +607,10 @@ class ExternalGenericMetadataBuilderContext {
530
607
531
608
target.size = sizeof (StoredPointer);
532
609
610
+ target.ptrauthKey = ptrauthKey;
611
+ target.addressDiversified = addressDiversified;
612
+ target.discriminator = discriminator;
613
+
533
614
if (auto *file = value.file ) {
534
615
auto contents = value.section .getContents ();
535
616
if (!contents) {
@@ -624,7 +705,9 @@ class ExternalGenericMetadataBuilderContext {
624
705
checkPtr (where);
625
706
where->SignedValue .value = ~(uintptr_t )value.ptr ;
626
707
627
- writePointerImpl (where, value);
708
+ writePointerImpl (where, value, PtrauthInfo<U>::key,
709
+ PtrauthInfo<U>::addressDiversified,
710
+ PtrauthInfo<U>::discriminator);
628
711
}
629
712
630
713
template <typename U>
@@ -638,6 +721,15 @@ class ExternalGenericMetadataBuilderContext {
638
721
void writeFunctionPointer (void *where, Buffer<const char > target) {
639
722
writePointer (reinterpret_cast <StoredPointer *>(where), target);
640
723
}
724
+
725
+ template <unsigned discriminator>
726
+ void writeFunctionPointer (
727
+ ExternalRuntime64::ValueWitnessFunctionPointer<discriminator> *where,
728
+ Buffer<const char > target) {
729
+ checkPtr (where);
730
+
731
+ writePointerImpl (where, target, PtrauthKey::IA, true , discriminator);
732
+ }
641
733
};
642
734
643
735
ExternalGenericMetadataBuilderContext () {
@@ -660,7 +752,11 @@ class ExternalGenericMetadataBuilderContext {
660
752
return allocate<T>(count * sizeof (T));
661
753
}
662
754
663
- void setArch (const char *arch) { this ->arch = arch; }
755
+ void setArch (const char *arch) {
756
+ this ->arch = arch;
757
+ this ->usePtrauth = this ->arch == " arm64e" ;
758
+ }
759
+
664
760
void setNamesToBuild (const std::vector<std::string> &names) {
665
761
this ->mangledNamesToBuild = names;
666
762
}
@@ -723,6 +819,9 @@ class ExternalGenericMetadataBuilderContext {
723
819
// The architecture being targeted.
724
820
std::string arch;
725
821
822
+ // Does this target use pointer authentication?
823
+ bool usePtrauth = false ;
824
+
726
825
// The readerWriter and builder helper objects.
727
826
std::unique_ptr<ReaderWriter<Runtime>> readerWriter;
728
827
std::unique_ptr<Builder> builder;
@@ -2127,6 +2226,14 @@ void ExternalGenericMetadataBuilderContext<Runtime>::writeAtomContentsJSON(
2127
2226
J.attribute (" addend" , atomTarget.offset );
2128
2227
J.attribute (" kind" , ptrTargetKind);
2129
2228
}
2229
+
2230
+ if (usePtrauth && targetsCursor->ptrauthKey != PtrauthKey::None) {
2231
+ J.attributeObject (" authPtr" , [&] {
2232
+ J.attribute (" key" , static_cast <uint8_t >(targetsCursor->ptrauthKey ));
2233
+ J.attribute (" addr" , targetsCursor->addressDiversified );
2234
+ J.attribute (" diversity" , targetsCursor->discriminator );
2235
+ });
2236
+ }
2130
2237
});
2131
2238
2132
2239
bufferCursor = targetsCursor->offset + targetsCursor->size ;
@@ -2286,16 +2393,11 @@ BuilderErrorOr<unsigned> getPointerWidth(std::string arch) {
2286
2393
2287
2394
} // namespace swift
2288
2395
2289
- using ExternalRuntime32 =
2290
- swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<4 >>>;
2291
- using ExternalRuntime64 =
2292
- swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<8 >>>;
2293
-
2294
2396
struct SwiftExternalMetadataBuilder {
2295
2397
using Builder32 =
2296
- swift::ExternalGenericMetadataBuilderContext<ExternalRuntime32>;
2398
+ swift::ExternalGenericMetadataBuilderContext<swift:: ExternalRuntime32>;
2297
2399
using Builder64 =
2298
- swift::ExternalGenericMetadataBuilderContext<ExternalRuntime64>;
2400
+ swift::ExternalGenericMetadataBuilderContext<swift:: ExternalRuntime64>;
2299
2401
2300
2402
std::variant<Builder32, Builder64> context;
2301
2403
0 commit comments