# How to use a Debugger

For many, a debugger is an essential tool for the process of writing functional programs. While some prefer "manual" debugging, e.g., through adding various log or print statements, a debugger can greatly accelerate the process (if used correctly).

***

## Why should you use a debugger?

When it comes to Assembly programming, a debugger is almost indispensable. *Why is that so?* You may suspect that a function is misbehaving because something is wrong with the arguments that are passed. To confirm this suspicion you would want to know what values are present in the registers at a certain moment in time (→ a certain line of your program). However, if you test this by adding a call to `printf` this call will change the state of various (caller-saved) registers.

Another common issue is with segmentation faults. When your program crashes due to a segmentation fault you can only estimate the location in the code that caused the segmentation fault by the progress of your program (e.g., through its output). However, depending on the program, this might still be a very wide range of possible locations for the issue. A debugger, on the other hand, is able to determine the exact line that caused the segmentation fault.

***

## Starting the Debugger

The recommended approach is to use the LLDB debugger through the VS Code interface. Thereby, you can graphically follow the progress of your program, examine register states, and set breakpoints - without needing to type commands. The framework already has this setup configured for you. You can find an explanation of how to start the debugger in the `README.md` file.

{% hint style="warning" %}
If you are on Windows, make sure that your **VS Code is running through WSL**, otherwise the debugger will not work. You can validate this by checking whether the bottom left corner of the window shows a small blue box with the "WSL: Ubuntu" text in it: <img src="/files/g6JVLA4TjDh7lGK6NoQn" alt="" data-size="line">

To open VS Code through WSL, follow the last step of the [Windows Setup Guide](/co-lab-manual/setup-guides/technical-setup/windows.md#step-5-open-vs-code-from-wsl).
{% endhint %}

<details>

<summary>Command Line Debugger</summary>

If you prefer a command line debugger (instead of one with a GUI) you can also use the `lldb` or `gdb` commands in your terminal. For gdb, you can furthermore install the [GEF extension](https://github.com/hugsy/gef) for some advanced features and a more easily usable command line interface. To get started with GEF, you can follow the [Nightmare Guide](https://guyinatuxedo.github.io/02-intro_tooling/gdb-gef/index.html), which gives an introduction to the debugger.

Gdb is furthermore scriptable. If you are interested in this, you may want to read the [pwntools-tutorial Guide](https://github.com/Gallopsled/pwntools-tutorial/blob/master/debugging.md) on debugging.

</details>

***

## Using the Debugger

{% hint style="info" %}
This is merely an introductory guide to using a debugger. It should be sufficient to get you started with debugging your assignments. However, most debuggers offer much more (complex) functionality and it is highly recommended to consider further sources (debugger manuals/online tutorials/...) to extend your debugging toolbox.
{% endhint %}

### Breakpoints

You may have noticed that a small red dot appears when you are hovering over the line numbers in your VS Code editor. These red dots indicate the option to set a breakpoint. If you click such a faded red dot, it should become more prominent and remain visible even when you move the mouse somewhere else. You have just set your first breakpoint!

*But what even is a breakpoint?* A breakpoint is, as the name suggests, a point at which your program execution should stop (→ break) when run through the debugger. You can set as many breakpoints as you want (or at least as you have lines) and you can even set *conditional* breakpoints (however, that may go beyond the basics of using a debugger - and with that beyond this guide).

### Controls

Once you have set some breakpoints, you can start the debugger (as described in the `README.md`). This will first assemble and link your program and then start the debugger with your program as the input. You will notice that a small bar with controls will have appeared in your VS Code window, looking something like the one shown below:

<picture><source srcset="/files/EZyVLTO5FU53nipgiJBc" media="(prefers-color-scheme: dark)"><img src="/files/pYOFTNfJgsjrYnmjaQMA" alt=""></picture>

Let's break down the individual controls (from left to right):

* **Continue (F5)**\
  In this example, the debugger is currently stopped at a breakpoint. The Continue button resumes the program execution (until reaching the next breakpoint)
* **Step Over (F10)**\
  Instead of resuming the execution until the next breakpoint, instructions can also be executed one by one. The Step Over will execute the next instruction. However, as the name suggests, it will *step over* any function/subroutine calls. So if the next instruction of the program is a `call` instruction, it will continue the execution until the program reaches the next instruction **after** the call.
* **Step Into (F11)**\
  Similarly to Step Over, Step Into also executes a single instruction. However, as opposed to the former, it will *step into* any function/subroutine calls. So if the next instruction of the program is a `call` it will stop at the first instruction of the subroutine that is called.\
  **Note:** whether this also works for Library functions (like `printf`) depends on the system. On some systems, it will simply *step over* library function calls.
* **Step Out (⇧F11 | Shift + F11)**\
  As you can s\_tep into\_ a function/subroutine you can also *step out*. This will continue the program execution until the current function/subroutine returns.
* **Restart (⇧⌘F5 | Ctrl + Shift + F5)**\
  As the name suggests, this will *restart* the current debugger configuration. So it will rebuild the program and start the debugger again.
* **Stop** **(⇧F5 | Shift + F5)**\
  Again, as the name suggests, this will *stop* the debugger.

### Registers

The debugger not only allows you to take control over the individual execution steps of your program but it also allows you to examine the status of the CPU registers.

To do so, open the "Run and Debug" panel ("View" → "Run" | ⇧⌘D | Ctrl + Shift + D) while the debugger is running. You should see the label "VARIABLES" in this panel. Upon extending this label, you should see various categories, one of which is labeled "Registers". Here, you will find information about all (relevant) CPU registers. Most interesting for you will be the group of "General Purpose Registers".

You can use this view to examine the current register values, but also to change the values to any desired value.

### Memory

Often you are not only interested in the data stored in your registers, but also in the data stored in memory, such as the stack.

To examine the memory contents, simply hover over a register that holds the associated address (e.g., `rsp` for the stack) and click the small <picture><source srcset="/files/rp9lNABy7OAfVuHyty20" media="(prefers-color-scheme: dark)"><img src="/files/QOttPny5HcxnlKuOuj3L" alt="" data-size="line"></picture> icon on the right.

This will open a file with the raw contents of that (and the following) memory addresses. I you installed the recommended extensions of the framework, this page should open in a Hex Viewer.

{% hint style="warning" %}
Note that the memory view does not automatically update when you advance in your program. It will stay as a snapshot from when it was opened.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://computerscienceeducation.gitbook.io/co-lab-manual/appendix/how-to-use-a-debugger.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
