Skip to content

Commit 5ce824f

Browse files
authored
Merge pull request #71522 from mikeash/externalgenericmetadatabuilder-arm64e-fix
[ExternalGenericMetadataBuilder] Support ARM64e fixups.
2 parents bca1dd7 + 89e5a80 commit 5ce824f

File tree

6 files changed

+146
-24
lines changed

6 files changed

+146
-24
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
@@ -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+
127177
template <typename T>
128178
inline MetadataKind getEnumeratedMetadataKind(T kind,
129179
decltype(kind.value) dummy = 0) {
@@ -189,6 +239,26 @@ class ReaderWriter;
189239

190240
template <typename Runtime>
191241
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+
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-
23192421
struct 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

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: 5 additions & 4 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
//
89
// 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)