最も一般的なものは何ですか?また、Linuxカーネルでライブデバッグを行うために使用される珍しい方法やツールはありませんか?私は、例えばLinusを知っています。 against Linuxカーネルのこの種のデバッグ、またはそれが最も少なかったため、当時はその意味で何も行われていませんでしたが、正直なところ、2000年から多くの時間が経過し、 Linuxプロジェクトに関する考え方が変わりました。また、現時点(ローカルまたはリモート)でLinuxカーネルのライブデバッグを行うために使用されている現在の方法は何ですか?
言及されたテクニックとツールに関するチュートリアルとチュートリアルへの参照は大歓迎です。
別のオプションは [〜#〜] ice [〜#〜] /JTAGコントローラーとGDBを使用することです。この「ハードウェア」ソリューションは、特に組み込みシステムで使用され、
しかし、例えばQemuは同様の機能を提供します:
「localhost:1234」でリッスンするgdb「リモート」スタブでqemuを開始します:qemu -s ...
、
次に、GDBを使用して、デバッグ情報でコンパイルされたカーネルファイルvmlinux
を開きます(カーネルの非最適化について議論する this メーリングリストスレッドを見ることができます)。
gDBとQemuを接続します:target remote localhost:1234
liveカーネルを参照してください:
(gdb) where
#0 cpu_v7_do_idle () at Arch/arm/mm/proc-v7.S:77
#1 0xc0029728 in Arch_idle () atarm/mach-realview/include/mach/system.h:36
#2 default_idle () at arm/kernel/process.c:166
#3 0xc00298a8 in cpu_idle () at Arch/arm/kernel/process.c:199
#4 0xc00089c0 in start_kernel () at init/main.c:713
残念ながら、GDBではこれまでのところユーザー空間のデバッグはできません(タスクリスト情報なし、異なるプロセスコンテキストを表示するためのMMU再プログラミングなしなど)。
info threads
は、異なるCPUのリストと状態を提供します編集:
このPDFで手順の詳細を確認できます。
Linuxカーネルのデバッグ中に、デバッガー(KDB、KGDB)、クラッシュ時のダンプ(LKCD)、トレースツールキット(LTT、LTTV、LTTng)、カスタムカーネルインストゥルメント(dprobes、kprobes)などのいくつかのツールを利用できます。次のセクションでは、それらのほとんどを要約しようとしましたが、これらが役立つことを願っています。
[〜#〜] lkcd [〜#〜](Linux Kernel Crash Dump)ツールにより、クラッシュ時にLinuxシステムがメモリの内容を書き込むことができます発生します。これらのログは、クラッシュの根本原因をさらに分析できます。 LKCDに関するリソース
Oopsカーネルが問題を検出すると、Oopsメッセージを出力します。このようなメッセージは、障害ハンドラー(Arch/*/kernel/traps.c)。printkステートメントで使用されているカーネル内の専用リングバッファーOopsには、Oopsで発生した、CPUレジスタの内容、Oopの数、説明、スタックバックトレースなど。カーネルOopに関するリソース
Dynamic Probes は、IBMが開発したLinux用の一般的なデバッグツールの1つです。このツールを使用すると、ユーザー空間とカーネル空間の両方で、システムのほぼすべての場所に「プローブ」を配置できます。プローブは、制御が特定のポイントに到達したときに実行されるコード(特殊なスタック指向言語で記述された)で構成されます。以下にリストされている動的プローブに関するリソース
Linux Trace Toolkit は、カーネルパッチと、カーネル内のイベントのトレースを可能にする関連ユーティリティのセットです。トレースにはタイミング情報が含まれており、特定の期間に発生した事象の合理的に完全な全体像を作成できます。 LTT、LTT Viewer、およびLTT Next Generationのリソース
[〜#〜] memwatch [〜#〜] はオープンソースのメモリエラー検出ツールです。 gccステートメントでMEMWATCHを定義し、コードにヘッダーファイルを追加することで機能します。これにより、メモリリークとメモリ破損を追跡できます。 MEMWATCHに関するリソース
ftrace は、Linuxカーネルに適したトレースフレームワークです。 ftraceは、カーネルの内部操作をトレースします。このツールは、2.6.27のLinuxカーネルに含まれていました。さまざまなトレーサープラグインを使用すると、ftraceは、スケジューリングイベント、割り込み、メモリマップI/O、CPU電力状態の移行、ファイルシステムと仮想化に関連する操作など、さまざまな静的トレースポイントをターゲットにできます。また、カーネル関数呼び出しの動的追跡が利用可能です。オプションで、グロブを使用して関数のサブセットに制限したり、呼び出しグラフを生成してスタックの使用状況を提供したりできます。 https://events.linuxfoundation.org/slides/2010/linuxcon_japan/linuxcon_jp2010_rostedt.pdf でftraceの優れたチュートリアルを見つけることができます。
ltrace はLinuxのデバッグユーティリティであり、ユーザー空間アプリケーションが共有ライブラリに対して行う呼び出しを表示するために使用されます。このツールを使用して、動的ライブラリ関数呼び出しをトレースできます。実行されたプロセスによって呼び出される動的ライブラリ呼び出しと、そのプロセスによって受信される信号をインターセプトして記録します。また、プログラムによって実行されるシステムコールをインターセプトして印刷することもできます。
[〜#〜] kdb [〜#〜]は、Linuxカーネルのカーネル内デバッガーです。 KDBは、単純なシェルスタイルのインターフェイスに従います。これを使用して、メモリ、レジスタ、プロセスリスト、dmesgを検査し、ブレークポイントを設定して特定の場所で停止することもできます。 KDBを介して、ブレークポイントを設定し、いくつかの基本的なカーネル実行制御を実行できます(KDBはソースレベルのデバッガーではありません)。 KDBに関するいくつかの便利なリソース
[〜#〜] kgdb [〜#〜]は、Linuxカーネルのソースレベルデバッガとして使用することを目的としています。 Linuxカーネルをデバッグするためにgdbとともに使用されます。 kgdbを使用するには、2台のマシンが必要です。これらのマシンの1つは開発マシンであり、もう1つはターゲットマシンです。デバッグするカーネルは、ターゲットマシンで実行されます。期待は、gdbを使用してカーネルに「侵入」し、メモリ、変数を検査し、アプリケーション開発者がgdbを使用してアプリケーションをデバッグする方法と同様のコールスタック情報を調べることができることです。カーネルコードにブレークポイントを配置し、制限された実行ステップを実行することができます。 KGDBに関するいくつかの便利なリソース
wiki によると、kgdb
は2.6.26
のカーネルにマージされましたが、これは過去数年以内です。 kgdb
は リモートデバッガー であるため、 カーネルでアクティブ化 してから、何らかの方法でgdbをアタッチします。多くのオプションがあるように思えるので、私は何とか言います- connecting gdb を参照してください。 kgdb
が現在ソースツリーにあることを考えると、これが今後使用したいものだと思います。
だから、Linusは譲歩したように見える。しかし、私は彼の議論を強調したい。これはカーネルの土地です。何か問題が発生した場合、segfault
が表示されず、システム全体がダウンするまでのあいまいな問題から何かが取得されます。ここにドラゴンがいます。注意して続行すると、警告が表示されます。
「ライブ」デバッグ用のもう1つの優れたツールは、kprobes/dynamic probeです。
これにより、特定のアドレスが実行されたときに実行される小さなブレークポイントのような小さなモジュールを動的に構築できます。
それらの大きな利点は次のとおりです。
ブレークポイントへのヒット、データ値の確認、変更や上書きなどの確認などを行うのに最適です。「コードをステップスルー」したい場合は、そうしません。
追加-2018:
もう1つの非常に強力な方法は、「動的」プローブなどの多くのツールをロールアップし、他のツール(oprofileなど)を置き換え/非推奨にする「perf」と呼ばれるプログラムです。
特に、perf probe
コマンドを使用すると、システムに動的プローブを簡単に作成/追加できます。その後、perf record
はシステムをサンプリングし、perf report
(またはperf script
)を介したレポートでプローブがヒットしたときに情報(およびバックトレース)を報告できます。カーネルに適切なデバッグシンボルがある場合、カーネルを停止することなく、システムから優れたインテルを取得できます。このツールの詳細については、(Googleまたはシステムで)man perf
を実行するか、次のすばらしいページを参照してください。
KGDB + QEMUステップバイステップ
KGDBは、ホストGDBからカーネル自体をステップデバッグできるカーネルサブシステムです。
私のQEMU + Buildrootの例は、実際のハードウェアなしでそれを味わう良い方法です: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/1969cd6f8d30dace81d9848c6bacbb8bad9dacd8#kgdb
長所と短所と他の方法:
主な手順は次のとおりです。
次を使用してカーネルをコンパイルします。
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y
CONFIG_CONSOLE_POLL=y
CONFIG_KDB_CONTINUE_CATASTROPHIC=0
CONFIG_KDB_DEFAULT_ENABLE=0x1
CONFIG_KDB_KEYBOARD=y
CONFIG_KGDB=y
CONFIG_KGDB_KDB=y
CONFIG_KGDB_LOW_LEVEL_TRAP=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_KGDB_TESTS=y
CONFIG_KGDB_TESTS_ON_BOOT=n
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
CONFIG_SERIAL_KGDB_NMI=n
それらのほとんどは必須ではありませんが、これは私がテストしたものです。
QEMUコマンドに追加します。
-append 'kgdbwait kgdboc=ttyS0,115200' \
-serial tcp::1234,server,nowait
LinuxカーネルソースツリーのルートからGDBを実行します:
gdb -ex 'file vmlinux' -ex 'target remote localhost:1234'
GDBの場合:
(gdb) c
ブートが完了するはずです。
QEMUの場合:
echo g > /proc/sysrq-trigger
そしてGDBは壊れるはずです。
これで完了です。通常どおりGDBを使用できます。
b sys_write
c
Ubuntu 14.04でテスト済み。
KGDB + Raspberry Pi
上記とまったく同じセットアップが、Raspberry Pi 2、Raspbian Jessie 2016-05-27でほとんど機能しました。
PiでQEMUステップを実行することを学ぶ必要があります。これは簡単にグーグル化できます。
https://www.raspberrypi.org/documentation/linux/kernel/building.md で説明されているように、構成オプションを追加し、カーネルを再コンパイルしますシンボルをデバッグするため、再コンパイルが必要です。
ブートパーティションのcmdline.txt
を編集して追加します。
kgdbwait kgdboc=ttyAMA0,115200
gdb
をシリアルに接続するには:
arm-linux-gnueabihf-gdb -ex 'file vmlinux' -ex 'target remote /dev/ttyUSB0'
シリアルに慣れていない場合は、これをチェックしてください: https://www.youtube.com/watch?v=da5Q7xL_OTo 必要なのは安価なアダプターだけです このような 。 KGDBを試す前に、シリアルからシェルを取得して、シェルが機能していることを確認してください。
行う:
echo g | Sudo tee /proc/sysrq-trigger
シリアルはすでにGDBによって取得されているため、SSHセッション内から。
このセットアップでは、sys_write
にブレークポイントを設定し、プログラムの実行を一時停止し、ソースを一覧表示して続行できました。
しかし、時々sys_write
のnext
を実行すると、GDBがハングし、このエラーメッセージを数回出力しました。
Ignoring packet error, continuing...
そのため、セットアップに問題があるかどうか、またはより複雑なRaspbianイメージで何らかのバックグラウンドプロセスが実行しているためにこれが予想されるかどうかはわかりません。
また、Linuxブートオプションでマルチプロセッシングを無効にするように言われましたが、まだ試していません。
実際、冗談は、Linuxが2.2.12以降、xmon
カーネル内デバッガーを備えていたということです。ただし、powerpc
アーキテクチャーのみです(実際には当時はppc
でした)。
これはソースレベルのデバッガーではなく、ほとんど完全にドキュメント化されていませんが、それでもあります。
http://lxr.linux.no/linux-old+v2.2.12/Arch/ppc/xmon/xmon.c#L119
Ubuntu 16.10ホストでテストされたQEMU + GDBの段階的な手順
最初からすぐに始めるために、最小限の完全自動化QEMU + Buildrootの例を作成しました: https://github.com/cirosantilli/linux-kernel-module-cheat 以下で説明します。
まず、ルートファイルシステムrootfs.cpio.gz
を取得します。必要な場合は、以下を検討してください。
init
- only実行可能イメージ: https://unix.stackexchange.com/questions/122717/custom-linux-distro-that-runs-just-one-program-nothing-else/238579#238579次に、Linuxカーネルで:
git checkout v4.9
make mrproper
make x86_64_defconfig
cat <<EOF >.config-fragment
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
CONFIG_GDB_SCRIPTS=y
EOF
./scripts/kconfig/merge_config.sh .config .config-fragment
make -j"$(nproc)"
qemu-system-x86_64 -kernel Arch/x86/boot/bzImage \
-initrd rootfs.cpio.gz -S -s
別の端末で、start_kernel
からデバッグを開始するとします。
gdb \
-ex "add-auto-load-safe-path $(pwd)" \
-ex "file vmlinux" \
-ex 'set Arch i386:x86-64:intel' \
-ex 'target remote localhost:1234' \
-ex 'break start_kernel' \
-ex 'continue' \
-ex 'disconnect' \
-ex 'set Arch i386:x86-64' \
-ex 'target remote localhost:1234'
完了です!!
カーネルモジュールについては、次を参照してください: LinuxカーネルモジュールをQEMUでデバッグする方法
Ubuntu 14.04、GDB 7.7.1では、hbreak
が必要でしたが、break
ソフトウェアブレークポイントは無視されました。 16.10ではもうそうではありません。参照: https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944
厄介なdisconnect
とその後に来るのは、エラーを回避することです。
Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000
関連するスレッド:
こちらもご覧ください:
既知の制限:
-O0
をサポートしていません(そして、パッチなしでもコンパイルしません): Linuxカーネルを最適化せずに-O0でコンパイルする方法は?max-completions
修正後でも、いくつかのタイプのタブ補完でメモリを消費します: 大きなバイナリのタブ補完割り込み 。したがって、ulimit -Sv 500000
はデバッグ前の賢明なアクションです。 file<tab>
のfilename
引数のsys_execve
が次のように完了したときに具体的に爆発しました: https://stackoverflow.com/a/42290593/895245カーネルコードをたくさん書く人として、私はkgdbを使用したことがなく、kprobesなどを使用することはめったにないと言わなければなりません。
多くの場合、戦略的なprintks
を投入するのが最善の方法です。最近のカーネルではtrace_printk
は、dmesgをスパムせずにそれを行う良い方法です。
ユーザーモードLinux(UML)
https://en.wikipedia.org/wiki/User-mode_Linux
カーネルコードのステップデバッグを可能にする別の仮想化方法。
UMLは非常に独創的です。x86
と同様にArch
として実装されますが、低レベルの命令を使用する代わりに、ユーザーランドシステムコールでArch
関数を実装します。
その結果、Linuxホスト上でLinuxカーネルコードをユーザーランドプロセスとして実行できるようになります。
最初にrootfsを作成し、次のように実行します。 https://unix.stackexchange.com/questions/73203/how-to-create-rootfs-for-user-mode-linux-on-Fedora-18/372207#372207
um
defconfigはデフォルトでCONFIG_DEBUG_INFO=y
を設定します(そう、これは開発用です)ので、大丈夫です。
ゲスト:
i=0
while true; do echo $i; i=$(($i+1)); done
別のシェルのホスト:
ps aux | grep ./linux
gdb -pid "$pid"
GDBの場合:
break sys_write
continue
continue
そして今、あなたはGDBからカウントを制御しており、期待どおりにソースを見ることができます。
長所:
短所:
カーネル自体のコンパイル方法が変わるため、非常に侵襲的です。
ただし、Arch
仕様以外の高レベルAPIは変更しないでください。
おそらくあまりアクティブではありません: ユーザーモードlinux(UML)プロジェクトは停止していますか?
参照: https://unix.stackexchange.com/questions/127829/why-would-someone-want-to-run-usermode-linux-uml
皆さんは間違っています。kgdbは最新のカーネルでもうまく機能します。分割イメージのカーネル構成、ランダム化の最適化に注意する必要があります。
シリアルポート経由のkgdbは役に立たない。なぜなら今日のマザーボードシリアルポートでDB9をサポートするコンピューターはなく、USBシリアルポートはポーリングモードをサポートしていないからである。
新しいゲームはkgdboeで、ログトレースは次のとおりです。
以下はホストマシンです。vmlinuxはターゲットマシンのものです。
root@Thinkpad-T510:~/KGDBOE# gdb vmlinux
Reading symbols from vmlinux...done.
(gdb) target remote udp:192.168.1.22:31337
1077 kernel/debug/debug_core.c: No such file or directory.
(gdb) l oom_kill_process
828 mm/oom_kill.c: No such file or directory.
(gdb) l oom_kill_process
828 in mm/oom_kill.c
(gdb) break oom_kill_process
Breakpoint 1 at 0xffffffff8119e0c0: file mm/oom_kill.c, line 833.
(gdb) c
Continuing.
[New Thread 1779]
[New Thread 1782]
[New Thread 1777]
[New Thread 1778]
[New Thread 1780]
[New Thread 1781]
[Switching to Thread 1779]
Thread 388 hit Breakpoint 1, oom_kill_process (oc=0xffffc90000d93ce8, message=0xffffffff82098fbc "Out of memory")
at mm/oom_kill.c:833
833 in mm/oom_kill.c
(gdb) s
834 in mm/oom_kill.c
(gdb)
ピアターゲットマシンでは、次のようにしてクラッシュを取得し、ホストマシンにキャプチャします。
#swapoff -a
#stress -m 4 --vm-bytes=500m