-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 |
[例]
#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
|