Skip to the content.

Debugger 的理念,原理和使用

理念

关于 debugger 的理念,我的想法和这篇 blog 完全相同:

I do not use a debugger

如果出现 bug ,你应该想到的是:

而不是使用 debugger 让自己陷入到细节中。

当然也有例外,如果你刚刚接手陌生的一个大项目,debugger 是分析代码流程的好工具。

[ ] gdb 的原理

gdb 的使用

首先强烈推荐 gdb-dashboard

Basic

breakpoints

watch

catch

backtrace

print

例如打印内核中的变量: jiffies

>>> x/xw &jiffies
0xffffffff82807980 <jiffies_64>:        0xfffb6c20
>>> x/xg &jiffies
0xffffffff82807980 <jiffies_64>:        0x00000000fffb6c20

attach

gdb -p PID

thread

signal

frame

frame 4 info locals

info

frame

分析 core 的时候,可以指定 frame 的位置,然后来分析:

(gdb) frame 4
(gdb) info local

参考:https://stackoverflow.com/questions/2770889/how-can-i-examine-the-stack-frame-with-gdb

[ ] gdb script

高级

给定一个虚拟地址,获取其所在源代码地址,一种方法是通过 add2line

➜  test git:(fix-kern) ✗ addr2line -e posted_ipi 0x406aec
/home/maritns3/core/dune/libdune/apic.c:53

但是 gdb 也可以,使用 disassemble 0x406aec 来查看

小技巧

打印一个结构体

https://stackoverflow.com/questions/1768620/how-do-i-show-what-fields-a-struct-has-in-gdb

由于 gdb-dashboard ,直接使用这个就可以了:

# 如果就是函数的结构体
p *m->file->f_path.dentry

# 如果是地址
p *(struct dentry *)0xffff88800581d780

misc

gdb 封装工具

  1. https://www.gdbgui.com/
  2. https://github.com/rohanrhu/gdb-frontend

其他工具

这里列举了 Linux 平台上的各种 debugger,https://scattered-thoughts.net/writing/the-state-of-linux-debuggers/

record debugger

记录下一个程序所有的状态,从而可以切入到任何一个时间点来调试

内存泄露调试技术

代码覆盖率工具

静态检查工具

misc

关键参考

TODO

[ ] 介绍下 coredump 的生成原理

corefile 在 /var/lib/systemd/coredump/ 中:

gdb ~/data/qemu/build/qemu-system-x86_64 core.qemu-system-x86.1000.7aa8ee09ca4945878399165f6bde1405.492790.1742904831000000
$ bt
#0  0x00007f5b41f55661 in ?? ()
#1  0x0000000000000000 in ?? ()

显然是有 debuginfo 的,但是都是问号,如何理解?

[ ] 配合 coredump 使用

如果 data type 是一个结构体,而且这个结构体很大,那怎么办 ?

[ ] 看看这个

https://news.ycombinator.com/item?id=39170901

Fedora 上调试自动下载 debuginfo 包,真的 nb

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.fedoraproject.org/>
Enable debuginfod for this session? (y or [n]) y
Debuginfod has been enabled.
To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit.
Downloading separate debug info for /lib64/libz.so.1
Downloading separate debug info for /lib64/libgbm.so.1
Downloading separate debug info for system-supplied DSO at 0xfffecc4bc000
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
0x0000fffeca8c6604 in __GI_ppoll (fds=0xaaab6a61c720, nfds=<optimized out>, timeout=<optimized out>, timeout@entry=0xffffdff22960,
    sigmask=sigmask@entry=0x0) at ../sysdeps/unix/sysv/linux/ppoll.c:42
42        return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
─── Source ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 37  #ifndef __NR_ppoll_time64
 38  # define __NR_ppoll_time64 __NR_ppoll
 39  #endif
 40
 41  #ifdef __ASSUME_TIME64_SYSCALLS
 42    return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
 43               __NSIG_BYTES);
 44  #else
 45    int ret;
 46    bool need_time64 = timeout != NULL && !in_int32_t_range (timeout->tv_sec);
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Missing separate debuginfos, use: dnf debuginfo-install mesa-libgbm-24.1.0~asahipre20240228-2.fc40.aarch64

但是问题是,他每次要下载

[ ] 有用吗?

https://beej.us/guide/bggdb/

[ ] 有趣的

https://poormansprofiler.org/

https://news.ycombinator.com/item?id=30512302

gcore 的使用

kvmclock_vm_state_change 中添加 abort

ls -la /var/lib/systemd/coredump

cp /var/lib/systemd/coredump/core.qemu-system-x86.1000.fa6ca1ad83a64170b4aa5ae69f86a4ed.35104.1744643421000000.zst /tmp

堆栈可以看的很清楚:

#0  0x00007fcf8fc0188c in __pthread_kill_implementation () from /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/libc.so.6
#1  0x00007fcf8fbaf576 in raise () from /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/libc.so.6
#2  0x00007fcf8fb97935 in abort () from /nix/store/maxa3xhmxggrc5v2vc0c3pjb79hjlkp9-glibc-2.40-66/lib/libc.so.6
#3  0x000055ba45f586da in kvmclock_vm_state_change (opaque=<optimized out>, running=<optimized out>, state=<optimized out>)
    at ../hw/i386/kvm/clock.c:171
#4  0x000055ba45e4db54 in vm_state_notify (running=running@entry=true, state=state@entry=RUN_STATE_RUNNING)
    at ../system/runstate.c:396
#5  0x000055ba45e44537 in vm_prepare_start (step_pending=step_pending@entry=false) at ../system/cpus.c:776
#6  0x000055ba45e4458b in vm_start () at ../system/cpus.c:783
#7  0x000055ba45e9f831 in qmp_cont (errp=0x0) at ../monitor/qmp-cmds.c:112
#8  0x000055ba45e55f35 in qemu_init (argc=<optimized out>, argv=<optimized out>) at ../system/vl.c:3843
#9  0x000055ba45bc2449 in main (argc=<optimized out>, argv=<optimized out>) at ../system/main.c:68

看看这个 help 工具

List of classes of commands:

aliases -- User-defined aliases of other commands.
breakpoints -- Making program stop at certain points.
data -- Examining data.
files -- Specifying and examining files.
internals -- Maintenance commands.
obscure -- Obscure features.
running -- Running the program.
stack -- Examining the stack.
status -- Status inquiries.
support -- Support facilities.
text-user-interface -- TUI is the GDB text based interface.
tracepoints -- Tracing of program execution without stopping the program.
user-defined -- User-defined commands.

看汇编的小技巧

layout asm

然后使用 si 逐条指令执行

当你的 vmcore 无法正常使用的时候在,也许,很多时候,是由于 debugsyml 无法自动找到导致的

手动执行这个东西: symbol-file /usr/lib/debug/usr/libexec/qemu-kvm-10.2.x86_64.debug

好东西

https://hugsy.github.io/gef/settings/print-format/

原来gdb 执行的命令可以直接放到文件中

gdb -x src_commands.txt –args

这个人写了很多 lldb 相关的 blog

https://www.moritz.systems/blog/full-multiprocess-support-in-lldb-server/

coredump

nixos 的处理方式:

🧀  cat /proc/sys/kernel/core_pattern
|/nix/store/34am2kh69ll6q03731imxf21jdbizda2-systemd-251.15/lib/systemd/systemd-coredump %P %u %g %s %t %c %h

ubuntu 的处理方式:

var/lib/systemd/coredump$  cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E

通过检查 /var/log/apport.log 可以知道

ERROR: apport (pid 17768) Thu Apr 27 03:08:58 2023: called for pid 17767, signal 11, core limit 0, dump mode 1
ERROR: apport (pid 17768) Thu Apr 27 03:08:58 2023: executable: /a.out (command line "./a.out")
ERROR: apport (pid 17768) Thu Apr 27 03:08:58 2023: executable does not belong to a package, ignoring

所以需要调整一下:

ulimit -c unlimited

其路径也是在 /var/lib/apport/coredump 中。

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。