🧇
内部割り込みを簡単に覗いてみる
サマリ
内部割り込みについて可視化をしてみたく、C言語でゼロ除算を行いその後lldbで処理を追ってみました。
マシンスペック
MacBook Air M2 arm64
ソースコードの準備
C言語でゼロ除算を行う簡単なコードを書きます。
#include <stdio.h>
int main() {
int a = 1;
int b = 0;
int result = a / b;
printf("Result: %d\n", result);
return 0;
}
コンパイル・実行
通常コンパイル
gccでコンパイルをします。
-fsanitize=undefined
のオプションを付与して、エラー発生時の原因を行番号付きで出力してもらいます。
gcc -fsanitize=undefined test_division.c -o test_division
実行します。
./test_division
test_division.c:6:20: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test_division.c:6:20 in
Result: 0
runtime error: division by zero
でゼロ除算でエラーとなっていますが、そのままコードが実行されResult: 0
まで出力されました。
オプションを付与
コンパイル時に-fno-sanitize-recover=undefined
オプションを付与して、確実にエラーで落ちてもらいます。
gcc -fsanitize=undefined -fno-sanitize-recover=undefined test_division.c -o test_division2
実行します。
./test_division2
test_division.c:6:20: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test_division.c:6:20 in
zsh: abort ./test_division
printf("Result: %d\n", result);
まで実行されずに終了したことがわかります。
lldbで可視化してみる
macではgdbではなく、lldbがデフォルトでインストールされていたため、そちらを使用します。
通常コンパイル
gcc -fsanitize=undefined test_division.c -o test_division
lldb test_division
(lldb) target create "test_division"
Current executable set to '/Users/hoge/interrupt/test_division' (arm64).
(lldb) run
Process 70496 launched: '/Users/hoge/interrupt/test_division' (arm64)
Process 70496 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = Integer divide by zero
frame #0: 0x00000001005c5348 libclang_rt.ubsan_osx_dynamic.dylib`__ubsan_on_report
libclang_rt.ubsan_osx_dynamic.dylib`:
-> 0x1005c5348 <+0>: ret
libclang_rt.ubsan_osx_dynamic.dylib`__ubsan::UndefinedBehaviorReport::UndefinedBehaviorReport:
0x1005c534c <+0>: pacibsp
0x1005c5350 <+4>: sub sp, sp, #0x40
0x1005c5354 <+8>: stp x22, x21, [sp, #0x10]
Target 0: (test_division2) stopped.
オプションを付与
gcc -fsanitize=undefined -fno-sanitize-recover=undefined test_division.c -o test_division2
lldb test_division2
(lldb) target create "test_division2"
Current executable set to '/Users/hoge/interrupt/test_division2' (arm64).
(lldb) run
Process 70477 launched: '/Users/hoge/interrupt/test_division2' (arm64)
Process 70477 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = Integer divide by zero
frame #0: 0x00000001005c5348 libclang_rt.ubsan_osx_dynamic.dylib`__ubsan_on_report
libclang_rt.ubsan_osx_dynamic.dylib`:
-> 0x1005c5348 <+0>: ret
libclang_rt.ubsan_osx_dynamic.dylib`__ubsan::UndefinedBehaviorReport::UndefinedBehaviorReport:
0x1005c534c <+0>: pacibsp
0x1005c5350 <+4>: sub sp, sp, #0x40
0x1005c5354 <+8>: stp x22, x21, [sp, #0x10]
Target 0: (test_division) stopped.
libclang_rt.ubsan_osx_dynamic.dylib`__ubsan::UndefinedBehaviorReport::UndefinedBehaviorReport:
とあり、こちらで制御されていそうです。
Discussion