Skip to content

Commit ea6e5e7

Browse files
authored
Merge pull request swiftlang#76047 from mikeash/remote-mirror-resilient-superclasses
[RemoteMirror] Fix generic subclasses of resilient superclasses.
2 parents fad9a5f + 4e1962a commit ea6e5e7

File tree

3 files changed

+119
-47
lines changed

3 files changed

+119
-47
lines changed

include/swift/Remote/CMemoryReader.h

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "swift/Remote/MemoryReader.h"
2323

2424
struct MemoryReaderImpl {
25+
uint8_t PointerSize;
26+
2527
// Opaque pointer passed to all the callback functions.
2628
void *reader_context;
2729

@@ -40,8 +42,39 @@ namespace remote {
4042
class CMemoryReader final : public MemoryReader {
4143
MemoryReaderImpl Impl;
4244

45+
uint64_t ptrauthMask;
46+
47+
uint64_t getPtrauthMask() {
48+
if (ptrauthMask == 0) {
49+
int success;
50+
if (Impl.PointerSize == 4) {
51+
uint32_t ptrauthMask32 = 0;
52+
success = queryDataLayout(DataLayoutQueryType::DLQ_GetPtrAuthMask,
53+
nullptr, &ptrauthMask32);
54+
ptrauthMask = ptrauthMask32;
55+
} else if (Impl.PointerSize == 8) {
56+
success = queryDataLayout(DataLayoutQueryType::DLQ_GetPtrAuthMask,
57+
nullptr, &ptrauthMask);
58+
} else {
59+
success = 0;
60+
}
61+
62+
if (!success)
63+
ptrauthMask = ~0ull;
64+
}
65+
return ptrauthMask;
66+
}
67+
68+
// Check to see if an address has bits outside the ptrauth mask. This suggests
69+
// that we're likely failing to strip a signed pointer when reading from it.
70+
bool hasSignatureBits(RemoteAddress address) {
71+
return false;
72+
uint64_t addressData = address.getAddressData();
73+
return addressData != (addressData & getPtrauthMask());
74+
}
75+
4376
public:
44-
CMemoryReader(MemoryReaderImpl Impl) : Impl(Impl) {
77+
CMemoryReader(MemoryReaderImpl Impl) : Impl(Impl), ptrauthMask(0) {
4578
assert(this->Impl.queryDataLayout && "No queryDataLayout implementation");
4679
assert(this->Impl.getStringLength && "No stringLength implementation");
4780
assert(this->Impl.readBytes && "No readBytes implementation");
@@ -60,11 +93,13 @@ class CMemoryReader final : public MemoryReader {
6093
}
6194

6295
uint64_t getStringLength(RemoteAddress address) {
96+
assert(!hasSignatureBits(address));
6397
return Impl.getStringLength(Impl.reader_context,
6498
address.getAddressData());
6599
}
66100

67101
bool readString(RemoteAddress address, std::string &dest) override {
102+
assert(!hasSignatureBits(address));
68103
auto length = getStringLength(address);
69104
if (length == 0) {
70105
// A length of zero unfortunately might mean either that there's a zero
@@ -83,17 +118,20 @@ class CMemoryReader final : public MemoryReader {
83118
}
84119

85120
ReadBytesResult readBytes(RemoteAddress address, uint64_t size) override {
86-
void *FreeContext;
87-
auto Ptr = Impl.readBytes(Impl.reader_context, address.getAddressData(), size,
88-
&FreeContext);
89-
90-
auto Free = Impl.free;
91-
if (Free == nullptr)
92-
return ReadBytesResult(Ptr, [](const void *) {});
93-
94-
auto ReaderContext = Impl.reader_context;
95-
auto freeLambda = [=](const void *Ptr) { Free(ReaderContext, Ptr, FreeContext); };
96-
return ReadBytesResult(Ptr, freeLambda);
121+
assert(!hasSignatureBits(address));
122+
void *FreeContext;
123+
auto Ptr = Impl.readBytes(Impl.reader_context, address.getAddressData(),
124+
size, &FreeContext);
125+
126+
auto Free = Impl.free;
127+
if (Free == nullptr)
128+
return ReadBytesResult(Ptr, [](const void *) {});
129+
130+
auto ReaderContext = Impl.reader_context;
131+
auto freeLambda = [=](const void *Ptr) {
132+
Free(ReaderContext, Ptr, FreeContext);
133+
};
134+
return ReadBytesResult(Ptr, freeLambda);
97135
}
98136
};
99137

include/swift/Remote/MetadataReader.h

Lines changed: 66 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,13 +1814,10 @@ class MetadataReader {
18141814
if (!type->hasResilientSuperclass())
18151815
return type->getNonResilientGenericArgumentOffset();
18161816

1817-
auto bounds = readMetadataBoundsOfSuperclass(descriptor);
1817+
auto bounds = computeMetadataBoundsFromSuperclass(descriptor);
18181818
if (!bounds)
18191819
return std::nullopt;
18201820

1821-
bounds->adjustForSubclass(type->areImmediateMembersNegative(),
1822-
type->NumImmediateMembers);
1823-
18241821
return bounds->ImmediateMembersOffset / sizeof(StoredPointer);
18251822
}
18261823

@@ -1841,39 +1838,72 @@ class MetadataReader {
18411838

18421839
using ClassMetadataBounds = TargetClassMetadataBounds<Runtime>;
18431840

1844-
// This follows computeMetadataBoundsForSuperclass.
1841+
// This follows getMetadataBounds in ABI/Metadata.h.
18451842
std::optional<ClassMetadataBounds>
1846-
readMetadataBoundsOfSuperclass(ContextDescriptorRef subclassRef) {
1847-
auto subclass = cast<TargetClassDescriptor<Runtime>>(subclassRef);
1848-
if (!subclass->hasResilientSuperclass())
1849-
return ClassMetadataBounds::forSwiftRootClass();
1843+
getClassMetadataBounds(ContextDescriptorRef classRef) {
1844+
auto classDescriptor = cast<TargetClassDescriptor<Runtime>>(classRef);
1845+
1846+
if (!classDescriptor->hasResilientSuperclass()) {
1847+
auto nonResilientImmediateMembersOffset =
1848+
classDescriptor->areImmediateMembersNegative()
1849+
? -int32_t(classDescriptor->MetadataNegativeSizeInWords)
1850+
: int32_t(classDescriptor->MetadataPositiveSizeInWords -
1851+
classDescriptor->NumImmediateMembers);
1852+
typename Runtime::StoredPointerDifference immediateMembersOffset =
1853+
nonResilientImmediateMembersOffset * sizeof(StoredPointer);
18501854

1851-
auto rawSuperclass =
1852-
resolveRelativeField(subclassRef, subclass->getResilientSuperclass());
1853-
if (!rawSuperclass) {
1854-
return ClassMetadataBounds::forSwiftRootClass();
1855+
ClassMetadataBounds bounds{immediateMembersOffset,
1856+
classDescriptor->MetadataNegativeSizeInWords,
1857+
classDescriptor->MetadataPositiveSizeInWords};
1858+
return bounds;
18551859
}
18561860

1857-
return forTypeReference<ClassMetadataBounds>(
1858-
subclass->getResilientSuperclassReferenceKind(), rawSuperclass,
1859-
[&](ContextDescriptorRef superclass)
1860-
-> std::optional<ClassMetadataBounds> {
1861-
if (!isa<TargetClassDescriptor<Runtime>>(superclass))
1862-
return std::nullopt;
1863-
return readMetadataBoundsOfSuperclass(superclass);
1864-
},
1865-
[&](MetadataRef metadata) -> std::optional<ClassMetadataBounds> {
1866-
auto cls = dyn_cast<TargetClassMetadata>(metadata);
1867-
if (!cls)
1868-
return std::nullopt;
1861+
return computeMetadataBoundsFromSuperclass(classRef);
1862+
}
18691863

1870-
return cls->getClassBoundsAsSwiftSuperclass();
1871-
},
1872-
[](StoredPointer objcClassName) -> std::optional<ClassMetadataBounds> {
1873-
// We have no ability to look up an ObjC class by name.
1874-
// FIXME: add a query for this; clients may have a way to do it.
1875-
return std::nullopt;
1876-
});
1864+
// This follows computeMetadataBoundsFromSuperclass in Metadata.cpp.
1865+
std::optional<ClassMetadataBounds>
1866+
computeMetadataBoundsFromSuperclass(ContextDescriptorRef subclassRef) {
1867+
auto subclass = cast<TargetClassDescriptor<Runtime>>(subclassRef);
1868+
std::optional<ClassMetadataBounds> bounds;
1869+
1870+
if (!subclass->hasResilientSuperclass()) {
1871+
bounds = ClassMetadataBounds::forSwiftRootClass();
1872+
} else {
1873+
auto rawSuperclass =
1874+
resolveRelativeField(subclassRef, subclass->getResilientSuperclass());
1875+
if (!rawSuperclass) {
1876+
return std::nullopt;
1877+
}
1878+
1879+
bounds = forTypeReference<ClassMetadataBounds>(
1880+
subclass->getResilientSuperclassReferenceKind(), rawSuperclass,
1881+
[&](ContextDescriptorRef superclass)
1882+
-> std::optional<ClassMetadataBounds> {
1883+
if (!isa<TargetClassDescriptor<Runtime>>(superclass))
1884+
return std::nullopt;
1885+
return getClassMetadataBounds(superclass);
1886+
},
1887+
[&](MetadataRef metadata) -> std::optional<ClassMetadataBounds> {
1888+
auto cls = dyn_cast<TargetClassMetadata>(metadata);
1889+
if (!cls)
1890+
return std::nullopt;
1891+
1892+
return cls->getClassBoundsAsSwiftSuperclass();
1893+
},
1894+
[](StoredPointer objcClassName)
1895+
-> std::optional<ClassMetadataBounds> {
1896+
// We have no ability to look up an ObjC class by name.
1897+
// FIXME: add a query for this; clients may have a way to do it.
1898+
return std::nullopt;
1899+
});
1900+
}
1901+
if (!bounds) {
1902+
return std::nullopt;
1903+
}
1904+
bounds->adjustForSubclass(subclass->areImmediateMembersNegative(),
1905+
subclass->NumImmediateMembers);
1906+
return bounds;
18771907
}
18781908

18791909
template <class Result, class DescriptorFn, class MetadataFn,
@@ -1885,11 +1915,12 @@ class MetadataReader {
18851915
const ClassNameFn &classNameFn) {
18861916
switch (refKind) {
18871917
case TypeReferenceKind::IndirectTypeDescriptor: {
1888-
StoredPointer descriptorAddress = 0;
1889-
if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress))
1918+
StoredSignedPointer descriptorAddress;
1919+
if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress)) {
18901920
return std::nullopt;
1921+
}
18911922

1892-
ref = descriptorAddress;
1923+
ref = stripSignedPointer(descriptorAddress);
18931924
LLVM_FALLTHROUGH;
18941925
}
18951926

stdlib/public/SwiftRemoteMirror/SwiftRemoteMirror.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ swift_reflection_createReflectionContext(void *ReaderContext,
180180
auto *DataLayout = PointerSize == 4 ? minimalDataLayoutQueryFunction<4>
181181
: minimalDataLayoutQueryFunction<8>;
182182
MemoryReaderImpl ReaderImpl {
183+
PointerSize,
183184
ReaderContext,
184185
DataLayout,
185186
Free,
@@ -198,7 +199,9 @@ swift_reflection_createReflectionContextWithDataLayout(void *ReaderContext,
198199
ReadBytesFunction ReadBytes,
199200
GetStringLengthFunction GetStringLength,
200201
GetSymbolAddressFunction GetSymbolAddress) {
202+
uint8_t PointerSize = sizeof(uintptr_t);
201203
MemoryReaderImpl ReaderImpl {
204+
PointerSize,
202205
ReaderContext,
203206
DataLayout,
204207
Free,

0 commit comments

Comments
 (0)