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.
3940class 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+
4052public:
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;
0 commit comments