# Developer's Guide for Debugging Radare2

This document explains common development practices used to debug radare2
in order to find, identify and fix bugs, memory corruptions, leaks or race
conditions.

## Compilation

When changing your code you need to rebuild r2 to test it. In case you use ACR/Make
you just need to type `make` in the directory where you changed the code. But if you
use `meson` you must run `ninja -C ../../b` instead.

Bear in mind that meson tracks source dependencies more deeply than acr/make, so it's
possible that for some changes in `.h` files `meson` builds will require a full
recompilation, while `make` could just be faster and handier.

The reason why source build changes are available system wide is because the default
installation method `./sys/install.sh` uses `sudo make symstall` which creates
symlinks instead of copying the executables, libraries and support files to $PREFIX.

Other important `CFLAGS` are:

* `-Wall` - show more warnings useful to improve code quality
* `-Wshadow` - show if you have variables with the same name in nested scopes
* `-w` - in case `-Werror` is set, stop treating warnings as errors

## Multiple r2

In order to develop for r2 it is common to have two or more builds of radare2,
so you can compare `master` behaviour with your patched code at any time.

You can achieve this in different ways, but bear in mind that using `--with-rpath`
for meson or acr builds is important to avoid having one r2 using the other r2's
libraries.

* Use ACR source build for your patched code
* Keep a --with-rpath meson build in a custom directory for running it
* Statically build r2 (`sys/static.sh`)
* Use `r2env` to switch between release or git builds

## Symbols

By default radare2 is compiled with debug symbols, but in case the source-line
information is not available you may want to set the `CFLAGS=-g` before calling
`./configure` or `meson b`.

## ASAN

Stands for Address Sanitizer and it's a compiler plugin available for clang, gcc
and msvc that adds extra checks in the generated binary, which permits to identify
many types of bugs.

* undefined: behaviour (binary operations on signed variable)
* memory: uninitialized variables (compiler warnings may catch that too)
* thread: sanitizer - detect race conditions and deadlocks
* address: memory corruption, read and write overflows
* leak: track memory usage and detect memory leaks

In case you are coming from another branch or another non-sanitized build you may
want to have a clean build dir. To do this, reset your git state into a clean state.

```
$ make mrproper
$ git clean -xdf
```

Works like valgrind, but faster. Use `sys/sanitize.sh` to get that build ready to use.

```
$ export SANITIZE=$leak memory address"
$ sys/sanitize.sh
```

Now you can just run `r2` and get a nice crash report without the need of a debugger.

But it is also compatible with any debugger like `gdb` or `lldb`.

## Valgrind

It's a Linux tool that pseudo-emulates programs in order to detect runtime memory
corruption problems and other types (like the ones listed above).

Valgrind was working on macOS and other BSDs, but it lacks for that porting. So
we may want to use it only when we are on Linux and we dont want to modify the
binary we want to execute.

There are different *plugins* that can be used for different purposes:

### Memory Profiling

By default *valgrind* will identify `undefined behaviour`, `memory corruptions`,
`race conditions` and more. Just call it like this:

```
$ valgrind r2 /bin/ls
```

### Time Profiling

Identifying bottlenecks is an important thing to do when looking for optimizations.
This can be achieved with `callgrind` which is a plugin for tracing function calls
and profile the time spent on them, specifying how many times are called.

```
$ valgrind --tool=callgrind --dump-instr=yes --simulate-cache=yes --collect-jumps=yes \
    /usr/local/bin/r2 /bin/ls
```

To visualize the generated logs use `kcachegrind`

```
kcachegrind callgrind.*
```

## GPerfTools

This package can be used on macOS or Linux systems and uses *tcmalloc* to track heap
allocations and create a graph with the memory allocated by each function during the
execution.

```
$ brew ls gperftools
$ DYLD_INSERT_LIBRARIES=/opt/homebrew/Cellar/gperftools/2.9.1_1/lib/libtcmalloc.4.dylib \
  HEAPPROFILE=/tmp/b.txt \
  r2 /bin/ls
$ pprof --web /usr/local/bin/radare2 /tmp/b.txt*
```

## Frida-Trace

One of the tools shipped with `frida` is `frida-trace`, and allows us to trace function
calls easily, and visualize their arguments, what they return and its backtraec.

```
$ frida-trace -i 'r_core_cmd*' r2 /bin/ls
```

## Debuggers

You can also debug r2 using `gdb`, `lldb`, `x64dbg` or any other debugger you like.

Launching lldb and r2 in the same terminal it's usually handy, unless you are going to debug
a bug in visual or panels mode, because the terminal configuration may be different. In
those cases you may want to attach to the process by calling it with `lldb -p <pidofr2>`

## PD

Read the `DEVELOPERS.md` document for more development and debugging tips!

--pancake
