debugfsを利用した実際のデバッグ利用した実際のデバッグした実際のデバッグ実際のデバッグのデバッグデバッグ

Yoichi Yuasa
OSAKA NDS Embedded Linux Cross Forum #11

自己紹介
●

湯浅陽一

●

1999年よりよりLinux kernel開発に参加に参加参加●

MIPSアーキテクチャのいくつかののデバッグいくつかのデバッグCPUへLinuxkernelを利用した実際のデバッグ移植

本日の内容のデバッグ内容●

デバイスドライバデバッグ手法概要●

debugfsを利用した実際のデバッグ利用した実際のデバッグした実際のデバッグデバッグ実装●

debugfsを利用した実際のデバッグ利用した実際のデバッグするポイントポイント

デバイスドライバデバッグ手法●

printk●ftrace●Kprobes●debugfs

printk●●●

利用した実際のデバッグが簡単簡単
出力追加に参加はkernel/デバイスドライバモジュールのビルドのデバッグビルのビルドドが簡単必要
出力レベルのビルドを利用した実際のデバッグ設定可能(コンソールのビルド上に出力するに参加出力するポイント/しないを利用した実際のデバッグ選択可能)– KERN_DEBUG、KERN_INFO、KERN_NOTICE...

●

シリアルのビルドコンソールのビルドと組み合わせると出力の保存を             組み合わせると出力の保存を             み合わせると出力の保存を             合わせると出力の保存を             わせるポイントと組み合わせると出力の保存を             出力のデバッグ保存を             を利用した実際のデバッグ
外部に依存できるに参加依存を             できるポイント

printk●kernel全体で利用されるので排他制御なども   で利用した実際のデバッグされるポイントのデバッグで排他制御なども   などもありそれほど軽い処理ではないい処理ではないではない– 追加するポイントこと組み合わせると出力の保存を             に参加より動作に影響がある可能性に参加影響がある可能性が簡単あるポイント可能性– 不具合わせると出力の保存を             現象が発生しなくなるか頻度が下がるなどが簡単発に参加生しなくなるか頻度が下がるなどしなくなるポイントか頻度が下がるなどが簡単下がるなどが簡単るポイントなど

ftrace●●OSAKA NDS Embedded Linux Cross Forum#4で詳細に紹介   に参加紹介(資料がダウンロード可能が簡単ダウンロード可能)
Kernel Function Tracer– Linux kernel標準搭載ののデバッグKernel Tracerのデバッグ一つ– Kernel Function Graph Traceと組み合わせると出力の保存を             いう階層表示も可能階層表示も可能も可能●●

コンパイルのビルド時プロファイリング用プローブ関数を各関数の先頭プロファイリング用した実際のデバッグプローブ関数を各関数の先頭関数を各関数の先頭を利用した実際のデバッグ各関数を各関数の先頭のデバッグ先頭に参加挿入してトレースデータを取得してトレースデータを取得トレースデータを取得を利用した実際のデバッグ取得
利用した実際のデバッグするポイントに参加はKernel Function Tracer/Kernel Function Graph
Tracerを利用した実際のデバッグオンに参加してトレースデータを取得kernelを利用した実際のデバッグビルのビルドドしてトレースデータを取得おく必要が簡単あるポイント

Kernel Function Graph Trace表示も可能# tracer: function_graph## CPU DURATIONFUNCTION CALLS# |||||||
1)0.720 us| mutex_unlock();
1)
0.120 us
| __fsnotify_parent();1)
0.120 us| fsnotify();
1)| __sb_end_write() {1)|
percpu_up_read() {1)|
update_fast_ctr() {1)0.120 us|preempt_count_add();1)
0.120 us|preempt_count_sub();
1)
2.640 us|}1)
4.320 us|}1)5.520 us| }8

Kprobes
OSAKA NDS Embedded Linux Cross Forum#3で詳細に紹介   に参加紹介(資料がダウンロード可能が簡単ダウンロード可能)●ブ関数を各関数の先頭レイクポイント命令などを利用してなどを利用した実際のデバッグ利用した実際のデバッグしてトレースデータを取得kernelを利用した実際のデバッグ動的に変更に参加変更●●

指定位置に処理に参加処理ではない(プローブ関数を各関数の先頭)を利用した実際のデバッグ追加(複数を各関数の先頭可)●ほと組み合わせると出力の保存を             んどのデバッグ位置に処理に参加プローブ関数を各関数の先頭を利用した実際のデバッグ追加可能(制限はありはあり)– 割込み処理でも追加可能み合わせると出力の保存を             処理ではないでも追加可能●

Loadable moduleと組み合わせると出力の保存を             してトレースデータを取得後からプローブを追加可能からプローブを追加可能プローブ関数を各関数の先頭を利用した実際のデバッグ追加可能●

プローブ関数を各関数の先頭内に参加てトレースデータを取得kernel内データを取得を利用した実際のデバッグ変更可能●

Kprobes, Jprobes, Return probesのデバッグ3種類があるが簡単あるポイント●

利用した実際のデバッグするポイントに参加はKprobesを利用した実際のデバッグオンに参加してトレースデータを取得kernelを利用した実際のデバッグビルのビルドドしてトレースデータを取得おく必要が簡単あるポイント

debugfs●●

kernel開発に参加者がユーザースペースへ大きなデータを渡す   が簡単ユーザースペースへ大きなデータを渡す   きなデータを取得を利用した実際のデバッグ渡す   す
た実際のデバッグめのデバッグ方法を利用した実際のデバッグ提供
フルのビルドのデバッグファイルのビルド形式アクセスを提供アクセスを利用した実際のデバッグ提供– read/write以外に参加seekなど利用した実際のデバッグ可能●●

単体で利用されるので排他制御なども   では単なるポイントインタを取得ーフェースなのデバッグでデバッグのデバッグた実際のデバッグめのデバッグ
実装が簡単別途必要
利用した実際のデバッグするポイントに参加はDebug Filesystemを利用した実際のデバッグオンに参加してトレースデータを取得kernelを利用した実際のデバッグ
ビルのビルドドしてトレースデータを取得おく必要が簡単あるポイント

デバッグに参加おけるポイントdebugfs利用した実際のデバッグ方法●●●

デバイスドライバに参加てトレースデータを取得デバッグ用した実際のデバッグに参加記録したい  した実際のデバッグい
内容を利用した実際のデバッグローカルのビルドバッファなどに参加保存を             してトレースデータを取得おく
ローカルのビルドバッファ上に出力するに参加記録したい  するポイント場合わせると出力の保存を             printkと組み合わせると出力の保存を             比較して処理は軽いしてトレースデータを取得処理ではないは軽い処理ではないいdebugfsのデバッグread処理ではないに参加てトレースデータを取得ローカルのビルドバッファ上に出力するのデバッグ
データを取得を利用した実際のデバッグユーザーランドに参加転送して解析してトレースデータを取得解析

debugfsのデバッグ利点●

大きなデータを渡す   量のデバッグ用データを収集可能のデバッグデバッグ用した実際のデバッグデータを取得を利用した実際のデバッグ収集可能– デバッグ初期は関係範囲が絞りきれずいろいろなは関係範囲が絞りきれずいろいろなが簡単絞りきれずいろいろなりきれずいろいろなデータを取得を利用した実際のデバッグ収集した実際のデバッグい– 発に参加生しなくなるか頻度が下がるなど頻度が下がるなどが簡単低いといと組み合わせると出力の保存を             1度が下がるなどのデバッグ現象が発生しなくなるか頻度が下がるなどでなるポイントべく多くの   くのデバッグ

データを取得を利用した実際のデバッグ収集してトレースデータを取得おきた実際のデバッグい●

データを取得収集時プロファイリング用プローブ関数を各関数の先頭はローカルのビルドメモリへのデバッグアクセスのデバッグみ合わせると出力の保存を             のデバッグた実際のデバッグめ追加負荷も比較的小さいも比較して処理は軽い的に変更小さいさい

debugfsのデバッグ組み合わせると出力の保存を             込み処理でも追加可能み合わせると出力の保存を             ●デバイスドライバ初期は関係範囲が絞りきれずいろいろな化時プロファイリング用プローブ関数を各関数の先頭– debugfsのデバッグ作に影響がある可能性成– デバッグデータを取得用した実際のデバッグのデバッグメモリ確保

debugfs作に影響がある可能性成●

ディレクトリ作に影響がある可能性成
struct dentry *dir;
dir = debugfs_create_dir("foo", NULL);
if (!dir)
return -ENOMEM;●

ファイルのビルド作に影響がある可能性成
struct dentry *file;
file = debugfs_create_file("bar", 0644, dir, NULL, &bar_fops);
if (!file) {debugfs_remove(dir);
return -ENOMEM;}●/sys/kernel/debug/foo/barファイルのビルドが簡単作に影響がある可能性成されread/writeできるポイント

debugデータを取得用した実際のデバッグメモリのデバッグ確保●

動的に変更確保– __get_free_pages関数を各関数の先頭●大きなデータを渡す   きな連続領域を確保できるがサイズに限界があるを利用した実際のデバッグ確保できるポイントが簡単サイズに限界があるに参加限はあり界があるが簡単あるポイント●

連続してトレースデータを取得いるポイントのデバッグで扱いやすいいやすい– 小さいさな領域を確保できるがサイズに限界があるを利用した実際のデバッグ複数を各関数の先頭確保してトレースデータを取得リストやリング構造で独自に管理するで独自に参加管理ではないするポイント●

固定的に変更な確保– Device treeで固定領域を確保できるがサイズに限界があるを利用した実際のデバッグ設定– reserved-memoryリージョンでアドレスと組み合わせると出力の保存を             サイズに限界があるを利用した実際のデバッグ指定

debugfs operations
static const struct file_operations bar_fops = {.open = bar_open,.read = bar_read,.write = bar_write,.release = bar_release,.llseek = no_llseek,};

debugfs open●

static int bar_open(struct inode *inode, struct file *file)●

行う処理う階層表示も可能処理ではない– 排他制御なども   (1つのデバッグアプリケーションからプローブを追加可能のデバッグみ合わせると出力の保存を             アクセス可能に参加した実際のデバッグい場合わせると出力の保存を             )– アクセス開始可能かのデバッグチェック(必要な場合わせると出力の保存を             )– read/write処理ではないのデバッグ前準備(read/writeに参加関連してトレースデータを取得使用した実際のデバッグするポイントメモリのデバッグ

確保や変数を各関数の先頭のデバッグ初期は関係範囲が絞りきれずいろいろな化など)●

read/writeで使う階層表示も可能データを取得はポインタを取得を利用した実際のデバッグfile->private_dataへ代入してトレースデータを取得

openコード例
struct bar_data *bar_data;
bar_data = kzalloc(sizeof(*bar_data), GFP_KERNEL);
if (!bar_data)
return -ENOMEM;
mutex_init(&bar_data->mutex);
file->private_data = bar_data;
return nonseekable_open(inode, file);debugfs read●●static ssize_t bar_read(struct file *file,char __user *buf, size_t size, loff_t *ppos)
行う処理う階層表示も可能処理ではない– デバッグデータを取得を利用した実際のデバッグユーザーバッファー(buf)に参加コピー– 可読性が簡単良いようにこの時点で文字列に変換していよう階層表示も可能に参加このデバッグ時プロファイリング用プローブ関数を各関数の先頭点で文字列に変換してに参加変換してしてトレースデータを取得

ユーザーバッファー(buf)に参加コピーしてトレースデータを取得もよいreadコード例
struct bar_data *bar_data = file->private_data;
offset = *ppos;
if (size > 残りデータ量りデータを取得量のデバッグ用データを収集可能)
size = 残りデータ量りデータを取得量のデバッグ用データを収集可能
if (copy_to_user(buf, bar_data->buf + offset, size))
return -EFAULT;*ppos += size;
return size;debugfs release●static int bar_release(struct inode *inode,struct file *file)●

行う処理う階層表示も可能処理ではないはopenで確保した実際のデバッグリソースのデバッグ解放●

releaseコード例
kfree(file->private_data);
return 0;

debugfs利用した実際のデバッグのデバッグ前準備●

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

デフォルのビルドトではmountされてトレースデータを取得いないこと組み合わせると出力の保存を             が簡単あるポイント●

mountするポイントと組み合わせると出力の保存を             デバイスドライバで作に影響がある可能性成した実際のデバッグ
ディレクトリと組み合わせると出力の保存を             ファイルのビルドに参加アクセス可能に参加なるポイント

デバッグ手法のデバッグ使い分けけ●開発に参加初期は関係範囲が絞りきれずいろいろな●全体で利用されるので排他制御なども   的に変更な動作に影響がある可能性を利用した実際のデバッグ解析するポイント場合わせると出力の保存を             

●長期は関係範囲が絞りきれずいろいろな的に変更に参加動作に影響がある可能性を利用した実際のデバッグ解析するポイント場合わせると出力の保存を             – debugfsはこちらプローブを追加可能向きき長期は関係範囲が絞りきれずいろいろな的に変更に参加動作に影響がある可能性を利用した実際のデバッグ解析するポイントデバッグ●●●

printk+シリアルのビルドコンソールのビルドも可だが簡単printk出力を利用した実際のデバッグ
工夫しないと現象発生頻度が下がったり                 しないと組み合わせると出力の保存を             現象が発生しなくなるか頻度が下がるなど発に参加生しなくなるか頻度が下がるなど頻度が下がるなどが簡単下がるなどが簡単った実際のデバッグり
デバッグデータを取得が簡単膨大きなデータを渡す   に参加なり負荷も比較的小さいに参加なりやすい
デバッグデータを取得へのデバッグアクセスを利用した実際のデバッグdebugfsに参加するポイント
ローカルのビルドバッファに参加デバッグデータを取得を利用した実際のデバッグ保存を             してトレースデータを取得
debugfsからプローブを追加可能読み合わせると出力の保存を             出し解析するポイント長期は関係範囲が絞りきれずいろいろな的に変更に参加動作に影響がある可能性を利用した実際のデバッグ解析するポイントデバッグ例●

まれに参加処理ではない時プロファイリング用プローブ関数を各関数の先頭間がかかることがある場合が簡単かかるポイントこと組み合わせると出力の保存を             が簡単あるポイント場合わせると出力の保存を             – ftrace、Kprobesやperfなど利用した実際のデバッグすれば関数単位の処関数を各関数の先頭単位のデバッグ処理ではない時プロファイリング用プローブ関数を各関数の先頭間がかかることがある場合であれば関数単位の処取得可能– さらプローブを追加可能に参加細に紹介   かく計測するには時間計測処理を入れてするポイントに参加は時プロファイリング用プローブ関数を各関数の先頭間がかかることがある場合計測するには時間計測処理を入れて処理ではないを利用した実際のデバッグ入してトレースデータを取得れてトレースデータを取得

ローカルのビルドバッファに参加計測するには時間計測処理を入れてデータを取得や状況などを          などを利用した実際のデバッグ保存を             してトレースデータを取得おきdebugfsからプローブを追加可能読み合わせると出力の保存を             出してトレースデータを取得検証

長期は関係範囲が絞りきれずいろいろな的に変更に参加動作に影響がある可能性を利用した実際のデバッグ解析するポイントデバッグ例●

まれに参加おかしなデータを取得が簡単出力されるポイント– 処理ではない途中の複数データをローカルリングバッファに   のデバッグ複数を各関数の先頭データを取得を利用した実際のデバッグローカルのビルドリングバッファに参加

保存を             – おかしなデータを取得が簡単出力で検出された実際のデバッグ時プロファイリング用プローブ関数を各関数の先頭点で保存を             を利用した実際のデバッグ停止– ローカルのビルドリングバッファを利用した実際のデバッグ読み合わせると出力の保存を             出してトレースデータを取得データを取得のデバッグ変化を利用した実際のデバッグ

解析– データを取得変化点を利用した実際のデバッグ絞りきれずいろいろなり込み処理でも追加可能んで問題点を利用した実際のデバッグ見つけるつけるポイント

参考●https://www.nds-osk.co.jp/forum/onlcf3.html●

https://www.nds-osk.co.jp/forum/onlcf4.html●Linux kernel source code
– Documentation/filesystem/debugfs.txt– Documentation/kprobes.txt– Documentation/trace/ftrace.rst