1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
gcc/
2010-05-06 Magnus Granberg <zorry@gentoo.org>, Kevin F. Quinn <kevquinn@gentoo.org>
* builtins.c: (expand_builtin_init_trampoline): if warn_trampolines make a warning.
* common.opt: Add -Wtrampolines.
* varasm.c: (file_end_indicate_exec_stack): if warn_trampolines make a warning.
gcc/doc
2010-05-06 Magnus Granberg <zorry@gentoo.org>
* invoke.texi: Add -Wtrampolines.
gcc/testsuite/
2010-05-06 Magnus Granberg <zorry@gentoo.org>
* gcc.dg/Wtrampolines.c: New.
--- gcc/builtins.c.zorry 2010-04-13 15:47:11.000000000 +0200
+++ gcc/builtins.c 2010-06-16 12:33:54.000000000 +0200
@@ -5150,6 +5150,10 @@
targetm.calls.trampoline_init (m_tramp, t_func, r_chain);
trampolines_created = 1;
+
+ if (warn_trampolines)
+ warning (OPT_Wtrampolines, "trampoline generated for nested function %s", (IDENTIFIER_POINTER(DECL_NAME(t_func))));
+
return const0_rtx;
}
--- gcc/common.opt.zorry 2010-03-18 04:01:09.000000000 +0100
+++ gcc/common.opt 2010-05-06 00:44:18.000000000 +0200
@@ -192,6 +192,10 @@
Common Var(warn_system_headers) Warning
Do not suppress warnings from system headers
+Wtrampolines
+Common Var(warn_trampolines) Warnings
+Warn whenever a trampoline is generated and warn if it requires executable stack to
+
Wtype-limits
Common Var(warn_type_limits) Init(-1) Warning
Warn if a comparison is always true or always false due to the limited range of the data type
--- gcc/varasm.c.zorry 2010-03-27 12:56:30.000000000 +0100
+++ gcc/varasm.c 2010-05-29 15:06:33.000000000 +0200
@@ -6768,7 +6768,11 @@
{
unsigned int flags = SECTION_DEBUG;
if (trampolines_created)
+ {
flags |= SECTION_CODE;
+ if (warn_trampolines)
+ warning (OPT_Wtrampolines, "setting the stack as executable stack");
+ }
switch_to_section (get_section (".note.GNU-stack", flags, NULL));
}
--- gcc/doc/invoke.texi.zorry 2010-04-06 16:02:22.000000000 +0200
+++ gcc/doc/invoke.texi 2010-05-06 00:20:25.000000000 +0200
@@ -258,8 +258,8 @@
-Wstrict-aliasing -Wstrict-aliasing=n @gol
-Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand @gol
--Wsystem-headers -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized @gol
--Wunknown-pragmas -Wno-pragmas @gol
+-Wsystem-headers -Wtrampolines -Wtrigraphs -Wtype-limits -Wundef @gol
+-Wuninitialized -Wunknown-pragmas -Wno-pragmas @gol
-Wunsuffixed-float-constants -Wunused -Wunused-function @gol
-Wunused-label -Wunused-parameter -Wno-unused-result -Wunused-value -Wunused-variable @gol
-Wvariadic-macros -Wvla @gol
@@ -3603,6 +3603,19 @@
option will @emph{not} warn about unknown pragmas in system
headers---for that, @option{-Wunknown-pragmas} must also be used.
+@item -Wtrampolines
+@opindex Wtrampolines
+@opindex Wno-trampolines
+ Warn about trampolines generated for pointers to nested functions.
+ Warn when the trampoline requires the stack to be made executable.
+
+ A trampoline is a small piece of data or code that is created at run
+ time on the stack when the address of a nested function is taken, and
+ is used to call the nested function indirectly. For some targets, it
+ is made up of data only and thus requires no special treatment. But,
+ for most targets, it is made up of code and thus requires the stack
+ to be made executable in order for the program to work properly.
+
@item -Wfloat-equal
@opindex Wfloat-equal
@opindex Wno-float-equal
--- gcc/testsuite/gcc.dg/Wtrampolines.c.zorry 2010-05-05 12:53:11.000000000 +0200
+++ gcc/testsuite/gcc.dg/Wtrampolines.c 2010-05-06 00:26:05.000000000 +0200
@@ -0,0 +1,59 @@
+/* Origin: trampoline-1.c Waldek Hebisch <hebisch@math.uni.wroc.pl> */
+/* Ported to test -Wtrampolines Magnus Granberg <zorry@gentoo.org> */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target trampolines } */
+/* { dg-options "-O2 -Wtrampolines" } */
+/* { dg-warning "trampoline" "" { target *-*-* } 31 } */
+/* { dg-prune-output "stack" } */
+
+#ifndef NO_TRAMPOLINES
+
+/* This used to fail on various versions of Solaris 2 because the
+ trampoline couldn't be made executable. */
+
+extern void abort(void);
+extern double fabs(double);
+
+void foo (void)
+{
+ const int correct[1100] = {1, 0, -2, 0, 1, 0, 1, -1, -10, -30, -67};
+ int i;
+
+ double x1 (void) {return 1; }
+ double x2 (void) {return -1;}
+ double x3 (void) {return -1;}
+ double x4 (void) {return 1; }
+ double x5 (void) {return 0; }
+
+ typedef double pfun(void);
+
+ double a (int k, pfun x1, pfun x2, pfun x3, pfun x4, pfun x5)
+ {
+ double b (void)
+ {
+ k = k - 1;
+ return a (k, b, x1, x2, x3, x4 );
+ }
+
+ if (k <= 0)
+ return x4 () + x5 ();
+ else
+ return b ();
+ }
+
+ for (i=0; i<=10; i++)
+ {
+ if (fabs(a( i, x1, x2, x3, x4, x5 ) - correct [i]) > 0.1)
+ abort();
+ }
+}
+#endif
+
+int main (void)
+{
+#ifndef NO_TRAMPOLINES
+ foo ();
+#endif
+ return 0;
+}
|