Also get the correct source code with apt source
In addition to the symbols, you will also to get the source with apt source
as mentioned at:
and then point GDB to them with substitute-path
as mentioned at: https://stackoverflow.com/questions/23868252/gdb-source-path
Some fully working commands on Ubuntu 22.04, e.g. to debug ls
from coreutils
:
# Get debug symbols.
printf "deb http://ddebs.ubuntu.com %s main restricted universe multiverse\n" $(lsb_release -cs){,-updates,-security,-proposed} | \
sudo tee -a /etc/apt/sources.list.d/ddebs.list
sudo apt install ubuntu-dbgsym-keyring
sudo apt update
sudo apt install coreutils-dbgsym
# Get source as per: https://askubuntu.com/questions/496549/error-you-must-put-some-source-uris-in-your-sources-list
# Produces directory "coreutils-8.32"
sudo cp /etc/apt/sources.list /etc/apt/sources.list~
sudo sed -Ei 's/^# deb-src /deb-src /'
/etc/apt/sources.list sudo apt-get update
apt source coreutils
# Run ls pointing to the downloaded source.
gdb -ex 'set substitute-path . coreutils-8.32' ls
in which I see the source correctly as:
(gdb) start
Temporary breakpoint 1 at 0x4d20: file src/ls.c, line 1622.
Starting program: /usr/bin/ls
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffce08) at src/ls.c:1622
warning: Source file is more recent than executable.
1622 {
(gdb) l
1617 signal_setup (false);
1618 }
1619
1620 int
1621 main (int argc, char **argv)
1622 {
1623 int i;
1624 struct pending *thispend;
1625 int n_files;
1626
The choice of set substitute-path .
is because without substitute-path
it would fail with:
1622 src/ls.c: No such file or directory.
so we help GDB find the source by making it convert .
to coreutils-8.32/
where the src/
lives.
GDB step debug into glibc
The exact same procedure works for shared libraries. E.g. to GDB step debug glibc as asked at:
In that case, the debug symbols already appear to come preinstalled, otherwise we would need:
sudo apt install libc6-dbg
and then get source with:
apt source libc6
which produces directory: glibc-2.35
.
We then make a C hello world to test with:
main.c
#include <stdio.h>
int main(void) {
puts("hello");
}
If we try to compile, GDB and go into glibc
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
gdb main.out
as:
(gdb) start
Temporary breakpoint 1 at 0x1151: file main.c, line 4.
Starting program: /home/ciro/tmp/main.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Temporary breakpoint 1, main () at main.c:4
4 puts("hello");
(gdb) s
__GI__IO_puts (str=0x555555556004 "hello") at ./libio/ioputs.c:33
33 ./libio/ioputs.c: No such file or directory.
(gdb)
we see that the library also searches for files under ./
, so once again we:
set substitute-path . glibc-2.35
and now we can see the source:
(gdb) l
28 #include <string.h>
29 #include <limits.h>
30
31 int
32 _IO_puts (const char *str)
33 {
34 int result = EOF;
35 size_t len = strlen (str);
36 _IO_acquire_lock (stdout);
37
Some other versions of Ubuntu had sources at an absolute location like:
/tmp/build138741687/
in which case you would instead want:
set substitute-path /tmp/build138741687/ glibc-2.35