Chapters

Hide chapters

Advanced Apple Debugging & Reverse Engineering

Fourth Edition · iOS 16, macOS 13.3 · Swift 5.8, Python 3 · Xcode 14

Section I: Beginning LLDB Commands

Section 1: 10 chapters
Show chapters Hide chapters

Section IV: Custom LLDB Commands

Section 4: 8 chapters
Show chapters Hide chapters

6. Thread, Frame & Stepping Around
Written by Walter Tyree

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

You’ve learned how to create breakpoints, how to print and modify values, as well as how to execute code while paused in the debugger. But so far, you’ve been left high and dry on how to move around in the debugger and inspect data beyond the immediate scope. It’s time to fix that!

In this chapter, you’ll learn how to move the debugger in and out of code while lldb has suspended a program.

This is a critical skill to have since you often want to inspect values as they change over time when entering or exiting snippets of code.

Stack 101

When a computer program executes, it stores values in the stack and the heap. Both have their merits. As an advanced debugger, you’ll need to have a good understanding of how these work. Right now, let’s take a brief look at the stack.

You may already know the whole spiel about what a stack is in computer science terms. In any case, it’s worth having an intro/refresher of how a process keeps track of code and variables when executing.

The stack is a LIFO (Last-In-First-Out) queue that stores references to your currently executing code. This LIFO ordering means that whatever is added most recently, is removed first. Think of a stack of plates. Add a plate to the top, and it will be the one you take off first.

The stack pointer points to the current top of the stack. In the plate analogy, the stack pointer points to that top plate, telling you where to take the next plate from, or where to put the next plate on.

Migrating the plates analogy to the stack in computer memory, now imagine the plates had Velcro and were attached to the ceiling. Each time you added a plate onto the last one, the stack would grow downwards towards the floor.

In this diagram, the high address is shown at the top (0xFFFFFFFF) and the low address is shown at the bottom (0x00000000) demonstrating that the stack grows downwards.

You’ll take an in depth look at the stack pointer and other registers in Chapter 13, “Assembly & the Stack”, but in this chapter you’ll explore various ways to step through code that is on the stack.

Examining the Stack’s Frames

You’ll continue to use the Signals project for this chapter.

Signals.MainViewController.viewWillAppear

(lldb) thread backtrace
(lldb) frame info
frame #0: 0x0000000104a7edcc Signals`MainViewController.viewWillAppear(animated=false, self=0x0000000000000000) at MainViewController.swift:53
(lldb) frame select 1

Stepping

There are 3 essential stepping actions you can do while a program is paused to execute one “chunk” of code and then re-suspend program execution. Through lldb, you can step over, step in, or step out of code.

Stepping Over

Stepping over allows you to step to the next code statement in a particular frame. This means if the current statement is calling another function, lldb will run until this function has completed and returned.

(lldb) run

(lldb) next

Stepping In

Stepping in means if the next statement is a function call, the debugger will move into the start of that function and then pause again.

(lldb) run
(lldb) step
(lldb) settings show target.process.thread.step-in-avoid-nodebug
(lldb) step -a0

Stepping Out

Stepping out means a function will continue for its duration then stop when it has returned. From a stack viewpoint, execution continues until the stack frame is popped off. If you’re having a hard time visualizing this, remember the plates attached to the ceiling. A plate is removed and the stack pointer is now higher as it’s closer to the ceiling.

(lldb) finish

Stepping in the Xcode GUI

Although you get much more fine-grained control using the console, Xcode already provides these options for you as buttons just above the lldb console. These buttons appear when an application is running.

Examining Data in the Stack

A very interesting option of the frame command is the frame variable subcommand. This command will take the debug symbol information found in the headers of your executable, or a dYSM if your app is stripped… more on that later, and dump information for that particular stack frame into the console. Thanks to the debug information, the frame variable command can easily tell you the scope of all the variables in your function as well as any global variables within your program using the appropriate options.

(lldb) frame variable
(Bool) animated = false
(Signals.MainViewController) self = 0x0000000138f0a770 {
  UIKit.UITableViewController = {
    baseUIViewController@0 = {
      baseUIResponder@0 = {
        baseNSObject@0 = {
          isa = Signals.MainViewController
        }
      }
      _overrideTransitioningDelegate = 0x0000000000000000
      _view = some {
        some = 0x000000013a016e00 {
          baseUIScrollView@0 = {
            baseUIView@0 = {
              baseUIResponder@0 = {
... etc ...

Key Points

  • In a stack trace, each level is called a frame.
  • The thread backtrace and frame info commands provide similar information to Xcode’s Debug navigator pane.
  • frame select lets you switch lldb to a different frame in the stack trace.
  • The run command relaunches your application without recompiling it.
  • Use the next command to advance your app by one line.
  • The step command will step into a function. Add the -a0 switch to step into functions that are not your code.
  • Use finish or thread return to step out of a function.
  • frame variable, v and vo are all ways to dump information about the current frame into the console.

Where to Go From Here?

In this chapter, you’ve explored stack frames and the content in them. You’ve also learned how to navigate the stack by stepping in, out, and over code.

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.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now