In iOS development, I’ve noticed that when I set a breakpoint on a dispatch_*
object (e.g., dispatch_async
) in Xcode, it sometimes allows me to trace back to the original caller of the dispatch. In the call stack view, Xcode shows an entry labeled "(Recorded stack frame)" for the caller.
How can I reproduce this manually?
Rob is right, these originating backtraces are an instance of what lldb calls "extended backtraces" and the way to display them is with the command thread backtrace -e 1
.
You can also access this information from the SB API's using the API:
SBThread::GetExtendedBacktraceThread("libdispatch")
As that form indicates, this is a general feature for program entities that have interesting origin points, though at present libdispatch is the only implementation. You can also use the same API on SBQueue to find out when dispatch queues were created.
The way it works is that when debugging, Xcode inserts a debug version of libdispatch in place of the normal libdispatch dylib. The debug version keeps track of originating threads and provides a set of API's to return this info. lldb calls these API's in the program being debugged to fetch the information when you ask for the extended backtrace.
If you are super-curious, the lldb side of this work is implemented in the function SystemRuntimeMacOSX::GetExtendedBacktraceThread in this file:
Command-line lldb won't insert the debug dylib by default, though it will use it if it is present. In Xcode, the feature is controlled by the "Queue Debugging" checkbox in the Options tab of the Run Scheme.