🧇

内部割り込みを簡単に覗いてみる

に公開

サマリ

内部割り込みについて可視化をしてみたく、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