Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/assets/rdev26.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/rdev27.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/rdev28.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
116 changes: 116 additions & 0 deletions docs/tutorials/debugging_with_lldb.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#### 1. Go to the Source Directory

Rebuild R with debugging symbols so LLDB can access C source lines and
variables. Make sure your build uses the `-g` flag. Open a bash terminal
Comment on lines +3 to +4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They may have already built R with the correct CFLAGS. So here we can say something like:

Suggested change
Rebuild R with debugging symbols so LLDB can access C source lines and
variables. Make sure your build uses the `-g` flag. Open a bash terminal
If you have not yet built a version of R-devel, follow the [Building R](<link>) instructions, including the optional step to set `CFLAGS="-g -O0"`.
Otherwise, change to the build directory and check the `CFLAGS` configuration:
```bash
cd $BUILDDIR
R CMD config CFLAGS
```
If the output begins `-g 02`, you should reconfigure and rebuild R. Start from [Step 5](<link needed>) in the Building R tutorial.
Once you have a version of R-devel configured with `CFLAGS="-g -O0"`, use `which_r` to switch to this version.

You need to add the relevant links: "Step 5" should link to "5) Set CFLAGS (Optional—For Debugging C Code)" - you will need to add an anchor somehow, it may be easier to convert the item headers to proper HTML headings of the appropriate level.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we will update the docs to always use CFLAGS="-g -O0", we can delete this part. It is probably best to start with a step like:

#### 1. Switch to a built version of R

Use `which_r` to switch to a version of R you have built in the devcontainer, e.g. `r-devel`.

and then go on to launch an R terminal, etc.

and navigate to the root of your project’s source directory.

```bash
cd $TOP_SRCDIR
```

#### 2. Run R Using the Debug Wrapper Script

Run R through the wrapper script (`launch_r.sh`) that
sets up `LD_PRELOAD` and debugging environment:

```bash
./scripts/launch_r.sh
```

This ensures the ptrace helper library is loaded
for debugging support.
Comment on lines +5 to +21
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user does not have to do this, the way which_r updates the VS Code settings means that the launch_r script is run when they start an R terminal.


#### 3. Attach LLDB to the Running R Process

Find the process ID (PID) of your R session. You
can do this within R, Start an R terminal by using
the command R in the terminal,then:
Comment on lines +25 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

People should not run R in the bash terminal, they should start an R terminal, e.g. by clicking on R (not attached) or by using the Command Palette. We don't need to document how to start an R terminal as that is covered in an earlier tutorial.

Suggested change
Find the process ID (PID) of your R session. You
can do this within R, Start an R terminal by using
the command R in the terminal,then:
Start an R terminal and find the process ID (PID) of the R session using


```r
Sys.getpid()
```

Attach LLDB to this PID, using the command palette type
`LLDB: Attach to Process` then select the PID you just
got or you can do this via the terminal:

```bash
lldb -p <PID>
```
Comment on lines +33 to +39
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The aim is not to use lldb from the command line, but to use the LLDB extension as I demoed in our meeting the other week. So once you have the pid from R, go to the Run and Debug panel and click the green arrow (Start Debugging to launch the debugger (as defined in the launch.json file). This opens a dialog where you type in the pid to select the R process to attach to.


#### 4. Set a Breakpoint in Native C Code

For example, to debug `rlogis.c`, set a breakpoint at
the start of its function in `rlogis.c` (line 25):

```lldb
breakpoint set --file rlogis.c --line 25
```

You can do this by clicking the r
ed dot on the left side
of a line in a program as shown i
n the screenshot below:
Comment on lines +50 to +53
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These lines should not be so narrow! it should be okay to have lines that are 80 characters width.


![alt text](../assets/rdev26.png)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshots should not use dark mode - ideally they would be take from GitHub Codespaces as that is the default interface, but of course that requires #267 to be merged in first, so using light mode locally should be okay.


#### 5. Trigger the Function in R

Use this command directly in the LLDB debug
console to call the C function and see its
result:

```lldb
expr (double)rlogis(1.0, 1.0)
```
Comment on lines +59 to +65
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that we trigger the breakpoint from R. So within the R terminal, we type the R command

rlogis(1)

This R wrapper will call the C function and stop at the breakpoint in the C code.


This will activate your breakpoint and pause
at the specified line for inspection as shown
below.

![alt text](../assets/rdev27.png)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When it is working correctly it should look like this:

image


#### 6. Debugging Actions in LLDB

After pausing at a breakpoint, use the LLDB
toolbar buttons and commands to control execution:

- **Continue Execution:** Resume running until
the next breakpoint (Run icon ▷ in blue).
- **Step Through the Code:** Move line-by-line,
stepping into functions (Step Into ↓ in blue)
or stepping out of the current function
(Step Out ↑ in blue).
- **Stop Execution:** Pause the running process
(interrupt command, icon may not always be shown).
- **Additional Controls:**
ack (↶ in blue) for reverse debugging
if available.
t (⟲ in green) to restart the session.
nect (🔗 in orange) to detach the debugger
while leaving the process running.
Comment on lines +84 to +91
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would only document the buttons that are visible in the screenshot (so not Stop Execution or Back for reverse debugging).

As we are attaching to a running process, restart and disconnect have the same behaviour: they stop the debugger and return to R.

(Note you have some letters missing here).

It would be nice to use actual pictures of the buttons here. According to ChatGPT you could do this in markdown

Click the ![Menu Button](images/menu-button.png){: .icon } to open the menu.

Then in docs/css/custom.css (which should be included via extra_css in mkdocs.yml):

.icon {
    height: 20px;
    vertical-align: middle;
}


Use these controls to navigate and inspect your native
C code during debugging within R.

#### 7. Inspect Variables and Expressions

LLDB allows watching variables and
evaluating expressions. For example,
in the context of debugging `rlogis`,
you can inspect the variable `u` or
watch the result of an expression:

```lldb
expr u
expr log(u / 1.0 - u)
```

The side panel or variable/watch
window updates as you step through
the code. Finally, when you exit
the debugger using the disconnect
button or te exit command, the
screen shown below is displayed:
Comment on lines +98 to +114
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea here was to document the Watch panel in the Run and Debug panel on VS Code:

image

As you can see, you can watch simple expressions like u and u / (1.0 - u), but log(u/(1.0 - u) doesn't work in the watch panel as it can't find the log function. I was trying to find a way round this, but it's not that simple. So for now just document simple expressions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you exit the debugger (e.g. via disconnect) it should just finish running the command and return to the R terminal:

image


![alt text](../assets/rdev28.png)
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ nav:
- 'Building R': 'tutorials/building_r.md'
- 'R Contribution Workflow' : 'tutorials/contribution_workflow.md'
- 'Updating Source Code' : 'tutorials/update_source.md'
- 'Debugging with LLDB' : 'tutorials/debugging_with_lldb.md'
- 'Creating a Patch File' : 'tutorials/patch_update.md'
- 'Multiple R Versions' : 'tutorials/multi_r_compilation.md'
- 'SVN Help' : 'tutorials/svn_help.md'
Expand Down