连续复制
一键复制
一键打包

(调试篇):如何使用dynamic debug动态打印调试

📢 动态打印(Dynamic Printk Debugging)是内核子系统开发者最喜欢的打印手段之一。

在系统运行时候,动态打印可以由系统维护者动态打开内核子系统的打印,可以有选择性地打开某些模块的打印,而printk是全局的,只能设置打印等级。要使用动态打印,必须在内核配置时打开CONFIG_DYNAMIC_DEBUG宏。

1、defconfig 配置

CONFIG_DEBUG_FS=y
CONFIG_DYNAMIC_DEBUG=y

2、dynamic debug参数介绍

文件目录:kernel-4.14\Documentation\admin-guide\dynamic-debug-howto.rst
if CONFIG_DYNAMIC_DEBUG is set, then all

  • pr_debug()

  • dev_dbg()

  • print_hex_dump_debug()

  • print_hex_dump_bytes()

  • calls can be dynamically enabled per-callsite.

参数作用
p enables the pr_debug() callsite.

f Include the function name in the printed message

l Include line number in the printed message

m Include module name in the printed message

t Include thread ID in messages not generated from interrupt context

_ No flags are set. (Or’d with others on input)

3、dynamic debug的查看与设置

动态打印在debugfs文件系统中有个control文件节点,文件节点记录了系统中所有使用动态打印技术的文件名路径、打印所在的行号、模块名字和要打印的语句。

cat /sys/kernel/debug/dynamic_debug/control |busybox grep "suspend"

如上不是所有的日志都会在dmesg中打印,我们的dev_dbg就不会直接显示在dmesg中。
只有 =p的日志才会打印。
配置文件开启dev_dbg的打印功能,使用下述配置即可:

  • 打开一个文中所有动态打印语句

echo -n "file gadget.c +p "> /sys/kernel/debug/dynamic_debug/control

  • 打开一个模块所有动态打印语句

echo "module dwc3 +p" > /sys/kernel/debug/dynamic_debug/control
  • 打开一个函数中所有的动态打印语句

echo "func svc_process +p" > /sys/kernel/debug/dynamic_debug/control
  • 打开文件路径中包含usb的文件里所有的动态打印语句

echo -n "*usb* +p" > /sys/kernel/debug/dynamic_debug/control
  • 打开系统所有的动态打印语句

echo -n "+p" > /sys/kernel/debug/dynamic_debug/control
  • 关闭一个函数中所有的动态打印语句

echo -n "func svc_process -p" > /sys/kernel/debug/dynamic_debug/control

上面是打开动态打印语句的例子,除了能打印pr_debug()/dev_dbg()函数中定义的输出外,还能打印一些额外信息,例如函数名、行号、模块名字和线程ID等。

  • p:打开动态打印语句。

  • f:打印函数名

  • I:打印行号

  • m:打印模块名字

  • t:打印线程ID

4、添加一个dynamic debug:dev_dbg

实验打印:

echo -n "file gadget.c +p "> /sys/kernel/debug/dynamic_debug/control
dmesg |busybox grep -r "IRQ"

5、dynamic 动态打印转为printk正常打印

c文件开头添加如下代码:

#undef dev_dbg
#define dev_dbg dev_info
#undef pr_debug
#define pr_debug pr_info

6、启动时候如何动态打印

在调试一些系统启动方法的代码,例如USB核心初始化等,这些代码在系统进入shell 终端时已经初始化完成,因此无法及时打开动态打印语句。这时可以在内核启动时传递参数给内核,在系统初始化时动态打开它们,这是一个实际工程中非常好用的技巧。

在内核commandline中添加”dwc3.dyndbg=+plft“字符串。
还可以在各个子系统的Makefile中添加 ccflags 来打开动态打印。

ccflags-y  := -DDEBUG
ccflags-y  +=  -DVERBOSE_DEBUG