コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2021年3月4日 >>> 2021年3月4日
link もっと後

2021年3月4日

VSCodeを使ってWindowsからLinuxアプリのデバッグ その2

目次: Linux

その1その2

昨日(2021年3月3日の日記参照)の続きです。

GDBの準備

Windows側で使用するGDBを用意します。最初はMinGWのバイナリが使えるかと思ったのですが、MinGWのバイナリはWindowsの実行形式(COFF)のデバッグ用で、Linuxの実行形式(ELF)は認識せず、ダメでした。残念。

GDBはbinutilsに含まれています。ビルド方法を下記に示します。バージョンは何でも良いと思いますが、私はMinGWも使っている2.32にしました。

binutils, gdbのビルド
$ git clone git://sourceware.org/git/binutils-gdb.git
$ cd binutils-gdb
$ git checkout -b 2_32 binutils-2_32

$ mkdir build
$ cd build
$ ../configure \
    --host=x86_64-w64-mingw32 \
    --target=x86_64-unknown-linux-gnu \
    --prefix=`pwd`/_install \
    --disable-werror \
    --with-expat=no \
    --enable-sim \
    --enable-libdecnumber \
    --enable-libreadline \
    --enable-gas \
    --enable-binutils \
    --enable-ld \
    --disable-gold \
    --enable-gprof

$ make -j8
$ make install

ビルドが成功すると、build/_installディレクトリにWindows用のbinutilsのバイナリ(GDBも含む)がインストールされます。フォルダごとWindows側にコピーすれば動きます。ディレクトリの名前 _installはWindows側に持っていったあとに変更しても構いません。

比較的、新しい環境(Ubuntu 20など)だとMinGWが何か変らしく、gdb/common/common-defs.hにある _FORTIFY_SOURCEの定義を消さないと、リンクの時に __memcpy_chk() などの関数が見当たらないと言われてエラーになります。

比較的新しいMinGWでbinutilsをビルドすると遭遇するエラー
  CXXLD  gdb.exe
/usr/bin/x86_64-w64-mingw32-ld: ada-tasks.o:/usr/share/mingw-w64/include/string.h:202: undefined reference to `__memcpy_chk'
/usr/bin/x86_64-w64-mingw32-ld: amd64-tdep.o:/usr/share/mingw-w64/include/string.h:202: undefined reference to `__memcpy_chk'
/usr/bin/x86_64-w64-mingw32-ld: breakpoint.o:/usr/share/mingw-w64/include/string.h:228: undefined reference to `__strcpy_chk'
/usr/bin/x86_64-w64-mingw32-ld: breakpoint.o:/usr/share/mingw-w64/include/string.h:228: undefined reference to `__strcpy_chk'
...

とりあえず下記のパッチでエラーは回避できますが、おそらく正しい直し方ではありません。原因は調べていません。もしご存知の方は教えていただけると嬉しいです。

FORTIFY_SOURCEを無効化するパッチ

diff --git a/gdb/common/common-defs.h b/gdb/common/common-defs.h
index e574de5ed66..a9b0520b4c5 100644
--- a/gdb/common/common-defs.h
+++ b/gdb/common/common-defs.h
@@ -69,7 +69,7 @@
    then we don't do anything.  */

 #if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__ > 0
-#define _FORTIFY_SOURCE 2
+//#define _FORTIFY_SOURCE 2
 #endif

 #include <stdarg.h>

面倒であれば、ビルド済みのバイナリ(link binutils_x86_64-unknown-linux-gnu.zip)をどこか適当なディレクトリに展開してもらえれば動くはずです。Windows 10で動作確認しています。

Windows側の準備

Visual Studio Codeをインストールします。Microsoftのサイトからダウンロードできます(Visual Studio Code - Code Editing. Redefined)。

はじめにC/C++ Extensionをインストールします。GDBと連携するためです。


VSCode C/C++ Extensionのインストール画面

先ほどのテストプログラムが置いてあるディレクトリを開きます。メニューの [File] - [Open Folder] です。ここではZ:\projects\c\test_argvにあるとします。

左側のタブからRun and Debugを選択します。Ctrl + Shift + Dでも良いです。次に青いRun and Debugボタンを押します。するとSelect Environmentというコンボボックスが出てくるのでC++ (GDB/LLDB) を選択します。


Run and Debug


C/C++ (GDB/LLDB) を選択

ソースコードペインにlaunch.jsonのテンプレートが表示されると思うので、下記の内容に書き換えます。miDebuggerPathやmiDebuggerServerAddressは適宜、環境に合わせて書き換えてください。

launch.jsonの記述例

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Attach",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/a.out",
            "cwd": "${workspaceFolder}",
            "MIMode": "gdb",
            "miDebuggerPath": "c:\\app\\binutils\\bin\\x86_64-unknown-linux-gnu-gdb.exe",
            "miDebuggerServerAddress": "192.168.1.2:1234",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true,
                },
                {
                    "description": "Relace absolute path of source code",
                    "ignoreFailures": false,
                    "text": "set substitute-path /home/katsuhiro/share/falcon z:/",
                },
            ],
        },
    ]
}

ここで大事なのはsetupCommandsのset substitute-pathです。gdbはLinux側の絶対パスでソースコードの場所を通知してくることがあります。Linux側の絶対パスを渡されてもWindows側ではファイルを探せませんから、絶対パスの一部をWindows側に存在するパスに置き換えることで、VSCodeがソースコードを見つけられるように設定してあげないと、こんなエラーで怒られます。


ソースコードの場所の設定に失敗しているとエラーが出る

今回の例では、

  • Linuxから見たテストプログラムのある場所: /home/katsuhiro/share/falcon/projects/c/test_argv
  • LinuxからSambaでWindowsに見せている場所: /home/katsuhiro/share/falcon
  • Windowsのリモートドライブレター: Z:
  • Windowsから見たテストプログラムのある場所: Z:/projects/c/test_argv

このような設定にしていますから、Windows側のネットワークドライブZ:/ が、Linux側の /home/katsuhiro/share/falconを指していることを伝えるために、上記の例のように "set substitute-path /home/katsuhiro/share/falcon z:/" にします。もし対応がわからない場合はSambaの設定を確認しましょう。

いざデバッグ

いよいよ最終目的であるLinux側のgdbserverと、Windows側のVSCode + GDBを連携させます。図示するとこのような構成です。


WindowsからLinuxアプリのデバッグ、それぞれの役割(再掲)

実際にやってみましょう。最初にLinux側でgdbserverを起動します。

Linux側の操作
$ gdbserver --multi localhost:1234 ./a.out a b c d

Process ./a.out created; pid = 15409
Listening on port 1234
Remote debugging from host ::ffff:192.168.1.112, port 64957

★mainでbreakしたあとcontinueすると下記が出力される

argc: 5
argv[1]: aa
argv[2]: bb
argv[3]: cc
argv[4]: dd
 
Child exited with status 0

その後、VSCodeでmainにブレークポイントを設定します。F5キーを押してデバッグ開始すると、main() 関数で停止し、ソースコードが表示されるはずです。


Windows側からデバッグできている状態

うまくいきました、良かった良かった。

繋がらないときは

Unable to start debugging. Unexpected GDB output from command... のように言われて、デバッグできない場合は、

  • miDebuggerPathの場所にx86_64-unknown-linux-gnu-gdb.exeはあるか?
  • miDebuggerPathに指定したファイルはコマンドプロンプトなどから実行可能か?
  • miDebuggerServerAddressは正しいか?
  • gdbserverを起動し忘れていないか?
  • Windows用のGDBからtarget remote [miDebuggerServerAddressに指定したアドレス] としたとき繋がるか?

上記を今一度チェックしてみてください。特にgdbserverはデバッグの度に毎回起動しなければなりません。割と忘れがちです。これ非常に面倒なので、改善方法が既にありそうな気がします(今はわかりません)。

Windows要らなくない?

そこに気づかれましたか、鋭いですね、おっしゃる通りです。私もbinutilsをビルドし終わった辺りで、もしやVSCodeをLinux側で動かせば何の苦労もなかったのでは?と気づきましたが、遅すぎたのでここまで突っ走りました。正直、Windowsを使うだけ面倒で、何も利点がないです。なるほど、この方法を実践している人が誰もいないわけです。

Windowsからデバッグだけする方法が向いている人、環境ですか……?うーん、ほとんど居ないと思いますが、強いていえばLinux PCのGUI環境を整備しておらず、整備も面倒と思っていて、普段遣いのWindows PCしか持っていないような方でしょうか。この手順も大概面倒くさいけどね。

編集者:すずき(2023/12/25 19:10)

コメント一覧

  • 名無しさん(2022/01/13 17:10)
    setupCommandsに"text": "shell ssh remoteHost gdbserver :1234 a.out ${args[@]}"}\nlocalなら、\n{"text": "shell gdbserver :1234 a.out ${args[@]}"}\n
  • すずきさん(2022/01/14 09:16)
    なるほど。setupCommandsでgdbserverを起動できるんですね。コメントありがとうございます。
open/close この記事にコメントする



link もっと前
2021年3月4日 >>> 2021年3月4日
link もっと後

管理用メニュー

link 記事を新規作成

<2021>
<<<03>>>
-123456
78910111213
14151617181920
21222324252627
28293031---

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事3件

  • link 24年4月25日
    すずき (04/26 16:49)
    「[AVIFの変換] AVIFが読めないアプリケーションがたまにあるので、AVIF(AV1 Image File Format)...」
  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/26 16:49