Search code examples
xcodedebuggingbreakpoints

How to find which call caused the symbolic breakpoint?


I put in a symbolic breakpoint, and it's gone off:

enter image description here

The thread and backtrace are below.

I don't understand, in Xcode, how to find what actually was called when the symbolic breakpoint went off. Or even, how to know which UIView it was.

(I can see that it's in a tableview, but it could be anywhere in any number of tableviews.)

How is this done?

UIKit`-[UIView(Hierarchy) layoutIfNeeded]:
->  0x10fd4d2ec <+0>:  pushq  %rbp
    0x10fd4d2ed <+1>:  movq   %rsp, %rbp
    0x10fd4d2f0 <+4>:  pushq  %rbx
    0x10fd4d2f1 <+5>:  pushq  %rax
    0x10fd4d2f2 <+6>:  movq   %rdi, %rbx
    0x10fd4d2f5 <+9>:  leaq   0x1128470(%rip), %rax     ; _UIApplicationLinkedOnVersion
    0x10fd4d2fc <+16>: movl   (%rax), %eax
    0x10fd4d2fe <+18>: testl  %eax, %eax
    0x10fd4d300 <+20>: je     0x10fd4d30b               ; <+31>
    0x10fd4d302 <+22>: cmpl   $0x60000, %eax            ; imm = 0x60000 
    0x10fd4d307 <+27>: jb     0x10fd4d325               ; <+57>
    0x10fd4d309 <+29>: jmp    0x10fd4d319               ; <+45>
    0x10fd4d30b <+31>: movl   $0x60000, %edi            ; imm = 0x60000 
    0x10fd4d310 <+36>: callq  0x10fc9c15d               ; _UIApplicationLinkedOnOrAfter
    0x10fd4d315 <+41>: testb  %al, %al
    0x10fd4d317 <+43>: je     0x10fd4d325               ; <+57>
    0x10fd4d319 <+45>: movq   0x1099810(%rip), %rsi     ; "layoutBelowIfNeeded"
    0x10fd4d320 <+52>: movq   %rbx, %rdi
    0x10fd4d323 <+55>: jmp    0x10fd4d337               ; <+75>
    0x10fd4d325 <+57>: movq   0x10d80b4(%rip), %rax     ; UIView._layer
    0x10fd4d32c <+64>: movq   (%rbx,%rax), %rdi
    0x10fd4d330 <+68>: movq   0x1095809(%rip), %rsi     ; "layoutIfNeeded"
    0x10fd4d337 <+75>: addq   $0x8, %rsp
    0x10fd4d33b <+79>: popq   %rbx
    0x10fd4d33c <+80>: popq   %rbp
    0x10fd4d33d <+81>: jmpq   *0xdcd04d(%rip)           ; (void *)0x000000010e558ac0: objc_msgSend

and the backtrace...

(lldb) bt
* thread #1: tid = 0x28e3d, 0x000000010fd4d2ec UIKit`-[UIView(Hierarchy) layoutIfNeeded], queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x000000010fd4d2ec UIKit`-[UIView(Hierarchy) layoutIfNeeded]
    frame #1: 0x000000010fd54239 UIKit`+[UIView(Animation) performWithoutAnimation:] + 90
    frame #2: 0x000000010fe08718 UIKit`-[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 1161
    frame #3: 0x000000010fe087e2 UIKit`-[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
    frame #4: 0x000000010fddc2b0 UIKit`-[UITableView _updateVisibleCellsNow:isRecursive:] + 3295
    frame #5: 0x000000010fe11b64 UIKit`-[UITableView _performWithCachedTraitCollection:] + 110
    frame #6: 0x000000010fdf83be UIKit`-[UITableView layoutSubviews] + 222
    frame #7: 0x000000010fd5fab8 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1237
    frame #8: 0x000000010f6edbf8 QuartzCore`-[CALayer layoutSublayers] + 146
    frame #9: 0x000000010f6e1440 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 366
    frame #10: 0x000000010f6e12be QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 24
    frame #11: 0x000000010f66f318 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 280
    frame #12: 0x000000010f69c3ff QuartzCore`CA::Transaction::commit() + 475
    frame #13: 0x000000010f69cd6f QuartzCore`CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 113
    frame #14: 0x000000010ea85267 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    frame #15: 0x000000010ea851d7 CoreFoundation`__CFRunLoopDoObservers + 391
    frame #16: 0x000000010ea69f8e CoreFoundation`__CFRunLoopRun + 1198
    frame #17: 0x000000010ea69884 CoreFoundation`CFRunLoopRunSpecific + 420
    frame #18: 0x00000001149eda6f GraphicsServices`GSEventRunModal + 161
    frame #19: 0x000000010fc9ac68 UIKit`UIApplicationMain + 159
    frame #20: 0x000000010dbd0bcf DevSF`main + 111 at AppDelegate.swift:12
    frame #21: 0x0000000111c8068d libdyld.dylib`start + 1
(lldb) 

Solution

  • You need to show the "watch window" using the highlighted button in the bottom right corner:

    button.

    button zoomed

    The watch window will look somtehing like

    XCode watch windows

    and there you can see self. Note that if you put breakpoint at arbitrary asm, it might not get reasonable values there because Obj-c method call is a bit complicated in asm. Symbolic breakpoints at methods entries typically work OK in this respect.

    If you want to go one level deeper you should learn lldb command interface. You may start at this LLDB cheat sheet and GDB and LLDB Command Examples Apple's doc