はじめまして、Quipperに再来週に入社予定のujihisaと申します。 本記事では、Vim本体のC実装をデバグするのにGNU Debugger (GDB)を用いる方法について説明します。 巷には「GDBをVimに統合させて何らかのプログラムをデバグする方法」はいくつか解説記事がありますが、本記事はそうではなく、Vim自体のデバグについてに着目します。
Quipperでは社内のソフトウェアエンジニアのうち4割 *1がVimを使用しており、我々はVim本体の未解決バグを踏んだときに自力で解決しVimコア開発者にフィードバックできるようになっているべきです。
Vimを debug_info, not stripped
でビルドする
お使いのVimのバイナリは、おそらくdebug buildではないです。ちょっと確認してみましょう。
$ file `which vim` /usr/sbin/vim: ELF 64-bit LSB pie executable x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=453c03888b6bf2b68fb92ba2efb59b139a9b0b76, stripped
末尾の stripped
に注目してください。このバイナリに対してはGDBを使うことはほぼ出来ません *2。
- Vimソースコードを取得します。単に https://github.com/vim/vim からgit cloneするだけで大丈夫です
- 以下ではこれを ~/git/vim に展開したものとします
- configureのあと、
src/Makefile
ファイルを直接編集します (以下のパッチを参照せよ)- 直接編集するってこれ全然直感的じゃないと感じると思いますが、これはなんとVimの
src/Makefile
でそう指示されています *3
- 直接編集するってこれ全然直感的じゃないと感じると思いますが、これはなんとVimの
:terminal make -C src reconfig clean all install
diff --git a/src/Makefile b/src/Makefile index f2fafa4dc..8b41d0648 100644 --- a/src/Makefile +++ b/src/Makefile @@ -591,7 +591,7 @@ CClink = $(CC) # When using -g with some older versions of Linux you might get a # statically linked executable. # When not defined, configure will try to use -O2 -g for gcc and -O for cc. -#CFLAGS = -g +CFLAGS = -g #CFLAGS = -O # Optimization limits - depends on the compiler. Automatic check in configure @@ -1006,6 +1006,7 @@ TOOLS = xxd/xxd$(EXEEXT) # # Uncomment the next line to install Vim in your home directory. #prefix = $(HOME) +prefix = $(HOME)/git/vim/local ### exec_prefix is the top directory for the executable (default $(prefix)) # @@ -1156,7 +1157,7 @@ INSTALL_DATA_R = cp -r ### Program to run on installed binary. Use the second one to disable strip. #STRIP = strip -#STRIP = /bin/true +STRIP = /bin/true ### Permissions for binaries {{{1 BINMOD = 755
なお、ここの prefix
部分は僕用の設定です。これをやるときは別に全く同じよう設定する必要はありません。こうしておくと /usr/local
以下ではないところにmake installすることになりますので、sudoが不要になって便利です。
このようにして生成されたVimバイナリに改めて file
をかけて、 debug_info, not stripped
がついていることを確認してください。
$ file ~/git/vim/local/bin/vim /home/ujihisa/git/vim/local/bin/vim: ELF 64-bit LSB pie executable x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=c8da01b6b400e7f8e37046f5313145fc2e15be2b, with debug_info, not stripped
2. GDBを使う
以下で実行します。勝利が約束されています。
$ gdb ~/git/vim/local/bin/vim -q --tui
以下のように見ることができます。音声のない短い動画ですので気軽にみてみてください。
このデモでは以下のGDBのコマンドを利用しました。詳しくはGDBの中で help
してみてください。
start
(Vimのコマンドラインオプション-u NONE
などを渡しています。)break
でbreakpointを貼っていますc
= continue = breakpointまで一気に実行n
= next = Cで一行分実行
おまけ: :Termdebug
を使う
すでにGDBは使えているので、ここからは必須ではありません。
Vim 8から搭載されている, Vimの中でターミナルを起動する :terminal
。これを前提としたVimプラギンのtermdebugというものがあり、これはなんとVim 8にすでに標準搭載されています。
packadd termdebug
この一行を~/.vimrcに書くだけで、 :Termdebug
コマンドが使えるようになります。こうすることで、Vimの中でVimのデバグを行うことができます。この場合新しく起動する子Vimは親の :terminal
内で起動されるため、それぞれが端末描画を競い合うなどといったことを回避でき、大変便利です。
おわりに
ujihisa個人ブログ (英語) にて同様の内容の記事を先日投稿しました。が、日本語では相当する記事がないため、需要があると判断して執筆してみました。
Quipperに入社したらVimなどを用いてQuipperのあれやこれをこれから開発したり手伝ったり便利したりと貢献していく所存です。みなさま今後共よろしくおねがいします。
ujihisa