Re-learning Vim (9)

Date: 2024/06/08 (initial publish), 2024/06/16 (last update)

Source: en/note-00075.md

Previous Post Top Next Post

TOC

An example C program with Makefile

In order to practice with a simple C program, I created test.c and Makefile at github.

Let me recap basic GCC options used in this example together with some popular situation.

Uninitialized variable was zeroed by code generated by -Og and -O2 but not by -O0. So I should use -O2 or -Og to make debug easy.

Jump to errors in the source code: C program example with quickfix

Above example compiles without issue. So let me intensionally break it by removing ; in some lines by editing with:

$ vi test.c

While in Nvim, let me type :make in NORMAL mode. This runs the content of Makefile with make. It sure causes errors and the cursor moves to the first error position. I can jump around errors with [q and ]q. Cool.

I can also open quickfix list window with :copen.

Pressing ENTER on quickfix list window line jumps cursor to its corresponding position.

Inspect running program (direct GDB)

Use of GDB was touched in Fun to Program – Debug: level 3.

$ make
$ gdb -q ./test
Reading symbols from ./test...
(gdb) list 1,15
1#include <stdlib.h>
2#include <stdio.h>
3int main() {
4  int i, final, factorial = 1;
5  printf("Enter the number: ");
6  if (scanf("%d", &final)) {
7    for (i = 1; i <= final; i++)
8      factorial = factorial * i;
9    printf("The factorial of %d is %d\n", final, factorial);
10    exit(0);
11  } else {
12    exit(1);
13  }
14}
(gdb) b 8
Breakpoint 1 at 0x1199: file test.c, line 8.
(gdb) run
Starting program: /home/osamu/github/osamuaoki.github.io/osamuaoki-hugo-proj/021_gcc_debug/test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Enter the number: 17

Breakpoint 1, main () at test.c:8
8      factorial = factorial * i;
(gdb) info locals
i = 1
final = 17
factorial = 1
(gdb) c 16
Will ignore next 15 crossings of breakpoint 1.  Continuing.

Breakpoint 1, main () at test.c:8
8      factorial = factorial * i;
(gdb) info locals
i = 17
final = 17
factorial = 2004189184
(gdb) n
7    for (i = 1; i <= final; i++)
(gdb) n
9    printf("The factorial of %d is %d\n", final, factorial);
(gdb) info locals
i = 18
final = 17
factorial = -288522240
(gdb) n
The factorial of 17 is -288522240
10    exit(0);
(gdb) c
Continuing.
[Inferior 1 (process 72091) exited normally]

Since 17 * 2,004,189,184 = 36,507,221,999, and int is 32 bit signed integer, overflow occurred (max = 0x7FFF_FFFF= 2,147,483,647).

Inspect running program (remote GDB)

Let’s think about simple single host with 2 terminal console case.

On console GDBSERVER (remote), let’s start gdbserver to test ./test:

$ gdbserver localhost:1234 ./test
Process ./test created; pid = 32761
Listening on port 1234

On console GDB (local), start gdb:

$ gdb -q
(gdb) target remote localhost:1234
(gdb) b 7
Breakpoint 1 at 0x55555555519c: file test.c, line 7.
(gdb) c
Continuing.
Reading /lib/x86_64-linux-gnu/libc.so.6 from remote target...

On console GDBSERVER, we now see the following and enter 5 on prompt.

$ gdbserver localhost:1234 ./test
Process ./test created; pid = 32761
Listening on port 1234
Remote debugging from host ::1, port 60566
Enter the number: 5

On console GDB, we now see gdb stopping at break point:

$ gdb -q
(gdb) target remote localhost:1234
(gdb) b 7
Breakpoint 1 at 0x55555555519c: file test.c, line 7.
(gdb) c
Continuing.
Reading /lib/x86_64-linux-gnu/libc.so.6 from remote target...
Breakpoint 1, main () at test.c:7

With above, ./test is tested with full access to stdin and stdout.

Inspect running program (via DAP)

Since Debian/Bookworm 12 currently has GDB 13, we need to follow “C C Rust (gdb via vscode cpptools)” using “github: microsoft/vscode-cpptools”. LazyVim can activate dap.core LazyExtra and activate cpptools in DAP by running :Mason (or <leader>cm).

Next GDB 14 can support DAP (Debug Adapter Protocol) natively.

Problem is Nvim with DAP UI doesn’t seem to allow running program using STDIN.

Run ./test on a separate console under gdbserver as above solved this issue for me.

I need to read nvim-dap-ui/doc/nvim-dap-ui.txt and nvim-dap-ui/README.md directory since this is not shown in normal Vim-help system.

Let’s check the meaning of DAP-UI. Following are reordered to match the GUI display by the lua source code of nvim-dap-ui (for icons in repl element):

(The above needs font support)

Now I see why debug session terminated when I was playing with icons. Variable names give me good hints, here.

Setting BP etc., are by keymaps like <leader>db etc. in the main C source display.

As for each meanings of sidebar elements, I guess them as follows from variable names in the layout table:

Also, I see following keymaps. These seem to work in left and bottom sidebars. The meaning of these are still vague for me, though.

Also UI dialog for “Input” and “Condition” needs to be investigated. ….

After fiddling updates, DAP stops working even with simple hello with direct gdb run without using gdbserver. It errors as:

DAP Couldn't connect to localhost:${port}: ECONNREFUSED

This makes no sense to me. TBH, it’s too complicated and unstable for me at this moment to use this DAP.

Hmmm… it looks like LazyExtras store data in ~/.config/$NVIM_APPNAME/*.json. Ensuring to store these updated data in VCS seems to be important.

Let me stick to the basic direct CLI GDB usage for now.

Jump to the specific position in a file: generic Vim

Let me revisit trick to jump to the specific position manually.

To go to line 99 of file.txt, try:

$ vim +99 file.txt

To go to line 99 column 40 of file.txt, try any one of the following:

$ vim +99 file.txt +'norm 40|'
$ vim file.txt +'norm 99G40|'
$ vim +'call cursor(99, 40)' file.txt

NOTE: | (bar) in NORMAL mode is “goto column”, and in EX-mode is “command separator”. NOTE: Indexing for line and column in Vim starts at 1. 0G is for the last line. (List index in Vim Script starts at 0.)

My TODO list

Previous Post Top Next Post