Skip to content

Commit f625fac

Browse files
authored
[lldb] Support po of memory addresses from Swift frames (#6442)
Update `dwim-print` to support `po 0xaddress` in Swift frames, to match the support of doing the same in ObjC frames. rdar://101174673
1 parent 2347eb8 commit f625fac

File tree

4 files changed

+91
-1
lines changed

4 files changed

+91
-1
lines changed

lldb/source/Commands/CommandObjectDWIMPrint.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
#include "lldb/Interpreter/CommandReturnObject.h"
1616
#include "lldb/Interpreter/OptionGroupFormat.h"
1717
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
18+
#include "lldb/Target/MemoryRegionInfo.h"
1819
#include "lldb/Target/StackFrame.h"
1920
#include "lldb/Utility/ConstString.h"
2021
#include "lldb/lldb-defines.h"
2122
#include "lldb/lldb-enumerations.h"
2223
#include "lldb/lldb-forward.h"
24+
#include "lldb/lldb-types.h"
2325
#include "llvm/ADT/StringRef.h"
2426
#include "llvm/Support/FormatVariadic.h"
2527

@@ -84,8 +86,10 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
8486
m_expr_options.m_verbosity, m_format_options.GetFormat());
8587
dump_options.SetHideName(eval_options.GetSuppressPersistentResult());
8688

89+
StackFrame *frame = m_exe_ctx.GetFramePtr();
90+
8791
// First, try `expr` as the name of a frame variable.
88-
if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
92+
if (frame) {
8993
auto valobj_sp = frame->FindVariable(ConstString(expr));
9094
if (valobj_sp && valobj_sp->GetError().Success()) {
9195
if (!eval_options.GetSuppressPersistentResult())
@@ -105,6 +109,47 @@ bool CommandObjectDWIMPrint::DoExecute(StringRef command,
105109
}
106110
}
107111

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+
108153
// Second, also lastly, try `expr` as a source expression to evaluate.
109154
{
110155
auto *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
SWIFT_SOURCES := main.swift
2+
include Makefile.rules
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
In Swift, test `po 0x12345600`, via dwim-print.
3+
"""
4+
5+
import lldb
6+
from lldbsuite.test.lldbtest import *
7+
from lldbsuite.test.decorators import *
8+
import lldbsuite.test.lldbutil as lldbutil
9+
10+
11+
class TestCase(TestBase):
12+
def test_swift_po_address(self):
13+
self.build()
14+
_, _, thread, _ = lldbutil.run_to_source_breakpoint(
15+
self, "// break here", lldb.SBFileSpec("main.swift")
16+
)
17+
frame = thread.frame[0]
18+
addr = frame.FindVariable("object").GetLoadAddress()
19+
hex_addr = f"{addr:x}"
20+
self.expect(f"dwim-print -O -- 0x{hex_addr}", patterns=[f"Object@0x0*{hex_addr}"])
21+
self.expect(f"dwim-print -O -- {addr}", patterns=[f"Object@0x0*{hex_addr}"])
22+
23+
def test_swift_po_non_address_hex(self):
24+
"""No special handling of non-memory integer values."""
25+
self.build()
26+
lldbutil.run_to_source_breakpoint(
27+
self, "// break here", lldb.SBFileSpec("main.swift")
28+
)
29+
self.expect(f"dwim-print -O -- 0x1000", substrs=["4096"])
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Object: CustomStringConvertible {
2+
var description: String {
3+
let address = unsafeBitCast(self, to: Int.self)
4+
let hexAddress = String(address, radix: 16)
5+
return "Object@0x\(hexAddress)"
6+
}
7+
}
8+
9+
func main() {
10+
let object = Object()
11+
_ = object // break here
12+
}
13+
14+
main()

0 commit comments

Comments
 (0)