MingwのGCCにて、-fstack-protectorを使ったC言語プログラムの実行時セグメンテーションエラーの原因について
解決済
回答 2
投稿
- 評価
- クリップ 0
- VIEW 1,347
前提・実現したいこと
・MingwのGCCにて、-fstack-protectorを使った際のセグメンテーションエラーについて原因を知りたいです。
・また、-fstack-protector以外に、デバッグ(特にメモリ破壊のチェック)に役立つものがありましたらご教授ください。(現在のMingwでは、mudflap は「gcc.exe: warning: switch '-fmudflap' is no longer supported」と拒否されます。ValgrindはWindowsに対応していないようです。)
発生している問題・エラーメッセージ
(元々は別の問題を解決するために)Mingwの最新版で、C言語のソースコードを-fstack-protector-all 指定してコンパイルしたところ、プログラム開始直後に
Program received signal SIGSEGV, Segmentation fault.
が発生します。
検証用のシンプルなプログラムでも同様の問題が発生するため、-fstack-protector-all の使い方?に問題があると考えています。
以下のコードを、次のコンパイルオプションでコンパイル、リンクしています。
コンパイルコマンド1
gcc -std=gnu99 -DUNICODE -D_UNICODE -Ddebug -g3 -O0 -static -Wextra -ftrapv -Wshadow -Wstrict-prototypes -Wmissing-declarations -Winit-self -Wswitch-default -Wswitch-enum -Wfloat-equal -Wcast-align -Wsign-compare -fstack-protector-all -ftrapv -Wall -Wuninitialized -s -c -o debug_tst.obj debug_tst.c
コンパイルコマンド2
gcc -std=gnu99 -static -fstack-protector-all -o debug_tst.exe debug_tst.obj
リンク
gcc -std=gnu99 -g3 -static -fstack-protector-all -ftrapv -o debug_tst.exe debug_tst.obj
該当のソースコード
#include <stdio.h>
#include <tchar.h>
int funct(int a, int b);
int funct(int a, int b){
int c;
// 無意味な処理です
a = b;
c = a + b;
return c;
}
int main(int argc, char **argv){
//int _tmain(int argc, TCHAR **argv){
int a, b, c;
if( argc>2 || argv==NULL ) return 1;
a = 1;
b = 2;
c = funct( a, b);
_tprintf( _T("c=%d\n"), c );
return 0;
}
試したこと
GDBで実行した場合、次のように即死します。
(gdb) run
Starting program: D:\work\debug_tst.exe
[New Thread 4868.0xda4]
Program received signal SIGSEGV, Segmentation fault.
0x0040147a in main (argc=1, argv=0x2d0f40) at debug_tst.c:18
18 int main(int argc, char **argv){
(gdb) bt
#0 0x0040147a in main (argc=1, argv=0x2d0f40) at debug_tst.c:18
(gdb) frame 0
#0 0x0040147a in main (argc=1, argv=0x2d0f40) at debug_tst.c:18
18 int main(int argc, char **argv){
(gdb) disp argc
1: argc = 1
(gdb) disp argv[0]
2: argv[0] = 0x2d1528 "D:\\work\\debug_tst.exe"
このように、バックトレースしてもほとんど何の情報もありません。
コンパイルオプションをできる限り削っていくと、-fstack-protector-all があるときだけ即死するようなのですが、バグの入るようなソースでもない上、そもそもmain()に入った途端にSegmentation faultというのが理解に苦しみます。
stack-protectorにバグがあるとは思えませんが、使用法の問題でしょうか?
なお、この機能については、「Binary Hacks(オライリー・ジャパン)」の
P168 HACK#46 -fstack-protector でスタックを保護する
を参考にしています。
補足情報(FW/ツールのバージョンなど)
開発環境
Win7 Home 32bit
gcc version 8.2.0 (MinGW.org GCC-8.2.0-3)
GNU gdb (GDB) 7.6.1
stack-protectorのバージョンは、次のように表示されています。
よろしくお願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
Windows固有のヘッダファイル(tchar.h)や定義(_tprintf( _T("c=%d\n"), c );)を使っているのは?
当方Windows環境がないのでわからないのですが、上記2箇所をコメントアウトして printf( "c=%d\n", c );に書き換えコンパイル&実行した所正常に動作しました。
当方の環境↓
Linux Mint191 5.0.0-19-generic
gcc-8 (Ubuntu 8.3.0-6ubuntu1~18.04.1) 8.3.0
結果:
usr ~/Project/test % gcc -std=gnu99 -static -fstack-protector-all t2.c
usr ~/Project/test % ./a.out
c=4
usr ~/Project/test % echo $?
0
usr ~/Project/test % cat t2.c
#include <stdio.h>
//#include <tchar.h>
int funct(int a, int b);
int funct(int a, int b){
int c;
// 無意味な処理です
a = b;
c = a + b;
return c;
}
int main(int argc, char **argv){
//int _tmain(int argc, TCHAR **argv){
int a, b, c;
if( argc>2 || argv==NULL ) return 1;
a = 1;
b = 2;
c = funct( a, b);
// _tprintf( _T("c=%d\n"), c );
printf( "c=%d\n", c );
return 0;
}
usr ~/Project/test %
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
解決には至りませんでしたが、問題の箇所、対策はある程度判明したのでまとめておきます。
・問題の原因
-fstack-protectorオプションで libssp.a 等を利用する際の、オブジェクトファイルの作成にそもそも失敗している。つまり、原因の一つは、gccによる処理のミスと思われる。
・対策(確実ではありません)
32bit Windows OSで-fstack-protector 特に-fstack-protector-all を使わない。既にサポートが終了しようとしているWin7 の32bit OS はバグフィックスも遅いのかもしれない。特に、後述するように-fstack-protectorはスタックのローカル変数前後にカナリア値を入れたり、ガード値のチェック?などを行うため、OSのbitが32bitか64bitかが重要っぽいです。
・試したこと
mingw-w64シリーズの導入
→ 変化無し。-fstack-protector-allでセグフォ。MinGW Installation Manager で入手したgcc6.3.0の
libssp.a、libssp.dll.a、libssp_nonshared.a を
gcc8.2.0と置き換えてみる
→ gcc8.2.0を使っている限り常にセグフォ。gcc 6.3.0 で作ったオブジェクトファイルを、gcc 8.2.0 でリンク
→DLL?エラーは出るものの、実行は可能。gcc 8.2.0 で作ったオブジェクトファイルを、gcc 6.3.0 でリンク
→セグフォ。アセンブリ出力の比較
アセンブラは全く読んだことがないので注釈は一部間違っているかもしれませんが、比較するとこんな感じでした。左から順に「gcc6.3.0で-fstack-protector-all使用」「gcc6.3.0で単純コンパイル」「gcc8.2.0で-fstack-protector-all使用」
となります。
見たところ特にgcc6とgcc8でアセンブラソースレベルでの大きな違いは見当たりません。にもかかわらず「gcc6.3.0で-fstack-protector-all使用」では起こらないセグメンテーションエラーが「gcc8.2.0で-fstack-protector-all使用」で起こるということは、gccのここ以外での内部処理に問題があるのではないかと思うわけです。そして、前述の通りリンクされるライブラリを挿げ替えても結果は変わりません。
というわけで、セグメンテーションエラーが起こる絶対条件はgcc 8.2.0 でのコンパイルで、ライブラリは直接は関係ないようです。
無念でありますが、個人のプログラマがいじれる難易度をオーバーフローしている感じなので、以上を結果といたします。
別環境で試してくださった回答者様に感謝いたします。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
cateye
2019/06/28 07:14 編集
gccは32ビットバージョンですか?
コンパイルオプション付けない時は正常に実行できるのですか?
kolona
2019/06/28 09:56
はい。gccは32bitバージョンで、他のプログラムは一応正常に実行はできる設定です。
-fstack-protectorをつけなければ、警告もなくビルドでき、実行すれば正常終了します。