15
15
#include " lldb/Interpreter/CommandReturnObject.h"
16
16
#include " lldb/Interpreter/OptionGroupFormat.h"
17
17
#include " lldb/Interpreter/OptionGroupValueObjectDisplay.h"
18
+ #include " lldb/Target/MemoryRegionInfo.h"
18
19
#include " lldb/Target/StackFrame.h"
19
20
#include " lldb/Utility/ConstString.h"
20
21
#include " lldb/lldb-defines.h"
21
22
#include " lldb/lldb-enumerations.h"
22
23
#include " lldb/lldb-forward.h"
24
+ #include " lldb/lldb-types.h"
23
25
#include " llvm/ADT/StringRef.h"
24
26
#include " llvm/Support/FormatVariadic.h"
25
27
@@ -84,8 +86,10 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
84
86
m_expr_options.m_verbosity , m_format_options.GetFormat ());
85
87
dump_options.SetHideName (eval_options.GetSuppressPersistentResult ());
86
88
89
+ StackFrame *frame = m_exe_ctx.GetFramePtr ();
90
+
87
91
// First, try `expr` as the name of a frame variable.
88
- if (StackFrame * frame = m_exe_ctx. GetFramePtr () ) {
92
+ if (frame) {
89
93
auto valobj_sp = frame->FindVariable (ConstString (expr));
90
94
if (valobj_sp && valobj_sp->GetError ().Success ()) {
91
95
if (!eval_options.GetSuppressPersistentResult ())
@@ -105,6 +109,47 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
105
109
}
106
110
}
107
111
112
+ // For Swift frames, rewrite `po 0x12345600` to use `unsafeBitCast`.
113
+ //
114
+ // This works only when the address points to an instance of a class. This
115
+ // matches the behavior of `po` in Objective-C frames.
116
+ //
117
+ // The following conditions are required:
118
+ // 1. The command is `po` (or equivalently the `-O` flag is used)
119
+ // 2. The current language is Swift
120
+ // 3. The expression is entirely a integer value (decimal or hex)
121
+ // 4. The integer passes sanity checks as a memory address
122
+ //
123
+ // The address sanity checks are:
124
+ // 1. The integer represents a readable memory address
125
+ //
126
+ // Future potential sanity checks:
127
+ // 1. Accept tagged pointers/values
128
+ // 2. Verify the isa pointer is a known class
129
+ // 3. Require addresses to be on the heap
130
+ std::string modified_expr_storage;
131
+ // Either Swift was explicitly specified, or the frame is Swift.
132
+ bool is_swift = false ;
133
+ if (m_expr_options.language == lldb::eLanguageTypeSwift)
134
+ is_swift = true ;
135
+ else if (m_expr_options.language == lldb::eLanguageTypeUnknown)
136
+ is_swift = frame && frame->GuessLanguage () == lldb::eLanguageTypeSwift;
137
+ bool is_po = m_varobj_options.use_objc ;
138
+ if (is_swift && is_po) {
139
+ lldb::addr_t addr;
140
+ bool is_integer = !expr.getAsInteger (0 , addr);
141
+ if (is_integer) {
142
+ MemoryRegionInfo mem_info;
143
+ m_exe_ctx.GetProcessRef ().GetMemoryRegionInfo (addr, mem_info);
144
+ bool is_readable = mem_info.GetReadable () == MemoryRegionInfo::eYes;
145
+ if (is_readable) {
146
+ modified_expr_storage =
147
+ llvm::formatv (" unsafeBitCast({0}, to: AnyObject.self)" , expr).str ();
148
+ expr = modified_expr_storage;
149
+ }
150
+ }
151
+ }
152
+
108
153
// Second, also lastly, try `expr` as a source expression to evaluate.
109
154
{
110
155
auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope ();
0 commit comments