14

Little-known fact: It is now possible, in Xcode, while paused in the debugger, to introspect the notification center to learn what objects are registered to receive what notifications:

(lldb) po NotificationCenter.default

<NSNotificationCenter:0x6040000d40b0>
Name, Object, Observer, Options
com.apple.accessibility.reduce.motion.status, 0x10b126190, 0x7fc795700140, 1001
com.apple.accessibility.asst.scanner.status, 0x10b126190, 0x7fc795700140, 1001
// ... etc. ...

Very nice, but how do I go from obtaining the memory address 0x7fc795700140 to learning what object that is?

EDIT I'm leaving this question here, but I think the correct answer is the kind of thing shown at LLDB (Swift): Casting Raw Address into Usable Type

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I think I got lucky with `po
    as NSObject` to first get the object, and then try as native type (but in my recollection, both were the same)
    – Chris Conover Jul 23 '20 at 17:15

3 Answers3

22

The Swift equivalent of Phillip's answer is:

(lldb) expr -l objc -O -- 0x7fc795700140
<UIApplication: 0x7fc795700140>
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 3
    Hi – that's neat, but how to I get a value that I can then send methods to, please? – Benjohn Apr 13 '18 at 13:09
  • @Benjohn well presumably you recognize the object and know how to refer to it – matt Apr 13 '18 at 14:05
  • @AlexZavatone What's this edit about? I thought you had to talk in Objective-C to make this work. If you could just say it in swift you wouldn't need the language designator at all. – matt Apr 16 '20 at 21:12
  • Hi Matt. I just updated the edit. The commands that I pasted in show how to print out the object contents when given only a memory address if the debugger is looking at an Objective-C class or a Swift class. What I've seen is that it's really easy to screw this up and located my reference samples that I used in the past. Matt! Hey, it's you! I neglected to notice Mr. Neuburg. I'll email you. – Alex Zavatone Apr 16 '20 at 21:36
  • 1
    @AlexZavatone Sorry, I'm not convinced. Feel free to give your own answer, though! – matt Apr 16 '20 at 23:45
  • This is the Swift equivalent that I used. `expr -l swift -O -- 0x7fc795700140`. The exact text that you have DOES work but only for Objective-C object instances. I'm confused that you said "The Swift equivalent is" and then used an LLDB expr command that tells it to search for an Objective-C object. I tested these both rigorously tracking down 1400+ memory leaks. Anyway. Cheers man. – Alex Zavatone Apr 17 '20 at 00:17
  • FYI, (e -l is useful in other contexts too. e -l Swift allows you to run Swift code even when your stack frame is Objective-C.) – Alex Zavatone Apr 17 '20 at 18:45
10

po works for addresses (In Objective-C/Mac context, at least)

e.g.:

(lldb) po [NSNotificationCenter defaultCenter]

NSWindowDidResizeNotification, 0x7fff9a0e98e0, 0x6100001246a0, 1400

(lldb) po 0x6100001246a0

ExpandOneView: 0x6100001246a0

Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • 1
    Hi Phillip! Alas, `(lldb) po 0x7fc795700140` OMM results in `140495182364992`. Maybe because this is neither Objective-C nor Mac OS. – matt Aug 02 '17 at 15:10
  • 3
    Okay, I see how to do it: `expr -l objc -O -- 0x7fc795700140` gives the result you got. – matt Aug 02 '17 at 15:15
  • 5
    Maybe relevant background: It helps to remember that `po` is just an alias for `expr -O --`. What it does is evaluate the expression after the -- in the given (or current frame's) language, then call its "language appropriate description method". In the case of ObjC lldb also implicitly casts the result of the expression to `id` before sending the description message. Swift doesn't have a base object type in this way, leaving us no good way to call description on something we know only as an Int, so we can't play the same trick for Swift. – Jim Ingham Aug 02 '17 at 17:42
8

First, the LLDB commands I used.

(lldb) expr -l objc -O -- 0x600001582d00

<__NSArrayI 0x600001582d00>(
<UIStoryboardShowSegueTemplate: 0x600002c3e4c0>,
<UIStoryboardPresentationSegueTemplate: 0x600001582210>,
<UIStoryboardPresentationSegueTemplate: 0x600001582620>,
<UIStoryboardShowSegueTemplate: 0x600002c3f4c0>,
<UIStoryboardPresentationSegueTemplate: 0x6000015839d0>,
<UIStoryboardShowSegueTemplate: 0x600002c3d680>,
<UIStoryboardEmbedSegueTemplate: 0x600002c3dc40>
)

For an instance of a Swift class.

expr -l swift -O -- 

For an instance of an Objective-C class.

expr -l objc -O --

For an instance of a C class.

expr -l c -O --

Now, an explanation. I had the joy of fixing over 1400 lemory leaks in our jr. iOS developers' code. Often when in the Memory Graph Debugger, and I was inspecting leaked objects, all that I had was the object’s address in memory. This was in an Objective-C and Swift app, so we had to be able to inspect objects from both languages. While in LLDB, I had to specify the language of the variable at the memory address being inspected. This worked in Swift and Objective-C. What I provided above is sample output and examples of the command for Swift, Objective-C and C.

Alex Zavatone
  • 4,106
  • 36
  • 54