Home iOS & Swift Books Advanced Apple Debugging & Reverse Engineering

Attaching with LLDB Written by Derek Selander

Heads up... You're reading this book for free, with parts of this chapter shown beyond this point as scrambled text.

You can unlock the rest of this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Now that you’ve learned about the two most essential commands, help and 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 
pkill Finder
lldb -f /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder
(lldb) process launch

Options while launching

The 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

Environment variables

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) env
(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 stdout?

(lldb) process launch -o /tmp/ls_output.txt -- /Applications
Process 15194 launched: '/bin/ls' (x86_64)
Process 15194 exited with status = 0 (0x00000000) 
cat /tmp/ls_output.txt
(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) run
(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.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.

Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:

© 2021 Razeware LLC

You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.

Unlock Now

To highlight or take notes, you’ll need to own this book in a subscription or purchased by itself.