使用Linux Kernel Dynamic Debug

在研讀LInux Kernel Drivers 時,常會遇到netif_dbgpr_debug 相關的debug 函數。此文章將介紹如何開啟此類函數的輸出Log。以下將以Arm Linux Kernel 3.18.44版本做為例子介紹。

1. 準備一台Arm 架構Linux 機器。打開其Console 並輸入以下指令。可以確定其Kernel Version和使用平台。

uname -r; uname -m;

2. 打開其Kernel Source Code。在drivers 中,以emac_main.c 為例子(僅以此檔案做為範例)。在第501中有使用netif_dbg,如下圖。

我們嘗試Rebuild Linux Kernel,讓機器可以動態輸出這些Log。

3. 在Kernel Menuconfig 中選擇CONFIG_DYNAMIC_DEBUG(Enable dynamic printk() support),如下圖。

儲存設定之後,其.config 如下圖。

4. 回到Kernel Source Code。開啟emac_main.c 並其檔案內加入巨集DEBUG,如下圖。

5. 重新編譯Kernel,完成之後並將FW 燒入機器。

6. 將機器重新開機,在Console輸入以下指令。

cat /sys/kernel/debug/dynamic_debug/control

可以顯示出使用Dynamic Debug 的文件路徑、行號、Module 名稱、函數名稱和輸出Log 格式。下圖為emac_main.c 中的例子,在501 行印出Log。

其中可以看到一個「控制輸出Log 的Flag」,此 Flag 可以控制是否輸出Log。如輸入以下指令,即可以開啟輸出Log。

echo -n 'file emac_main.c line 501 =p' > /sys/kernel/debug/dynamic_debug/control

則「控制輸出Log 的Flag」也會跟著改變。

目前支持的Flags 如下。

  • p enables the callsite
  • f include the function name in thre 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

而增加、刪減Flags,可以使用以下三個運算子。

  • remove the given flags
  • + add the given flags
  • = set the flags to the given flags

以下用範例,簡介Dynamic Debug 的操作指令。(echo -n 為不換行輸出)

// 打開檔案emac_main.c 中第501行的動態輸出
echo -n 'file emac_main.c line 501 =p' > /sys/kernel/debug/dynamic_debug/control

// 打開檔案emac_main.c 中第501行的動態輸出
echo -n 'file emac_main.c line 501 +p' > /sys/kernel/debug/dynamic_debug/control

// 打開檔案emac_main.c 中第501行的動態輸出,且印出Log 會包含函數名稱、行號、Module 名稱
echo -n 'file emac_main.c line 501 +pflm' > /sys/kernel/debug/dynamic_debug/control

// 關閉檔案emac_main.c 中第501行的函數名稱輸出
echo -n 'file emac_main.c line 501 -f' > /sys/kernel/debug/dynamic_debug/control

// 關閉檔案emac_main.c 中第501行的Module 名稱輸出
echo -n 'file emac_main.c line 501 -m' > /sys/kernel/debug/dynamic_debug/control

// 關閉檔案emac_main.c 中第501行的行號輸出
echo -n 'file emac_main.c line 501 -l' > /sys/kernel/debug/dynamic_debug/control

// 關閉檔案emac_main.c 中第501行的動態輸出
echo -n 'file emac_main.c line 501 =_' > /sys/kernel/debug/dynamic_debug/control

// 打開檔案emac_main.c 中所有的動態輸出
echo -n 'file emac_main.c +p' > /sys/kernel/debug/dynamic_debug/control

// 關閉檔案emac_main.c 中所有的動態輸出
echo -n 'file emac_main.c =_' > /sys/kernel/debug/dynamic_debug/control

// 打開Module test_module 中所有的動態輸出
echo -n 'module test_module +p' > /sys/kernel/debug/dynamic_debug/control

// 打開函數test_func 中所有的動態輸出
echo -n 'func test_func +p' > /sys/kernel/debug/dynamic_debug/control

// 打開所有的動態輸出
echo -n '=p' > /sys/kernel/debug/dynamic_debug/control

// 關閉所有的動態輸出
echo -n '=_' > /sys/kernel/debug/dynamic_debug/control

7. 驗證輸出Log。在emac_main.c 範例中,使用以下指令開啟第501 行動態輸出。

echo -n 'file emac_main.c line 501 =p' > /sys/kernel/debug/dynamic_debug/control

在輸入dmesg,印出Log 如下。

Reference: Dynamic debug

發佈留言