-stack_protector/-stack_protector_all 【Professional版のみ】 【V2.04.00以降】


コンパイル・オプション / オブジェクトオプション

[指定形式]

-stack_protector[=<数値>]
-stack_protector_all[=<数値>]

[詳細説明]

-

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

(1) 関数の入口で、ローカル変数領域の直前(0xFFFFFFFF番地に向かう方向)に4バイトの領域を確保し、その領域に<数値>で指定した値を格納します。

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

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

-

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

-

__stack_chk_fail関数はユーザが定義する必要があり、スタックの破壊検出時に実行する処理を記述します。

-

__stack_chk_fail関数を定義する際には、次の項目に注意してください。

-

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

-

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

-

__stack_chk_fail関数は、オプション-stack_protector、-stack_protector_allと#pragma stack_protectorに関わらずスタック破壊検出コードの生成の対象にはなりません。

-

C++プログラム内で__stack_chk_fail関数を定義する場合は「extern "C"」を付加してください。

-

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

-

__stack_chk_fail関数を定義する場合は、staticを指定しないでください。

-

-stack_protectorを指定すると、構造体、共用体または配列のローカル変数を持つ関数があり、コンパイラがそれらの変数に対して8バイトより大きな領域をスタックに確保した場合、この関数はスタック破壊検出コードを生成する対象となります。-stack_protector_all を指定した場合には全ての関数に対してスタック破壊検出コードを生成します。

-

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

-

以下の#pragma が指定された関数は、本オプションを指定した場合でもスタック破壊検出コードを生成しません。
#pragma inline、#pragma inline_asm、#pragma entry、#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 の場合にスタックが破壊される
    }
}
 
#ifdef __cplusplus
extern "C" {
#endif
void __stack_chk_fail(void)
{
    printf("stack is broken!");
    abort(); 
}
#ifdef __cplusplus
}
#endif

-

<出力コード>

-stack_protector=0 を指定してコンパイルした場合

    .glb    _test
    .glb    ___stack_chk_fail
    .glb    _printf
    .glb    _abort
    .SECTION        P,CODE
_test:
    .STACK  _test=20
    MOV.L #00000000H, R14   ; 指定した<数値> 0 をスタックの領域へ格納する
    PUSH.L R14
    SUB #0CH, R0
    MOV.L #00000000H, R14
    MOV.L #0000000BH, R15
    ADD #02H, R0, R5
L12:    ; parse_bb
    MOV.B R14, [R5+]
    ADD #01H, R14
    SUB #01H, R15
    BNE L12
L13:    ; return
    MOV.L 0CH[R0], R14      ; 関数の入口で<数値>を格納した位置からロードし、
    CMP #00H, R14           ; 指定した<数値>0 と比較する
    BNE L15                 ; 異なっている場合には、L15へ分岐する
L14:    ; return
    RTSD #10H
L15:    ; return
    BRA ___stack_chk_fail   ; __stack_chk_failを呼び出す
 
___stack_chk_fail:
    .STACK  ___stack_chk_fail=8
    SUB #04H, R0
    MOV.L #_L10, R14
    MOV.L R14, [R0]
    BSR _printf
    ADD #04H, R0
    BRA _abort
 
    .SECTION        L,ROMDATA,ALIGN=4
_L10:
    .byte   "stack is broken!"
    .byte   00H
    .END