1
/*===========================================================================
2
* FileName : storage-protection.c
3
* About : GC protection interface
5
* Copyright (C) 2005 by YamaKen
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. Neither the name of authors nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
22
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
23
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
26
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
* =========================================================================*/
35
/* This file will be removed soon */
37
/* CAUTION: following description is obsoleted. It will be rewritten soon. */
40
* **** THE FUNCTIONS OF THIS FILE MUST NOT BE INLINED INTO CALLER ****
42
* This file is intentionally separated from datas.c to make the SigScheme GC
43
* safe against an advanced storage layout optimization on stack. At least GCC
44
* 4.0 performs such optimization (reported in [Anthy-dev 2273] by Jun
45
* Inoue. Thank you a lot).
50
* On the previous stack protection strategy, following problem occurs.(the
51
* explanation is based on [Anthy-dev 2273]).
53
* Take a look in following code fragment.
57
* ScmObj str_port = SCM_FALSE;
58
* ScmObj ret = SCM_FALSE;
60
* SigScm_GC_ProtectStack(&stack_start);
62
* str_port = Scm_NewStringPort(exp);
63
* ret = SigScm_Read(str_port);
64
* ret = EVAL(ret, SCM_NULL);
66
* SigScm_GC_UnprotectStack(stack_start);
69
* The previous strategy assumes that stack_start is certainly located at
70
* lower than str_port and ret. But the optimization breaks the assumption as
73
* At the breakpoint immediately before SigScm_GC_ProtectStack() of the code
74
* compiled with gcc4 ((GCC) 4.0.1 20050617 (prerelease) (Debian 4.0.0-10)
75
* (IA32)), actual storage layout had reported as follows.
77
* (gdb) p &stack_start
78
* $6 = (ScmObj *) 0xbfffe7d8
80
* $7 = (ScmObj *) 0xbfffe7dc
82
* $12 = (void *) 0xbfffe7d0
84
* This result indicates the storage location order inversion:
86
* expected: %esp < &str_port < &stack_start
87
* actual: %esp < &stack_start < &str_port
89
* So str_port is not protected in the case.
94
* - Allocate the stack_start dummy variable in a separated function
96
* - Ensure that a code fragment that its stack must be protected is
97
* certainly executed on the stack higher than stack_start
99
* To achieve it, a series of macros which turns a function into
100
* stack-protected. See following steps to know how to use it.
102
* 1) Split a code fragment that its stack must be protected off into a
103
* function. No stack treatment is appried here. The function must return
104
* a value and cannot be void. Return dummy value if return value is not
107
* static const char *eval_str(const char *exp)
109
* ScmObj str_port = SCM_FALSE;
110
* ScmObj ret = SCM_FALSE;
112
* str_port = Scm_NewStringPort(exp);
113
* ret = SigScm_Read(str_port);
114
* ret = EVAL(ret, SCM_NULL);
115
* return SCM_STRING_STR(ret);
118
* 2) Rewrite 1) with the macro as follows. Select appropriate one that
119
* accepts same number of arguments of the function. In this case, single
120
* argument version is selected. Where to be rewritten is only the
121
* function header. Function body is kept untouched. If the function has
122
* no storage class specifier such as static, make 1st argument empty.
124
* SCM_DEFINE_GC_PROTECTED_FUNC1(static, const char *,
125
* eval_str, const char *, exp)
127
* ScmObj str_port = SCM_FALSE;
128
* ScmObj ret = SCM_FALSE;
130
* str_port = Scm_NewStringPort(exp);
131
* ret = SigScm_Read(str_port);
132
* ret = EVAL(ret, SCM_NULL);
133
* return SCM_STRING_STR(ret);
136
* 3) To apply stack protection to the function, simply call it as ordinary
137
* function. The protection is implicitly performed by hidden code
138
* fragments embedded in the function by the macro. See following code
139
* fragment for instance.
145
* <stack is not protected before the function invocation>
147
* str = eval_str("(number->string (* 32 1024))");
149
* <stack is not protected after the function invocation>
153
* Design Considerations
155
* - Why don't you merge this file into datas.c?
157
* To prevent implicit inlining of the functions. Although the noinline
158
* attribute is specified for GCC, other platforms needs another
159
* method. Compiling into a separated object file is an easy way to prevent
163
* - Why SCM_DEFINE_GC_PROTECTED_FUNCn() does not support void for return
166
* Since my macro programming skill is not enough orz. Would you help me?
169
* - Why don't you use variadic macro?
171
* To support C89 environments. Please don't assume that newest GCC on an
172
* UNIX flavor is the only platform of SigScheme
175
* - Why don't you use SCM_GC_CALL_PROTECTED_FUNC() in client-side code
178
* Although following form can perform separated gc_protect_stack() and set
179
* the stack_start pointer appropriately, a corruption may occur.
181
* SCM_GC_CALL_PROTECTED_FUNC(str, eval_str("(number->string 32)"));
183
* In this case, the target function (eval_str) may be expanded into the
184
* calee code. This means that its local variables may be relocated into
185
* caller's own stack frame. Once such relocation has occurred, the
186
* stack_start pointer will be set to a wrong point upper then the target's
189
* To avoid this condition, gc_protect_stack() and gc_unprotect_stack()
190
* must certainly be invoked in a separated function which will not be
191
* inlined. So SigScm_GC_CallProtectedFuncn() are prepared as function.
193
* -- YamaKen 2005-09-07
196
/*=======================================
198
=======================================*/
200
/*=======================================
202
=======================================*/
203
#include "sigscheme.h"
204
#include "sigschemeinternal.h"
206
/*=======================================
207
File Local Struct Declarations
208
=======================================*/
210
/*=======================================
211
File Local Macro Declarations
212
=======================================*/
214
/*=======================================
215
Variable Declarations
216
=======================================*/
218
/*=======================================
219
File Local Function Declarations
220
=======================================*/
222
/*=======================================
223
Extern Function Declarations
224
=======================================*/
226
/*=======================================
227
Function Implementations
228
=======================================*/