Skip to content

Commit a3c9ba1

Browse files
committed
[RemoteMirror] Fix generic subclasses of resilient superclasses.
Fix readMetadataBoundsOfSuperclass to recursively apply adjustForSubclass while going through the superclass chain. Strip indirect descriptor pointers so we can deal with signed pointers here. Make CMemoryReader assert (in asserts builds) that the addresses being read don't have any signature bits set, which helps track down places where we need to add stripping. rdar://134448718
1 parent e27f195 commit a3c9ba1

File tree

3 files changed

+93
-44
lines changed

3 files changed

+93
-44
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: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,9 +1818,6 @@ class MetadataReader {
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

@@ -1845,35 +1842,45 @@ class MetadataReader {
18451842
std::optional<ClassMetadataBounds>
18461843
readMetadataBoundsOfSuperclass(ContextDescriptorRef subclassRef) {
18471844
auto subclass = cast<TargetClassDescriptor<Runtime>>(subclassRef);
1848-
if (!subclass->hasResilientSuperclass())
1849-
return ClassMetadataBounds::forSwiftRootClass();
1845+
std::optional<ClassMetadataBounds> bounds;
18501846

1851-
auto rawSuperclass =
1852-
resolveRelativeField(subclassRef, subclass->getResilientSuperclass());
1853-
if (!rawSuperclass) {
1854-
return ClassMetadataBounds::forSwiftRootClass();
1855-
}
1847+
if (!subclass->hasResilientSuperclass()) {
1848+
bounds = ClassMetadataBounds::forSwiftRootClass();
1849+
} else {
1850+
auto rawSuperclass =
1851+
resolveRelativeField(subclassRef, subclass->getResilientSuperclass());
1852+
if (!rawSuperclass) {
1853+
return std::nullopt;
1854+
}
18561855

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)
1856+
bounds = forTypeReference<ClassMetadataBounds>(
1857+
subclass->getResilientSuperclassReferenceKind(), rawSuperclass,
1858+
[&](ContextDescriptorRef superclass)
1859+
-> std::optional<ClassMetadataBounds> {
1860+
if (!isa<TargetClassDescriptor<Runtime>>(superclass))
1861+
return std::nullopt;
1862+
return readMetadataBoundsOfSuperclass(superclass);
1863+
},
1864+
[&](MetadataRef metadata) -> std::optional<ClassMetadataBounds> {
1865+
auto cls = dyn_cast<TargetClassMetadata>(metadata);
1866+
if (!cls)
1867+
return std::nullopt;
1868+
1869+
return cls->getClassBoundsAsSwiftSuperclass();
1870+
},
1871+
[](StoredPointer objcClassName)
1872+
-> 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.
18681875
return std::nullopt;
1869-
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-
});
1876+
});
1877+
}
1878+
if (!bounds) {
1879+
return std::nullopt;
1880+
}
1881+
bounds->adjustForSubclass(subclass->areImmediateMembersNegative(),
1882+
subclass->NumImmediateMembers);
1883+
return bounds;
18771884
}
18781885

18791886
template <class Result, class DescriptorFn, class MetadataFn,
@@ -1885,11 +1892,12 @@ class MetadataReader {
18851892
const ClassNameFn &classNameFn) {
18861893
switch (refKind) {
18871894
case TypeReferenceKind::IndirectTypeDescriptor: {
1888-
StoredPointer descriptorAddress = 0;
1889-
if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress))
1895+
StoredSignedPointer descriptorAddress;
1896+
if (!Reader->readInteger(RemoteAddress(ref), &descriptorAddress)) {
18901897
return std::nullopt;
1898+
}
18911899

1892-
ref = descriptorAddress;
1900+
ref = stripSignedPointer(descriptorAddress);
18931901
LLVM_FALLTHROUGH;
18941902
}
18951903

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)