Movatterモバイル変換


[0]ホーム

URL:


Upgrade to Pro — share decks privately, control downloads, hide ads and more …
Speaker DeckSpeaker Deck
Speaker Deck

デバッガと和解せよ

Avatar for Takaya Saeki Takaya Saeki
May 03, 2023

 デバッガと和解せよ

2022/08/28 Kernel/VM探検隊online part5 (https://kernelvm.connpass.com/event/256248/) の @nullpo_head (https://twitter.com/nullpo_head) の発表資料です。

ptraceを使って対象コマンドの全子プロセスにattachしてDwarfを見つつデバッグしたいプロセスを探し、最終的には他のデバッガに処理を流すような不思議なデバッガ(?)を作ることで、zero configurationでvscodeでブレークポイントを打ったプロセスのデバッグを始めてくれる dbgee (https://github.com/nullpo-head/dbgee) という便利ツールを作ったときの話をしました。

Avatar for Takaya Saeki

Takaya Saeki

May 03, 2023
Tweet

More Decks by Takaya Saeki

See All by Takaya Saeki

Other Decks in Technology

See All in Technology

Featured

See All Featured

Transcript

  1. デバッガと 和解せよ Takaya Saeki (@nullpo_head) Kernel/VM 探検隊 online part 5

    @nullpo_head 1 2022/08/27
  2. デバッガー使うの、 腰 が 重 く な い ? 2

  3. 3 デバッガーは少し面倒で気軽に使えない アタッチが 面倒 使い方を 忘れる その他 デバッガーを使うのが面倒な理由(発表者脳内調べ) GDBコマンド 忘れた

    - list? s? si? Gdb用のmake run ターゲットがない VSCodeの launch.json 書きたくない デ バ ッ ガ の ア タ ッ チ / 起 動 は 既存の開発フローと親和性が低い デバッガはいつもより一手間必要
  4. デバッガを気軽に 使えるようにする 便利ツールを作ろう 4 Key technology • Ptrace • Seccomp-BPF

    • DWARF
  5. 5 デバッガーはなぜ面倒か? アタッチが 面倒 使い方を 忘れる その他 デバッガーを使うのが面倒な理由(発表者脳内調べ)

  6. 6 使い方を忘れる 使い方を 忘れる デバッガーを使うのが面倒な理由(発表者脳内調べ) (解決済み)フロントエンドを使おう • VSCode 起動さえすれば使いやすい •

    Vim/NeoVim Vim 8.1から termdebug が入ったらしい (未体験 • Emacs emacsユーザーではないので割愛
  7. 7 アタッチ/起動が面倒 アタッチが 面倒 デバッガーを使うのが面倒な理由(発表者脳内調べ) GDB/LLDBなら • デバッグ対象の起動がシェルスクリプトや ビルドシステムでラップされていると デバッガで起動するのが大変

    VSCodeなら加えて • Launch.jsonを書くのが面倒 • Stdin/outがあるとやや使いづらい
  8. 単体バイナリを起動するシンプルな場合 簡単にデバッガを挿入できる 8 起動スクリプトとデバッガ相性悪い問題 ※RustやC/C++、Goのようなバイナリコンパイル言語をひとまず話題にします 👌

  9. Makeやもっと複雑なビルドスクリプトで起動がラップされていると? スクリプトを覗かないとデバッガの挿入方法/可否が分からない • debugターゲットがある?それとも自前で修正? 9 起動スクリプトとデバッガ相性悪い問題 🤔

  10. _人人人人人人人人人人人人人人人人人_ > 仕様を調べるのがもうすでに面倒 <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄ 10 VSCode、便利だけどlaunch.jsonが面倒

  11. _人人人人人人人人人人人人人人人人人_ > 仕様を調べるのがもうすでに面倒 <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄ 11 VSCode、便利だけどlaunch.jsonが面倒 ボーナス点 _人人人人人人人人人人人人人人人人人_ >

    CLI引数やリダイレクトが必要なら < > さらに面倒なことに! <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^^Y^ ̄
  12. 理想のデバッガの 起動方法は何だ? 12

  13. 普段のコマンドに足すだけでデバッガが起動してほしい (無茶ブリ) 13 既存のCLIワークフローに親和してほしい

  14. 普段のコマンドに足すだけでデバッガが起動してほしい (VScode編) 14

  15. 普段のコマンドに足すだけで デバッガが起動してほしい!!! 15

  16. このコマンドが欲しい!!! 16

  17. 実は前に”dbgee”を作ったのだが… 17

  18. `Run`: ターゲットプログラムのパスと引数を指定してデバッグ `Set`: ターゲットプログラムのパスを指定すると、それをデバッガ起動コマンドでラップする • VSCodeのシェル内で叩けばVSCodeのデバッグセッションが始まる (with vscode plugin) •

    普通のターミナルで叩けば、tmux paneでgdb –tuiが起動する 18 Dbgeeができること
  19. `Run`: ターゲットプログラムのパスと引数を指定してデバッグ `Set`: ターゲットプログラムのパスを指定すると、それをデバッガ起動コマンドでラップする • VSCodeのシェル内で叩けばVSCodeのデバッグセッションが始まる (with vscode plugin) •

    普通のターミナルで叩けば、tmux paneでgdb –tuiが起動する 19 Dbgee、まだ使いづらい・・・ ビルド方法によってはビルド後の パ ス を 指 定 す る の が 結 構 面 倒
  20. ターゲットプログラムのパス を指定しないでいい方法が欲しい! 20

  21. • プログラム中で特定の出力をすれば、どこにビルドされていようと/どんなスクリプトから 起動されていようとブレークできれば便利では?? 21 第1案 どんなコマンドでビルド/起動さ れていようとここでブレーク Secomp-bpfとptraceで 実 現

    で き そ う !
  22. デバッグ対象をptraceにより起動直後に停止させて、VSCodeやgdbに明け渡す 1. Dbgee `fork()` 2. 親(dbgee) 3. 子を`waitpid()` 6. `SIGTRAP`を受信

    7. `ptrace(PTRACE_CONT, …, SIGSTOP)`で、子からデタッチしつつ子を停止 8. Gdbやそのほかのデバッガを起動し、Attach by PIDで子にアタッチさせる VSCodeなら、dbgeeプラグインとのfifoコネクションにアタッチリクエストを送信 2. 子 4. `ptrace(TRACE_ME, …)` 5. `execve(ターゲットPATH, …)` ここでSIGTRAPが発生 ← ptraceの仕様 22 現Dbgeeの仕組み兼Ptraceのおさらい
  23. • Ptraceとseccomp-bpfの組み合わせで可能 • Ptraceにはすべてのforkを追跡するオプションがあ る • Seccomp-bpfには、bpfでフックするシステムコー ルを条件判定してSIGTRAPするオプションがある • Seccomp-bpf触りたい!これはKernel/VM向き

    だ!! 23 特定出力でブレークの実現
  24. いやまてよ・・・ 24

  25. もっと簡単に実現できるくない? 25

  26. • すべてのExecveをトラップする • 新プロセスのDWARFを読んで、ソース一覧に編集中のソースファイルが含まれているか判断 • Yesならアタッチ でよくない? 26 第2案 Secomp-bpfいらねぇ!

  27. 27 そしてメインからLTへ・・・

  28. • ビルド先は知らずに & 起動スクリプトの内容も知らずに • ソースコードの場所さえ知っていれば デバッガをアタッチ可能 28 第2案でのデバッガ起動

  29. 29 処理の流れ Ptraceですべての子孫プロセスにアタッチしつつ、DWARFをパースして目的のプロセスを探す 1. `ptrace(PTRACE_SETOPTIONS, …, PTRACE_O_TRACECLONE)` • すべてのcloneされたプロセスもptrace配下になる •

    ちなみにLinux専用機能になります(macOSでは同様の機能はない 2. 子孫プロセスがexecveするたびにSIGTRAPを受信 3. `/proc/PID/exe`を見て、DWARFがあればパース、ソースコードのリストを得る 4. ソースコードの中に、引数で与えられたソースがある? • If YES • そのプロセスを`ptrace(PTRACE_CONT, …, SIGSTOP)`でデタッチしつつ止める • 真のデバッガにそのプロセスを渡す • 全プロセスからデタッチ
  30. • Cargo.tomlに二行足すだけで、DWARFのパーサが入る • Crateのドキュメントを書く文化とLSPのおかげで快適にDWARFライブラリが使える システムプログラミングにも低レイヤプラグラミングにも本当におすすめ 30 Rust最高!

  31. 普段のコマンドに足すだけで デバッガが起動してほしい!!! できる!!! 31

  32. このコマンド相当ができた!!! 32

  33. 33 デモ

  34. デバッガーがかなり 気軽に使えるように! デバッガと和解しよう 34

  35. • Dockerへの対応 • Dockerで実行されると、子ではなくデーモンの方で実行されてしまうのでptraceできない • Minikubeやkindでの実行にも対応したい • ので、runcをptraceでラップしたOCIランタイムとして実装して対応したい • Pythonへの対応

    • 今回の新機能はいまのところC/C++/Rust/Goにだけ対応 • こっちは本当にseccomp-bpfいるかも? やる気がないやつ • macOS対応 • Ptraceが実質「無」で、macOSのAPIを学ばないと厳しいので 35 TODO(かつやる気があるやつ)

[8]ページ先頭

©2009-2025 Movatter.jp