-stack_protector/-stack_protector_all 【Professional版のみ】 【V1.02以降】


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

[指定形式]

-stack_protector[=num]
-stack_protector_all[=num]

 

-

省略時解釈

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

[詳細説明]

-

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

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

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

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

-

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

-

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

-

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

-

戻り値および引数の型をvoid型とし,far領域に配置してください。

-

static関数にしないでください。

-

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

-

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

-

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

-

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

-

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

-

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

-

以下が指定された関数は,スタック破壊検出コードを生成しません。

#pragma inline,__inlineキーワード,#pragma inline_asm,#pragma no_stack_protector,#pragma rtos_interrupt,#pragma rtos_task

[例]

-

<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(); 
}

-

<出力コード>

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

_f1:
        .STACK _f1 = 16
        movw hl, #0x1234     ; 指定したnumをスタックの領域へ格納する
        push hl
        subw sp, #0x0A
        mov h, #0x00
        movw bc, #0x000B
        movw ax, sp
        movw de, ax
.BB@LABEL@1_1:  ; bb
        mov a, h
        mov [de], a
        inc a
        mov h, a
        movw ax, bc
        addw ax, #0xFFFF
        movw bc, ax
        incw de
        bnz $.BB@LABEL@1_1
.BB@LABEL@1_2:  ; return
        addw sp, #0x0A
        pop ax              ; 関数の入口でnumを格納した位置からpop命令によりロードし,
        cmpw ax, #0x1234    ; オプションで指定した0x1234と比較する
        sknz                ; 異なっている場合には,.BB@LABEL@1_4へ分岐する
.BB@LABEL@1_3:  ; return
        ret
.BB@LABEL@1_4:  ; return
        br $___stack_chk_fail  ; __stack_chk_failを呼び出す
 
___stack_chk_fail:
        .STACK ___stack_chk_fail = 4
        movw de, #SMRLW(.STR@1)
        mov a, #0x0F
        call !!_printf
        br !!_abort
        .SECTION .const,CONST
.STR@1:
        .DB 0x73
        .DB 0x74
        .DB 0x61
        .DB 0x63
        .DB 0x6B
        .DB 0x20
        .DB 0x69
        .DB 0x73
        .DB 0x20
        .DB 0x62
        .DB 0x72
        .DB 0x6F
        .DB 0x6B
        .DB 0x65
        .DB 0x6E
        .DB 0x21
        .DS (1)