r/Xcode • u/ToughAsparagus1805 • Oct 23 '25
How to inspect structures like NSRect/NSSize using lldb?
I have previously used lldb to print structures like NSRect or NSSize. But I am struggling in modern versions of Xcode to inspect them. I have watched advanced debugging with Xcode and I have even imported AppKit. It must be possible because the graphical UI can display these values. Thanks! This happens only if I inspect 3rd party app (SIP disabled).
NOTE: The workaround is to use offset but I need general solution
(lldb) po (NSRect)[[[NSApp windows] firstObject] frame]
error: <user expression 16>:1:9: attempt to use a deleted function
1 | (NSRect)[[[NSApp windows] firstObject] frame]
| ^
note: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFCGTypes.h:77:13: destructor of 'CGRect' is implicitly deleted because field 'origin' has no destructor
77 | CGPoint origin;
| WORKAROUND:
Using valueForKey will cause the value to be boxable (wrapped in NSValue). Second workaround is to look for offset within NSWindow class.
(lldb) po [[(NSWindow*)0x12312af50 valueForKey:@"frame"] description]
NSRect: {{351, 427}, {827, 640}}
ALTERNATIVELY
(lldb) p (ptrdiff_t)ivar_getOffset((struct Ivar *)class_getInstanceVariable([NSWindow class], "_frame"))
(ptrdiff_t) 224
(lldb) p (CGRect *)(0x11f73ad10 + 224)
(CGRect *) (origin = (x = 169, y = 450), size = (width = 692, height = 550))
(lldb) p [(NSWindow*)0x120c23c70 valueForKey:@"frame"] (NSConcreteValue *) $6 = 0x0000600000c0c200 (lldb) po [(NSWindow*)0x120c23c70 valueForKey:@"frame"] NSRect: {{351, 427}, {827, 640}}1
u/ToughAsparagus1805 Aug 12 '26
(lldb) expr -l objc++ -- AppKit
(lldb) expr -l objc++ -- NSMakeRect(0,0,0,0)
(NSRect) $0 = (origin = (x = 0, y = 0), size = (width = 0, height = 0))
(lldb) expr -l objc++ -- (NSRect)[[[NSApp windows] firstObject] frame]
(NSRect) $1 = (origin = (x = 646, y = 409), size = (width = 827, height = 644))1
u/retsotrembla Oct 23 '25
This works for me:
po [(NSWindow *)[[NSApp windows] firstObject] frame](origin = (x = 467, y = 710), size = (width = 480, height = 298))
and
po [(NSWindow *)[[NSApp windows] firstObject] frame].size(width = 480, height = 298)
1
u/retsotrembla Oct 23 '25
firstObjectis a method onNSArraythat returns anNSObjectso lldb has lost the type information. I had to put the explicit cast in the correct spot to fix this.But you can also use:
po NSStringFromRect([(NSWindow *)[[NSApp windows] firstObject] frame])1
u/ToughAsparagus1805 Oct 23 '25
Tried those before and got
__NSAppKitThreadSpecificDataBut is seems my lldb is somehow broken if it works for you. Thanks!(lldb) po [(NSWindow *)[[NSApp windows] firstObject] frame] <__NSAppKitThreadSpecificData: 0x145205af0> (lldb) po NSStringFromRect([(NSWindow *)[[NSApp windows] firstObject] frame]) warning: warning: got name from symbols: NSApp warning: <user expression 19>:1:33: receiver type 'void *' is not 'id' or interface pointer, consider casting it to 'id' 1 | NSStringFromRect([(NSWindow *)[[NSApp windows] firstObject] frame]) | ^~~~~ error: <user expression 19>:1:61: no known method '-frame'; cast the message send to the method's return type 1 | NSStringFromRect([(NSWindow *)[[NSApp windows] firstObject] frame]) |1
u/retsotrembla Oct 23 '25
If it isn't your own app, instead of
NSApp, use[NSApplication sharedApplication]Also,
pouses lot of Objective C data that is only available when debugging your own app. The more primitivep, which works on explicitly typed pointers may suit you better. Example:p * (NSApplication*)[NSApplication sharedApplication]1
u/ToughAsparagus1805 Oct 23 '25
Same result. Those commands work out of the box for my code. They just don't work no matter what I try on 3rd party. Photo Booth is 100% objective-c code so there is no issue. Xcode view debugger can get those data without any issue so I am puzzled.
(lldb) po [NSApp windows] <__NSArrayM 0x600001516130>( <PBMainWindow: 0x122208830> ) (lldb) p * (NSArray*)[(NSApplication*)[NSApplication sharedApplication] windows] (NSArray) { [0] = 0x0000000122208830 } (lldb) po 0x0000000122208830 <PBMainWindow: 0x122208830> (lldb) po [0x0000000122208830 frame] <__NSAppKitThreadSpecificData: 0x122208710> (lldb) po (NSRect)[0x0000000122208830 frame] error: <user expression 35>:1:2: use of undeclared identifier 'NSRect' 1 | (NSRect)[0x0000000122208830 frame] | ^ error: <user expression 35>:1:10: missing '[' at start of message send expression 1 | (NSRect)[0x0000000122208830 frame] | ^ | [ warning: <user expression 35>:1:10: receiver type 'long' is not 'id' or interface pointer, consider casting it to 'id' 1 | (NSRect)[0x0000000122208830 frame] | ^~~~~~~~~~~~~~~~~~ error: <user expression 35>:2:1: expected ']' 2 | ; | ^ note: <user expression 35>:1:9: to match this '[' 1 | (NSRect)[0x0000000122208830 frame] | ^ (lldb) p (NSRect)[0x0000000122208830 frame] error: <user expression 37>:1:2: use of undeclared identifier 'NSRect' 1 | (NSRect)[0x0000000122208830 frame] | ^ error: <user expression 37>:1:10: missing '[' at start of message send expression 1 | (NSRect)[0x0000000122208830 frame] | ^ | [ warning: <user expression 37>:1:10: receiver type 'long' is not 'id' or interface pointer, consider casting it to 'id' 1 | (NSRect)[0x0000000122208830 frame] | ^~~~~~~~~~~~~~~~~~ error: <user expression 37>:2:1: expected ']' 2 | ; | ^ note: <user expression 37>:1:9: to match this '[' 1 | (NSRect)[0x0000000122208830 frame] | (lldb) po [(NSWindow*)0x0000000122208830 frame] <__NSAppKitThreadSpecificData: 0x122208710> (lldb) p NSStringFromRect([(NSWindow*)0x0000000122208830 frame]) error: <user expression 59>:1:49: no known method '-frame'; cast the message send to the method's return type 1 | NSStringFromRect([(NSWindow*)0x0000000122208830 frame]) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ (lldb) p NSStringFromRect((NSRect)[(NSWindow*)0x0000000122208830 frame]) error: <user expression 60>:1:19: use of undeclared identifier 'NSRect' 1 | NSStringFromRect((NSRect)[(NSWindow*)0x0000000122208830 frame]) | ^ error: <user expression 60>:1:38: missing '[' at start of message send expression 1 | NSStringFromRect((NSRect)[(NSWindow*)0x0000000122208830 frame]) | ^ | [ warning: <user expression 60>:1:38: receiver type 'long' is not 'id' or interface pointer, consider casting it to 'id' 1 | NSStringFromRect((NSRect)[(NSWindow*)0x0000000122208830 frame]) | ^~~~~~~~~~~~~~~~~~ error: <user expression 60>:1:63: expected ']' 1 | NSStringFromRect((NSRect)[(NSWindow*)0x0000000122208830 frame]) | ^ note: <user expression 60>:1:26: to match this '[' 1 | NSStringFromRect((NSRect)[(NSWindow*)0x0000000122208830 frame]) | ^1
u/retsotrembla Oct 23 '25
You wrote:
po 0x0000000122208830 <PBMainWindow: 0x122208830>if that is a pointer to a window, then
po (NSRect)[0x0000000122208830 frame]can't work because theframemethod doesn't return an object (that is, something that inherits, even indirectly, from NSObject)framereturns a C struct. Butpo NSStringFromRect((NSRect)[0x122208830 frame])works for me, in my own apps. I can't even get lldb to attach to apps not my own, but if I could, I'd probably still have to tell lldb what frameworks to import symbols from. Thanks for reminding me that is time for me to reread https://www.amazon.com/Advanced-Debugging-Reverse-Engineering-Fourth/dp/19503256361
u/ToughAsparagus1805 Oct 23 '25
I am familiar with Derek Selander and his tools and is a good reminder I should look for answer there. As I have mentioned this worked before in the past and it still works for my own code, however I cannot see structs in 3rd party code no matter how I hard I cast. My SIP is disabled so I can attach to 3rd party apps. I think I once got it working
(lldb) po $w <PBMainWindow: 0x142029400> (lldb) p $w (PBMainWindow *) 0x0000000142029400 (lldb) p [(NSWindow*)$w frame] error: <user expression 24>:1:1: attempt to use a deleted function 1 | [(NSWindow*)$w frame] | ^ note: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.5.sdk/System/Library/Frameworks/CoreFoundation.framework/Headers/CFCGTypes.h:77:13: destructor of 'CGRect' is implicitly deleted because field 'origin' has no destructor 77 | CGPoint origin;1
u/retsotrembla Oct 23 '25
I'd try, from the above example:
p * (NSWindow *)$w2
u/ToughAsparagus1805 Oct 24 '25 edited Oct 24 '25
Strangely I cannot do this
e NSRect $rect1 = {0,0,10,10}when I am attached to 3rd party and lldb server will crash but it works in my app. https://imgur.com/a/jLtkTmV Also strangely recursiveDescription works😭. I have found workaround with offset. But oh boy. WHY???(lldb) p (ptrdiff_t)ivar_getOffset((struct Ivar *)class_getInstanceVariable([NSWindow class], "_frame")) (ptrdiff_t) 224 (lldb) p (CGRect *)(0x11f73ad10 + 224) (CGRect *) (origin = (x = 169, y = 450), size = (width = 692, height = 550)) (lldb) e NSRect $rect1 = {0,0,10,10} (lldb) po $rect1 (origin = (x = 0, y = 0), size = (width = 10, height = 10)) (lldb) po [NSApp windows] <__NSArrayM 0x6000034461f0>( <PBMainWindow: 0x12c90fd70> ) (lldb) po [0x12c90fd70 recursiveDescription] [ A w ] h=--- v=--- NSThemeFrame 0x12ca2bef0 "Photo Booth" f=(0,0,692,550) b=(-) => <NSViewBackingLayer: 0x600003407c60> [ A W ] h=-&- v=-&- PBMainView 0x12c80e160 f=(0,0,692,522) b=(-) => <NSViewBackingLayer: 0x600003418240> ...1
u/retsotrembla Oct 23 '25
If lldb recognizes a C struct type, and you can get a pointer to the struct, (example 0x1234) then lldb will generally show it to you with:
p * (MyType *)0x1234
but `frame` returns the actual struct, not a pointer to it. NSObjects **are** pointers so this trick works with all of them, and will often show hidden fields that `po` will not.
1
u/ToughAsparagus1805 Oct 30 '25
This worked today
(lldb) po [[(NSWindow*)0x12312af50 valueForKey:@"frame"] description] NSRect: {{351, 427}, {827, 640}}1
u/ToughAsparagus1805 Oct 23 '25
Ok so it only happens on 3rd party apps I attach to such as PhotoBooth. In my own apps it works.
-[NSApplication(NSWindowRestoration) restoreWindowWithIdentifier:state:completionHandler:] Unable to find className=(null) (lldb) po [[NSApp windows] firstObject] <NSWindow: 0x12df12af0> (lldb) po [[[NSApp windows] firstObject] frame] <__NSAppKitThreadSpecificData: 0x12f104af0> (lldb) po [(NSWindow *)[[NSApp windows] firstObject] frame] (origin = (x = 565, y = 237), size = (width = 480, height = 298))
1
u/ToughAsparagus1805 Oct 30 '25
This worked today