Skip to content

Commit 89e5a80

Browse files
committed
[ExternalGenericMetadataBuilder] Support ARM64e fixups.
Add ptrauth attributes to the witness tables and descriptor pointers, and have the test support ARM64e. rdar://122660111
1 parent 1691786 commit 89e5a80

File tree

6 files changed

+147
-25
lines changed

6 files changed

+147
-25
lines changed

include/swift/Runtime/GenericMetadataBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,13 @@ class GenericMetadataBuilder {
289289
extraDataPattern->SizeInWords, extraDataPattern->OffsetInWords);
290290
auto patternPointers =
291291
patternBuffer.resolvePointer(&extraDataPattern->Pattern);
292+
if (!patternPointers)
293+
return *patternPointers.getError();
292294
for (unsigned i = 0; i < extraDataPattern->SizeInWords; i++) {
293295
auto patternPointer =
294296
patternPointers->resolvePointer(&patternPointers->ptr[i]);
297+
if (!patternPointer)
298+
return *patternPointer.getError();
295299
data.writePointer(
296300
&metadataExtraData[i + extraDataPattern->OffsetInWords],
297301
patternPointer->template cast<const StoredPointer>());
@@ -303,6 +307,8 @@ class GenericMetadataBuilder {
303307
// necessary.
304308
auto valueWitnesses =
305309
patternBuffer.resolvePointer(&pattern->ValueWitnesses);
310+
if (!valueWitnesses)
311+
return *valueWitnesses.getError();
306312
METADATA_BUILDER_LOG("Setting initial value witnesses");
307313
data.writePointer(&fullMetadata->ValueWitnesses, *valueWitnesses);
308314

lib/ExternalGenericMetadataBuilder/ExternalGenericMetadataBuilder.cpp

Lines changed: 112 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,62 @@ struct TypedExternal {
117117
template <typename T, bool Nullable = true, typename Offset = int32_t>
118118
using CompactFunctionPointer = TypedInteger<T, int32_t, Nullable>;
119119

120+
template <unsigned discriminator>
121+
struct ValueWitnessFunctionPointer {
122+
StoredPointer pointer;
123+
};
124+
120125
StoredPointer
121126
getStrippedSignedPointer(const StoredSignedPointer pointer) const {
122127
return swift_ptrauth_strip(pointer);
123128
}
124129
};
125130

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+
126176
template <typename T>
127177
inline MetadataKind getEnumeratedMetadataKind(T kind,
128178
decltype(kind.value) dummy = 0) {
@@ -188,6 +238,26 @@ class ReaderWriter;
188238

189239
template <typename Runtime>
190240
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+
191261
struct Atom;
192262

193263
struct FileTarget {
@@ -207,6 +277,10 @@ class ExternalGenericMetadataBuilderContext {
207277
unsigned offset;
208278
unsigned size;
209279

280+
PtrauthKey ptrauthKey;
281+
bool addressDiversified;
282+
unsigned discriminator;
283+
210284
std::variant<FileTarget, AtomTarget> fileOrAtom;
211285
};
212286

@@ -512,7 +586,10 @@ class ExternalGenericMetadataBuilderContext {
512586
}
513587

514588
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) {
516593
if (!value) {
517594
memset(where, 0, sizeof(StoredPointer));
518595
return;
@@ -530,6 +607,10 @@ class ExternalGenericMetadataBuilderContext {
530607

531608
target.size = sizeof(StoredPointer);
532609

610+
target.ptrauthKey = ptrauthKey;
611+
target.addressDiversified = addressDiversified;
612+
target.discriminator = discriminator;
613+
533614
if (auto *file = value.file) {
534615
auto contents = value.section.getContents();
535616
if (!contents) {
@@ -624,7 +705,9 @@ class ExternalGenericMetadataBuilderContext {
624705
checkPtr(where);
625706
where->SignedValue.value = ~(uintptr_t)value.ptr;
626707

627-
writePointerImpl(where, value);
708+
writePointerImpl(where, value, PtrauthInfo<U>::key,
709+
PtrauthInfo<U>::addressDiversified,
710+
PtrauthInfo<U>::discriminator);
628711
}
629712

630713
template <typename U>
@@ -638,6 +721,15 @@ class ExternalGenericMetadataBuilderContext {
638721
void writeFunctionPointer(void *where, Buffer<const char> target) {
639722
writePointer(reinterpret_cast<StoredPointer *>(where), target);
640723
}
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+
}
641733
};
642734

643735
ExternalGenericMetadataBuilderContext() {
@@ -660,7 +752,11 @@ class ExternalGenericMetadataBuilderContext {
660752
return allocate<T>(count * sizeof(T));
661753
}
662754

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+
664760
void setNamesToBuild(const std::vector<std::string> &names) {
665761
this->mangledNamesToBuild = names;
666762
}
@@ -723,6 +819,9 @@ class ExternalGenericMetadataBuilderContext {
723819
// The architecture being targeted.
724820
std::string arch;
725821

822+
// Does this target use pointer authentication?
823+
bool usePtrauth = false;
824+
726825
// The readerWriter and builder helper objects.
727826
std::unique_ptr<ReaderWriter<Runtime>> readerWriter;
728827
std::unique_ptr<Builder> builder;
@@ -2127,6 +2226,14 @@ void ExternalGenericMetadataBuilderContext<Runtime>::writeAtomContentsJSON(
21272226
J.attribute("addend", atomTarget.offset);
21282227
J.attribute("kind", ptrTargetKind);
21292228
}
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+
}
21302237
});
21312238

21322239
bufferCursor = targetsCursor->offset + targetsCursor->size;
@@ -2286,16 +2393,11 @@ BuilderErrorOr<unsigned> getPointerWidth(std::string arch) {
22862393

22872394
} // namespace swift
22882395

2289-
using ExternalRuntime32 =
2290-
swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<4>>>;
2291-
using ExternalRuntime64 =
2292-
swift::TypedExternal<swift::WithObjCInterop<swift::RuntimeTarget<8>>>;
2293-
22942396
struct SwiftExternalMetadataBuilder {
22952397
using Builder32 =
2296-
swift::ExternalGenericMetadataBuilderContext<ExternalRuntime32>;
2398+
swift::ExternalGenericMetadataBuilderContext<swift::ExternalRuntime32>;
22972399
using Builder64 =
2298-
swift::ExternalGenericMetadataBuilderContext<ExternalRuntime64>;
2400+
swift::ExternalGenericMetadataBuilderContext<swift::ExternalRuntime64>;
22992401

23002402
std::variant<Builder32, Builder64> context;
23012403

stdlib/public/runtime/GenericMetadataBuilder.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -485,13 +485,6 @@ bool swift::compareGenericMetadata(const Metadata *original,
485485
equal = false;
486486
}
487487

488-
if (memcmp(original, newMetadata, genericArgumentsStart)) {
489-
validationLog(
490-
true,
491-
"Metadatas do not match in the part before generic arguments");
492-
equal = false;
493-
}
494-
495488
for (unsigned i = 0; i < genericContextHeader.NumKeyArguments; i++) {
496489
auto *originalArg =
497490
originalDescriptor->getGenericArguments(original)[i];

stdlib/public/runtime/LibPrespecialized.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@ static const LibPrespecializedData<InProcess> *findLibPrespecialized() {
3636
auto path = runtime::environment::SWIFT_DEBUG_LIB_PRESPECIALIZED_PATH();
3737
if (path && path[0]) {
3838
void *handle = dlopen(path, RTLD_LAZY);
39-
if (!handle)
39+
if (!handle) {
40+
swift::warning(0, "Failed to load prespecializations library: %s\n",
41+
dlerror());
4042
return nullptr;
43+
}
4144

4245
dataPtr = dlsym(handle, LIB_PRESPECIALIZED_TOP_LEVEL_SYMBOL_NAME);
4346
}

test/ExternalGenericMetadataBuilder/Inputs/json2c.swift

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ enum ParseError: Error {
77
case invalidHex(Substring)
88
}
99

10+
struct Ptrauth: Decodable {
11+
var key: Int8
12+
var addr: Bool
13+
var diversity: UInt
14+
}
15+
1016
struct Fixup: Decodable {
1117
var target: String
1218
var addend: Int64
19+
var authPtr: Ptrauth?
1320
}
1421

1522
enum AtomContent: Decodable {
@@ -99,8 +106,18 @@ func printDeclarations(_ document: Document) {
99106
switch content {
100107
case .bytes(let bytes):
101108
print(" uint8_t \(name)[\(bytes.count)];")
102-
case .pointer(_):
103-
print(" const char *\(name);")
109+
case .pointer(let fixup):
110+
let ptrauthQualifier: String
111+
if let ptrauth = fixup.authPtr {
112+
ptrauthQualifier = """
113+
__ptrauth(\(ptrauth.key),
114+
\(ptrauth.addr ? 1 : 0),
115+
\(ptrauth.diversity))
116+
"""
117+
} else {
118+
ptrauthQualifier = ""
119+
}
120+
print(" const char *\(ptrauthQualifier) \(name);")
104121
}
105122
}
106123
print("};")

test/ExternalGenericMetadataBuilder/VerifyExternalMetadata.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-build-swift -Xfrontend -disable-availability-checking -I %swift-lib-dir -I %swift_src_root/lib/ExternalGenericMetadataBuilder -L%swift-lib-dir -lswiftGenericMetadataBuilder -enable-experimental-feature Extern %s -o %t/VerifyExternalMetadata
2+
// RUN: %target-build-swift -Xfrontend -disable-availability-checking -I %swift-lib-dir -I %swift_src_root/lib/ExternalGenericMetadataBuilder -enable-experimental-feature Extern %s -o %t/VerifyExternalMetadata
33
// RUN: %target-codesign %t/VerifyExternalMetadata
44
//
5-
// RUN: %target-build-swift -I %swift-lib-dir -I %swift_src_root/lib/ExternalGenericMetadataBuilder -L%swift-lib-dir -lswiftGenericMetadataBuilder -enable-experimental-feature Extern %S/Inputs/buildMetadataJSON.swift -o %t/buildMetadataJSON
5+
// RUN: %host-build-swift -Xfrontend -disable-availability-checking -I %swift-lib-dir -I %swift_src_root/lib/ExternalGenericMetadataBuilder -L%swift-lib-dir -lswiftGenericMetadataBuilder -Xlinker -rpath -Xlinker %swift-lib-dir -enable-experimental-feature Extern %S/Inputs/buildMetadataJSON.swift -o %t/buildMetadataJSON
6+
// no: %target-build-swift -I %swift-lib-dir -I %swift_src_root/lib/ExternalGenericMetadataBuilder -L%swift-lib-dir -lswiftGenericMetadataBuilder -enable-experimental-feature Extern %S/Inputs/buildMetadataJSON.swift -o %t/buildMetadataJSON
67
// RUN: %target-codesign %t/buildMetadataJSON
78
//
8-
// RUN: %target-build-swift %S/Inputs/json2c.swift -o %t/json2c
9+
// RUN: %target-build-swift -Xfrontend -disable-availability-checking %S/Inputs/json2c.swift -o %t/json2c
910
// RUN: %target-codesign %t/json2c
1011
//
1112
// RUN: %target-run %t/VerifyExternalMetadata getJSON > %t/names.json
12-
// RUN: %target-run %t/buildMetadataJSON arm64 %t/VerifyExternalMetadata %stdlib_dir/libswiftCore.dylib < %t/names.json > %t/libswiftPrespecialized.json
13+
// RUN: %target-run %t/buildMetadataJSON %target-arch %t/VerifyExternalMetadata %stdlib_dir/libswiftCore.dylib < %t/names.json > %t/libswiftPrespecialized.json
1314
// RUN: %target-run %t/json2c %t/libswiftPrespecialized.json > %t/libswiftPrespecialized.c
14-
// RUN: %clang -isysroot %sdk -bundle %t/libswiftPrespecialized.c -L%stdlib_dir -lswiftCore -bundle_loader %t/VerifyExternalMetadata -o %t/libswiftPrespecialized.bundle
15+
// RUN: %clang -isysroot %sdk -target %target-triple -bundle %t/libswiftPrespecialized.c -L%stdlib_dir -lswiftCore -bundle_loader %t/VerifyExternalMetadata -o %t/libswiftPrespecialized.bundle
1516
//
1617
//
1718
// RUN: env SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED_LOGGING=y SWIFT_DEBUG_LIB_PRESPECIALIZED_PATH=%t/libswiftPrespecialized.bundle %target-run %t/VerifyExternalMetadata

0 commit comments

Comments
 (0)