~ubuntu-branches/ubuntu/hardy/sigscheme/hardy-proposed

« back to all changes in this revision

Viewing changes to storage-protection.c

  • Committer: Bazaar Package Importer
  • Author(s): NIIBE Yutaka
  • Date: 2006-05-23 21:46:41 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060523214641-6ix4gz34wpiehub8
Tags: 0.5.0-2
* debian/control (Build-Depends): Added ruby.
  Thanks to Frederik Schueler.  Closes: #368571
* debian/rules (clean): invoke 'distclean' instead of 'clean'.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*===========================================================================
2
 
 *  FileName : storage-protection.c
3
 
 *  About    : GC protection interface
4
 
 *
5
 
 *  Copyright (C) 2005      by YamaKen
6
 
 *
7
 
 *  All rights reserved.
8
 
 *
9
 
 *  Redistribution and use in source and binary forms, with or without
10
 
 *  modification, are permitted provided that the following conditions
11
 
 *  are met:
12
 
 *
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.
21
 
 *
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
 
 *  =========================================================================*/
34
 
 
35
 
/* This file will be removed soon */
36
 
 
37
 
/* CAUTION: following description is obsoleted. It will be rewritten soon. */
38
 
 
39
 
/*
40
 
 * **** THE FUNCTIONS OF THIS FILE MUST NOT BE INLINED INTO CALLER ****
41
 
 *
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).
46
 
 *
47
 
 *
48
 
 * The Problem
49
 
 *
50
 
 *   On the previous stack protection strategy, following problem occurs.(the
51
 
 *   explanation is based on [Anthy-dev 2273]).
52
 
 *
53
 
 *   Take a look in following code fragment.
54
 
 *
55
 
 *   {
56
 
 *       ScmObj stack_start;
57
 
 *       ScmObj str_port = SCM_FALSE;
58
 
 *       ScmObj ret = SCM_FALSE;
59
 
 *
60
 
 *       SigScm_GC_ProtectStack(&stack_start);
61
 
 *
62
 
 *       str_port = Scm_NewStringPort(exp);
63
 
 *       ret = SigScm_Read(str_port);
64
 
 *       ret = EVAL(ret, SCM_NULL);
65
 
 *
66
 
 *       SigScm_GC_UnprotectStack(stack_start);
67
 
 *   }
68
 
 *
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
71
 
 *   follows.
72
 
 *
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.
76
 
 *
77
 
 *   (gdb) p &stack_start
78
 
 *   $6 = (ScmObj *) 0xbfffe7d8
79
 
 *   (gdb) p &str_port
80
 
 *   $7 = (ScmObj *) 0xbfffe7dc
81
 
 *   (gdb) p $sp
82
 
 *   $12 = (void *) 0xbfffe7d0
83
 
 *
84
 
 *   This result indicates the storage location order inversion:
85
 
 *
86
 
 *     expected: %esp < &str_port < &stack_start
87
 
 *     actual:   %esp < &stack_start < &str_port
88
 
 *
89
 
 *   So str_port is not protected in the case.
90
 
 *
91
 
 *
92
 
 * Solution
93
 
 *
94
 
 *   - Allocate the stack_start dummy variable in a separated function
95
 
 *
96
 
 *   - Ensure that a code fragment that its stack must be protected is
97
 
 *     certainly executed on the stack higher than stack_start
98
 
 *
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.
101
 
 *
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
105
 
 *      needed.
106
 
 *
107
 
 *      static const char *eval_str(const char *exp)
108
 
 *      {
109
 
 *          ScmObj str_port = SCM_FALSE;
110
 
 *          ScmObj ret = SCM_FALSE;
111
 
 *
112
 
 *          str_port = Scm_NewStringPort(exp);
113
 
 *          ret = SigScm_Read(str_port);
114
 
 *          ret = EVAL(ret, SCM_NULL);
115
 
 *          return SCM_STRING_STR(ret);
116
 
 *      }
117
 
 *
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.
123
 
 *
124
 
 *      SCM_DEFINE_GC_PROTECTED_FUNC1(static, const char *,
125
 
 *                                    eval_str, const char *, exp)
126
 
 *      {
127
 
 *          ScmObj str_port = SCM_FALSE;
128
 
 *          ScmObj ret = SCM_FALSE;
129
 
 *
130
 
 *          str_port = Scm_NewStringPort(exp);
131
 
 *          ret = SigScm_Read(str_port);
132
 
 *          ret = EVAL(ret, SCM_NULL);
133
 
 *          return SCM_STRING_STR(ret);
134
 
 *      }
135
 
 *
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.
140
 
 *
141
 
 *      caller:
142
 
 *      {
143
 
 *          const char *str;
144
 
 *
145
 
 *          <stack is not protected before the function invocation>
146
 
 *
147
 
 *          str = eval_str("(number->string (* 32 1024))");
148
 
 *
149
 
 *          <stack is not protected after the function invocation>
150
 
 *      }
151
 
 *
152
 
 *
153
 
 * Design Considerations
154
 
 *
155
 
 *   - Why don't you merge this file into datas.c?
156
 
 *
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
160
 
 *     the inlining.
161
 
 *
162
 
 *
163
 
 *   - Why SCM_DEFINE_GC_PROTECTED_FUNCn() does not support void for return
164
 
 *     type?
165
 
 *
166
 
 *     Since my macro programming skill is not enough orz. Would you help me?
167
 
 *
168
 
 *
169
 
 *   - Why don't you use variadic macro?
170
 
 *
171
 
 *     To support C89 environments. Please don't assume that newest GCC on an
172
 
 *     UNIX flavor is the only platform of SigScheme
173
 
 *
174
 
 *
175
 
 *   - Why don't you use SCM_GC_CALL_PROTECTED_FUNC() in client-side code
176
 
 *     directly?
177
 
 *
178
 
 *     Although following form can perform separated gc_protect_stack() and set
179
 
 *     the stack_start pointer appropriately, a corruption may occur.
180
 
 *
181
 
 *       SCM_GC_CALL_PROTECTED_FUNC(str, eval_str("(number->string 32)"));
182
 
 *
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
187
 
 *     local variables.
188
 
 *
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.
192
 
 *
193
 
 *  -- YamaKen 2005-09-07
194
 
 */
195
 
 
196
 
/*=======================================
197
 
  System Include
198
 
=======================================*/
199
 
 
200
 
/*=======================================
201
 
  Local Include
202
 
=======================================*/
203
 
#include "sigscheme.h"
204
 
#include "sigschemeinternal.h"
205
 
 
206
 
/*=======================================
207
 
  File Local Struct Declarations
208
 
=======================================*/
209
 
 
210
 
/*=======================================
211
 
  File Local Macro Declarations
212
 
=======================================*/
213
 
 
214
 
/*=======================================
215
 
  Variable Declarations
216
 
=======================================*/
217
 
 
218
 
/*=======================================
219
 
  File Local Function Declarations
220
 
=======================================*/
221
 
 
222
 
/*=======================================
223
 
  Extern Function Declarations
224
 
=======================================*/
225
 
 
226
 
/*=======================================
227
 
  Function Implementations
228
 
=======================================*/