dyndbg(dynamic debug)の使い方

printk()はデバッグ出力無効化の際には、コメントアウトするなりして再ビルドする必要があります。


何度もビルドを繰り返すのは面倒なので、デバッグ出力の有効/無効を実行時に動的に切り替えられるようにする機能が
dyndbg(dynamic debug)です。




なお以降の説明は、Linux 3.14.51で確認したものです。
また、debugfsのマウントポイントをで略記しています。


参考: debugfsのマウント方法
(マウントポイント /sys/kernel/debug の場合)

sudo mount -t debugfs none /sys/kernel/debug

カーネルコンフィギュレーションの変更

dyndbgを使用するには、カーネルコンフィギュレーションの変更が必要です。
まず、以下の場所にある「CONFIG_DYNAMIC_DEBUG」を有効化します。

  • Kernel hacking
    • printk and dmesg options
      • [*] Enable dynamic printk() support <- 有効化

pr_debug()でデバッグログを仕込む

そして、デバッグログを出力させたい場所に、
以下の例のようにpr_debug()を追加します。
例)

pr_debug("%s: timer fired with data %lu\n", __func__, __data);

※ 書式はprintk()と同じです。


最後に、カーネルをビルドし、生成されたカーネルで起動します。

動的にdyndbgのデバッグログを有効化/無効化する方法

pr_debug()のデバッグログは以下で確認できます。

  • /var/log/messages ファイル
  • dmesg コマンド


ですが、初期状態ではpr_debug()の内容は出力されません。
出力の有効化/無効化は /dynamic_debug/control への書き込みで行います。


有効化/無効化の方法はいくつかあります。
例えば、

  • svcsock.cの全てのpr_debug()を有効化
    • echo -n 'file svcsock.c +p' > /dynamic_debug/control
  • svcsock.cの1603行目のpr_debug()を有効化
    • echo -n 'file svcsock.c line 1603 +p' > /dynamic_debug/control
  • imx.cのimx_int()内の全てのpr_debug()を有効化
    • echo -n 'file imx.c func imx_int +p' > /sys/kernel/debug/dynamic_debug/control

※ 無効化の際は、最後の"+p"を"-p"と指定してください


pr_debug()有効/無効の確認は、/dynamic_debug/controlを読み出すことで行えます。


例として、controlを読みだした先頭部分を以下に示します。

# filename:lineno [module]function flags format
init/main.c:687 [main]do_one_initcall_debug =p "initcall %pF returned %d after %lld usecs\012"
init/main.c:680 [main]do_one_initcall_debug =p "calling  %pF @ %i\012"
arch/x86/kernel/cpu/common.c:1264 [common]cpu_init =_ "Initializing CPU#%d\012"
arch/x86/kernel/cpu/perf_event_amd_iommu.c:373 [perf_event_amd_iommu]perf_iommu_add =_ "perf: amd_iommu:perf_iommu_add\012"
arch/x86/kernel/cpu/perf_event_amd_iommu.c:394 [perf_event_amd_iommu]perf_iommu_del =_ "perf: amd_iommu:perf_iommu_del\012"
arch/x86/kernel/cpu/perf_event_amd_iommu.c:299 [perf_event_amd_iommu]perf_iommu_start =_ "perf: amd_iommu:perf_iommu_start\012"
arch/x86/kernel/cpu/perf_event_amd_iommu.c:350 [perf_event_amd_iommu]perf_iommu_stop =_ "perf: amd_iommu:perf_iommu_stop\012"
arch/x86/kernel/cpu/perf_event_amd_iommu.c:324 [perf_event_amd_iommu]perf_iommu_read =_ "perf: amd_iommu:perf_iommu_read\012"
arch/x86/kernel/cpu/mtrr/main.c:484 [main]mtrr_del_page =p "mtrr: no MTRR for %lx000,%lx000 found\012"
arch/x86/kernel/cpu/mtrr/main.c:393 [main]mtrr_check =p "mtrr: size: 0x%lx  base: 0x%lx\012"
arch/x86/kernel/cpu/mtrr/generic.c:305 [generic]print_fixed_last =p "  %05X-%05X %s\012"
arch/x86/kernel/cpu/mtrr/generic.c:381 [generic]print_mtrr_state =p "TOM2: %016llx aka %lldM\012"

各行の記述のフォーマットは、1行目で説明されているとおりです。
各行がpr_debug()のデバッグログを示し、半角スペース区切り第3カラム目のflagsが有効/無効などの状態を示します。
'='の後の1文字が状態を示しており、'_'はデフォルト(無効)、'p'は有効を示しています。


その他の使い方など、詳しくは以下を参照してください。