*参照元 [#w0e03eb9] #backlinks *説明 [#t3020dbb] -パス: [[linux-2.6.33/arch/x86/include/asm/bug.h]] -BUG() マクロの実装です。x86 版です。 **引数 [#g6f89863] -なし **返り値 [#b8ec9c00] -なし **参考 [#yd1d7a70] *実装 [#n055fa36] ***CONFIG_DEBUG_BUGVERBOSE が On の場合 [#xe433e31] #ifdef CONFIG_DEBUG_BUGVERBOSE - --[[linux-2.6.33/CONFIG_DEBUG_BUGVERBOSE]] #ifdef CONFIG_X86_32 -32bit の場合 --[[linux-2.6.33/CONFIG_X86_32]] # define __BUG_C0 "2:\t.long 1b, %c0\n" -BUG() の実行されたアドレス(= 1b(無効命令の先頭にある後方ラベル)を セクションに書く。 サイズは 32ビット。 -BUG() の実行されたファイル名のアドレス(= %c0: __FILE__)を セクションに書く。 サイズは 32ビット。 #else -64bit の場合 # define __BUG_C0 "2:\t.long 1b - 2b, %c0 - 2b\n" -BUG_C0 のアドレス(= 2b(__BUG_C0 の先頭にある後方ラベル))と BUG() の実行されたアドレス(= 1b(無効命令の先頭にある後方ラベル))の差を セクションに書く。 サイズは 32ビット。 -BUG_C0 のアドレス(= 2b(__BUG_C0 の先頭にある後方ラベル))と BUG() の実行されたファイル名のアドレス(= %c0: __FILE__)の差を セクションに書く。 サイズは 32ビット。 #endif ***BUG() 関数の定義 [#i3fef088] #define BUG() \ do { \ asm volatile("1:\tud2\n" \ -無効命令を実行する。無効命令実行割り込みが入る。 -コンパイラの最適化で移動、消去されないように volatile キーワードをつける。 ".pushsection __bug_table,\"a\"\n" \ -以降、__bug_table セクションに対する操作をする。 --元のセクションはコンパイラが記憶しておく(LIFO 方式)。 -__bug_table セクションは struct bug_entry の配列である。 bug_entry は BUG() の実行されたアドレスや ソースコードファイル名などを保持している。 --以下 .popsection までの命令にて、 struct bug_entry の各メンバに対応する情報をセクションに書き込む。 ---BUG() の実行されたアドレス ---BUG() の実行されたファイル名のアドレス ---BUG() が実行された行数 ---フラグ __BUG_C0 \ -無効命令のアドレスと、 __FILE__ のアドレスをセクションに書く -BUG() を実行したアドレスと、 BUG() の実行されたファイル名のアドレスを セクションに書く "\t.word %c1, 0\n" \ -BUG() が実行された行数(=%c1: __LINE__)をセクションに書く。 -BUG() が実行された行数(=%c1: __LINE__)を セクションに書く。 サイズは 16ビット。 -0 をセクションに書く。 -フラグ(0 固定)を セクションに書く。 サイズは 16ビット。 "\t.org 2b+%c2\n" \ - -次のエントリの開始地点を、 エントリの先頭(ラベル 2b)+ sizeof(struct bug_entry) にする。 --struct bug_entry の「末尾」に新しくメンバが追加されたが、 BUG() 関数に新しいメンバを書き込むコードがない…、 という場合でもエントリの開始位置がずれないようにするための工夫である。 例: BUG() が書き込む情報が 12 バイト |A B C| で、 sizeof(struct bug_entry) が 12 バイト |A B C| のとき、 書き込む側(BUG()) : |A0 B0 C0|A1 B1 C1|A2 B2 C2| 読み取る側(別関数): |A0 B0 C0|A1 B1 C1|A2 B2 C2| 以上のように問題ないが、 末尾に新メンバ D が追加されて、 sizeof(struct bug_entry) =(A B C D)= 16 になると 書き込む側(BUG()) : |A0 B0 C0|A1 B1 C1|A2 B2 C2| 読み取る側(別関数): |A0 B0 C0 D0|A1 B1 C1 D1|A2 B2 C2 D2| 以上のように 4バイトずれてしまう。 .org を用いることで、BUG() 側の変更は特にしなくても、 sizeof(struct bug_entry) ずつエントリの開始点を進められるので、 書き込む側(BUG()) : |A0 B0 C0 |A1 B1 C1 |A2 B2 C2 | 読み取る側(別関数): |A0 B0 C0 D0|A1 B1 C1 D1|A2 B2 C2 D2| となりバイトがずれなくなる。 ".popsection" \ -以降、__bug_table セクションに切り替える前の、 元のセクションに対する操作をする。 : : "i" (__FILE__), "i" (__LINE__), \ "i" (sizeof(struct bug_entry))); \ -%c0, %c1, %c2 の定義 --%c0: __FILE__ --%c1: __LINE__ --%c2: sizeof(struct bug_entry) --[[linux-2.6.33/bug_entry]] unreachable(); \ -実行されないコードであることをマークする。 --もし実行された場合は無限ループになる(x86)。 他のアーキテクチャでは不明。 --[[linux-2.6.33/unreachable()]] } while (0) ***CONFIG_DEBUG_BUGVERBOSE が Off の場合 [#e43efc0a] #else #define BUG() \ do { \ asm volatile("ud2"); \ -無効命令を実行する。無効命令実行割り込みが入る。 -コンパイラの最適化で移動、消去されない ように volatile キーワードをつける。 unreachable(); \ -実行されないコードであることをマークする。 --もし実行された場合は無限ループになる(x86)。 他のアーキテクチャでは不明。 } while (0) #endif *コメント [#zae4d2f4]