なにもわからない

気分で技術系の雑記を書きます

macOS Mojave で gdb を動かす(2020年10月)

2017年6月発表の macOS High Sierra(10.13)から SIP(System Integrity Protection: システム整合性保護)が導入され、gdb が動かなくなりました。過去には SIP 自体を無効化しなければなりませんでしたが、どうも最近ではそこそこ妥当な対処方法が取れるようになったようです。

困った話なので様々な対処方法がネットにありますが、現状にマッチした情報が見つかりませんでしたので、私の環境で動作した方法を書き記しておきます。 support.apple.com

対処方法

対処方法の手順はざっくり4つです。ポイントは SIP の無効化(csutil disable)や一部無効化(csutil enable --without=debug)しなくても動くという点です。

  1. ~/.gdbinitset startup-with-shell off を書く
  2. Code Signing Certificate を作る(Keychain\ Access.app
  3. --entitlements 付きで gdbcodesign する
  4. taskgated を殺す

動かすもの

今回動かすものはこちらの解説記事のものをそのまま使わせていただきました。 rat.cis.k.hosei.ac.jp

再現手順は以下の通りです。

$ gcc -g -O0 bubblesort.c

$ gdb a.out
GNU gdb (GDB) 10.1
Copyright (C) 2020 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-apple-darwin19.6.0".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://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 a.out...
Reading symbols from /private/tmp/gdb/a.out.dSYM/Contents/Resources/DWARF/a.out...
(gdb) break main
Breakpoint 1 at 0x100003db8: file bubblesort.c, line 9.
(gdb) run
Starting program: /private/tmp/gdb/a.out
Unable to find Mach task port for process-id 8203: (os/kern) failure (0x5).
 (please check gdb is codesigned - see taskgated(8))
(gdb) quit

1. ~/.gdbinitset startup-with-shell off を書く

brew install gdb 時にもメッセージが出る通り、~/.gdbinitset startup-with-shell off の記述が必要です。 これがないとコード署名の問題が解消しても During startup program terminated with signal SIGTRAP, Trace/breakpoint trap. が発生するようです。

2. Code Signing Certificate を作る

Keychain Access を使って Code Signing Certificate を作ります。

  • Keychain Access を開きます
  • メニューから「Keychain Access > Certificate Assistant > Create a certificate」を選びます
  • Create Your Certificate を設定します
    • Namegdb とします。この名前を後のコマンドで指定することになります。
    • Identity TypeSelf Signed Root を選択します
    • Certificate TypeCode Signing を選択します
    • Let me override defaults にチェックを入れます
  • Certificate Information を設定します
    • Validity Period (days) はデフォルト1年ですが10年程度に設定しておくとよいと思います
  • Key Pair Information を設定します
    • デフォルト選択肢のままでも動くようですが、念のため Key Size512 bitsAlgorithmECC にしておくとよいと思います
  • しばらく Continue で飛ばします
  • Specify a Location for The Certificate を設定します
    • KeychainSystem に設定します
  • Conclusion Your certificate has been successfully created. と表示されます
    • 作成された証明書の内容を確認してみてください
  • 一覧から作成された証明書(Name = gdb, Kind = certificate)をダブルクリックして詳細を開きます
    • Trust の三角矢印をクリックして開き、When using this certificateAlways Trust に設定します
    • この手順は不要かもしれません

f:id:tamakiii:20201029214015p:plain
Create Your Certificate
f:id:tamakiii:20201029214055p:plain
Certificate Information
f:id:tamakiii:20201029214127p:plain
Key Pair Information
f:id:tamakiii:20201029214157p:plain
Specify a Location for The Certificate
f:id:tamakiii:20201029223335p:plain
When using this certificate

3. --entitlements 付きで gdbcodesign する

以下の内容の gdb.xml を作ります。何度も使うものではないので適当な場所に作成してよいと思います。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.cs.debugger</key>
    <true/>
</dict>
</plist>

com.apple.security.cs.debugger という設定項目自体は、公式のドキュメントによると Availability は macOS 10.7+ とのことです。 developer.apple.com

codesign の状態を確認します

$ codesign -vv $(which gdb)
/usr/local/bin/gdb: code object is not signed at all
In architecture: x86_64

gdb--entitlements を指定して codesign します。このとき、-fs の引数に Keychain Access に登録したときの名前を指定します。

$ codesign --entitlements gdb.xml -fs gdb $(which gdb)

成功するとこのようになります

$ codesign -vv $(which gdb)
/usr/local/bin/gdb: valid on disk
/usr/local/bin/gdb: satisfies its Designated Requirement

4. taskgated を殺す

OS を再起動するか taskgated を殺して Code Sign を有効化します。

$ sudo pkill taskgated
Password:

しばらく待たないと以下のようにスレッドを立ち上げた所でハングするかもしれません。

Reading symbols from a.out...
Reading symbols from /private/tmp/gdb/a.out.dSYM/Contents/Resources/DWARF/a.out...
(gdb) break main
Breakpoint 1 at 0x100003db8: file bubblesort.c, line 9.
(gdb) run
Starting program: /private/tmp/gdb/a.out
[New Thread 0x2503 of process 8351]
[New Thread 0x2103 of process 8351]

動作確認

冒頭の再現手順を試します。期待通り動作しました。

Reading symbols from a.out...
Reading symbols from /private/tmp/gdb/a.out.dSYM/Contents/Resources/DWARF/a.out...
(gdb) break main
Breakpoint 1 at 0x100003db8: file bubblesort.c, line 9.
(gdb) run
Starting program: /private/tmp/gdb/a.out
[New Thread 0x1d03 of process 8511]
[New Thread 0x1f03 of process 8511]
warning: unhandled dyld version (16)

Thread 2 hit Breakpoint 1, main (argc=1, argv=0x7ffeefbff3f0) at bubblesort.c:9
9         int array[4] = {4, 1, 3, 2};
(gdb) 

動作環境情報

  • macOS Catalina (10.15.7)
$ gdb --version
GNU gdb (GDB) 10.1
Copyright (C) 2020 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.
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 12.0.0 (clang-1200.0.32.21)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$ csrutil status
System Integrity Protection status: enabled.

この記事の内容を含むリポジトリです。こちらも参考にどうぞ。 github.com

参考