ablog

不器用で落着きのない技術者のメモ

segfault の error_code の意味

メッセージ
command[pid]: segfault at address rip fault_address rsp stack_address error error_code
変数
command[pid]
    ページフォルトが発生したプロセスのコマンド名とプロセスID。 
address
    ページフォルトを発生させた仮想アドレス(リニアアドレス) 
fault_address
    ページフォルトを発生させた命令アドレス 
stack_address
    ページフォルトを発生した際のスタックポインタ 
error_code
    以下のフラグの組み合わせで表すエラーコード 
    bit0:: フォルトの原因を示すフラグ("0"=ページが見つからなかった "1"=ページプロテクション(保護例外)を検出した)
    bit1:: 該当メモリへのアクセス種別を示すフラグ("0"=読み込み "1"=書き込み)
    bit2:: フォルトが発生したモードを示すフラグ("0"=カーネルモード "1"=ユーザモード)
    bit3:: カーネルのページテーブルに不正を検出した際に設定されるフラグ。正確には将来予約されるビットフィールド(予約ビット)に"1"が設定されたことを検知した場合に"1"となる。通常は"0"。
説明

ユーザ空間でページフォルトが発生した場合に、該当プログラムがSIGSEGVに対応するシグナル出口を登録していない場合(SIG_IGN、またはSIG_DFLを設定している)に発生したフォルト情報をトレースするためのデバッグメッセージである。
本メッセージを出力後にSIG_IGN、またはSIG_DFLのシグナル処理を続ける。
x86_64カーネル(kernel-2.6.9-34.EL)は当該デバッグメッセージが標準で出力される設定となっている。この設定を無効にしたい場合は、/proc/sys/debug/exception_trace、またはsysctlコマンドで該当kernelパラメタを"0"に変更することで、出力を抑止できるようだ。

http://ossmpedia.org/messages/linux/2.6.9-34.EL/56980.ja


例えば、こんなエラーが出た場合、

ora_pmon_orcl[6500]: segfault at ... rip ... rsp ... error 4

10進数の4は

% perl -le 'print unpack(q/B8/,pack(q/C/,4))'
00000100

2進数だと 100 だから、ユーザーモードでメモリから読み込もうとしたがページが見つからなかったということになる。


エキスパートCプログラミング―知られざるCの深層 (Ascii books)
P.197 Software Dogma メモリ領域が足りない?
に興味深いことが書かれていた。

OS が提供できる以上のメモリを要求すると、プログラムは「セグメントフォールト」で終了させられる。
ここで紹介する方法を使えば、セグメントフォールトの原因がそれなのか、他のバグなのかを区別できる。
スタック領域を使い尽くしたかどうかを判断するには、dbx を使う。
(中略)
Cシェルなら、セグメントの限界を変更できる。

limit stacksize 10

(中略)
上のコマンドだと、スタックの最大サイズを10Kバイトに設定している。