VirtualBox(以降、box)によるlinux(ubuntu)カーネルのリモートシリアルデバッグ(gdb)

本内容を利用した場合の一切の責任を私は負いません。

###### 基本-0　準備
- boxメディア  
https://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html?ssSourceSiteId=otnjp
- ubuntuメディア  
https://jp.ubuntu.com/download

###### 基本-1　PC
Windows 10 Home
(メモリは8GB、CPUはi5)
解像度は1920x1080

###### 基本-2　各種バージョン
- box
![バージョン_box.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397476/f555d37a-ade9-b1e0-d67c-ea490f6dec3b.png)

- ubuntu
ubuntu-18.04.2-desktop-amd64.iso

###### 基本-3　boxインストール
「基本-0」手順のboxメディアで。

###### 基本-4　boxの環境設定
カーネルソースツリーをgit cloneしてビルドしたりするので、結構ディスクを食う。
「一般」の「デフォルトの仮想マシンフォルダー」を空きが十分あるところに変更する。
「ネットワーク」でNATネットワークを追加する。
「ポートフォワーディング」はdebug-host(実績はlabo)とdebug-target(実績はlabosub)分のssh(=22番)ポートを追加する。
(VM上でしか操作しないなら不要。)
debug-hostは、「ホストIP」は空で、「ホストポート」は10022(適宜)、「ゲストIP」は10.0.2.1(適宜)、「ゲストポート」は22。
debug-targetは、「ホストIP」は空で、「ホストポート」は20022(適宜)、「ゲストIP」は10.0.2.2(適宜)、「ゲストポート」は22。
(TeraTermからPC(localhost)の10022に接続すると、debug-hostのVMのsshに繋がる。
ゲストIPはNATネットワーク上であること。
デフォルトではDHCPのため、設定する場合はubuntuを固定IPにする設定がいる。)

###### 基本-5　VM環境構築
「バージョン」は「Ubuntu (64-bit)」を選択する。
仮想ハードディスクを追加しない。
(VM作成後に大きいサイズのディスクを追加するため。)
VM作成したら、SATAに下記のディスクを追加する。

- ポート0
- VDI
- 固定サイズ
- 50GB

IDEの光学ドライブにubuntuメディアを設定する。
ドライブを増設する場合は下記が参考になる。
http://d.hatena.ne.jp/moremagic/20150618/1434635047
簡単に言えば、VM作成時のディスクと違って、パーティション設定、ファイルシステム作成、自動マウント設定が必要になる。
ビルドはかなり重いので、VMとはいえスペックの効果は大きい。
(実績は、プロセッサー数3、メモリ4GB。)

###### 基本-6　ubuntuインストール
起動するとubuntuメディアで起動される。
始めの画面で日本語を選ぶと、以降日本語表示になる。
インストールを選択し、以降適宜指定するとインストールされる。
(規模で実績があるのは標準インストール。)
ホスト名はdebug-hostとする。(適宜)

###### 基本-7　debug-host環境設定
debug-hostを起動する。
解像度を1440x900に変更する。(適宜)
ネットワークの「IPv4」を「手動」にし、「基本-4」手順のdebug-hostの方のIPを設定する。
DNSはPCと同じものを設定する。
(アダプタ設定が自動で設定値が無い場合はnslookupコマンドの出力等。)

###### 基本-8　デバッグ環境構築
端末を開いて、「sudo apt install <下記>」コマンドで下記をインストールする。
(ソースファイルが足りないビルドエラーになる場合は、apt-fileコマンドでソースファイルが含まれるパッケージを特定してインストールすると対応できる場合がある。
https://www.atmarkit.co.jp/ait/articles/1709/08/news020.html)

- net-tools  
ifconfig、netstatが使えるようになる。
- openssh-sftp-server  
sshが使えるようになる。
- git  
gitが使えるようになる。
- fakeroot  
ビルドコマンド。
- libncurses5-dev  
fakeroot editconfigsで必要と言われる。
- libssl-dev  
ビルドで下記のエラーになるから。  
`fatal error: openssl/opensslv.h: そのようなファイルやディレクトリはありません`  
(http://kaworu.jpn.org/kaworu/2016-05-21-1.php)
- gawk  
ビルドで下記のエラーになるから。  
`gawk: command not found`
- libelf-dev  
ビルドで下記のエラーになるから。  
`Makefile:973: *** "Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel".  Stop.`
- libudev-dev  
ビルドで下記のエラーになるから。  
(/usr/include/libudev.hファイルが存在しない。)  
`configure: error: Missing /usr/include/libudev.h`
- libpci-dev  
ビルドで下記のエラーになるから。  
(/usr/include/pci/pci.hファイルが存在しない。)  
`utils/helpers/amd.c:8:10: fatal error: pci/pci.h: No such file or directory`
- flex  
ビルドで下記のエラーになるから。  
`Makefile.config:137: *** Error: flex is missing on this system, please install it.  Stop.`
- bison  
ビルドで下記のエラーになるから。  
`Makefile.config:141: *** Error: bison is missing on this system, please install it.  Stop.`

###### 基本-9　debug-target作成
debug-hostをシャットダウンする。
box上でdebug-hostのスナップを作成する。
box上でdebug-hostのクローンとしてdebug-targetを作成する。
作成する時は非リンクで、MAC再割り当てさせる。

###### 基本-10　debug-taget環境設定
ホスト名をdebug-targetにする。
ネットワークの「IPv4」を「手動」にし、「基本-4」手順のdebug-targetの方のIPを設定する。

###### 基本-11　カーネルソース取得
debug-targetをシャットダウンして、debug-hostを起動する。
ファイルシステムの空きが多い場所で下記を実行する。
`git clone git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git`
(bionicなのは、下記でubuntuメディアの18.04がbionicっぽいため。
https://help.ubuntu.com/
gitのWeb版は下記。
https://kernel.ubuntu.com/git/ubuntu/ubuntu-bionic.git/)
回線速度によるが、これはかなり時間がかかる。
時差的に夜中の方が速いかもしれない。
数時間かかる。
clone(git)はgit管理下で事故が起きる可能性があるため、archive(git)を使う方が望ましい。
(export(git)が禁止されているようで、clone下からしかarchive(git)を作れない。
archive(git)は下記で作れる。
`git archive --format zip -o src.zip HEAD`
ただ、変更をgit diff等で見れなくなるため、使い勝手は悪い。
一応、元を残しておけば、再帰diff等でわかる。
clone(git)のtarballだと1.8GBくらい。
archive(git)のzipだと200MBくらい。)

###### 基本-12　カーネルビルド
基本的に下記の手順になる。
(疎通は何も変更しないため「Modifying the configuration」分は飛ばす。)
https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel
GUIからソースをインストールする設定をする。

![ソースコード.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397476/88b910f0-cc30-7f07-3405-94834ff2538e.png)

(元情報は下記。
https://gihyo.jp/admin/serial/01/ubuntu-recipe/0526?page=2
build-depが失敗するため。
ubuntu手順で指定されているのはいまいちわからないのと、GUIだとコメント解除されるものが3つ以上あるため。)
手順に書かれた下記を実行する。
`sudo apt-get build-dep linux-image-$(uname -r)`
`fakeroot debian/rules clean`
`LANG=C fakeroot debian/rules binary-headers binary-generic binary-perarch > ../log_build.txt 2>&1`
(../log_build.txtがビルドログになる。
「LANG=C」がないと下記が大量に出る。
`/mnt/TERM/GIT/KERNEL/ubuntu-bionic/scripts/ubuntu-retpoline-extract-one: 134 行: printf: 0x十六進数ダンプ:: 無効な十六進数です`
`symbolmap: 00000000: invalid section`
更に下記で失敗する。
`debian/rules.d/4-checks.mk:15: recipe for target 'retpoline-check-generic' failed`
元情報は下記。
https://mongonta.com/howto-build-custom-kernel/
数時間かかる。
ソースツリーの上位にdebファイルが10コできる。
ビルドログは36000行くらい。)

###### 基本-13　カーネルインストール
debug-targetを起動する。
(念のため下記でインストール情報をPCに退避する。
`sudo apt list --installed`
`sudo apt list --installed | grep -E "^linux-"`
何かあっても、ブートできるならこの情報で元のカーネルをインストールして戻せるかも。)
ソースツリーの上位にビルドで作られた全てのdebファイルをdebug-targetに置く。
置いた場所で下記でインストールする。
`sudo dpkg -i linux*4.15.0-46.49*.deb`
下記の4つが失敗する。

- linux-cloud-tools-4.15.0-46
- linux-tools-4.15.0-46
- linux-cloud-tools-4.15.0-46-generic
- linux-tools-4.15.0-46-generic

エラーで出力されているように、下記を実行して依存を解決する。
`sudo apt --fix-broken install`
(エラーで足りないパッケージと言われているlinux-cloud-tools-common、linux-tools-commonがインストールされる。
インストールの前にこれらをインストールしておく手もある。
ただ、ubuntu手順では3ファイルのため、多いためにこれが必要になってしまっていると考えることもできる。
3ファイルだけならいらないかもしれないが、3ファイルだけでよいかもわからない。
ubuntu手順に将来のリリースではの断りがあるので、詳細は不明。)
エラーになったパッケージを下記で再インストールする。
`sudo dpkg -i <エラーになったdebファイル>`
下記で再起動する。
`sudo reboot`

###### 基本-14　ビルドカーネルでブート
ブートが始まったらshiftキーを何回か押す。
(GRUBメニューを表示するため。
https://linuxfan.info/post-3161)
GRUBメニューの「Advanced～」からインストールした4.15.0-46を選択する。
カーネルバージョンを確認する。

```text:カーネルバージョン
key@labosub:~$ uname -a
Linux labosub 4.15.0-46-generic #49 SMP Tue Apr 9 23:26:49 JST 2019 x86_64 x86_64 x86_64 GNU/Linux
key@labosub:~$
```

###### 基本-15　grubのメニュー設定変更
ブート時にshiftキーを押さなくてもgrubメニューが表示されるようにする。
/etc/default/grubを下記のように変更する。
(詳細は「info grub」コマンドのConfiguration。)

```text:/etc/default/grub
　GRUB_TIMEOUT_STYLE=hidden　→　menu
　GRUB_TIMEOUT=0　→　30
```

下記でgrub.cfgを差し替える。
`sudo grub-mkconfig -o /boot/grub/grub.cfg`

###### 実践-1　VMのスナップ作成
戻せるようにbox機能で。

###### 実践-2　デバッガ待ちのメニューを追加
/boot/grub/grub.cfgの4.15.0-46バージョンのmenuentryブロックを、/etc/grub.d/40_customに追記する。
デバッガ待ちするように、追記のメニュー名、カーネルオプション等の変更をする。

```text:40_custom(自動改行注意)
key@labosub:~$ more /etc/grub.d/40_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
        menuentry 'Ubuntu, with Linux 4.15.0-46-generic WAITING KGDB' --class ub　←　「 WAITING KGDB」追加
untu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.1
5.0-46-generic-advanced-8307283e-a072-487c-b347-6f41c66c48eb' {
                recordfail
                load_video
                gfxmode $linux_gfx_mode
                insmod gzio
                if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio;
fi
                insmod part_msdos
                insmod ext2
                set root='hd0,msdos1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1
 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1  8307283e-a072-487c-b347-6f
41c66c48eb
                else
                  search --no-floppy --fs-uuid --set=root 8307283e-a072-487c-b34
7-6f41c66c48eb
                fi
                echo    'Linux 4.15.0-46-generic をロード中...'
                linux   /boot/vmlinuz-4.15.0-46-generic root=UUID=8307283e-a072-
487c-b347-6f41c66c48eb ro  splash $vt_handoff kgdboc=ttyS0,115200 kgdbwait　←　「 kgdboc=ttyS0,115200 kgdbwait」追加、「 quiet」削除
                echo    '初期 RAM ディスクをロード中...'
                initrd  /boot/initrd.img-4.15.0-46-generic
        }

key@labosub:~$
```

「基本-15」手順同様、grub-mkconfigコマンドでgrub.cfgを差し替える。
(grubのトップメニューの最後に上記のメニューが追加される。
選択すると、kgdbが起動されて、デバッガ待ちになる。
シリアルを使わないと続行できないようであるため、VMを終了する。
再起動しても同じ場合は、終了状態でVMで「保存状態を破棄」を選べば解消する。
quietはブートメッセージの表示有無設定。(デバッグの時は表示される方がわかりやすい。)
諸々の元情報は下記。
http://rkx1209.hatenablog.com/entry/2017/07/13/184358
https://wiki.archlinux.jp/index.php/GRUB)

![grub.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397476/312ee0ac-0b76-1c09-a961-b954a49259e6.png)

![labosub_waiting.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397476/d249a549-9a2f-f332-547a-2176a015d0ca.png)


###### 実践-3　シリアル接続環境構築
debug-hostのシリアルポートのポート1を有効にして下記を設定する。
(パス/アドレスはboxヒントを参照のこと。)

- ポートモード:ホストにパイプ
- 存在するパイプ/ソケットに接続:チェック入り
- パス/アドレス:`\\.\pipe\labosub`

debug-targetのシリアルポートのポート1を有効にして下記を設定する。
(パス/アドレスはboxヒントを参照のこと。)

- ポートモード:ホストにパイプ
- 存在するパイプ/ソケットに接続:チェック外れ
- パス/アドレス:`\\.\pipe\labosub`

debug-targetが起動しきったら、debug-hostを起動する。
(debug-hostがシリアル接続することを前提にした設定になっているため、debug-target等のシリアルポートが存在する状態で起動しないと失敗する。)
debug-targetのターミナルで下記を実行する。
`sudo cat /dev/ttyS0`
debug-hostのターミナルで下記を実行する。
`sudo sh -c "echo a > /dev/ttyS0"`
(#1の後、#2を実行すると#3が表示される。)

```text:debug-target
key@labosub:~$ sudo cat /dev/ttyS0　#1
a　#3

^C
key@labosub:~$
```
```text:debug-host
key@labo:/dev$ sudo sh -c "echo a > /dev/ttyS0"　#2
key@labo:/dev$
```

(シリアルポートの状態はsetserialパッケージをインストールすれば下記でわかる。
`setserial -g -a /dev/ttyS0`
sudoでシェルを実行している理由は下記。
https://linuxfan.info/post-1818
表示されない時は2、3回やってみる。)

###### 実践-4　デバッガ待ちブートの疎通
debug-targetを「WAITING KGDB」で起動する。

```text:事後dmesg
[    0.856678] KGDB: Registered I/O driver kgdboc
[    0.856911] KGDB: Waiting for connection from remote gdb...
[  789.263897] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x2e02c6b261a, max_idle_ns: 440795349838 ns
```

debug-hostを起動し、ソースツリーでgdbを起動する。
(sudoなのはシリアル操作をするため。)

```text:gdb
key@labo:/mnt/TERM/GIT/KERNEL/ubuntu-bionic$ pwd
/mnt/TERM/GIT/KERNEL/ubuntu-bionic
key@labo:/mnt/TERM/GIT/KERNEL/ubuntu-bionic$ ll debian/build/build-generic/vmlinux
-rwxrwxr-x 1 key key 590971920  4月 10 01:57 debian/build/build-generic/vmlinux*
key@labo:/mnt/TERM/GIT/KERNEL/ubuntu-bionic$ sudo gdb !$
sudo gdb debian/build/build-generic/vmlinux
[sudo] key のパスワード:
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from debian/build/build-generic/vmlinux...done.
warning: File "/mnt/TERM/GIT/KERNEL/ubuntu-bionic/scripts/gdb/vmlinux-gdb.py" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
        add-auto-load-safe-path /mnt/TERM/GIT/KERNEL/ubuntu-bionic/scripts/gdb/vmlinux-gdb.py
line to your configuration file "/home/key/.gdbinit".
To completely disable this security protection add
        set auto-load safe-path /
line to your configuration file "/home/key/.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual.  E.g., run from the shell:
        info "(gdb)Auto-loading safe path"
(gdb)
```

シリアル接続する。

```text:シリアル接続
(gdb) target remote /dev/ttyS0
Remote debugging using /dev/ttyS0
0xffffffff969518d4 in ?? ()
(gdb)
```

カーネル処理を続行する。

```text:続行
(gdb) c
Continuing.
```

debug-targetのブートが続行する。
debug-hostでCTRL+cを数回押すとStop確認が出るので「y」で停止し、quitで終了する。
(boxのシリアルは不安定なため、VMを強制終了する必要がある場合もある。)

###### 実践-5　カーネルのデバッグビルド
下記で行う。
`LANG=C DEB_BUILD_OPTIONS="nostrip noopt debug" fakeroot debian/rules binary-headers binary-generic binary-perarch > ../log_build.txt 2>&1`
(追加分の元情報は下記。
http://maoe.hatenadiary.jp/entry/2015/02/11/162118)

###### 実践-6　デバッグビルドインストール
「基本-13」手順と同じ。
(前に、パッケージが依存するパッケージをインストールしているため、前のようなエラーにはならない。
名前を変更していないため、前のビルドに上書きされる。)

###### 実践-7　シンボル参照の疎通(ブート中)
debug-targetを起動し、40_customに設定したメニューの中のカーネルオプションにnokaslrを追加する。
(元情報は下記。
https://kernhack.hatenablog.com/entry/2018/02/15/223027)

```text:nokaslr
linux   /boot/vmlinuz-4.15.0-46-generic root=UUID=8307283e-a072-487c-b347-6f41c66c48eb ro  splash $vt_handoff kgdboc=ttyS0,115200 kgdbwait nokaslr
```

上記のgrub-mkconfigでgrub.cfgを差し替える。
再起動して「WAITING KGDB」で起動する。
debug-hostを起動して、「実践-4」手順のgdb起動時に出力されている~/.gdbinitを作る。

```text:~/.gdbinit
key@labo:~$ cat .gdbinit
add-auto-load-safe-path /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/scripts/gdb/vmlinux-gdb.py

key@labo:~$
```

gdbを起動し、シリアル接続し、シンボルにブレークポイントを設定して続行すると停止する。

```text:gdb
key@labo:/mnt2/TERM/GIT/KERNEL/ubuntu-bionic$ sudo gdb debian/build/build-generic/vmlinux
[sudo] key のパスワード:
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from debian/build/build-generic/vmlinux...done.
(gdb) target remote /dev/ttyS0
Remote debugging using /dev/ttyS0
kgdb_breakpoint ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/kernel/debug/debug_core.c:1073
1073            wmb(); /* Sync point after breakpoint */
(gdb) l
1068    noinline void kgdb_breakpoint(void)
1069    {
1070            atomic_inc(&kgdb_setting_breakpoint);
1071            wmb(); /* Sync point before breakpoint */
1072            arch_kgdb_breakpoint();
1073            wmb(); /* Sync point after breakpoint */
1074            atomic_dec(&kgdb_setting_breakpoint);
1075    }
1076    EXPORT_SYMBOL_GPL(kgdb_breakpoint);
1077
(gdb) i source
Current source file is /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/kernel/debug/debug_core.c
Compilation directory is /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/debian/build/build-generic
Located in /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/kernel/debug/debug_core.c
Contains 1089 lines.
Source language is c.
Producer is GNU C89 7.3.0 -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -mindirect-branch=thunk-extern -mindirect-branch-register -mfentry -march=x86-64 -g -gdwarf-4 -O2 -std=gnu90 -p -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -falign-jumps=1 -falign-loops=1 -funit-at-a-time -fno-asynchronous-unwind-tables -fno-delete-null-pointer-checks -fstack-protector-strong -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -fno-inline-functions-called-once -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fstack-check=no -fconserve-stack --param allow-store-data-races=0 -fstack-protector-strong.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.
(gdb) bt
#0  kgdb_breakpoint ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/kernel/debug/debug_core.c:1073
#1  0xffffffff811528a1 in kgdb_initial_breakpoint ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/kernel/debug/debug_core.c:974
#2  kgdb_register_io_module (new_dbg_io_ops=0xffffffff8258ce00 <kgdboc_io_ops>)
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/kernel/debug/debug_core.c:1014
#3  0xffffffff8160ee45 in configure_kgdboc ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/drivers/tty/serial/kgdboc.c:197
#4  0xffffffff826fd0e5 in init_kgdboc ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/drivers/tty/serial/kgdboc.c:226
#5  0xffffffff810021b2 in do_one_initcall (fn=0xffffffff826fd0ce <init_kgdboc>)
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/init/main.c:832
#6  0xffffffff826a42a6 in do_initcall_level (level=<optimized out>)
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/init/main.c:898
#7  do_initcalls () at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/init/main.c:906
#8  do_basic_setup () at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/init/main.c:924
#9  kernel_init_freeable ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/init/main.c:1079
#10 0xffffffff81992b3e in kernel_init (unused=<optimized out>)
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/init/main.c:1006
#11 0xffffffff81a00205 in ret_from_fork ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/arch/x86/entry/entry_64.S:406
#12 0x0000000000000000 in ?? ()
(gdb) b loop_init
Breakpoint 1 at 0xffffffff82703c3b: file /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/drivers/block/loop.c, line 2076.
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0xffffffff82703c3b in loop_init
                                                   at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/drivers/block/loop.c:2076
(gdb) c
Continuing.

Thread 2 hit Breakpoint 1, loop_init ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/drivers/block/loop.c:2076
2076    {
(gdb) l
2071
2072    MODULE_ALIAS_MISCDEV(LOOP_CTRL_MINOR);
2073    MODULE_ALIAS("devname:loop-control");
2074
2075    static int __init loop_init(void)
2076    {
2077            int i, nr;
2078            unsigned long range;
2079            struct loop_device *lo;
2080            int err;
(gdb) c
Continuing.
^C^CThe target is not responding to interrupt requests.
Stop debugging it? (y or n) y
Disconnected from target.
(gdb)
```

###### 実践-8　シンボル参照の疎通(ブート後)
VM環境では一度切断されたシリアルポートを復活することができないようなので、debug-hostをシャットダウンする。
起動したままのdebug-targetで、/etc/sysctl.confを変更してSysRqを有効にする。

```text:/etc/sysctl.conf
kernel.sysrq=1
```

(/etc/sysctl.confのコメントから、debianはデフォルトでは有効にならない。

```text:コメント
###################################################################
# Magic system request Key
# 0=disable, 1=enable all
# Debian kernels have this set to 0 (disable the key)
# See https://www.kernel.org/doc/Documentation/sysrq.txt
# for what other values do
#kernel.sysrq=1
```

ググると出ててくる、1を/proc/sys/kernel/sysrqに書き込む方法もダメ。
書き込んだ後にgを/proc/sysrq-triggerに書き込んでも無応答で、カーネルログ(/var/log/kern.log)に下記が出力されている。

```text:kern.log
sysrq: SysRq : This sysrq operation is disabled.
```
)
debug-targetをシャットダウンしてから「WAITING KGDB」で起動する。
(VMが終了しないとシリアルポートが復活しない。)
デバッガ待ちになったらdebug-hostを起動する。
gdbを起動し、シリアル接続し、続行する。

```text:gdb
key@labo:/mnt2/TERM/GIT/KERNEL/ubuntu-bionic$ sudo gdb debian/build/build-generic/vmlinux
[sudo] key のパスワード:
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 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 "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from debian/build/build-generic/vmlinux...done.
(gdb) target remote /dev/ttyS0
Remote debugging using /dev/ttyS0
kgdb_breakpoint ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/kernel/debug/debug_core.c:1073
1073            wmb(); /* Sync point after breakpoint */
(gdb) c
Continuing.
```

debug-targetのブート後、SysRqを下記で発行すると、debug-hostに制御が戻るのでブレークポイントを設定すると、そこを使う処理で止まるようになる。
`sudo sh -c "echo g > /proc/sysrq-trigger"`
(実行するとフリーズ状態になる。
gdbの待ちが長くなければ、gdbで続行すると制御が戻る。
\#4の後、#5を実行すると#6で止まる。
マルチスレッドのため、止まった後は同期が崩れるようでdebug-targetがフリーズする場合が結構ある。)

```text:debug-host
(gdb) c
Continuing.
[New Thread 1567]
[New Thread 79]
[New Thread 80]
[New Thread 81]
[New Thread 82]
[New Thread 83]
略
[New Thread 1464]
[New Thread 1469]
[New Thread 1555]
[New Thread 1556]
[New Thread 1566]

Thread 38 received signal SIGTRAP, Trace/breakpoint trap.
[Switching to Thread 1567]
kgdb_breakpoint ()
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/kernel/debug/debug_core.c:1073
1073            wmb(); /* Sync point after breakpoint */
(gdb) b version_proc_show
Breakpoint 1 at 0xffffffff812fba60: file /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/fs/proc/version.c, line 10.
(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0xffffffff812fba60 in version_proc_show
                                                   at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/fs/proc/version.c:10
(gdb) c　#4
Continuing.
[New Thread 1574]　#6
[New Thread 1571]
[Switching to Thread 1574]

Thread 396 hit Breakpoint 1, version_proc_show (m=0xffff880077df2280,
    v=0x1 <irq_stack_union+1>)
    at /mnt2/TERM/GIT/KERNEL/ubuntu-bionic/fs/proc/version.c:10
10      {
(gdb) l
5       #include <linux/proc_fs.h>
6       #include <linux/seq_file.h>
7       #include <linux/utsname.h>
8
9       static int version_proc_show(struct seq_file *m, void *v)
10      {
11              seq_printf(m, linux_proc_banner,
12                      utsname()->sysname,
13                      utsname()->release,
14                      utsname()->version);
(gdb)
```
```text:debug-target
key@labosub:~$ cat /proc/version　#5
```

※1
カーネルコンフィグ(ビルド後なら多分/debian/build/build-generic/.configだと思う)のCONFIG_LOCALVERSIONに値を設定するとカーネル名に付加されるはず。
ただ、今のビルド方法はmenuconfigではうまくいかなかったので、fakeroot edticonfigsとかからする必要があるかも。
また、Ubuntuの下記にあるコンフィグを変更した場合の手順も必要かも。
https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel