22
22
#include " swift/SwiftRemoteMirror/MemoryReaderInterface.h"
23
23
#include < optional>
24
24
25
+ #include < cstdint>
25
26
#include < cstdlib>
26
27
#include < cstring>
27
28
#include < functional>
@@ -37,7 +38,80 @@ namespace remote {
37
38
// / This abstraction presents memory as if it were a read-only
38
39
// / representation of the address space of a remote process.
39
40
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
+
40
52
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
+
41
115
// / A convenient name for the return type from readBytes.
42
116
using ReadBytesResult =
43
117
std::unique_ptr<const void , std::function<void (const void *)>>;
@@ -46,9 +120,6 @@ class MemoryReader {
46
120
using ReadObjResult =
47
121
std::unique_ptr<const T, std::function<void (const void *)>>;
48
122
49
- virtual bool queryDataLayout (DataLayoutQueryType type, void *inBuffer,
50
- void *outBuffer) = 0;
51
-
52
123
// / Look up the given public symbol name in the remote process.
53
124
virtual RemoteAddress getSymbolAddress (const std::string &name) = 0;
54
125
@@ -209,50 +280,37 @@ class MemoryReader {
209
280
// index (counting from 0).
210
281
bool readHeapObjectExtraInhabitantIndex (RemoteAddress address,
211
282
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)
225
288
return false ;
226
- }
289
+
227
290
uint64_t RawPointerValue;
228
- if (!readInteger (address, PointerSize, &RawPointerValue)) {
291
+ if (!readInteger (address, PointerSize. value () , &RawPointerValue)) {
229
292
return false ;
230
293
}
231
- if (RawPointerValue >= LeastValidPointerValue) {
294
+ if (RawPointerValue >= LeastValidPointerValue. value () ) {
232
295
*extraInhabitantIndex = -1 ; // Valid value, not an XI
233
296
} else {
234
- *extraInhabitantIndex = (RawPointerValue >> ObjCReservedLowBits);
297
+ *extraInhabitantIndex = (RawPointerValue >> ObjCReservedLowBits. value () );
235
298
}
236
299
return true ;
237
300
}
238
301
239
302
bool readFunctionPointerExtraInhabitantIndex (RemoteAddress address,
240
303
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)
244
307
return false ;
245
- }
246
- uint64_t LeastValidPointerValue;
247
- if (!queryDataLayout (DataLayoutQueryType::DLQ_GetLeastValidPointerValue,
248
- nullptr , &LeastValidPointerValue)) {
249
- return false ;
250
- }
308
+
251
309
uint64_t RawPointerValue;
252
- if (!readInteger (address, PointerSize, &RawPointerValue)) {
310
+ if (!readInteger (address, PointerSize. value () , &RawPointerValue)) {
253
311
return false ;
254
312
}
255
- if (RawPointerValue >= LeastValidPointerValue) {
313
+ if (RawPointerValue >= LeastValidPointerValue. value () ) {
256
314
*extraInhabitantIndex = -1 ; // Valid value, not an XI
257
315
} else {
258
316
*extraInhabitantIndex = RawPointerValue;
0 commit comments