-Xstack_protector/-Xstack_protector_all 【Professional 版のみ】


スタック破壊検出コード生成を指定します。

[指定形式]

-Xstack_protector[=num]
-Xstack_protector_all[=num]

 

-

省略時解釈

スタック破壊検出コードを生成しません。

[詳細説明]

-

関数の入口・出口にスタック破壊検出コードを生成します。スタック破壊検出コードとは次に示す3つの処理を実行するための命令を指します。

(1) 関数の入口で,当該関数スタック・フレームのローカル変数領域の直前(0xFFFFFFFF番地に向かう方向)に4バイトの領域を確保し,numで指定した値を確保した領域に格納します。

(2) 関数の出口で,numを格納した4バイトの領域が書き換わっていないことをチェックします。

(3) (2)で書き換わっている場合には,スタックが破壊されたとして __stack_chk_fail 関数を呼び出します。

-

numには 0 から 4294967295までの整数値を指定します。numの指定を省略した場合には,コンパイラが自動的に数値を指定します。

-

__stack_chk_fail関数はユーザが定義する必要があり,スタックの破壊検出時に実行する処理を記述します。
__stack_chk_fail関数を定義する際には,次の項目に注意してください。

-

返却値の型はvoid型のみであり,仮引数を持たない関数です。

-

通常の関数のように呼び出すことは禁止します。

-

__stack_chk_fail関数は,オプション-Xstack_protector,-Xstack_protector_allと#pragma stack_protectorによるスタック破壊検出コードの生成の対象にはなりません。

-

関数内ではabort()を呼び出してプログラムを終了させるなど,呼び出し元であるスタックの破壊を検出した関数にリターンしないようにしてください。

-

__stack_chk_fail 関数内で関数を呼び出す場合は,呼び出した先の関数内で再帰的にスタックの破壊を検出しないように注意してください。

-

-Xstack_protectorを指定すると,関数が持つ構造体,共用体または配列のローカル変数に対して,コンパイラが8byteを超えるオブジェクトとしてスタックに領域を確保する場合に,スタック破壊検出コードを生成する対象となります。-Xstack_protector_all を指定した場合には全ての関数に対してスタック破壊検出コードを生成します。

-

本オプションと#pragma stack_protector とを同時に使用した場合は,#pragma stack_protector の指定が有効になります。

-

以下の#pragma が指定された関数は,本オプションを指定した場合でもスタック破壊検出コードを生成しません。
#pragma inline,inlineキーワード,#pragma inline_asm,#pragma no_stack_protector

[例]

-

<Cソース>

#include <stdio.h>
#include <stdlib.h>
 
void f1()   // スタックが破壊されるプログラムの例
{
    volatile char str[10];
    int i;
    for (i = 0; i <= 10; i++){
      str[i] = i; // i=10 の場合にスタックが破壊される
    }
}
 
void __stack_chk_fail(void)
{
    printf("stack is broken!");
    abort();
}

-

<出力コード>
-Xstack_protector=1234 を指定してコンパイルした場合

_f1:
        .stack _f1 = 16
        add 0xFFFFFFF0, r3
        movea 0x000004D2, r0, r1  ; 指定した<数値> 1234 をスタックの領域へ格納する
        st.w r1, 0x0000000C[r3]
        mov 0x00000000, r2
        br9 .BB.LABEL.1_2
.BB.LABEL.1_1:  ; bb
        movea 0x00000002, r3, r5
        add r2, r5
        st.b r2, 0x00000000[r5]
        add 0x00000001, r2
.BB.LABEL.1_2:  ; bb7
        cmp 0x0000000B, r2
        blt9 .BB.LABEL.1_1
.BB.LABEL.1_3:  ; return
        ld.w 0x0000000C[r3], r1   ; 関数の入口で<数値>を格納した位置からロードし,
        movea 0x000004D2, r0, r12 ; 指定した<数値>1234 と,
        cmp r12, r1               ; 比較する
        bnz9 .BB.LABEL.1_5        ; 異なっている場合には,分岐する
.BB.LABEL.1_4:  ; return
        dispose 0x00000010, 0x00000000, [r31]
.BB.LABEL.1_5:  ; return
        br9 ___stack_chk_fail     ; __stack_chk_failを呼び出す
 
___stack_chk_fail:
        .stack ___stack_chk_fail = 4
        prepare 0x00000001, 0x00000000
        mov #.STR.1, r6
        jarl _printf, r31
        jarl _abort, r31
        dispose 0x00000000, 0x00000001, [r31]