Gives complete trace of a function execution including all sub-calls.
- Attach to a process, for example to
SimpleTraceTarget
contained in this repository:$ lldb -p `pgrep SimpleTrace`
- Import the trace script:
(lldb) command script import $DIR/trace.py
- Stop the process execution at the root function you're interested in tracing, e.g. using breakpoints.
- Trace:
(lldb) trace
- Output:
a + 0x1c ==> b
b + 0xd ==> usleep
usleep + 0x0 === usleep + 0x0
usleep + 0x31 ==> nanosleep
nanosleep + 0x0 === nanosleep + 0x0
nanosleep + 0x25 ==> pthread_testcancel
pthread_testcancel + 0x0 === pthread_testcancel + 0x0
pthread_testcancel + 0x20 === _pthread_testcancel + 0x0
_pthread_testcancel + 0x17 ==> OSSpinLockLock
OSSpinLockLock + 0x0 === _spin_lock + 0x0
_pthread_testcancel + 0x1c <==
_pthread_testcancel + 0x22 ==> OSSpinLockUnlock
OSSpinLockUnlock + 0x0 === _spin_unlock + 0x0
_pthread_testcancel + 0x27 <==
nanosleep + 0x2a <==
nanosleep + 0xc3 ==> __semwait_signal
__semwait_signal + 0x0 === __semwait_signal + 0x0
Syscall 0x000000000200014e
__semwait_signal + 0xf === cerror + 0x0
cerror + 0x8 ==> _pthread_exit_if_canceled
_pthread_exit_if_canceled + 0xa === _pthread_exit_if_canceled + 0x0
cerror + 0xd <==
cerror + 0xf ==> cerror_nocancel
cerror + 0x14 <==
nanosleep + 0xc8 <==
nanosleep + 0xcc ==> __error
__error + 0x0 === __error + 0x0
nanosleep + 0xd1 <==
usleep + 0x36 <==
b + 0x12 <==
a + 0x21 <==
where ==>
denotes call to a function, ===
jmp to a different symbol, <==
is a return, Syscall ID
is where a syscall of a given ID
is executed.
(lldb) trace -h
gives a list of options trace
accepts, currently:
Options:
-h, --help show this help message and exit
-v, --verbose Produce verbose output, useful for debugging
-f FILE, --file=FILE Redirect output to the specified file
-s, --stdout Log to stdout directly, which is against lldb policy,
but produces incremental output (flush works)
-m, --module-only Trace only in the module where root symbol was defined
trace
can trace any symbol in the current execution backtrace. Select the desired frame with(lldb) frame select FRAME_ID
before executingtrace
- Long-running
trace
doesn't produce any output by default, until the command execution is finished (seems to be by design).trace
makes it possible to produce incremental output by either outputing to a specified file(lldb) trace -f FILE
or by outputting directly to stdout (this may not always work properly since it's against the LLDB's policy)(lldb) trace -s
- If you're not interested in calling external symbols (external to the binary module in which the root symbol is defined) use
(lldb) trace -m
. Every time extrenal symbol is detected appropriate message (such asNot instrumenting since module X isn't the same as Y
) will be printed.
- Verbose output is available with
(lldb) trace -v
- If tracing fails, some of the breakpoints established for tracing may be left over. They are usually easy to distinguish from other breakpoinst since they are per thread (
Options: enabled tid: X
). All breakpoints can be deleted with(lldb) breakpoint delete
Ctrl-C
in LLDB session should stop the tracing, in some circumstances however (if the program managed to break-out from thetrace
's control), tracing may have to be stopped by sending the target process a singnal (e.g.$ pkill X
).
(lldb) trace -m
should give an ability to trace overobjc_sendMsg
- LLDB config for autoimporting
- wrapper script for running from breakpoint command (
breakpoint command add -F trace.trace_wrapper ID
)