文章目录
- printk
- sysrq
- kdb/kgdb
- TRACE_EVENT,tracepoint使用
- 参考
printk
通过proc/sys/kernel/printk查看打印等级
$ cat /proc/sys/kernel/printk
1 4 1 3
四个数字分别对应:
console_loglevel:控制台使用的日志级别;
default_message_loglevel:调用 printk() 未指定日志级别时使用的日志级别;
minimum_console_loglevel:允许设置的控制台日志级别(console_loglevel)最小值;
default_console_loglevel:系统启动时使用的日志级别。
修改等级
# echo 1 4 1 7 > /proc/sys/kernel/printk
# cat /proc/sys/kernel/printk
1 4 1 7
如果修改不了,可以使用dmesg命令修改
pi@link:~$ sudo dmesg -n debug
pi@link:~$ cat /proc/sys/kernel/printk
8 4 1 3
sysrq
需要在内核配置才能启用
CONFIG_MAGIC_SYSRQ=y
然后在shell下使用,比如查看task
echo 1 >/proc/sys/kernel/sysrq
echo t > /proc/sysrq-trigger
如果看不到打印,看下dmesg里是否有,调整下控制台打印等级
kdb/kgdb
这步是在编译内核之后进行的,因为有些特性需要在内核编译时就指定,比如kgdb。可以使用menuconfig把kernel debugging和KGDB选项打开,建议的配置
# CONFIG_STRICT_KERNEL_RWX is not set
# CONFIG_RANDOMIZE_BASE is not set
CONFIG_FRAME_POINTER=y
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_KGDB_KDB=y
CONFIG_KDB_KEYBOARD=y
CONFIG_DEBUG_INFO=y
CONFIG_GDB_SCRIPTS=y
使用make scripts_gdb显式编译gdb脚本
1.kdb
使用实例:
#echo g > /proc/sysrq-trigger
[255170.882750] sysrq: HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e) memory-full-oom-kill(f) kill-all-tasks(i) thaw-filesystems(j) sak(k) show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n) poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s) show-task-states(t) unmount(u) show-blocked-tasks(w)
#echo ttyAMA0 > /sys/module/kgdboc/parameters/kgdboc
[255630.457371] KGDB: Registered I/O driver kgdboc
#echo g > /proc/sysrq-trigger
[255639.294716] sysrq: DEBUGEntering kdb (current=0xffff00001dba4e00, pid 10020) on processor 0 due to Keyboard Entry
[0]kdb> btc
btc: cpu status: Currently on cpu 0
Available cpus: 0-1
Stack traceback for pid 10020
0xffff00001dba4e00 10020 10019 1 0 R 0xffff00001dba5700 *sh
CPU: 0 PID: 10020 Comm: sh Tainted: P O 5.10.0 #8
Hardware name: Netfactory soc928 EVB (DT)
Call trace:dump_backtrace+0x0/0x1b0show_stack+0x14/0x30dump_stack+0xc4/0xfc
...
常用参数
m$ 操作内存系列
go 继续运行
r$ 操作寄存器系列
b$ 操作栈系列
env 查看环境变量
set 设置环境变量//比如 set LINES 10000设置行数
cpu 切换cpu
ps 查看的任务
pid 切换到任务
b$ 操作断点系列
ss 单步操作
dump$ dump信息
2.kgdb/gdb
kgdb相对于kdb来说是源码级调试器
输入kgdb,并等待命令。
可以使用串口连接,或者使用socat实现远程gdb连接kgdb,另外还有agent-proxy小工具可用。
之前尝试过这两种工具发现连上都输入不了,后来发现可能是mac上的ch340驱动有问题,直接echo “xxx”>/dev/tty.wchusbserial220,会直接卡住。但是在wsl2上尝试全部成功。
目前远程方案全部尝试失败,先使用本地
1.接入串口线,使用usbipd实现共享到wsl2
2.在host设备上提前设置好kgdboc,并进入kgdb等待连接
3.使用gdb加载vmlinux,连接串口
(gdb) set serial baud 115200
(gdb) target remote /dev/ttyUSB0
Remote debugging using /dev/ttyUSB0
warning: multi-threaded target stopped without sending a thread-id, using first non-exited thread
Remote 'g' packet reply is too long (expected 312 bytes, got 788 bytes): 00206a09c0ffffff0100000000000000000000000000000040236a09c0ffffff102a173b80ffffff102a173b80ffffff0000000000000000d8464d09c0ffffffffefffff000000004c751808c0ffffffd8464d09c0ffffff200720072007200720072007200720077fb9e509c0ffffff000000000000000077b9e589c0ffffff00000000000000000000000000000000ffffffffffffffff670000000000000000c04709c0ffffff00d04509c0ffffff03000000000000000000000000000000000000000000000018fcc308c0ffffff00000000000000000000000000000000c01eee0180ffffff80bce509c0ffffff4c751808c0ffffff80bce509c0ffffffa4741808c0ffffff0500006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
报错,查看stackoverflow,说要重编gdb,后面再弄,猜测可能需要编build,host=x86-64,target=aarch64的gdb
3.kdb/kgdb切换
$3#33 切换回kdb
$D#44+ 继续运行,退出kgdb
4.从gdb运行kdb命令
可以使用monitor help命令查看可以在gdb使用的kdb命令
5.内核启动参数
kgdboc
kgdboc_earlycon kgdb将使用bootconsole知道使用kgdboc
kgdbwait 在启动内核时等待调试器连接
kgdbcon 在gdb连接到内核时在gdb中看到printk()消息。注意,不能在系统控制台同时使用kgdboc和kgdbcon。当在系统运行时通过echo 1 > /sys/module/kgdb/parameters/kgdb_use_con
配置了此功能,必须在下次i/o重配置时才能生效
kgdbreboot 更改调试器处理重新启动通知的方式
nokaslr 禁用随机化
6.同时进行调试和打印查看
可参考基于A33下linux内核的GDB+KGDB内核调试环境搭建的agent-proxy方法,或者尝试使用socat,比如linux云服务器之间利用socat进行虚拟串口通信采用一对串口的方式,或者使用socat使用网络转接
7.注意事项
在用 gdb 来调试内核的时候,由于内核在初始化的时候,会创建很多子线程。而默认 gdb
会接管所有的线程,如果你从一个线程切换到另外一个线程, gdb 会马上把原先的线程暂停。但是这样很容易导致 kernel 死掉,所以需要设置一下 gdb 。一般用 gdb 进行多线程调试,需要注意两个参数: follow-fork-mode 和detach-on-fork。
TRACE_EVENT,tracepoint使用
参考
内核通用调试方法
Development tools for the kernel
linux内核调试方法
内核调试跟踪
brendangregg的主页
linux 内核启动Initramfs与initrd 及其挂载
Ramfs, rootfs and initramfs
vscode+kgdb+qemu调试linux内核
使用gdb调试内核
关于Linux内核vmlinuz、initrd.img和System.map
关于内核镜像文件vmlinux-vmlinuz-vmlinux.bin-zimage-bzimage-uImage 之间的差异
RaspberryPi
Linux:内核调试之内核魔术键sysrq
Linux kernel:修改内核 printk 日志等级
Using kgdb, kdb and the kernel debugger internals
linux云服务器之间利用socat进行虚拟串口通信
gdb脚本报错
GNU调试器 GDB 8.3 发布及安装更新,支持RISC-V与IPv6连接等
玩转C++调试之Python的GDB库增强
GDB解coredump文件报Python异常解决办法
内核调试- vmlinux-gdb.py无法在gdb上运行
socat使用
socat网络工具
gdb报错
Remote ‘g’ packet reply is too long
Remote ‘g’ packet reply is too long问题的解决
小工具
agent-proxy小工具——用一个串口,既当控制台又当kgdb调试通道