VSCodeからNetBSD2(i386)をSSH経由でgdbアタッチデバッグする
VSCodeからNetBSD6(i386)をSSH経由でgdbアタッチデバッグするの続き
NetBSD 2.0.2(i386)に対応させる。
TL;DR
-
--interpreter=mi2
に対応するためにgdb-7.2a
をビルド・インストール - SSH接続時のアルゴリズム(鍵交換・暗号化)をNative Debugで指定する機能実装
- 鍵交換:
diffie-hellman-group-exchange-sha1
- 暗号化:
aes128-cbc
-
launch.json
で"ssh": {"kex": ["diffie-hellman-group-exchange-sha1"], "cipher": ["aes128-cbc"]}
を指定する
- 鍵交換:
-
launch.json
で"debugger_args": ["--symbols", "デバッグ情報のあるリモート上のバイナリパス"]
を指定する - 変更差分
事前準備:NetBSD2.0.2(i386)のQEMU作成
既に作成済みあるいはホストマシンがあればgdb-7.2a
のビルド・インストールまでスキップ。
流れはNetBSD6.0.1とほぼ同じのため重複部分は割愛するが、インストールウィザードが若干異なる。
OSイメージファイル取得
i386cd.iso
を保存。
初回起動コマンド
qemu-system-i386 ^
-m 1024 ^
-smp sockets=1,cores=4,threads=2 ^
-hda netbsd.qcow2 ^
-cdrom i386cd.iso ^
-netdev user,id=n1,ipv6=off ^
-device e1000,netdev=n1 ^
-monitor telnet::5432,server,nowait ^
-rtc base=utc
インストール
インストールウィザード
1番目を選択
1番目を選択
Yesを選択
エンター
1番目を選択
1番目を選択
2番目を選択
Yesを選択
1番目を選択
2番目のスワップサイズを適宜変更
一番下を選択
エンター
エンター
Yesを選択
1番目を選択
エンター
1番目を選択
3番目を選択
一番下を選択
ここでインストールが始まるのでしばらく待つ。
エンター
エンター
Japanを選択
一番下を選択
3番目を選択
Yesを選択
rootログイン用パスワードを設定
エンター
3番目を選択
エンター
4番目を選択
ブート画面が出たらウィンドウを閉じる
2回目以降の起動
qemu-system-i386 ^
-m 1024 ^
-smp sockets=1,cores=4,threads=2 ^
-hda netbsd.qcow2 ^
-netdev user,id=n1,ipv6=off,hostfwd=tcp::44444-:22 ^
-device e1000,netdev=n1 ^
-monitor telnet::5432,server,nowait ^
-rtc base=utc
キーボードレイアウトの修正
101キーになっているらしいので日本語レイアウトに変更する。
wsconsctl -k -w encoding=jp
※=
は ^
で入力できる。
永続的に変更するには/etc/wscons.conf
を編集する。
vi /etc/wscons.conf
encoding jp
SSH接続設定
vi /etc/rc.conf
dhclient=yes
sshd=yes
vi /etc/hosts
127.0.0.1 localhost.localdomain
vi /etc/ssh/sshd_config
-
PermitRootLogin
のコメントを削除してyes
に変更 -
PubkeyAuthentication
のコメントを削除 -
PasswordEmptyAuthentication
のコメントを削除
sshd
再起動
/etc/rc.d/sshd restart
マシン再起動
reboot now
参考
Unable to negotiate with ***: no matching key exchange method found. Their offer: diffie-hellman-group-exchange-sha1,…
、no matching cipher found. Their offer: aes128-cbc,…
等と表示されて接続できない
SSH接続でおそらくクライアント側で非推奨の接続形式を除外しているためかと思われる。
サーバー側から提案された方式を指定して接続する。
ssh root@127.0.0.1 -p 44444 -oKexAlgorithms=+diffie-hellman-group-exchange-sha1 -c +aes256-cbc
tset: terminal type vt100 is unknown Terminal type?
と入力を促される
SSH接続時に毎回詳細は未確認だが環境変数TERM=vt100
を事前に設定しておくと解消される。
~/.profile
を編集し、tset
のチェック処理の直前にexport TERM=vt100
を追記する。
vi ~/.profile
export TERM=vt100
if [ -x /usr/bin/tset ]; then
eval `tset -sQrm 'unknown:?unknown'`
fi
次回以降のSSH接続で入力が要求されなくなる。
ssh root@127.0.0.1 -p 44444 -oKexAlgorithms=+diffie-hellman-group-exchange-sha1 -c +aes256-cbc
root@127.0.0.1's password:
Last login: *** *** ** **:**:** ****
NetBSD 2.0.2 (GENERIC) #0: Wed Mar 23 08:53:42 UTC 2005
Welcome to NetBSD!
Terminal type is vt100.
We recommend creating a non-root account and using su(1) for root access.
#
gdb-7.2a
のビルド・インストール
gdb
のバージョン確認
gdb --version
GNU gdb 5.3nb1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386--netbsdelf".
Native DebugはMI2に準拠しているがMIが正式に2へ対応したのがおそらくgdb-6.0
からのようなのでプリインストール版では拡張機能が使えない。
- Default MI syntax changed to "mi2".
The default MI (machine interface) syntax, enabled by the command line
option "-i=mi", has been changed to "mi2". The previous MI syntax,
"mi1", can be enabled by specifying the option "-i=mi1"
ただ対応されているはずのバージョンgdb-7.0.1a
で確認したところ、デバッグモードに入れるもののローカル変数値がVSCodeから一覧で表示されないバグがあった/gdb-7.3.1
ではビルドエラーになったので、ビルドも通りかつローカル変数値一覧が表示できるgdb-7.2a
を選択する。
mkdir -p ~/build_ws
cd ~/build_ws
ftp ftp://gcc.gnu.org/pub/gdb/releases/
get gdb-7.2a.tar.gz
quit
tar zxvf gdb-7.2a.tar.gz
mkdir -p gdb-7.2/build
cd gdb-7.2/build
LDFLAGS=-static \
../configure \
--build=i486--netbsdelf
make -j8
make install
/usr/local/bin/gdb --version
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486--netbsdelf".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Native DebugにSSH接続方式機能を実装
NetBSD2の制約によりSSH接続方式を指定できないと以下のようなエラーが出てNative DebugからSSH接続できない。
Error running over ssh!
Error: error occurred on connecting the ssh.
Error: Handshake failed: no matching key exchange algorithm
Native DebugでのSSH接続にはnpmモジュールのssh2
を用いており、モジュール自体では対応できているがNative Debug側が未実装のためlaunch.json
から指定できないので、これらを指定できるように修正する。
SSH接続方式機能の変更差分
割り込み実装の変更差分を適用してからの差分。
変更差分
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -325,6 +325,53 @@
"type": "string",
"description": "Only connect via resolved IP address family for host",
"default": "IPv4"
+ },
+ "forceIPv6": {
+ "type": "boolean",
+ "description": "Only connect via resolved IPv6 address for host",
+ "default": false
+ },
+ "algorithms": {
+ "type": "object",
+ "description": "Specify algorithms",
+ "properties": {
+ "kex": {
+ "type": "array",
+ "description": "Key exchanges",
+ "default": [
+ "diffie-hellman-group-exchange-sha1",
+ "diffie-hellman-group1-sha1"
+ ]
+ },
+ "cipher": {
+ "type": "array",
+ "description": "Ciphers",
+ "default": [
+ "aes128-cbc",
+ "3des-cbc",
+ "blowfish-cbc",
+ "cast128-cbc",
+ "arcfour",
+ "aes192-cbc",
+ "aes256-cbc"
+ ]
+ },
+ "serverHostKey": {
+ "type": "array",
+ "description": "Server host keys",
+ "default": []
+ },
+ "hmac": {
+ "type": "array",
+ "description": "Hash based message authentication codes",
+ "default": []
+ },
+ "compress": {
+ "type": "array",
+ "description": "Compresses",
+ "default": []
+ }
+ }
}
}
}
@@ -518,6 +565,48 @@
"type": "string",
"description": "Only connect via resolved IP address family for host",
"default": "IPv4"
+ },
+ "algorithms": {
+ "type": "object",
+ "description": "Specify algorithms",
+ "properties": {
+ "kex": {
+ "type": "array",
+ "description": "Key exchanges",
+ "default": [
+ "diffie-hellman-group-exchange-sha1",
+ "diffie-hellman-group1-sha1"
+ ]
+ },
+ "cipher": {
+ "type": "array",
+ "description": "Ciphers",
+ "default": [
+ "aes128-cbc",
+ "3des-cbc",
+ "blowfish-cbc",
+ "cast128-cbc",
+ "arcfour",
+ "aes192-cbc",
+ "aes256-cbc"
+ ]
+ },
+ "serverHostKey": {
+ "type": "array",
+ "description": "Server host keys",
+ "default": []
+ },
+ "hmac": {
+ "type": "array",
+ "description": "Hash based message authentication codes",
+ "default": []
+ },
+ "compress": {
+ "type": "array",
+ "description": "Compresses",
+ "default": []
+ }
+ }
}
}
}
@@ -866,6 +955,53 @@
"type": "string",
"description": "Only connect via resolved IP address family for host",
"default": "IPv4"
+ },
+ "forceIPv6": {
+ "type": "boolean",
+ "description": "Only connect via resolved IPv6 address for host",
+ "default": false
+ },
+ "algorithms": {
+ "type": "object",
+ "description": "Specify algorithms",
+ "properties": {
+ "kex": {
+ "type": "array",
+ "description": "Key exchanges",
+ "default": [
+ "diffie-hellman-group-exchange-sha1",
+ "diffie-hellman-group1-sha1"
+ ]
+ },
+ "cipher": {
+ "type": "array",
+ "description": "Ciphers",
+ "default": [
+ "aes128-cbc",
+ "3des-cbc",
+ "blowfish-cbc",
+ "cast128-cbc",
+ "arcfour",
+ "aes192-cbc",
+ "aes256-cbc"
+ ]
+ },
+ "serverHostKey": {
+ "type": "array",
+ "description": "Server host keys",
+ "default": []
+ },
+ "hmac": {
+ "type": "array",
+ "description": "Hash based message authentication codes",
+ "default": []
+ },
+ "compress": {
+ "type": "array",
+ "description": "Compresses",
+ "default": []
+ }
+ }
}
}
}
diff --git a/src/backend/backend.ts b/src/backend/backend.ts
--- a/src/backend/backend.ts
+++ b/src/backend/backend.ts
@@ -38,6 +38,14 @@ export interface RegisterValue {
value: string;
}
+export interface SSHAlgorithms {
+ kex?: Array<any>;
+ cipher?: Array<any>;
+ serverHostKey?: Array<any>;
+ hmac?: Array<any>;
+ compress?: Array<any>;
+}
+
export interface SSHArguments {
forwardX11: boolean;
host: string;
@@ -53,6 +61,7 @@ export interface SSHArguments {
bootstrap: string;
sourceFileMap: { [index: string]: string };
forceIPAddressFamily?: string;
+ algorithms?: SSHAlgorithms;
}
export interface IBackend {
diff --git a/src/backend/mi2/mi2.ts b/src/backend/mi2/mi2.ts
--- a/src/backend/mi2/mi2.ts
+++ b/src/backend/mi2/mi2.ts
@@ -148,6 +148,9 @@ export class MI2 extends EventEmitter implements IBackend {
this.sshArgs.forceIPv6 = true;
}
}
+ if (args.algorithms) {
+ this.sshArgs.algorithms = args.algorithms;
+ }
this.sshClient = new SSHClient(this.sshArgs);
this.sshConn.on("ready", () => {
diff --git a/src/frontend/extension.ts b/src/frontend/extension.ts
--- a/src/frontend/extension.ts
+++ b/src/frontend/extension.ts
@@ -291,6 +291,9 @@ function selectProcess(settings?: any): Promise<String> {
sshArgs.forceIPv6 = true;
}
}
+ if (sshSettings.algorithms) {
+ sshArgs.algorithms = sshSettings.algorithms;
+ }
const client: SSHClient = new SSHClient(sshArgs);
let succeededCheckOS = false;
diff --git a/src/utils/ssh.ts b/src/utils/ssh.ts
--- a/src/utils/ssh.ts
+++ b/src/utils/ssh.ts
@@ -1,6 +1,14 @@
import { Client, ClientChannel } from "ssh2";
import { ExecCommandResult } from "./process";
+export interface SSHConnectionAlgorithms {
+ kex?: Array<any>;
+ cipher?: Array<any>;
+ serverHostKey?: Array<any>;
+ hmac?: Array<any>;
+ compress?: Array<any>;
+}
+
export interface SSHConnectionArgs {
host: string;
port: number;
@@ -10,6 +18,7 @@ export interface SSHConnectionArgs {
agent?: string;
forceIPv4?: boolean;
forceIPv6?: boolean;
+ algorithms?: SSHConnectionAlgorithms;
}
export class SSHClient {
launch.json
での設定方法
SSH接続方式についてはssh
: algorithms
で指定する。
またNetBSD2.0固有の問題なのか不明だが、デバッグ対象のプロセスにデバッグ情報が含まれていてもアタッチ時に自動でそれを読み込んでくれない。
代わりに、デバッガの引数に--symbols
でファイルパスを指定すると読み込めるようになるので、これをlaunch.json
で指定する(SSHの場合はリモート上のファイルパス)。
{
"type": "gdb",
"request": "attach",
"name": "Attach Program netbsd2 (SSH)",
"target": "${command:selectAttachProcess}",
"cwd": "${workspaceRoot}",
"showDevDebugOutput": false,
"printCalls": true,
"trace": false,
"skipCheckDebugger": true,
"suppressAttachFailure": false,
"withoutAsync": true,
"ssh": {
"host": "localhost",
"port": 44444,
"cwd": "/root/sample",
"user": "root",
"password": "root",
"forwardX11": false,
"sourceFileMap": {
"/root/sample": "C:\\ws\\sample"
},
"forceIPAddressFamily": "IPv4",
"algorithms": {
"kex": [
"diffie-hellman-group-exchange-sha1",
"diffie-hellman-group1-sha1"
],
"cipher": [
"aes128-cbc",
"3des-cbc",
"blowfish-cbc",
"cast128-cbc",
"arcfour",
"aes192-cbc",
"aes256-cbc"
]
}
},
"valuesFormatting": "parseText",
"gdbpath": "/usr/local/bin/gdb",
"debugger_args": ["--symbols", "/root/sample/sample"]
},
アタッチの実行例
Running /usr/local/bin/gdb over ssh...
1-list-features
2-environment-directory "/root/sample"
3-environment-cd "/root/sample"
4-target-attach 105
Reading symbols from /root/sample/sample...
done.
5-thread-info
6-stack-info-depth --thread 1
7-stack-list-frames --thread 1 0 1
8-thread-info
9-exec-continue
10-thread-info
11-stack-list-variables --thread 1 --frame 1 --simple-values
kill -INT 105
12-exec-continue
13-thread-info
kill -INT 105
14-break-insert -f "/root/sample/sample.c:9"
15-thread-info
16-stack-info-depth --thread 1
17-exec-continue
18-stack-info-depth --thread 1
19-stack-list-frames --thread 1 0 1
20-stack-list-frames --thread 1 0 0
21-stack-info-depth --thread 1
22-thread-info
23-stack-list-frames --thread 1 0 0
24-stack-info-depth --thread 1
25-stack-list-frames --thread 1 0 0
26-stack-list-variables --thread 1 --frame 0 --simple-values
27-exec-continue
kill -INT 105
28-target-detach
29-thread-info
参考
NetBSD6.0.1対応版(前回記事)
Discussion