Heads up... You're reading this book for free, with parts of this chapter shown beyond this point astext.
Now that you’ve learned about the two most essential commands,
apropos, it’s time to investigate how LLDB attaches itself to processes. You’ll learn all the different ways you can attach LLDB to processes using various options, as well as what happens behind the scenes when attaching to processes.
The phrase of LLDB “attaching” is actually a bit misleading. A program named
debugserver (found in
Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/) is responsible for attaching to a target process.
If it’s a remote process, such as an iOS, watchOS or tvOS application running on a remote device, a remote
debugserver gets launched on that remote device. It’s LLDB’s job to launch, connect, and coordinate with the
debugserver to handle all the interactions in debugging an application.
Attaching to an existing process
As you’ve already seen in Chapter 1, you can attach to a process like so:
lldb -n Xcode
However, there are other ways to do the same thing. You can attach to Xcode by providing the process identifier, or PID, of a running program.
Note: Just a reminder, if you didn’t disable SIP on your macOS computer, you will not be able to attach LLDB to Apple applications. Attaching to 3rd party applications (even from the App Store!) is still possible as of version 10.14.1 in Mojave provided there are no anti-debugging techniques in the application.
Open Xcode, then open a new
Terminal session, and finally run the following:
pgrep -x Xcode
This will output the PID of the Xcode process.
Next, run the following, replacing
89944 with the number output from the command above:
lldb -p 89944
This tells LLDB to attach to the process with the given PID. In this case, this is your running Xcode process.
Attaching to a future process
The previous command only addresses a running process. If Xcode isn’t running, or is already attached to a debugger, the previous commands will fail. How can you catch a process that’s about to be launched, if you don’t know the PID yet?
lldb -n Finder -w
lldb -f /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
(lldb) process launch
Options while launching
process launch command comes with a suite of options worth further exploration. If you’re curious and want to see the full list of available options for
process launch, simply type
help process launch.
lldb -f /bin/ls
(lldb) target create "/bin/ls" Current executable set to '/bin/ls' (x86_64).
(lldb) process launch
Process 7681 launched: '/bin/ls' (x86_64) ... # Omitted directory listing output Process 7681 exited with status = 0 (0x00000000)
(lldb) process launch -w /Applications
$ cd /Applications $ ls
(lldb) process launch -- /Applications
$ ls /Applications
(lldb) process launch -- ~/Desktop
Process 8103 launched: '/bin/ls' (x86_64) ls: ~/Desktop: No such file or directory Process 8103 exited with status = 1 (0x00000001)
(lldb) process launch -X true -- ~/Desktop
(lldb) help run
... Command Options Usage: run [<run-args>] 'run' is an abbreviation for 'process launch -X true --'
(lldb) run ~/Desktop
For Terminal programs, environment variables can be equally as important as the program’s arguments. If you were to consult the
man 1 ls, you’ll see at that the
ls command can display output in color so long as the color environment variable is enabled (
CSICOLOR) and you have the “color pallete” environment variable
LSCOLORS to tell how to display certain filetypes.
(lldb) process launch -v LSCOLORS=Ab -v CLICOLOR=1 -- /Applications/
(lldb) process launch -v LSCOLORS=Af -v CLICOLOR=1 -- /Applications/
LSCOLORS=Af CLICOLOR=1 ls /Applications/
stdin, stderr, and stout
What about changing the standard streams to a different location? You’ve already tried changing
stderr to a different Terminal tab in Chapter 1 using the
-e flag, but how about
(lldb) process launch -o /tmp/ls_output.txt -- /Applications
Process 15194 launched: '/bin/ls' (x86_64) Process 15194 exited with status = 0 (0x00000000)
(lldb) target delete
(lldb) target create /usr/bin/wc
echo "hello world" > /tmp/wc_input.txt
(lldb) process launch -i /tmp/wc_input.txt
Process 24511 launched: '/usr/bin/wc' (x86_64) 1 2 12 Process 24511 exited with status = 0 (0x00000000)
$ wc < /tmp/wc_input.txt
(lldb) process launch -n
Process 28849 launched: '/usr/bin/wc' (x86_64) Process 28849 exited with status = 0 (0x00000000)
Where to go from here?
There are a few more interesting options to play with (which you can find via the
help command), but that’s for you to explore on your own time.