Skip to content

Commit 2edec10

Browse files
authored
Merge pull request #82650 from mikeash/memoryreader-dataquery-cache
[Reflection] Cache the various DataQuery values.
2 parents ed3961b + ca06ced commit 2edec10

File tree

4 files changed

+101
-67
lines changed

4 files changed

+101
-67
lines changed

include/swift/Remote/CMemoryReader.h

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,38 +42,16 @@ namespace remote {
4242
class CMemoryReader final : public MemoryReader {
4343
MemoryReaderImpl Impl;
4444

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-
6845
// Check to see if an address has bits outside the ptrauth mask. This suggests
6946
// that we're likely failing to strip a signed pointer when reading from it.
7047
bool hasSignatureBits(RemoteAddress address) {
7148
uint64_t addressData = address.getAddressData();
72-
return addressData != (addressData & getPtrauthMask());
49+
uint64_t mask = getPtrAuthMask().value_or(~uint64_t(0));
50+
return addressData != (addressData & mask);
7351
}
7452

7553
public:
76-
CMemoryReader(MemoryReaderImpl Impl) : Impl(Impl), ptrauthMask(0) {
54+
CMemoryReader(MemoryReaderImpl Impl) : Impl(Impl) {
7755
assert(this->Impl.queryDataLayout && "No queryDataLayout implementation");
7856
assert(this->Impl.getStringLength && "No stringLength implementation");
7957
assert(this->Impl.readBytes && "No readBytes implementation");

include/swift/Remote/MemoryReader.h

Lines changed: 89 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/SwiftRemoteMirror/MemoryReaderInterface.h"
2323
#include <optional>
2424

25+
#include <cstdint>
2526
#include <cstdlib>
2627
#include <cstring>
2728
#include <functional>
@@ -37,7 +38,80 @@ namespace remote {
3738
/// This abstraction presents memory as if it were a read-only
3839
/// representation of the address space of a remote process.
3940
class MemoryReader {
41+
uint8_t cachedPointerSize = 0;
42+
uint8_t cachedSizeSize = 0;
43+
uint64_t cachedPtrAuthMask = 0;
44+
uint8_t cachedObjCReservedLowBits = 0xff;
45+
uint64_t cachedLeastValidPointerValue = 0;
46+
uint8_t cachedObjCInteropIsEnabled = 0xff;
47+
48+
protected:
49+
virtual bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
50+
void *outBuffer) = 0;
51+
4052
public:
53+
std::optional<uint8_t> getPointerSize() {
54+
if (cachedPointerSize == 0) {
55+
if (!queryDataLayout(DLQ_GetPointerSize, nullptr, &cachedPointerSize))
56+
return std::nullopt;
57+
}
58+
return cachedPointerSize;
59+
}
60+
61+
std::optional<uint8_t> getSizeSize() {
62+
if (cachedSizeSize == 0) {
63+
if (!queryDataLayout(DLQ_GetSizeSize, nullptr, &cachedSizeSize))
64+
return std::nullopt;
65+
}
66+
return cachedSizeSize;
67+
}
68+
69+
std::optional<uint64_t> getPtrAuthMask() {
70+
if (cachedPtrAuthMask == 0) {
71+
auto ptrSize = getPointerSize();
72+
if (!ptrSize)
73+
return std::nullopt;
74+
75+
if (ptrSize.value() == sizeof(uint64_t)) {
76+
if (!queryDataLayout(DLQ_GetPtrAuthMask, nullptr, &cachedPtrAuthMask))
77+
return std::nullopt;
78+
} else if (ptrSize.value() == sizeof(uint32_t)) {
79+
uint32_t mask;
80+
if (!queryDataLayout(DLQ_GetPtrAuthMask, nullptr, &mask))
81+
return std::nullopt;
82+
cachedPtrAuthMask = mask;
83+
}
84+
}
85+
return cachedPtrAuthMask;
86+
}
87+
88+
std::optional<uint8_t> getObjCReservedLowBits() {
89+
if (cachedObjCReservedLowBits == 0xff) {
90+
if (!queryDataLayout(DLQ_GetObjCReservedLowBits, nullptr,
91+
&cachedObjCReservedLowBits))
92+
return std::nullopt;
93+
}
94+
return cachedObjCReservedLowBits;
95+
}
96+
97+
std::optional<uint64_t> getLeastValidPointerValue() {
98+
if (cachedLeastValidPointerValue == 0) {
99+
if (!queryDataLayout(DLQ_GetLeastValidPointerValue, nullptr,
100+
&cachedLeastValidPointerValue))
101+
return std::nullopt;
102+
}
103+
return cachedLeastValidPointerValue;
104+
}
105+
106+
std::optional<bool> getObjCInteropIsEnabled() {
107+
if (cachedObjCInteropIsEnabled == 0xff) {
108+
if (!queryDataLayout(DLQ_GetObjCInteropIsEnabled, nullptr,
109+
&cachedObjCInteropIsEnabled))
110+
return std::nullopt;
111+
}
112+
return cachedObjCInteropIsEnabled;
113+
}
114+
41115
/// A convenient name for the return type from readBytes.
42116
using ReadBytesResult =
43117
std::unique_ptr<const void, std::function<void(const void *)>>;
@@ -46,9 +120,6 @@ class MemoryReader {
46120
using ReadObjResult =
47121
std::unique_ptr<const T, std::function<void(const void *)>>;
48122

49-
virtual bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
50-
void *outBuffer) = 0;
51-
52123
/// Look up the given public symbol name in the remote process.
53124
virtual RemoteAddress getSymbolAddress(const std::string &name) = 0;
54125

@@ -209,50 +280,37 @@ class MemoryReader {
209280
// index (counting from 0).
210281
bool readHeapObjectExtraInhabitantIndex(RemoteAddress address,
211282
int *extraInhabitantIndex) {
212-
uint8_t PointerSize;
213-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetPointerSize,
214-
nullptr, &PointerSize)) {
215-
return false;
216-
}
217-
uint64_t LeastValidPointerValue;
218-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetLeastValidPointerValue,
219-
nullptr, &LeastValidPointerValue)) {
220-
return false;
221-
}
222-
uint8_t ObjCReservedLowBits;
223-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetObjCReservedLowBits,
224-
nullptr, &ObjCReservedLowBits)) {
283+
auto PointerSize = getPointerSize();
284+
auto LeastValidPointerValue = getLeastValidPointerValue();
285+
auto ObjCReservedLowBits = getObjCReservedLowBits();
286+
287+
if (!PointerSize || !LeastValidPointerValue || !ObjCReservedLowBits)
225288
return false;
226-
}
289+
227290
uint64_t RawPointerValue;
228-
if (!readInteger(address, PointerSize, &RawPointerValue)) {
291+
if (!readInteger(address, PointerSize.value(), &RawPointerValue)) {
229292
return false;
230293
}
231-
if (RawPointerValue >= LeastValidPointerValue) {
294+
if (RawPointerValue >= LeastValidPointerValue.value()) {
232295
*extraInhabitantIndex = -1; // Valid value, not an XI
233296
} else {
234-
*extraInhabitantIndex = (RawPointerValue >> ObjCReservedLowBits);
297+
*extraInhabitantIndex = (RawPointerValue >> ObjCReservedLowBits.value());
235298
}
236299
return true;
237300
}
238301

239302
bool readFunctionPointerExtraInhabitantIndex(RemoteAddress address,
240303
int *extraInhabitantIndex) {
241-
uint8_t PointerSize;
242-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetPointerSize,
243-
nullptr, &PointerSize)) {
304+
auto PointerSize = getPointerSize();
305+
auto LeastValidPointerValue = getLeastValidPointerValue();
306+
if (!PointerSize || !LeastValidPointerValue)
244307
return false;
245-
}
246-
uint64_t LeastValidPointerValue;
247-
if (!queryDataLayout(DataLayoutQueryType::DLQ_GetLeastValidPointerValue,
248-
nullptr, &LeastValidPointerValue)) {
249-
return false;
250-
}
308+
251309
uint64_t RawPointerValue;
252-
if (!readInteger(address, PointerSize, &RawPointerValue)) {
310+
if (!readInteger(address, PointerSize.value(), &RawPointerValue)) {
253311
return false;
254312
}
255-
if (RawPointerValue >= LeastValidPointerValue) {
313+
if (RawPointerValue >= LeastValidPointerValue.value()) {
256314
*extraInhabitantIndex = -1; // Valid value, not an XI
257315
} else {
258316
*extraInhabitantIndex = RawPointerValue;

include/swift/Remote/MetadataReader.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,8 @@ class MetadataReader {
422422
}
423423

424424
StoredPointer queryPtrAuthMask() {
425-
StoredPointer QueryResult;
426-
if (Reader->queryDataLayout(DataLayoutQueryType::DLQ_GetPtrAuthMask,
427-
nullptr, &QueryResult)) {
428-
return QueryResult;
429-
}
430-
return ~StoredPointer(0);
425+
auto QueryResult = Reader->getPtrAuthMask();
426+
return QueryResult.value_or(~StoredPointer(0));
431427
}
432428

433429
template <class... T>

lib/StaticMirror/ObjectFileContext.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -565,16 +565,18 @@ std::unique_ptr<ReflectionContextHolder> makeReflectionContextForObjectFiles(
565565
const std::vector<const ObjectFile *> &objectFiles, bool ObjCInterop) {
566566
auto Reader = std::make_shared<ObjectMemoryReader>(objectFiles);
567567

568-
uint8_t pointerSize;
569-
Reader->queryDataLayout(DataLayoutQueryType::DLQ_GetPointerSize, nullptr,
570-
&pointerSize);
568+
auto pointerSize = Reader->getPointerSize();
569+
if (!pointerSize) {
570+
fputs("unable to get target pointer size\n", stderr);
571+
abort();
572+
}
571573

572-
switch (pointerSize) {
574+
switch (pointerSize.value()) {
573575
case 4:
574576
#define MAKE_CONTEXT(INTEROP, PTRSIZE) \
575577
makeReflectionContextForMetadataReader< \
576578
External<INTEROP<RuntimeTarget<PTRSIZE>>>>(std::move(Reader), \
577-
pointerSize)
579+
pointerSize.value())
578580
#if SWIFT_OBJC_INTEROP
579581
if (ObjCInterop)
580582
return MAKE_CONTEXT(WithObjCInterop, 4);

0 commit comments

Comments
 (0)