1

I'm trying to run GDB remote debugging on a single source file, very basic C code, and I'm hitting a wall on something that seems like it should be completely obvious. Specifically, I cannot figure out how to get GDB to find the boundaries of procedures defined within this single file, making it impossible to use either step or next when execution reaches any procedure call.

My environment:

  • Dockerized container, running Ubuntu 22.04
  • Two shell windows, both on the same host, both under the same container image
  • RISCV-64 emulation under QEMU: using qemu-riscv64, symlinked as qemu
  • GCC for RISCV-64, riscv64-unknown-linux-gnu-gcc, symlinked as gcc
  • Using riscv64-unknown-linux-gnu-gdb, symlinked as gdb

The source file is a basic selection sort demo, with bugs, compiled with

root@75229e1158dd:~# gcc -g -std=c99 -Wall -Werror buggy_sel_sort.c -o buggy_sel_sort

In one window, I start up QEMU for remote debugging:

root@75229e1158dd:~# qemu -g 1234 buggy_sel_sort

In the other, I invoke GDB with:

root@75229e1158dd:~# gdb  -ex 'target remote localhost:1234' -ex 'set sysroot /opt/riscv/' buggy_sel_sort
GNU gdb (GDB) 15.1
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from buggy_sel_sort...
Remote debugging using localhost:1234
Reading symbols from /opt/riscv/sysroot/lib/ld-linux-riscv64-lp64d.so.1...
(No debugging symbols found in /opt/riscv/sysroot/lib/ld-linux-riscv64-lp64d.so.1)
0x0000001555d6b9f4 in _start () from /opt/riscv/sysroot/lib/ld-linux-riscv64-lp64d.so.1
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
(gdb) 

So far, so good, at least I think so; my understanding is that the "dynamic linker breakpoint" warning can be ignored. I get the GDB prompt, set the breakpoint at main, and restart execution:

(gdb) break main
Breakpoint 1 at 0x1086c: file buggy_sel_sort.c, line 64.
(gdb) continue
Continuing.
warning: Could not load shared library symbols for 3 libraries, e.g. linux-vdso.so.1.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?

Breakpoint 1, main (argc=1, argv=0x1555d56d18) at buggy_sel_sort.c:64
64          long test_array[5] = {1,4,2,0,3};
(gdb) step
65          long test_array2[25] = {0xddad409b, 0x6b401dbe, 0xc59beda0, 0xf29ec713,

But the next line is a call to a selection_sort procedure, and this is where it goes off the rails:

(gdb) step
0x0000001555d667e4 in ?? ()
(gdb) step
Cannot find bounds of current function

Unsurprisingly, next doesn't fare any better. I can advance instructions using stepi or nexti, but all I get from that is information about the next instruction address. As you can probably tell, this is for a teaching project, so low-level representation like that really isn't helpful for beginners.

What's strange to me is that I can add explicit breakpoints for all the procedure names in the source file; continue will reach their entry points, and finish their returns. I can step through their bodies until the next call.

There has to be a better way around this. What am I missing that is making these procedure entry/exit points unfindable?

FWIW, here is the output of info sharedlibrary:

(gdb) info sharedlibrary
From                To                  Syms Read   Shared Object Library
                                        No          linux-vdso.so.1
                                        No          /lib/libc.so.6
                                        No          /lib/ld-linux-riscv64-lp64d.so.1
3
  • 1
    Bah. Sometimes you just need to write up something like that to solve it yourself. For one, I had the wrong sysroot value, which was evident from that initial "dynamic linker" warning. Also, I needed to use the file command explicitly. I'm not sure why, still. tl;dr version: I should have invoked GDB with bash gdb -ex 'target remote localhost:1234' -ex 'set sysroot /opt/riscv/sysroot' -ex 'file /root/buggy_sel_sort' Commented Jan 20 at 19:03
  • This is a good question for others having the same issue though. Commented Jan 21 at 0:17
  • @Kingsley - That's probably true. I took me almost a full day to figure out the basic mechanics of this Docker+QEMU+GDB combination, as I had to cobble it together from about a dozen sources. I meant to add on to my comment above that the full command to get everything to load correctly is to still include the target file as an argument, along with the -ex file <etc.> command. Any idea why that is? Why is the file argument even necessary? Commented Jan 21 at 18:56

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.