annotate gcc/tree-chkp.c @ 130:e108057fa461

merge
author mir3636
date Thu, 25 Oct 2018 08:08:40 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Pointer Bounds Checker insrumentation pass.
kono
parents:
diff changeset
2 Copyright (C) 2014-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
3 Contributed by Ilya Enkovich (ilya.enkovich@intel.com)
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include "config.h"
kono
parents:
diff changeset
22 #include "system.h"
kono
parents:
diff changeset
23 #include "coretypes.h"
kono
parents:
diff changeset
24 #include "backend.h"
kono
parents:
diff changeset
25 #include "target.h"
kono
parents:
diff changeset
26 #include "rtl.h"
kono
parents:
diff changeset
27 #include "tree.h"
kono
parents:
diff changeset
28 #include "gimple.h"
kono
parents:
diff changeset
29 #include "cfghooks.h"
kono
parents:
diff changeset
30 #include "tree-pass.h"
kono
parents:
diff changeset
31 #include "ssa.h"
kono
parents:
diff changeset
32 #include "cgraph.h"
kono
parents:
diff changeset
33 #include "diagnostic.h"
kono
parents:
diff changeset
34 #include "fold-const.h"
kono
parents:
diff changeset
35 #include "stor-layout.h"
kono
parents:
diff changeset
36 #include "varasm.h"
kono
parents:
diff changeset
37 #include "tree-iterator.h"
kono
parents:
diff changeset
38 #include "tree-cfg.h"
kono
parents:
diff changeset
39 #include "langhooks.h"
kono
parents:
diff changeset
40 #include "tree-ssa-address.h"
kono
parents:
diff changeset
41 #include "tree-ssa-loop-niter.h"
kono
parents:
diff changeset
42 #include "gimple-pretty-print.h"
kono
parents:
diff changeset
43 #include "gimple-iterator.h"
kono
parents:
diff changeset
44 #include "gimplify.h"
kono
parents:
diff changeset
45 #include "gimplify-me.h"
kono
parents:
diff changeset
46 #include "print-tree.h"
kono
parents:
diff changeset
47 #include "calls.h"
kono
parents:
diff changeset
48 #include "expr.h"
kono
parents:
diff changeset
49 #include "tree-ssa-propagate.h"
kono
parents:
diff changeset
50 #include "tree-chkp.h"
kono
parents:
diff changeset
51 #include "gimple-walk.h"
kono
parents:
diff changeset
52 #include "tree-dfa.h"
kono
parents:
diff changeset
53 #include "ipa-chkp.h"
kono
parents:
diff changeset
54 #include "params.h"
kono
parents:
diff changeset
55 #include "stringpool.h"
kono
parents:
diff changeset
56 #include "attribs.h"
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 /* Pointer Bounds Checker instruments code with memory checks to find
kono
parents:
diff changeset
59 out-of-bounds memory accesses. Checks are performed by computing
kono
parents:
diff changeset
60 bounds for each pointer and then comparing address of accessed
kono
parents:
diff changeset
61 memory before pointer dereferencing.
kono
parents:
diff changeset
62
kono
parents:
diff changeset
63 1. Function clones.
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 See ipa-chkp.c.
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 2. Instrumentation.
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 There are few things to instrument:
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 a) Memory accesses - add checker calls to check address of accessed memory
kono
parents:
diff changeset
72 against bounds of dereferenced pointer. Obviously safe memory
kono
parents:
diff changeset
73 accesses like static variable access does not have to be instrumented
kono
parents:
diff changeset
74 with checks.
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 Example:
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 val_2 = *p_1;
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 with 4 bytes access is transformed into:
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 __builtin___chkp_bndcl (__bound_tmp.1_3, p_1);
kono
parents:
diff changeset
83 D.1_4 = p_1 + 3;
kono
parents:
diff changeset
84 __builtin___chkp_bndcu (__bound_tmp.1_3, D.1_4);
kono
parents:
diff changeset
85 val_2 = *p_1;
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 where __bound_tmp.1_3 are bounds computed for pointer p_1,
kono
parents:
diff changeset
88 __builtin___chkp_bndcl is a lower bound check and
kono
parents:
diff changeset
89 __builtin___chkp_bndcu is an upper bound check.
kono
parents:
diff changeset
90
kono
parents:
diff changeset
91 b) Pointer stores.
kono
parents:
diff changeset
92
kono
parents:
diff changeset
93 When pointer is stored in memory we need to store its bounds. To
kono
parents:
diff changeset
94 achieve compatibility of instrumented code with regular codes
kono
parents:
diff changeset
95 we have to keep data layout and store bounds in special bound tables
kono
parents:
diff changeset
96 via special checker call. Implementation of bounds table may vary for
kono
parents:
diff changeset
97 different platforms. It has to associate pointer value and its
kono
parents:
diff changeset
98 location (it is required because we may have two equal pointers
kono
parents:
diff changeset
99 with different bounds stored in different places) with bounds.
kono
parents:
diff changeset
100 Another checker builtin allows to get bounds for specified pointer
kono
parents:
diff changeset
101 loaded from specified location.
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103 Example:
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 buf1[i_1] = &buf2;
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 is transformed into:
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 buf1[i_1] = &buf2;
kono
parents:
diff changeset
110 D.1_2 = &buf1[i_1];
kono
parents:
diff changeset
111 __builtin___chkp_bndstx (D.1_2, &buf2, __bound_tmp.1_2);
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 where __bound_tmp.1_2 are bounds of &buf2.
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115 c) Static initialization.
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 The special case of pointer store is static pointer initialization.
kono
parents:
diff changeset
118 Bounds initialization is performed in a few steps:
kono
parents:
diff changeset
119 - register all static initializations in front-end using
kono
parents:
diff changeset
120 chkp_register_var_initializer
kono
parents:
diff changeset
121 - when file compilation finishes we create functions with special
kono
parents:
diff changeset
122 attribute 'chkp ctor' and put explicit initialization code
kono
parents:
diff changeset
123 (assignments) for all statically initialized pointers.
kono
parents:
diff changeset
124 - when checker constructor is compiled checker pass adds required
kono
parents:
diff changeset
125 bounds initialization for all statically initialized pointers
kono
parents:
diff changeset
126 - since we do not actually need excess pointers initialization
kono
parents:
diff changeset
127 in checker constructor we remove such assignments from them
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 d) Calls.
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 For each call in the code we add additional arguments to pass
kono
parents:
diff changeset
132 bounds for pointer arguments. We determine type of call arguments
kono
parents:
diff changeset
133 using arguments list from function declaration; if function
kono
parents:
diff changeset
134 declaration is not available we use function type; otherwise
kono
parents:
diff changeset
135 (e.g. for unnamed arguments) we use type of passed value. Function
kono
parents:
diff changeset
136 declaration/type is replaced with the instrumented one.
kono
parents:
diff changeset
137
kono
parents:
diff changeset
138 Example:
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 val_1 = foo (&buf1, &buf2, &buf1, 0);
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 is translated into:
kono
parents:
diff changeset
143
kono
parents:
diff changeset
144 val_1 = foo.chkp (&buf1, __bound_tmp.1_2, &buf2, __bound_tmp.1_3,
kono
parents:
diff changeset
145 &buf1, __bound_tmp.1_2, 0);
kono
parents:
diff changeset
146
kono
parents:
diff changeset
147 e) Returns.
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 If function returns a pointer value we have to return bounds also.
kono
parents:
diff changeset
150 A new operand was added for return statement to hold returned bounds.
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 Example:
kono
parents:
diff changeset
153
kono
parents:
diff changeset
154 return &_buf1;
kono
parents:
diff changeset
155
kono
parents:
diff changeset
156 is transformed into
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 return &_buf1, __bound_tmp.1_1;
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 3. Bounds computation.
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 Compiler is fully responsible for computing bounds to be used for each
kono
parents:
diff changeset
163 memory access. The first step for bounds computation is to find the
kono
parents:
diff changeset
164 origin of pointer dereferenced for memory access. Basing on pointer
kono
parents:
diff changeset
165 origin we define a way to compute its bounds. There are just few
kono
parents:
diff changeset
166 possible cases:
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 a) Pointer is returned by call.
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 In this case we use corresponding checker builtin method to obtain returned
kono
parents:
diff changeset
171 bounds.
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 Example:
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 buf_1 = malloc (size_2);
kono
parents:
diff changeset
176 foo (buf_1);
kono
parents:
diff changeset
177
kono
parents:
diff changeset
178 is translated into:
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 buf_1 = malloc (size_2);
kono
parents:
diff changeset
181 __bound_tmp.1_3 = __builtin___chkp_bndret (buf_1);
kono
parents:
diff changeset
182 foo (buf_1, __bound_tmp.1_3);
kono
parents:
diff changeset
183
kono
parents:
diff changeset
184 b) Pointer is an address of an object.
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 In this case compiler tries to compute objects size and create corresponding
kono
parents:
diff changeset
187 bounds. If object has incomplete type then special checker builtin is used to
kono
parents:
diff changeset
188 obtain its size at runtime.
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 Example:
kono
parents:
diff changeset
191
kono
parents:
diff changeset
192 foo ()
kono
parents:
diff changeset
193 {
kono
parents:
diff changeset
194 <unnamed type> __bound_tmp.3;
kono
parents:
diff changeset
195 static int buf[100];
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 <bb 3>:
kono
parents:
diff changeset
198 __bound_tmp.3_2 = __builtin___chkp_bndmk (&buf, 400);
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 <bb 2>:
kono
parents:
diff changeset
201 return &buf, __bound_tmp.3_2;
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 Example:
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 Address of an object 'extern int buf[]' with incomplete type is
kono
parents:
diff changeset
207 returned.
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 foo ()
kono
parents:
diff changeset
210 {
kono
parents:
diff changeset
211 <unnamed type> __bound_tmp.4;
kono
parents:
diff changeset
212 long unsigned int __size_tmp.3;
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 <bb 3>:
kono
parents:
diff changeset
215 __size_tmp.3_4 = __builtin_ia32_sizeof (buf);
kono
parents:
diff changeset
216 __bound_tmp.4_3 = __builtin_ia32_bndmk (&buf, __size_tmp.3_4);
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 <bb 2>:
kono
parents:
diff changeset
219 return &buf, __bound_tmp.4_3;
kono
parents:
diff changeset
220 }
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 c) Pointer is the result of object narrowing.
kono
parents:
diff changeset
223
kono
parents:
diff changeset
224 It happens when we use pointer to an object to compute pointer to a part
kono
parents:
diff changeset
225 of an object. E.g. we take pointer to a field of a structure. In this
kono
parents:
diff changeset
226 case we perform bounds intersection using bounds of original object and
kono
parents:
diff changeset
227 bounds of object's part (which are computed basing on its type).
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 There may be some debatable questions about when narrowing should occur
kono
parents:
diff changeset
230 and when it should not. To avoid false bound violations in correct
kono
parents:
diff changeset
231 programs we do not perform narrowing when address of an array element is
kono
parents:
diff changeset
232 obtained (it has address of the whole array) and when address of the first
kono
parents:
diff changeset
233 structure field is obtained (because it is guaranteed to be equal to
kono
parents:
diff changeset
234 address of the whole structure and it is legal to cast it back to structure).
kono
parents:
diff changeset
235
kono
parents:
diff changeset
236 Default narrowing behavior may be changed using compiler flags.
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 Example:
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 In this example address of the second structure field is returned.
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 foo (struct A * p, __bounds_type __bounds_of_p)
kono
parents:
diff changeset
243 {
kono
parents:
diff changeset
244 <unnamed type> __bound_tmp.3;
kono
parents:
diff changeset
245 int * _2;
kono
parents:
diff changeset
246 int * _5;
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 <bb 2>:
kono
parents:
diff changeset
249 _5 = &p_1(D)->second_field;
kono
parents:
diff changeset
250 __bound_tmp.3_6 = __builtin___chkp_bndmk (_5, 4);
kono
parents:
diff changeset
251 __bound_tmp.3_8 = __builtin___chkp_intersect (__bound_tmp.3_6,
kono
parents:
diff changeset
252 __bounds_of_p_3(D));
kono
parents:
diff changeset
253 _2 = &p_1(D)->second_field;
kono
parents:
diff changeset
254 return _2, __bound_tmp.3_8;
kono
parents:
diff changeset
255 }
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 Example:
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 In this example address of the first field of array element is returned.
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 foo (struct A * p, __bounds_type __bounds_of_p, int i)
kono
parents:
diff changeset
262 {
kono
parents:
diff changeset
263 long unsigned int _3;
kono
parents:
diff changeset
264 long unsigned int _4;
kono
parents:
diff changeset
265 struct A * _6;
kono
parents:
diff changeset
266 int * _7;
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 <bb 2>:
kono
parents:
diff changeset
269 _3 = (long unsigned int) i_1(D);
kono
parents:
diff changeset
270 _4 = _3 * 8;
kono
parents:
diff changeset
271 _6 = p_5(D) + _4;
kono
parents:
diff changeset
272 _7 = &_6->first_field;
kono
parents:
diff changeset
273 return _7, __bounds_of_p_2(D);
kono
parents:
diff changeset
274 }
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 d) Pointer is the result of pointer arithmetic or type cast.
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 In this case bounds of the base pointer are used. In case of binary
kono
parents:
diff changeset
280 operation producing a pointer we are analyzing data flow further
kono
parents:
diff changeset
281 looking for operand's bounds. One operand is considered as a base
kono
parents:
diff changeset
282 if it has some valid bounds. If we fall into a case when none of
kono
parents:
diff changeset
283 operands (or both of them) has valid bounds, a default bounds value
kono
parents:
diff changeset
284 is used.
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 Trying to find out bounds for binary operations we may fall into
kono
parents:
diff changeset
287 cyclic dependencies for pointers. To avoid infinite recursion all
kono
parents:
diff changeset
288 walked phi nodes instantly obtain corresponding bounds but created
kono
parents:
diff changeset
289 bounds are marked as incomplete. It helps us to stop DF walk during
kono
parents:
diff changeset
290 bounds search.
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 When we reach pointer source, some args of incomplete bounds phi obtain
kono
parents:
diff changeset
293 valid bounds and those values are propagated further through phi nodes.
kono
parents:
diff changeset
294 If no valid bounds were found for phi node then we mark its result as
kono
parents:
diff changeset
295 invalid bounds. Process stops when all incomplete bounds become either
kono
parents:
diff changeset
296 valid or invalid and we are able to choose a pointer base.
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 e) Pointer is loaded from the memory.
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 In this case we just need to load bounds from the bounds table.
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 Example:
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 foo ()
kono
parents:
diff changeset
305 {
kono
parents:
diff changeset
306 <unnamed type> __bound_tmp.3;
kono
parents:
diff changeset
307 static int * buf;
kono
parents:
diff changeset
308 int * _2;
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310 <bb 2>:
kono
parents:
diff changeset
311 _2 = buf;
kono
parents:
diff changeset
312 __bound_tmp.3_4 = __builtin___chkp_bndldx (&buf, _2);
kono
parents:
diff changeset
313 return _2, __bound_tmp.3_4;
kono
parents:
diff changeset
314 }
kono
parents:
diff changeset
315
kono
parents:
diff changeset
316 */
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 typedef void (*assign_handler)(tree, tree, void *);
kono
parents:
diff changeset
319
kono
parents:
diff changeset
320 static tree chkp_get_zero_bounds ();
kono
parents:
diff changeset
321 static tree chkp_find_bounds (tree ptr, gimple_stmt_iterator *iter);
kono
parents:
diff changeset
322 static tree chkp_find_bounds_loaded (tree ptr, tree ptr_src,
kono
parents:
diff changeset
323 gimple_stmt_iterator *iter);
kono
parents:
diff changeset
324 static void chkp_parse_array_and_component_ref (tree node, tree *ptr,
kono
parents:
diff changeset
325 tree *elt, bool *safe,
kono
parents:
diff changeset
326 bool *bitfield,
kono
parents:
diff changeset
327 tree *bounds,
kono
parents:
diff changeset
328 gimple_stmt_iterator *iter,
kono
parents:
diff changeset
329 bool innermost_bounds);
kono
parents:
diff changeset
330 static void chkp_parse_bit_field_ref (tree node, location_t loc,
kono
parents:
diff changeset
331 tree *offset, tree *size);
kono
parents:
diff changeset
332 static tree
kono
parents:
diff changeset
333 chkp_make_addressed_object_bounds (tree obj, gimple_stmt_iterator *iter);
kono
parents:
diff changeset
334
kono
parents:
diff changeset
335 #define chkp_bndldx_fndecl \
kono
parents:
diff changeset
336 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDLDX))
kono
parents:
diff changeset
337 #define chkp_bndstx_fndecl \
kono
parents:
diff changeset
338 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDSTX))
kono
parents:
diff changeset
339 #define chkp_checkl_fndecl \
kono
parents:
diff changeset
340 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDCL))
kono
parents:
diff changeset
341 #define chkp_checku_fndecl \
kono
parents:
diff changeset
342 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDCU))
kono
parents:
diff changeset
343 #define chkp_bndmk_fndecl \
kono
parents:
diff changeset
344 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDMK))
kono
parents:
diff changeset
345 #define chkp_ret_bnd_fndecl \
kono
parents:
diff changeset
346 (targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET))
kono
parents:
diff changeset
347 #define chkp_intersect_fndecl \
kono
parents:
diff changeset
348 (targetm.builtin_chkp_function (BUILT_IN_CHKP_INTERSECT))
kono
parents:
diff changeset
349 #define chkp_narrow_bounds_fndecl \
kono
parents:
diff changeset
350 (targetm.builtin_chkp_function (BUILT_IN_CHKP_NARROW))
kono
parents:
diff changeset
351 #define chkp_sizeof_fndecl \
kono
parents:
diff changeset
352 (targetm.builtin_chkp_function (BUILT_IN_CHKP_SIZEOF))
kono
parents:
diff changeset
353 #define chkp_extract_lower_fndecl \
kono
parents:
diff changeset
354 (targetm.builtin_chkp_function (BUILT_IN_CHKP_EXTRACT_LOWER))
kono
parents:
diff changeset
355 #define chkp_extract_upper_fndecl \
kono
parents:
diff changeset
356 (targetm.builtin_chkp_function (BUILT_IN_CHKP_EXTRACT_UPPER))
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 static GTY (()) tree chkp_uintptr_type;
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 static GTY (()) tree chkp_zero_bounds_var;
kono
parents:
diff changeset
361 static GTY (()) tree chkp_none_bounds_var;
kono
parents:
diff changeset
362
kono
parents:
diff changeset
363 static GTY (()) basic_block entry_block;
kono
parents:
diff changeset
364 static GTY (()) tree zero_bounds;
kono
parents:
diff changeset
365 static GTY (()) tree none_bounds;
kono
parents:
diff changeset
366 static GTY (()) tree incomplete_bounds;
kono
parents:
diff changeset
367 static GTY (()) tree tmp_var;
kono
parents:
diff changeset
368 static GTY (()) tree size_tmp_var;
kono
parents:
diff changeset
369 static GTY (()) bitmap chkp_abnormal_copies;
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 struct hash_set<tree> *chkp_invalid_bounds;
kono
parents:
diff changeset
372 struct hash_set<tree> *chkp_completed_bounds_set;
kono
parents:
diff changeset
373 struct hash_map<tree, tree> *chkp_reg_bounds;
kono
parents:
diff changeset
374 struct hash_map<tree, tree> *chkp_bound_vars;
kono
parents:
diff changeset
375 struct hash_map<tree, tree> *chkp_reg_addr_bounds;
kono
parents:
diff changeset
376 struct hash_map<tree, tree> *chkp_incomplete_bounds_map;
kono
parents:
diff changeset
377 struct hash_map<tree, tree> *chkp_bounds_map;
kono
parents:
diff changeset
378 struct hash_map<tree, tree> *chkp_static_var_bounds;
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 static bool in_chkp_pass;
kono
parents:
diff changeset
381
kono
parents:
diff changeset
382 #define CHKP_BOUND_TMP_NAME "__bound_tmp"
kono
parents:
diff changeset
383 #define CHKP_SIZE_TMP_NAME "__size_tmp"
kono
parents:
diff changeset
384 #define CHKP_BOUNDS_OF_SYMBOL_PREFIX "__chkp_bounds_of_"
kono
parents:
diff changeset
385 #define CHKP_STRING_BOUNDS_PREFIX "__chkp_string_bounds_"
kono
parents:
diff changeset
386 #define CHKP_VAR_BOUNDS_PREFIX "__chkp_var_bounds_"
kono
parents:
diff changeset
387 #define CHKP_ZERO_BOUNDS_VAR_NAME "__chkp_zero_bounds"
kono
parents:
diff changeset
388 #define CHKP_NONE_BOUNDS_VAR_NAME "__chkp_none_bounds"
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 /* Static checker constructors may become very large and their
kono
parents:
diff changeset
391 compilation with optimization may take too much time.
kono
parents:
diff changeset
392 Therefore we put a limit to number of statements in one
kono
parents:
diff changeset
393 constructor. Tests with 100 000 statically initialized
kono
parents:
diff changeset
394 pointers showed following compilation times on Sandy Bridge
kono
parents:
diff changeset
395 server (used -O2):
kono
parents:
diff changeset
396 limit 100 => ~18 sec.
kono
parents:
diff changeset
397 limit 300 => ~22 sec.
kono
parents:
diff changeset
398 limit 1000 => ~30 sec.
kono
parents:
diff changeset
399 limit 3000 => ~49 sec.
kono
parents:
diff changeset
400 limit 5000 => ~55 sec.
kono
parents:
diff changeset
401 limit 10000 => ~76 sec.
kono
parents:
diff changeset
402 limit 100000 => ~532 sec. */
kono
parents:
diff changeset
403 #define MAX_STMTS_IN_STATIC_CHKP_CTOR (PARAM_VALUE (PARAM_CHKP_MAX_CTOR_SIZE))
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 struct chkp_ctor_stmt_list
kono
parents:
diff changeset
406 {
kono
parents:
diff changeset
407 tree stmts;
kono
parents:
diff changeset
408 int avail;
kono
parents:
diff changeset
409 };
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 /* Return 1 if function FNDECL is instrumented by Pointer
kono
parents:
diff changeset
412 Bounds Checker. */
kono
parents:
diff changeset
413 bool
kono
parents:
diff changeset
414 chkp_function_instrumented_p (tree fndecl)
kono
parents:
diff changeset
415 {
kono
parents:
diff changeset
416 return fndecl
kono
parents:
diff changeset
417 && lookup_attribute ("chkp instrumented", DECL_ATTRIBUTES (fndecl));
kono
parents:
diff changeset
418 }
kono
parents:
diff changeset
419
kono
parents:
diff changeset
420 /* Mark function FNDECL as instrumented. */
kono
parents:
diff changeset
421 void
kono
parents:
diff changeset
422 chkp_function_mark_instrumented (tree fndecl)
kono
parents:
diff changeset
423 {
kono
parents:
diff changeset
424 if (chkp_function_instrumented_p (fndecl))
kono
parents:
diff changeset
425 return;
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 DECL_ATTRIBUTES (fndecl)
kono
parents:
diff changeset
428 = tree_cons (get_identifier ("chkp instrumented"), NULL,
kono
parents:
diff changeset
429 DECL_ATTRIBUTES (fndecl));
kono
parents:
diff changeset
430 }
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 /* Return true when STMT is builtin call to instrumentation function
kono
parents:
diff changeset
433 corresponding to CODE. */
kono
parents:
diff changeset
434
kono
parents:
diff changeset
435 bool
kono
parents:
diff changeset
436 chkp_gimple_call_builtin_p (gimple *call,
kono
parents:
diff changeset
437 enum built_in_function code)
kono
parents:
diff changeset
438 {
kono
parents:
diff changeset
439 tree fndecl;
kono
parents:
diff changeset
440 /* We are skipping the check for address-spaces, that's
kono
parents:
diff changeset
441 why we don't use gimple_call_builtin_p directly here. */
kono
parents:
diff changeset
442 if (is_gimple_call (call)
kono
parents:
diff changeset
443 && (fndecl = gimple_call_fndecl (call)) != NULL
kono
parents:
diff changeset
444 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD
kono
parents:
diff changeset
445 && (fndecl = targetm.builtin_chkp_function (code))
kono
parents:
diff changeset
446 && (DECL_FUNCTION_CODE (gimple_call_fndecl (call))
kono
parents:
diff changeset
447 == DECL_FUNCTION_CODE (fndecl)))
kono
parents:
diff changeset
448 return true;
kono
parents:
diff changeset
449 return false;
kono
parents:
diff changeset
450 }
kono
parents:
diff changeset
451
kono
parents:
diff changeset
452 /* Emit code to build zero bounds and return RTL holding
kono
parents:
diff changeset
453 the result. */
kono
parents:
diff changeset
454 rtx
kono
parents:
diff changeset
455 chkp_expand_zero_bounds ()
kono
parents:
diff changeset
456 {
kono
parents:
diff changeset
457 tree zero_bnd;
kono
parents:
diff changeset
458
kono
parents:
diff changeset
459 if (flag_chkp_use_static_const_bounds)
kono
parents:
diff changeset
460 zero_bnd = chkp_get_zero_bounds_var ();
kono
parents:
diff changeset
461 else
kono
parents:
diff changeset
462 zero_bnd = chkp_build_make_bounds_call (integer_zero_node,
kono
parents:
diff changeset
463 integer_zero_node);
kono
parents:
diff changeset
464 return expand_normal (zero_bnd);
kono
parents:
diff changeset
465 }
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 /* Emit code to store zero bounds for PTR located at MEM. */
kono
parents:
diff changeset
468 void
kono
parents:
diff changeset
469 chkp_expand_bounds_reset_for_mem (tree mem, tree ptr)
kono
parents:
diff changeset
470 {
kono
parents:
diff changeset
471 tree zero_bnd, bnd, addr, bndstx;
kono
parents:
diff changeset
472
kono
parents:
diff changeset
473 if (flag_chkp_use_static_const_bounds)
kono
parents:
diff changeset
474 zero_bnd = chkp_get_zero_bounds_var ();
kono
parents:
diff changeset
475 else
kono
parents:
diff changeset
476 zero_bnd = chkp_build_make_bounds_call (integer_zero_node,
kono
parents:
diff changeset
477 integer_zero_node);
kono
parents:
diff changeset
478 bnd = make_tree (pointer_bounds_type_node,
kono
parents:
diff changeset
479 assign_temp (pointer_bounds_type_node, 0, 1));
kono
parents:
diff changeset
480 addr = build1 (ADDR_EXPR,
kono
parents:
diff changeset
481 build_pointer_type (TREE_TYPE (mem)), mem);
kono
parents:
diff changeset
482 bndstx = chkp_build_bndstx_call (addr, ptr, bnd);
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 expand_assignment (bnd, zero_bnd, false);
kono
parents:
diff changeset
485 expand_normal (bndstx);
kono
parents:
diff changeset
486 }
kono
parents:
diff changeset
487
kono
parents:
diff changeset
488 /* Build retbnd call for returned value RETVAL.
kono
parents:
diff changeset
489
kono
parents:
diff changeset
490 If BNDVAL is not NULL then result is stored
kono
parents:
diff changeset
491 in it. Otherwise a temporary is created to
kono
parents:
diff changeset
492 hold returned value.
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 GSI points to a position for a retbnd call
kono
parents:
diff changeset
495 and is set to created stmt.
kono
parents:
diff changeset
496
kono
parents:
diff changeset
497 Cgraph edge is created for a new call if
kono
parents:
diff changeset
498 UPDATE_EDGE is 1.
kono
parents:
diff changeset
499
kono
parents:
diff changeset
500 Obtained bounds are returned. */
kono
parents:
diff changeset
501 tree
kono
parents:
diff changeset
502 chkp_insert_retbnd_call (tree bndval, tree retval,
kono
parents:
diff changeset
503 gimple_stmt_iterator *gsi)
kono
parents:
diff changeset
504 {
kono
parents:
diff changeset
505 gimple *call;
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 if (!bndval)
kono
parents:
diff changeset
508 bndval = create_tmp_reg (pointer_bounds_type_node, "retbnd");
kono
parents:
diff changeset
509
kono
parents:
diff changeset
510 call = gimple_build_call (chkp_ret_bnd_fndecl, 1, retval);
kono
parents:
diff changeset
511 gimple_call_set_lhs (call, bndval);
kono
parents:
diff changeset
512 gsi_insert_after (gsi, call, GSI_CONTINUE_LINKING);
kono
parents:
diff changeset
513
kono
parents:
diff changeset
514 return bndval;
kono
parents:
diff changeset
515 }
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 /* Build a GIMPLE_CALL identical to CALL but skipping bounds
kono
parents:
diff changeset
518 arguments. */
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 gcall *
kono
parents:
diff changeset
521 chkp_copy_call_skip_bounds (gcall *call)
kono
parents:
diff changeset
522 {
kono
parents:
diff changeset
523 bitmap bounds;
kono
parents:
diff changeset
524 unsigned i;
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 bitmap_obstack_initialize (NULL);
kono
parents:
diff changeset
527 bounds = BITMAP_ALLOC (NULL);
kono
parents:
diff changeset
528
kono
parents:
diff changeset
529 for (i = 0; i < gimple_call_num_args (call); i++)
kono
parents:
diff changeset
530 if (POINTER_BOUNDS_P (gimple_call_arg (call, i)))
kono
parents:
diff changeset
531 bitmap_set_bit (bounds, i);
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 if (!bitmap_empty_p (bounds))
kono
parents:
diff changeset
534 call = gimple_call_copy_skip_args (call, bounds);
kono
parents:
diff changeset
535 gimple_call_set_with_bounds (call, false);
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 BITMAP_FREE (bounds);
kono
parents:
diff changeset
538 bitmap_obstack_release (NULL);
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 return call;
kono
parents:
diff changeset
541 }
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 /* Redirect edge E to the correct node according to call_stmt.
kono
parents:
diff changeset
544 Return 1 if bounds removal from call_stmt should be done
kono
parents:
diff changeset
545 instead of redirection. */
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 bool
kono
parents:
diff changeset
548 chkp_redirect_edge (cgraph_edge *e)
kono
parents:
diff changeset
549 {
kono
parents:
diff changeset
550 bool instrumented = false;
kono
parents:
diff changeset
551 tree decl = e->callee->decl;
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 if (e->callee->instrumentation_clone
kono
parents:
diff changeset
554 || chkp_function_instrumented_p (decl))
kono
parents:
diff changeset
555 instrumented = true;
kono
parents:
diff changeset
556
kono
parents:
diff changeset
557 if (instrumented
kono
parents:
diff changeset
558 && !gimple_call_with_bounds_p (e->call_stmt))
kono
parents:
diff changeset
559 e->redirect_callee (cgraph_node::get_create (e->callee->orig_decl));
kono
parents:
diff changeset
560 else if (!instrumented
kono
parents:
diff changeset
561 && gimple_call_with_bounds_p (e->call_stmt)
kono
parents:
diff changeset
562 && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDCL)
kono
parents:
diff changeset
563 && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDCU)
kono
parents:
diff changeset
564 && !chkp_gimple_call_builtin_p (e->call_stmt, BUILT_IN_CHKP_BNDSTX))
kono
parents:
diff changeset
565 {
kono
parents:
diff changeset
566 if (e->callee->instrumented_version)
kono
parents:
diff changeset
567 e->redirect_callee (e->callee->instrumented_version);
kono
parents:
diff changeset
568 else
kono
parents:
diff changeset
569 {
kono
parents:
diff changeset
570 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
kono
parents:
diff changeset
571 /* Avoid bounds removal if all args will be removed. */
kono
parents:
diff changeset
572 if (!args || TREE_VALUE (args) != void_type_node)
kono
parents:
diff changeset
573 return true;
kono
parents:
diff changeset
574 else
kono
parents:
diff changeset
575 gimple_call_set_with_bounds (e->call_stmt, false);
kono
parents:
diff changeset
576 }
kono
parents:
diff changeset
577 }
kono
parents:
diff changeset
578
kono
parents:
diff changeset
579 return false;
kono
parents:
diff changeset
580 }
kono
parents:
diff changeset
581
kono
parents:
diff changeset
582 /* Mark statement S to not be instrumented. */
kono
parents:
diff changeset
583 static void
kono
parents:
diff changeset
584 chkp_mark_stmt (gimple *s)
kono
parents:
diff changeset
585 {
kono
parents:
diff changeset
586 gimple_set_plf (s, GF_PLF_1, true);
kono
parents:
diff changeset
587 }
kono
parents:
diff changeset
588
kono
parents:
diff changeset
589 /* Mark statement S to be instrumented. */
kono
parents:
diff changeset
590 static void
kono
parents:
diff changeset
591 chkp_unmark_stmt (gimple *s)
kono
parents:
diff changeset
592 {
kono
parents:
diff changeset
593 gimple_set_plf (s, GF_PLF_1, false);
kono
parents:
diff changeset
594 }
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 /* Return 1 if statement S should not be instrumented. */
kono
parents:
diff changeset
597 static bool
kono
parents:
diff changeset
598 chkp_marked_stmt_p (gimple *s)
kono
parents:
diff changeset
599 {
kono
parents:
diff changeset
600 return gimple_plf (s, GF_PLF_1);
kono
parents:
diff changeset
601 }
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 /* Get var to be used for bound temps. */
kono
parents:
diff changeset
604 static tree
kono
parents:
diff changeset
605 chkp_get_tmp_var (void)
kono
parents:
diff changeset
606 {
kono
parents:
diff changeset
607 if (!tmp_var)
kono
parents:
diff changeset
608 tmp_var = create_tmp_reg (pointer_bounds_type_node, CHKP_BOUND_TMP_NAME);
kono
parents:
diff changeset
609
kono
parents:
diff changeset
610 return tmp_var;
kono
parents:
diff changeset
611 }
kono
parents:
diff changeset
612
kono
parents:
diff changeset
613 /* Get SSA_NAME to be used as temp. */
kono
parents:
diff changeset
614 static tree
kono
parents:
diff changeset
615 chkp_get_tmp_reg (gimple *stmt)
kono
parents:
diff changeset
616 {
kono
parents:
diff changeset
617 if (in_chkp_pass)
kono
parents:
diff changeset
618 return make_ssa_name (chkp_get_tmp_var (), stmt);
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 return make_temp_ssa_name (pointer_bounds_type_node, stmt,
kono
parents:
diff changeset
621 CHKP_BOUND_TMP_NAME);
kono
parents:
diff changeset
622 }
kono
parents:
diff changeset
623
kono
parents:
diff changeset
624 /* Get var to be used for size temps. */
kono
parents:
diff changeset
625 static tree
kono
parents:
diff changeset
626 chkp_get_size_tmp_var (void)
kono
parents:
diff changeset
627 {
kono
parents:
diff changeset
628 if (!size_tmp_var)
kono
parents:
diff changeset
629 size_tmp_var = create_tmp_reg (chkp_uintptr_type, CHKP_SIZE_TMP_NAME);
kono
parents:
diff changeset
630
kono
parents:
diff changeset
631 return size_tmp_var;
kono
parents:
diff changeset
632 }
kono
parents:
diff changeset
633
kono
parents:
diff changeset
634 /* Register bounds BND for address of OBJ. */
kono
parents:
diff changeset
635 static void
kono
parents:
diff changeset
636 chkp_register_addr_bounds (tree obj, tree bnd)
kono
parents:
diff changeset
637 {
kono
parents:
diff changeset
638 if (bnd == incomplete_bounds)
kono
parents:
diff changeset
639 return;
kono
parents:
diff changeset
640
kono
parents:
diff changeset
641 chkp_reg_addr_bounds->put (obj, bnd);
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
644 {
kono
parents:
diff changeset
645 fprintf (dump_file, "Regsitered bound ");
kono
parents:
diff changeset
646 print_generic_expr (dump_file, bnd);
kono
parents:
diff changeset
647 fprintf (dump_file, " for address of ");
kono
parents:
diff changeset
648 print_generic_expr (dump_file, obj);
kono
parents:
diff changeset
649 fprintf (dump_file, "\n");
kono
parents:
diff changeset
650 }
kono
parents:
diff changeset
651 }
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 /* Return bounds registered for address of OBJ. */
kono
parents:
diff changeset
654 static tree
kono
parents:
diff changeset
655 chkp_get_registered_addr_bounds (tree obj)
kono
parents:
diff changeset
656 {
kono
parents:
diff changeset
657 tree *slot = chkp_reg_addr_bounds->get (obj);
kono
parents:
diff changeset
658 return slot ? *slot : NULL_TREE;
kono
parents:
diff changeset
659 }
kono
parents:
diff changeset
660
kono
parents:
diff changeset
661 /* Mark BOUNDS as completed. */
kono
parents:
diff changeset
662 static void
kono
parents:
diff changeset
663 chkp_mark_completed_bounds (tree bounds)
kono
parents:
diff changeset
664 {
kono
parents:
diff changeset
665 chkp_completed_bounds_set->add (bounds);
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
668 {
kono
parents:
diff changeset
669 fprintf (dump_file, "Marked bounds ");
kono
parents:
diff changeset
670 print_generic_expr (dump_file, bounds);
kono
parents:
diff changeset
671 fprintf (dump_file, " as completed\n");
kono
parents:
diff changeset
672 }
kono
parents:
diff changeset
673 }
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 /* Return 1 if BOUNDS were marked as completed and 0 otherwise. */
kono
parents:
diff changeset
676 static bool
kono
parents:
diff changeset
677 chkp_completed_bounds (tree bounds)
kono
parents:
diff changeset
678 {
kono
parents:
diff changeset
679 return chkp_completed_bounds_set->contains (bounds);
kono
parents:
diff changeset
680 }
kono
parents:
diff changeset
681
kono
parents:
diff changeset
682 /* Clear comleted bound marks. */
kono
parents:
diff changeset
683 static void
kono
parents:
diff changeset
684 chkp_erase_completed_bounds (void)
kono
parents:
diff changeset
685 {
kono
parents:
diff changeset
686 delete chkp_completed_bounds_set;
kono
parents:
diff changeset
687 chkp_completed_bounds_set = new hash_set<tree>;
kono
parents:
diff changeset
688 }
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 /* This function is used to provide a base address for
kono
parents:
diff changeset
691 chkp_get_hard_register_fake_addr_expr. */
kono
parents:
diff changeset
692 static tree
kono
parents:
diff changeset
693 chkp_get_hard_register_var_fake_base_address ()
kono
parents:
diff changeset
694 {
kono
parents:
diff changeset
695 int prec = TYPE_PRECISION (ptr_type_node);
kono
parents:
diff changeset
696 return wide_int_to_tree (ptr_type_node, wi::min_value (prec, SIGNED));
kono
parents:
diff changeset
697 }
kono
parents:
diff changeset
698
kono
parents:
diff changeset
699 /* If we check bounds for a hard register variable, we cannot
kono
parents:
diff changeset
700 use its address - it is illegal, so instead of that we use
kono
parents:
diff changeset
701 this fake value. */
kono
parents:
diff changeset
702 static tree
kono
parents:
diff changeset
703 chkp_get_hard_register_fake_addr_expr (tree obj)
kono
parents:
diff changeset
704 {
kono
parents:
diff changeset
705 tree addr = chkp_get_hard_register_var_fake_base_address ();
kono
parents:
diff changeset
706 tree outer = obj;
kono
parents:
diff changeset
707 while (TREE_CODE (outer) == COMPONENT_REF || TREE_CODE (outer) == ARRAY_REF)
kono
parents:
diff changeset
708 {
kono
parents:
diff changeset
709 if (TREE_CODE (outer) == COMPONENT_REF)
kono
parents:
diff changeset
710 {
kono
parents:
diff changeset
711 addr = fold_build_pointer_plus (addr,
kono
parents:
diff changeset
712 component_ref_field_offset (outer));
kono
parents:
diff changeset
713 outer = TREE_OPERAND (outer, 0);
kono
parents:
diff changeset
714 }
kono
parents:
diff changeset
715 else if (TREE_CODE (outer) == ARRAY_REF)
kono
parents:
diff changeset
716 {
kono
parents:
diff changeset
717 tree indx = fold_convert(size_type_node, TREE_OPERAND(outer, 1));
kono
parents:
diff changeset
718 tree offset = size_binop (MULT_EXPR,
kono
parents:
diff changeset
719 array_ref_element_size (outer), indx);
kono
parents:
diff changeset
720 addr = fold_build_pointer_plus (addr, offset);
kono
parents:
diff changeset
721 outer = TREE_OPERAND (outer, 0);
kono
parents:
diff changeset
722 }
kono
parents:
diff changeset
723 }
kono
parents:
diff changeset
724
kono
parents:
diff changeset
725 return addr;
kono
parents:
diff changeset
726 }
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 /* Mark BOUNDS associated with PTR as incomplete. */
kono
parents:
diff changeset
729 static void
kono
parents:
diff changeset
730 chkp_register_incomplete_bounds (tree bounds, tree ptr)
kono
parents:
diff changeset
731 {
kono
parents:
diff changeset
732 chkp_incomplete_bounds_map->put (bounds, ptr);
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
735 {
kono
parents:
diff changeset
736 fprintf (dump_file, "Regsitered incomplete bounds ");
kono
parents:
diff changeset
737 print_generic_expr (dump_file, bounds);
kono
parents:
diff changeset
738 fprintf (dump_file, " for ");
kono
parents:
diff changeset
739 print_generic_expr (dump_file, ptr);
kono
parents:
diff changeset
740 fprintf (dump_file, "\n");
kono
parents:
diff changeset
741 }
kono
parents:
diff changeset
742 }
kono
parents:
diff changeset
743
kono
parents:
diff changeset
744 /* Return 1 if BOUNDS are incomplete and 0 otherwise. */
kono
parents:
diff changeset
745 static bool
kono
parents:
diff changeset
746 chkp_incomplete_bounds (tree bounds)
kono
parents:
diff changeset
747 {
kono
parents:
diff changeset
748 if (bounds == incomplete_bounds)
kono
parents:
diff changeset
749 return true;
kono
parents:
diff changeset
750
kono
parents:
diff changeset
751 if (chkp_completed_bounds (bounds))
kono
parents:
diff changeset
752 return false;
kono
parents:
diff changeset
753
kono
parents:
diff changeset
754 return chkp_incomplete_bounds_map->get (bounds) != NULL;
kono
parents:
diff changeset
755 }
kono
parents:
diff changeset
756
kono
parents:
diff changeset
757 /* Clear incomleted bound marks. */
kono
parents:
diff changeset
758 static void
kono
parents:
diff changeset
759 chkp_erase_incomplete_bounds (void)
kono
parents:
diff changeset
760 {
kono
parents:
diff changeset
761 delete chkp_incomplete_bounds_map;
kono
parents:
diff changeset
762 chkp_incomplete_bounds_map = new hash_map<tree, tree>;
kono
parents:
diff changeset
763 }
kono
parents:
diff changeset
764
kono
parents:
diff changeset
765 /* Build and return bndmk call which creates bounds for structure
kono
parents:
diff changeset
766 pointed by PTR. Structure should have complete type. */
kono
parents:
diff changeset
767 tree
kono
parents:
diff changeset
768 chkp_make_bounds_for_struct_addr (tree ptr)
kono
parents:
diff changeset
769 {
kono
parents:
diff changeset
770 tree type = TREE_TYPE (ptr);
kono
parents:
diff changeset
771 tree size;
kono
parents:
diff changeset
772
kono
parents:
diff changeset
773 gcc_assert (POINTER_TYPE_P (type));
kono
parents:
diff changeset
774
kono
parents:
diff changeset
775 size = TYPE_SIZE (TREE_TYPE (type));
kono
parents:
diff changeset
776
kono
parents:
diff changeset
777 gcc_assert (size);
kono
parents:
diff changeset
778
kono
parents:
diff changeset
779 return build_call_nary (pointer_bounds_type_node,
kono
parents:
diff changeset
780 build_fold_addr_expr (chkp_bndmk_fndecl),
kono
parents:
diff changeset
781 2, ptr, size);
kono
parents:
diff changeset
782 }
kono
parents:
diff changeset
783
kono
parents:
diff changeset
784 /* Traversal function for chkp_may_finish_incomplete_bounds.
kono
parents:
diff changeset
785 Set RES to 0 if at least one argument of phi statement
kono
parents:
diff changeset
786 defining bounds (passed in KEY arg) is unknown.
kono
parents:
diff changeset
787 Traversal stops when first unknown phi argument is found. */
kono
parents:
diff changeset
788 bool
kono
parents:
diff changeset
789 chkp_may_complete_phi_bounds (tree const &bounds, tree *slot ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
790 bool *res)
kono
parents:
diff changeset
791 {
kono
parents:
diff changeset
792 gimple *phi;
kono
parents:
diff changeset
793 unsigned i;
kono
parents:
diff changeset
794
kono
parents:
diff changeset
795 gcc_assert (TREE_CODE (bounds) == SSA_NAME);
kono
parents:
diff changeset
796
kono
parents:
diff changeset
797 phi = SSA_NAME_DEF_STMT (bounds);
kono
parents:
diff changeset
798
kono
parents:
diff changeset
799 gcc_assert (phi && gimple_code (phi) == GIMPLE_PHI);
kono
parents:
diff changeset
800
kono
parents:
diff changeset
801 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
802 {
kono
parents:
diff changeset
803 tree phi_arg = gimple_phi_arg_def (phi, i);
kono
parents:
diff changeset
804 if (!phi_arg)
kono
parents:
diff changeset
805 {
kono
parents:
diff changeset
806 *res = false;
kono
parents:
diff changeset
807 /* Do not need to traverse further. */
kono
parents:
diff changeset
808 return false;
kono
parents:
diff changeset
809 }
kono
parents:
diff changeset
810 }
kono
parents:
diff changeset
811
kono
parents:
diff changeset
812 return true;
kono
parents:
diff changeset
813 }
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 /* Return 1 if all phi nodes created for bounds have their
kono
parents:
diff changeset
816 arguments computed. */
kono
parents:
diff changeset
817 static bool
kono
parents:
diff changeset
818 chkp_may_finish_incomplete_bounds (void)
kono
parents:
diff changeset
819 {
kono
parents:
diff changeset
820 bool res = true;
kono
parents:
diff changeset
821
kono
parents:
diff changeset
822 chkp_incomplete_bounds_map
kono
parents:
diff changeset
823 ->traverse<bool *, chkp_may_complete_phi_bounds> (&res);
kono
parents:
diff changeset
824
kono
parents:
diff changeset
825 return res;
kono
parents:
diff changeset
826 }
kono
parents:
diff changeset
827
kono
parents:
diff changeset
828 /* Helper function for chkp_finish_incomplete_bounds.
kono
parents:
diff changeset
829 Recompute args for bounds phi node. */
kono
parents:
diff changeset
830 bool
kono
parents:
diff changeset
831 chkp_recompute_phi_bounds (tree const &bounds, tree *slot,
kono
parents:
diff changeset
832 void *res ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
833 {
kono
parents:
diff changeset
834 tree ptr = *slot;
kono
parents:
diff changeset
835 gphi *bounds_phi;
kono
parents:
diff changeset
836 gphi *ptr_phi;
kono
parents:
diff changeset
837 unsigned i;
kono
parents:
diff changeset
838
kono
parents:
diff changeset
839 gcc_assert (TREE_CODE (bounds) == SSA_NAME);
kono
parents:
diff changeset
840 gcc_assert (TREE_CODE (ptr) == SSA_NAME);
kono
parents:
diff changeset
841
kono
parents:
diff changeset
842 bounds_phi = as_a <gphi *> (SSA_NAME_DEF_STMT (bounds));
kono
parents:
diff changeset
843 ptr_phi = as_a <gphi *> (SSA_NAME_DEF_STMT (ptr));
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 for (i = 0; i < gimple_phi_num_args (bounds_phi); i++)
kono
parents:
diff changeset
846 {
kono
parents:
diff changeset
847 tree ptr_arg = gimple_phi_arg_def (ptr_phi, i);
kono
parents:
diff changeset
848 tree bound_arg = chkp_find_bounds (ptr_arg, NULL);
kono
parents:
diff changeset
849
kono
parents:
diff changeset
850 add_phi_arg (bounds_phi, bound_arg,
kono
parents:
diff changeset
851 gimple_phi_arg_edge (ptr_phi, i),
kono
parents:
diff changeset
852 UNKNOWN_LOCATION);
kono
parents:
diff changeset
853 }
kono
parents:
diff changeset
854
kono
parents:
diff changeset
855 return true;
kono
parents:
diff changeset
856 }
kono
parents:
diff changeset
857
kono
parents:
diff changeset
858 /* Mark BOUNDS as invalid. */
kono
parents:
diff changeset
859 static void
kono
parents:
diff changeset
860 chkp_mark_invalid_bounds (tree bounds)
kono
parents:
diff changeset
861 {
kono
parents:
diff changeset
862 chkp_invalid_bounds->add (bounds);
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
865 {
kono
parents:
diff changeset
866 fprintf (dump_file, "Marked bounds ");
kono
parents:
diff changeset
867 print_generic_expr (dump_file, bounds);
kono
parents:
diff changeset
868 fprintf (dump_file, " as invalid\n");
kono
parents:
diff changeset
869 }
kono
parents:
diff changeset
870 }
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872 /* Return 1 if BOUNDS were marked as invalid and 0 otherwise. */
kono
parents:
diff changeset
873 static bool
kono
parents:
diff changeset
874 chkp_valid_bounds (tree bounds)
kono
parents:
diff changeset
875 {
kono
parents:
diff changeset
876 if (bounds == zero_bounds || bounds == none_bounds)
kono
parents:
diff changeset
877 return false;
kono
parents:
diff changeset
878
kono
parents:
diff changeset
879 return !chkp_invalid_bounds->contains (bounds);
kono
parents:
diff changeset
880 }
kono
parents:
diff changeset
881
kono
parents:
diff changeset
882 /* Helper function for chkp_finish_incomplete_bounds.
kono
parents:
diff changeset
883 Check all arguments of phi nodes trying to find
kono
parents:
diff changeset
884 valid completed bounds. If there is at least one
kono
parents:
diff changeset
885 such arg then bounds produced by phi node are marked
kono
parents:
diff changeset
886 as valid completed bounds and all phi args are
kono
parents:
diff changeset
887 recomputed. */
kono
parents:
diff changeset
888 bool
kono
parents:
diff changeset
889 chkp_find_valid_phi_bounds (tree const &bounds, tree *slot, bool *res)
kono
parents:
diff changeset
890 {
kono
parents:
diff changeset
891 gimple *phi;
kono
parents:
diff changeset
892 unsigned i;
kono
parents:
diff changeset
893
kono
parents:
diff changeset
894 gcc_assert (TREE_CODE (bounds) == SSA_NAME);
kono
parents:
diff changeset
895
kono
parents:
diff changeset
896 if (chkp_completed_bounds (bounds))
kono
parents:
diff changeset
897 return true;
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 phi = SSA_NAME_DEF_STMT (bounds);
kono
parents:
diff changeset
900
kono
parents:
diff changeset
901 gcc_assert (phi && gimple_code (phi) == GIMPLE_PHI);
kono
parents:
diff changeset
902
kono
parents:
diff changeset
903 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
904 {
kono
parents:
diff changeset
905 tree phi_arg = gimple_phi_arg_def (phi, i);
kono
parents:
diff changeset
906
kono
parents:
diff changeset
907 gcc_assert (phi_arg);
kono
parents:
diff changeset
908
kono
parents:
diff changeset
909 if (chkp_valid_bounds (phi_arg) && !chkp_incomplete_bounds (phi_arg))
kono
parents:
diff changeset
910 {
kono
parents:
diff changeset
911 *res = true;
kono
parents:
diff changeset
912 chkp_mark_completed_bounds (bounds);
kono
parents:
diff changeset
913 chkp_recompute_phi_bounds (bounds, slot, NULL);
kono
parents:
diff changeset
914 return true;
kono
parents:
diff changeset
915 }
kono
parents:
diff changeset
916 }
kono
parents:
diff changeset
917
kono
parents:
diff changeset
918 return true;
kono
parents:
diff changeset
919 }
kono
parents:
diff changeset
920
kono
parents:
diff changeset
921 /* Helper function for chkp_finish_incomplete_bounds.
kono
parents:
diff changeset
922 Marks all incompleted bounds as invalid. */
kono
parents:
diff changeset
923 bool
kono
parents:
diff changeset
924 chkp_mark_invalid_bounds_walker (tree const &bounds,
kono
parents:
diff changeset
925 tree *slot ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
926 void *res ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
927 {
kono
parents:
diff changeset
928 if (!chkp_completed_bounds (bounds))
kono
parents:
diff changeset
929 {
kono
parents:
diff changeset
930 chkp_mark_invalid_bounds (bounds);
kono
parents:
diff changeset
931 chkp_mark_completed_bounds (bounds);
kono
parents:
diff changeset
932 }
kono
parents:
diff changeset
933 return true;
kono
parents:
diff changeset
934 }
kono
parents:
diff changeset
935
kono
parents:
diff changeset
936 /* When all bound phi nodes have all their args computed
kono
parents:
diff changeset
937 we have enough info to find valid bounds. We iterate
kono
parents:
diff changeset
938 through all incompleted bounds searching for valid
kono
parents:
diff changeset
939 bounds. Found valid bounds are marked as completed
kono
parents:
diff changeset
940 and all remaining incompleted bounds are recomputed.
kono
parents:
diff changeset
941 Process continues until no new valid bounds may be
kono
parents:
diff changeset
942 found. All remained incompleted bounds are marked as
kono
parents:
diff changeset
943 invalid (i.e. have no valid source of bounds). */
kono
parents:
diff changeset
944 static void
kono
parents:
diff changeset
945 chkp_finish_incomplete_bounds (void)
kono
parents:
diff changeset
946 {
kono
parents:
diff changeset
947 bool found_valid = true;
kono
parents:
diff changeset
948
kono
parents:
diff changeset
949 while (found_valid)
kono
parents:
diff changeset
950 {
kono
parents:
diff changeset
951 found_valid = false;
kono
parents:
diff changeset
952
kono
parents:
diff changeset
953 chkp_incomplete_bounds_map->
kono
parents:
diff changeset
954 traverse<bool *, chkp_find_valid_phi_bounds> (&found_valid);
kono
parents:
diff changeset
955
kono
parents:
diff changeset
956 if (found_valid)
kono
parents:
diff changeset
957 chkp_incomplete_bounds_map->
kono
parents:
diff changeset
958 traverse<void *, chkp_recompute_phi_bounds> (NULL);
kono
parents:
diff changeset
959 }
kono
parents:
diff changeset
960
kono
parents:
diff changeset
961 chkp_incomplete_bounds_map->
kono
parents:
diff changeset
962 traverse<void *, chkp_mark_invalid_bounds_walker> (NULL);
kono
parents:
diff changeset
963 chkp_incomplete_bounds_map->
kono
parents:
diff changeset
964 traverse<void *, chkp_recompute_phi_bounds> (NULL);
kono
parents:
diff changeset
965
kono
parents:
diff changeset
966 chkp_erase_completed_bounds ();
kono
parents:
diff changeset
967 chkp_erase_incomplete_bounds ();
kono
parents:
diff changeset
968 }
kono
parents:
diff changeset
969
kono
parents:
diff changeset
970 /* Return 1 if type TYPE is a pointer type or a
kono
parents:
diff changeset
971 structure having a pointer type as one of its fields.
kono
parents:
diff changeset
972 Otherwise return 0. */
kono
parents:
diff changeset
973 bool
kono
parents:
diff changeset
974 chkp_type_has_pointer (const_tree type)
kono
parents:
diff changeset
975 {
kono
parents:
diff changeset
976 bool res = false;
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 if (BOUNDED_TYPE_P (type))
kono
parents:
diff changeset
979 res = true;
kono
parents:
diff changeset
980 else if (RECORD_OR_UNION_TYPE_P (type))
kono
parents:
diff changeset
981 {
kono
parents:
diff changeset
982 tree field;
kono
parents:
diff changeset
983
kono
parents:
diff changeset
984 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
kono
parents:
diff changeset
985 if (TREE_CODE (field) == FIELD_DECL)
kono
parents:
diff changeset
986 res = res || chkp_type_has_pointer (TREE_TYPE (field));
kono
parents:
diff changeset
987 }
kono
parents:
diff changeset
988 else if (TREE_CODE (type) == ARRAY_TYPE)
kono
parents:
diff changeset
989 res = chkp_type_has_pointer (TREE_TYPE (type));
kono
parents:
diff changeset
990
kono
parents:
diff changeset
991 return res;
kono
parents:
diff changeset
992 }
kono
parents:
diff changeset
993
kono
parents:
diff changeset
994 unsigned
kono
parents:
diff changeset
995 chkp_type_bounds_count (const_tree type)
kono
parents:
diff changeset
996 {
kono
parents:
diff changeset
997 unsigned res = 0;
kono
parents:
diff changeset
998
kono
parents:
diff changeset
999 if (!type)
kono
parents:
diff changeset
1000 res = 0;
kono
parents:
diff changeset
1001 else if (BOUNDED_TYPE_P (type))
kono
parents:
diff changeset
1002 res = 1;
kono
parents:
diff changeset
1003 else if (RECORD_OR_UNION_TYPE_P (type))
kono
parents:
diff changeset
1004 {
kono
parents:
diff changeset
1005 bitmap have_bound;
kono
parents:
diff changeset
1006
kono
parents:
diff changeset
1007 bitmap_obstack_initialize (NULL);
kono
parents:
diff changeset
1008 have_bound = BITMAP_ALLOC (NULL);
kono
parents:
diff changeset
1009 chkp_find_bound_slots (type, have_bound);
kono
parents:
diff changeset
1010 res = bitmap_count_bits (have_bound);
kono
parents:
diff changeset
1011 BITMAP_FREE (have_bound);
kono
parents:
diff changeset
1012 bitmap_obstack_release (NULL);
kono
parents:
diff changeset
1013 }
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 return res;
kono
parents:
diff changeset
1016 }
kono
parents:
diff changeset
1017
kono
parents:
diff changeset
1018 /* Get bounds associated with NODE via
kono
parents:
diff changeset
1019 chkp_set_bounds call. */
kono
parents:
diff changeset
1020 tree
kono
parents:
diff changeset
1021 chkp_get_bounds (tree node)
kono
parents:
diff changeset
1022 {
kono
parents:
diff changeset
1023 tree *slot;
kono
parents:
diff changeset
1024
kono
parents:
diff changeset
1025 if (!chkp_bounds_map)
kono
parents:
diff changeset
1026 return NULL_TREE;
kono
parents:
diff changeset
1027
kono
parents:
diff changeset
1028 slot = chkp_bounds_map->get (node);
kono
parents:
diff changeset
1029 return slot ? *slot : NULL_TREE;
kono
parents:
diff changeset
1030 }
kono
parents:
diff changeset
1031
kono
parents:
diff changeset
1032 /* Associate bounds VAL with NODE. */
kono
parents:
diff changeset
1033 void
kono
parents:
diff changeset
1034 chkp_set_bounds (tree node, tree val)
kono
parents:
diff changeset
1035 {
kono
parents:
diff changeset
1036 if (!chkp_bounds_map)
kono
parents:
diff changeset
1037 chkp_bounds_map = new hash_map<tree, tree>;
kono
parents:
diff changeset
1038
kono
parents:
diff changeset
1039 chkp_bounds_map->put (node, val);
kono
parents:
diff changeset
1040 }
kono
parents:
diff changeset
1041
kono
parents:
diff changeset
1042 /* Check if statically initialized variable VAR require
kono
parents:
diff changeset
1043 static bounds initialization. If VAR is added into
kono
parents:
diff changeset
1044 bounds initlization list then 1 is returned. Otherwise
kono
parents:
diff changeset
1045 return 0. */
kono
parents:
diff changeset
1046 extern bool
kono
parents:
diff changeset
1047 chkp_register_var_initializer (tree var)
kono
parents:
diff changeset
1048 {
kono
parents:
diff changeset
1049 if (!flag_check_pointer_bounds
kono
parents:
diff changeset
1050 || DECL_INITIAL (var) == error_mark_node)
kono
parents:
diff changeset
1051 return false;
kono
parents:
diff changeset
1052
kono
parents:
diff changeset
1053 gcc_assert (VAR_P (var));
kono
parents:
diff changeset
1054 gcc_assert (DECL_INITIAL (var));
kono
parents:
diff changeset
1055
kono
parents:
diff changeset
1056 if (TREE_STATIC (var)
kono
parents:
diff changeset
1057 && chkp_type_has_pointer (TREE_TYPE (var)))
kono
parents:
diff changeset
1058 {
kono
parents:
diff changeset
1059 varpool_node::get_create (var)->need_bounds_init = 1;
kono
parents:
diff changeset
1060 return true;
kono
parents:
diff changeset
1061 }
kono
parents:
diff changeset
1062
kono
parents:
diff changeset
1063 return false;
kono
parents:
diff changeset
1064 }
kono
parents:
diff changeset
1065
kono
parents:
diff changeset
1066 /* Helper function for chkp_finish_file.
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 Add new modification statement (RHS is assigned to LHS)
kono
parents:
diff changeset
1069 into list of static initializer statementes (passed in ARG).
kono
parents:
diff changeset
1070 If statements list becomes too big, emit checker constructor
kono
parents:
diff changeset
1071 and start the new one. */
kono
parents:
diff changeset
1072 static void
kono
parents:
diff changeset
1073 chkp_add_modification_to_stmt_list (tree lhs,
kono
parents:
diff changeset
1074 tree rhs,
kono
parents:
diff changeset
1075 void *arg)
kono
parents:
diff changeset
1076 {
kono
parents:
diff changeset
1077 struct chkp_ctor_stmt_list *stmts = (struct chkp_ctor_stmt_list *)arg;
kono
parents:
diff changeset
1078 tree modify;
kono
parents:
diff changeset
1079
kono
parents:
diff changeset
1080 if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
kono
parents:
diff changeset
1081 rhs = build1 (CONVERT_EXPR, TREE_TYPE (lhs), rhs);
kono
parents:
diff changeset
1082
kono
parents:
diff changeset
1083 modify = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, rhs);
kono
parents:
diff changeset
1084 append_to_statement_list (modify, &stmts->stmts);
kono
parents:
diff changeset
1085
kono
parents:
diff changeset
1086 stmts->avail--;
kono
parents:
diff changeset
1087 }
kono
parents:
diff changeset
1088
kono
parents:
diff changeset
1089 /* Build and return ADDR_EXPR for specified object OBJ. */
kono
parents:
diff changeset
1090 static tree
kono
parents:
diff changeset
1091 chkp_build_addr_expr (tree obj)
kono
parents:
diff changeset
1092 {
kono
parents:
diff changeset
1093 /* We first check whether it is a "hard reg case". */
kono
parents:
diff changeset
1094 tree base = get_base_address (obj);
kono
parents:
diff changeset
1095 if (VAR_P (base) && DECL_HARD_REGISTER (base))
kono
parents:
diff changeset
1096 return chkp_get_hard_register_fake_addr_expr (obj);
kono
parents:
diff changeset
1097
kono
parents:
diff changeset
1098 /* If not - return regular ADDR_EXPR. */
kono
parents:
diff changeset
1099 return TREE_CODE (obj) == TARGET_MEM_REF
kono
parents:
diff changeset
1100 ? tree_mem_ref_addr (ptr_type_node, obj)
kono
parents:
diff changeset
1101 : build_fold_addr_expr (obj);
kono
parents:
diff changeset
1102 }
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 /* Helper function for chkp_finish_file.
kono
parents:
diff changeset
1105 Initialize bound variable BND_VAR with bounds of variable
kono
parents:
diff changeset
1106 VAR to statements list STMTS. If statements list becomes
kono
parents:
diff changeset
1107 too big, emit checker constructor and start the new one. */
kono
parents:
diff changeset
1108 static void
kono
parents:
diff changeset
1109 chkp_output_static_bounds (tree bnd_var, tree var,
kono
parents:
diff changeset
1110 struct chkp_ctor_stmt_list *stmts)
kono
parents:
diff changeset
1111 {
kono
parents:
diff changeset
1112 tree lb, ub, size;
kono
parents:
diff changeset
1113
kono
parents:
diff changeset
1114 if (TREE_CODE (var) == STRING_CST)
kono
parents:
diff changeset
1115 {
kono
parents:
diff changeset
1116 lb = build1 (CONVERT_EXPR, size_type_node, chkp_build_addr_expr (var));
kono
parents:
diff changeset
1117 size = build_int_cst (size_type_node, TREE_STRING_LENGTH (var) - 1);
kono
parents:
diff changeset
1118 }
kono
parents:
diff changeset
1119 else if (DECL_SIZE (var)
kono
parents:
diff changeset
1120 && !chkp_variable_size_type (TREE_TYPE (var)))
kono
parents:
diff changeset
1121 {
kono
parents:
diff changeset
1122 /* Compute bounds using statically known size. */
kono
parents:
diff changeset
1123 lb = build1 (CONVERT_EXPR, size_type_node, chkp_build_addr_expr (var));
kono
parents:
diff changeset
1124 size = size_binop (MINUS_EXPR, DECL_SIZE_UNIT (var), size_one_node);
kono
parents:
diff changeset
1125 }
kono
parents:
diff changeset
1126 else
kono
parents:
diff changeset
1127 {
kono
parents:
diff changeset
1128 /* Compute bounds using dynamic size. */
kono
parents:
diff changeset
1129 tree call;
kono
parents:
diff changeset
1130
kono
parents:
diff changeset
1131 lb = build1 (CONVERT_EXPR, size_type_node, chkp_build_addr_expr (var));
kono
parents:
diff changeset
1132 call = build1 (ADDR_EXPR,
kono
parents:
diff changeset
1133 build_pointer_type (TREE_TYPE (chkp_sizeof_fndecl)),
kono
parents:
diff changeset
1134 chkp_sizeof_fndecl);
kono
parents:
diff changeset
1135 size = build_call_nary (TREE_TYPE (TREE_TYPE (chkp_sizeof_fndecl)),
kono
parents:
diff changeset
1136 call, 1, var);
kono
parents:
diff changeset
1137
kono
parents:
diff changeset
1138 if (flag_chkp_zero_dynamic_size_as_infinite)
kono
parents:
diff changeset
1139 {
kono
parents:
diff changeset
1140 tree max_size, cond;
kono
parents:
diff changeset
1141
kono
parents:
diff changeset
1142 max_size = build2 (MINUS_EXPR, size_type_node, size_zero_node, lb);
kono
parents:
diff changeset
1143 cond = build2 (NE_EXPR, boolean_type_node, size, size_zero_node);
kono
parents:
diff changeset
1144 size = build3 (COND_EXPR, size_type_node, cond, size, max_size);
kono
parents:
diff changeset
1145 }
kono
parents:
diff changeset
1146
kono
parents:
diff changeset
1147 size = size_binop (MINUS_EXPR, size, size_one_node);
kono
parents:
diff changeset
1148 }
kono
parents:
diff changeset
1149
kono
parents:
diff changeset
1150 ub = size_binop (PLUS_EXPR, lb, size);
kono
parents:
diff changeset
1151 stmts->avail -= targetm.chkp_initialize_bounds (bnd_var, lb, ub,
kono
parents:
diff changeset
1152 &stmts->stmts);
kono
parents:
diff changeset
1153 if (stmts->avail <= 0)
kono
parents:
diff changeset
1154 {
kono
parents:
diff changeset
1155 cgraph_build_static_cdtor ('B', stmts->stmts,
kono
parents:
diff changeset
1156 MAX_RESERVED_INIT_PRIORITY + 2);
kono
parents:
diff changeset
1157 stmts->avail = MAX_STMTS_IN_STATIC_CHKP_CTOR;
kono
parents:
diff changeset
1158 stmts->stmts = NULL;
kono
parents:
diff changeset
1159 }
kono
parents:
diff changeset
1160 }
kono
parents:
diff changeset
1161
kono
parents:
diff changeset
1162 /* Return entry block to be used for checker initilization code.
kono
parents:
diff changeset
1163 Create new block if required. */
kono
parents:
diff changeset
1164 static basic_block
kono
parents:
diff changeset
1165 chkp_get_entry_block (void)
kono
parents:
diff changeset
1166 {
kono
parents:
diff changeset
1167 if (!entry_block)
kono
parents:
diff changeset
1168 entry_block
kono
parents:
diff changeset
1169 = split_block_after_labels (ENTRY_BLOCK_PTR_FOR_FN (cfun))->dest;
kono
parents:
diff changeset
1170
kono
parents:
diff changeset
1171 return entry_block;
kono
parents:
diff changeset
1172 }
kono
parents:
diff changeset
1173
kono
parents:
diff changeset
1174 /* Return a bounds var to be used for pointer var PTR_VAR. */
kono
parents:
diff changeset
1175 static tree
kono
parents:
diff changeset
1176 chkp_get_bounds_var (tree ptr_var)
kono
parents:
diff changeset
1177 {
kono
parents:
diff changeset
1178 tree bnd_var;
kono
parents:
diff changeset
1179 tree *slot;
kono
parents:
diff changeset
1180
kono
parents:
diff changeset
1181 slot = chkp_bound_vars->get (ptr_var);
kono
parents:
diff changeset
1182 if (slot)
kono
parents:
diff changeset
1183 bnd_var = *slot;
kono
parents:
diff changeset
1184 else
kono
parents:
diff changeset
1185 {
kono
parents:
diff changeset
1186 bnd_var = create_tmp_reg (pointer_bounds_type_node,
kono
parents:
diff changeset
1187 CHKP_BOUND_TMP_NAME);
kono
parents:
diff changeset
1188 chkp_bound_vars->put (ptr_var, bnd_var);
kono
parents:
diff changeset
1189 }
kono
parents:
diff changeset
1190
kono
parents:
diff changeset
1191 return bnd_var;
kono
parents:
diff changeset
1192 }
kono
parents:
diff changeset
1193
kono
parents:
diff changeset
1194 /* If BND is an abnormal bounds copy, return a copied value.
kono
parents:
diff changeset
1195 Otherwise return BND. */
kono
parents:
diff changeset
1196 static tree
kono
parents:
diff changeset
1197 chkp_get_orginal_bounds_for_abnormal_copy (tree bnd)
kono
parents:
diff changeset
1198 {
kono
parents:
diff changeset
1199 if (bitmap_bit_p (chkp_abnormal_copies, SSA_NAME_VERSION (bnd)))
kono
parents:
diff changeset
1200 {
kono
parents:
diff changeset
1201 gimple *bnd_def = SSA_NAME_DEF_STMT (bnd);
kono
parents:
diff changeset
1202 gcc_checking_assert (gimple_code (bnd_def) == GIMPLE_ASSIGN);
kono
parents:
diff changeset
1203 bnd = gimple_assign_rhs1 (bnd_def);
kono
parents:
diff changeset
1204 }
kono
parents:
diff changeset
1205
kono
parents:
diff changeset
1206 return bnd;
kono
parents:
diff changeset
1207 }
kono
parents:
diff changeset
1208
kono
parents:
diff changeset
1209 /* Register bounds BND for object PTR in global bounds table.
kono
parents:
diff changeset
1210 A copy of bounds may be created for abnormal ssa names.
kono
parents:
diff changeset
1211 Returns bounds to use for PTR. */
kono
parents:
diff changeset
1212 static tree
kono
parents:
diff changeset
1213 chkp_maybe_copy_and_register_bounds (tree ptr, tree bnd)
kono
parents:
diff changeset
1214 {
kono
parents:
diff changeset
1215 bool abnormal_ptr;
kono
parents:
diff changeset
1216
kono
parents:
diff changeset
1217 if (!chkp_reg_bounds)
kono
parents:
diff changeset
1218 return bnd;
kono
parents:
diff changeset
1219
kono
parents:
diff changeset
1220 /* Do nothing if bounds are incomplete_bounds
kono
parents:
diff changeset
1221 because it means bounds will be recomputed. */
kono
parents:
diff changeset
1222 if (bnd == incomplete_bounds)
kono
parents:
diff changeset
1223 return bnd;
kono
parents:
diff changeset
1224
kono
parents:
diff changeset
1225 abnormal_ptr = (TREE_CODE (ptr) == SSA_NAME
kono
parents:
diff changeset
1226 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ptr)
kono
parents:
diff changeset
1227 && gimple_code (SSA_NAME_DEF_STMT (ptr)) != GIMPLE_PHI);
kono
parents:
diff changeset
1228
kono
parents:
diff changeset
1229 /* A single bounds value may be reused multiple times for
kono
parents:
diff changeset
1230 different pointer values. It may cause coalescing issues
kono
parents:
diff changeset
1231 for abnormal SSA names. To avoid it we create a bounds
kono
parents:
diff changeset
1232 copy in case it is computed for abnormal SSA name.
kono
parents:
diff changeset
1233
kono
parents:
diff changeset
1234 We also cannot reuse such created copies for other pointers */
kono
parents:
diff changeset
1235 if (abnormal_ptr
kono
parents:
diff changeset
1236 || bitmap_bit_p (chkp_abnormal_copies, SSA_NAME_VERSION (bnd)))
kono
parents:
diff changeset
1237 {
kono
parents:
diff changeset
1238 tree bnd_var = NULL_TREE;
kono
parents:
diff changeset
1239
kono
parents:
diff changeset
1240 if (abnormal_ptr)
kono
parents:
diff changeset
1241 {
kono
parents:
diff changeset
1242 if (SSA_NAME_VAR (ptr))
kono
parents:
diff changeset
1243 bnd_var = chkp_get_bounds_var (SSA_NAME_VAR (ptr));
kono
parents:
diff changeset
1244 }
kono
parents:
diff changeset
1245 else
kono
parents:
diff changeset
1246 bnd_var = chkp_get_tmp_var ();
kono
parents:
diff changeset
1247
kono
parents:
diff changeset
1248 /* For abnormal copies we may just find original
kono
parents:
diff changeset
1249 bounds and use them. */
kono
parents:
diff changeset
1250 if (!abnormal_ptr && !SSA_NAME_IS_DEFAULT_DEF (bnd))
kono
parents:
diff changeset
1251 bnd = chkp_get_orginal_bounds_for_abnormal_copy (bnd);
kono
parents:
diff changeset
1252 /* For undefined values we usually use none bounds
kono
parents:
diff changeset
1253 value but in case of abnormal edge it may cause
kono
parents:
diff changeset
1254 coalescing failures. Use default definition of
kono
parents:
diff changeset
1255 bounds variable instead to avoid it. */
kono
parents:
diff changeset
1256 else if (SSA_NAME_IS_DEFAULT_DEF (ptr)
kono
parents:
diff changeset
1257 && TREE_CODE (SSA_NAME_VAR (ptr)) != PARM_DECL)
kono
parents:
diff changeset
1258 {
kono
parents:
diff changeset
1259 bnd = get_or_create_ssa_default_def (cfun, bnd_var);
kono
parents:
diff changeset
1260
kono
parents:
diff changeset
1261 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1262 {
kono
parents:
diff changeset
1263 fprintf (dump_file, "Using default def bounds ");
kono
parents:
diff changeset
1264 print_generic_expr (dump_file, bnd);
kono
parents:
diff changeset
1265 fprintf (dump_file, " for abnormal default def SSA name ");
kono
parents:
diff changeset
1266 print_generic_expr (dump_file, ptr);
kono
parents:
diff changeset
1267 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1268 }
kono
parents:
diff changeset
1269 }
kono
parents:
diff changeset
1270 else
kono
parents:
diff changeset
1271 {
kono
parents:
diff changeset
1272 tree copy;
kono
parents:
diff changeset
1273 gimple *def = SSA_NAME_DEF_STMT (ptr);
kono
parents:
diff changeset
1274 gimple *assign;
kono
parents:
diff changeset
1275 gimple_stmt_iterator gsi;
kono
parents:
diff changeset
1276
kono
parents:
diff changeset
1277 if (bnd_var)
kono
parents:
diff changeset
1278 copy = make_ssa_name (bnd_var);
kono
parents:
diff changeset
1279 else
kono
parents:
diff changeset
1280 copy = make_temp_ssa_name (pointer_bounds_type_node,
kono
parents:
diff changeset
1281 NULL,
kono
parents:
diff changeset
1282 CHKP_BOUND_TMP_NAME);
kono
parents:
diff changeset
1283 bnd = chkp_get_orginal_bounds_for_abnormal_copy (bnd);
kono
parents:
diff changeset
1284 assign = gimple_build_assign (copy, bnd);
kono
parents:
diff changeset
1285
kono
parents:
diff changeset
1286 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1287 {
kono
parents:
diff changeset
1288 fprintf (dump_file, "Creating a copy of bounds ");
kono
parents:
diff changeset
1289 print_generic_expr (dump_file, bnd);
kono
parents:
diff changeset
1290 fprintf (dump_file, " for abnormal SSA name ");
kono
parents:
diff changeset
1291 print_generic_expr (dump_file, ptr);
kono
parents:
diff changeset
1292 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1293 }
kono
parents:
diff changeset
1294
kono
parents:
diff changeset
1295 if (gimple_code (def) == GIMPLE_NOP)
kono
parents:
diff changeset
1296 {
kono
parents:
diff changeset
1297 gsi = gsi_last_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
1298 if (!gsi_end_p (gsi) && is_ctrl_stmt (gsi_stmt (gsi)))
kono
parents:
diff changeset
1299 gsi_insert_before (&gsi, assign, GSI_CONTINUE_LINKING);
kono
parents:
diff changeset
1300 else
kono
parents:
diff changeset
1301 gsi_insert_after (&gsi, assign, GSI_CONTINUE_LINKING);
kono
parents:
diff changeset
1302 }
kono
parents:
diff changeset
1303 else
kono
parents:
diff changeset
1304 {
kono
parents:
diff changeset
1305 gimple *bnd_def = SSA_NAME_DEF_STMT (bnd);
kono
parents:
diff changeset
1306 /* Sometimes (e.g. when we load a pointer from a
kono
parents:
diff changeset
1307 memory) bounds are produced later than a pointer.
kono
parents:
diff changeset
1308 We need to insert bounds copy appropriately. */
kono
parents:
diff changeset
1309 if (gimple_code (bnd_def) != GIMPLE_NOP
kono
parents:
diff changeset
1310 && stmt_dominates_stmt_p (def, bnd_def))
kono
parents:
diff changeset
1311 gsi = gsi_for_stmt (bnd_def);
kono
parents:
diff changeset
1312 else
kono
parents:
diff changeset
1313 gsi = gsi_for_stmt (def);
kono
parents:
diff changeset
1314 gsi_insert_after (&gsi, assign, GSI_CONTINUE_LINKING);
kono
parents:
diff changeset
1315 }
kono
parents:
diff changeset
1316
kono
parents:
diff changeset
1317 bnd = copy;
kono
parents:
diff changeset
1318 }
kono
parents:
diff changeset
1319
kono
parents:
diff changeset
1320 if (abnormal_ptr)
kono
parents:
diff changeset
1321 bitmap_set_bit (chkp_abnormal_copies, SSA_NAME_VERSION (bnd));
kono
parents:
diff changeset
1322 }
kono
parents:
diff changeset
1323
kono
parents:
diff changeset
1324 chkp_reg_bounds->put (ptr, bnd);
kono
parents:
diff changeset
1325
kono
parents:
diff changeset
1326 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1327 {
kono
parents:
diff changeset
1328 fprintf (dump_file, "Regsitered bound ");
kono
parents:
diff changeset
1329 print_generic_expr (dump_file, bnd);
kono
parents:
diff changeset
1330 fprintf (dump_file, " for pointer ");
kono
parents:
diff changeset
1331 print_generic_expr (dump_file, ptr);
kono
parents:
diff changeset
1332 fprintf (dump_file, "\n");
kono
parents:
diff changeset
1333 }
kono
parents:
diff changeset
1334
kono
parents:
diff changeset
1335 return bnd;
kono
parents:
diff changeset
1336 }
kono
parents:
diff changeset
1337
kono
parents:
diff changeset
1338 /* Get bounds registered for object PTR in global bounds table. */
kono
parents:
diff changeset
1339 static tree
kono
parents:
diff changeset
1340 chkp_get_registered_bounds (tree ptr)
kono
parents:
diff changeset
1341 {
kono
parents:
diff changeset
1342 tree *slot;
kono
parents:
diff changeset
1343
kono
parents:
diff changeset
1344 if (!chkp_reg_bounds)
kono
parents:
diff changeset
1345 return NULL_TREE;
kono
parents:
diff changeset
1346
kono
parents:
diff changeset
1347 slot = chkp_reg_bounds->get (ptr);
kono
parents:
diff changeset
1348 return slot ? *slot : NULL_TREE;
kono
parents:
diff changeset
1349 }
kono
parents:
diff changeset
1350
kono
parents:
diff changeset
1351 /* Add bound retvals to return statement pointed by GSI. */
kono
parents:
diff changeset
1352
kono
parents:
diff changeset
1353 static void
kono
parents:
diff changeset
1354 chkp_add_bounds_to_ret_stmt (gimple_stmt_iterator *gsi)
kono
parents:
diff changeset
1355 {
kono
parents:
diff changeset
1356 greturn *ret = as_a <greturn *> (gsi_stmt (*gsi));
kono
parents:
diff changeset
1357 tree retval = gimple_return_retval (ret);
kono
parents:
diff changeset
1358 tree ret_decl = DECL_RESULT (cfun->decl);
kono
parents:
diff changeset
1359 tree bounds;
kono
parents:
diff changeset
1360
kono
parents:
diff changeset
1361 if (!retval)
kono
parents:
diff changeset
1362 return;
kono
parents:
diff changeset
1363
kono
parents:
diff changeset
1364 if (BOUNDED_P (ret_decl))
kono
parents:
diff changeset
1365 {
kono
parents:
diff changeset
1366 bounds = chkp_find_bounds (retval, gsi);
kono
parents:
diff changeset
1367 bounds = chkp_maybe_copy_and_register_bounds (ret_decl, bounds);
kono
parents:
diff changeset
1368 gimple_return_set_retbnd (ret, bounds);
kono
parents:
diff changeset
1369 }
kono
parents:
diff changeset
1370
kono
parents:
diff changeset
1371 update_stmt (ret);
kono
parents:
diff changeset
1372 }
kono
parents:
diff changeset
1373
kono
parents:
diff changeset
1374 /* Force OP to be suitable for using as an argument for call.
kono
parents:
diff changeset
1375 New statements (if any) go to SEQ. */
kono
parents:
diff changeset
1376 static tree
kono
parents:
diff changeset
1377 chkp_force_gimple_call_op (tree op, gimple_seq *seq)
kono
parents:
diff changeset
1378 {
kono
parents:
diff changeset
1379 gimple_seq stmts;
kono
parents:
diff changeset
1380 gimple_stmt_iterator si;
kono
parents:
diff changeset
1381
kono
parents:
diff changeset
1382 op = force_gimple_operand (unshare_expr (op), &stmts, true, NULL_TREE);
kono
parents:
diff changeset
1383
kono
parents:
diff changeset
1384 for (si = gsi_start (stmts); !gsi_end_p (si); gsi_next (&si))
kono
parents:
diff changeset
1385 chkp_mark_stmt (gsi_stmt (si));
kono
parents:
diff changeset
1386
kono
parents:
diff changeset
1387 gimple_seq_add_seq (seq, stmts);
kono
parents:
diff changeset
1388
kono
parents:
diff changeset
1389 return op;
kono
parents:
diff changeset
1390 }
kono
parents:
diff changeset
1391
kono
parents:
diff changeset
1392 /* Generate lower bound check for memory access by ADDR.
kono
parents:
diff changeset
1393 Check is inserted before the position pointed by ITER.
kono
parents:
diff changeset
1394 DIRFLAG indicates whether memory access is load or store. */
kono
parents:
diff changeset
1395 static void
kono
parents:
diff changeset
1396 chkp_check_lower (tree addr, tree bounds,
kono
parents:
diff changeset
1397 gimple_stmt_iterator iter,
kono
parents:
diff changeset
1398 location_t location,
kono
parents:
diff changeset
1399 tree dirflag)
kono
parents:
diff changeset
1400 {
kono
parents:
diff changeset
1401 gimple_seq seq;
kono
parents:
diff changeset
1402 gimple *check;
kono
parents:
diff changeset
1403 tree node;
kono
parents:
diff changeset
1404
kono
parents:
diff changeset
1405 if (!chkp_function_instrumented_p (current_function_decl)
kono
parents:
diff changeset
1406 && bounds == chkp_get_zero_bounds ())
kono
parents:
diff changeset
1407 return;
kono
parents:
diff changeset
1408
kono
parents:
diff changeset
1409 if (dirflag == integer_zero_node
kono
parents:
diff changeset
1410 && !flag_chkp_check_read)
kono
parents:
diff changeset
1411 return;
kono
parents:
diff changeset
1412
kono
parents:
diff changeset
1413 if (dirflag == integer_one_node
kono
parents:
diff changeset
1414 && !flag_chkp_check_write)
kono
parents:
diff changeset
1415 return;
kono
parents:
diff changeset
1416
kono
parents:
diff changeset
1417 seq = NULL;
kono
parents:
diff changeset
1418
kono
parents:
diff changeset
1419 node = chkp_force_gimple_call_op (addr, &seq);
kono
parents:
diff changeset
1420
kono
parents:
diff changeset
1421 check = gimple_build_call (chkp_checkl_fndecl, 2, node, bounds);
kono
parents:
diff changeset
1422 chkp_mark_stmt (check);
kono
parents:
diff changeset
1423 gimple_call_set_with_bounds (check, true);
kono
parents:
diff changeset
1424 gimple_set_location (check, location);
kono
parents:
diff changeset
1425 gimple_seq_add_stmt (&seq, check);
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427 gsi_insert_seq_before (&iter, seq, GSI_SAME_STMT);
kono
parents:
diff changeset
1428
kono
parents:
diff changeset
1429 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1430 {
kono
parents:
diff changeset
1431 gimple *before = gsi_stmt (iter);
kono
parents:
diff changeset
1432 fprintf (dump_file, "Generated lower bound check for statement ");
kono
parents:
diff changeset
1433 print_gimple_stmt (dump_file, before, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
1434 fprintf (dump_file, " ");
kono
parents:
diff changeset
1435 print_gimple_stmt (dump_file, check, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
1436 }
kono
parents:
diff changeset
1437 }
kono
parents:
diff changeset
1438
kono
parents:
diff changeset
1439 /* Generate upper bound check for memory access by ADDR.
kono
parents:
diff changeset
1440 Check is inserted before the position pointed by ITER.
kono
parents:
diff changeset
1441 DIRFLAG indicates whether memory access is load or store. */
kono
parents:
diff changeset
1442 static void
kono
parents:
diff changeset
1443 chkp_check_upper (tree addr, tree bounds,
kono
parents:
diff changeset
1444 gimple_stmt_iterator iter,
kono
parents:
diff changeset
1445 location_t location,
kono
parents:
diff changeset
1446 tree dirflag)
kono
parents:
diff changeset
1447 {
kono
parents:
diff changeset
1448 gimple_seq seq;
kono
parents:
diff changeset
1449 gimple *check;
kono
parents:
diff changeset
1450 tree node;
kono
parents:
diff changeset
1451
kono
parents:
diff changeset
1452 if (!chkp_function_instrumented_p (current_function_decl)
kono
parents:
diff changeset
1453 && bounds == chkp_get_zero_bounds ())
kono
parents:
diff changeset
1454 return;
kono
parents:
diff changeset
1455
kono
parents:
diff changeset
1456 if (dirflag == integer_zero_node
kono
parents:
diff changeset
1457 && !flag_chkp_check_read)
kono
parents:
diff changeset
1458 return;
kono
parents:
diff changeset
1459
kono
parents:
diff changeset
1460 if (dirflag == integer_one_node
kono
parents:
diff changeset
1461 && !flag_chkp_check_write)
kono
parents:
diff changeset
1462 return;
kono
parents:
diff changeset
1463
kono
parents:
diff changeset
1464 seq = NULL;
kono
parents:
diff changeset
1465
kono
parents:
diff changeset
1466 node = chkp_force_gimple_call_op (addr, &seq);
kono
parents:
diff changeset
1467
kono
parents:
diff changeset
1468 check = gimple_build_call (chkp_checku_fndecl, 2, node, bounds);
kono
parents:
diff changeset
1469 chkp_mark_stmt (check);
kono
parents:
diff changeset
1470 gimple_call_set_with_bounds (check, true);
kono
parents:
diff changeset
1471 gimple_set_location (check, location);
kono
parents:
diff changeset
1472 gimple_seq_add_stmt (&seq, check);
kono
parents:
diff changeset
1473
kono
parents:
diff changeset
1474 gsi_insert_seq_before (&iter, seq, GSI_SAME_STMT);
kono
parents:
diff changeset
1475
kono
parents:
diff changeset
1476 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1477 {
kono
parents:
diff changeset
1478 gimple *before = gsi_stmt (iter);
kono
parents:
diff changeset
1479 fprintf (dump_file, "Generated upper bound check for statement ");
kono
parents:
diff changeset
1480 print_gimple_stmt (dump_file, before, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
1481 fprintf (dump_file, " ");
kono
parents:
diff changeset
1482 print_gimple_stmt (dump_file, check, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
1483 }
kono
parents:
diff changeset
1484 }
kono
parents:
diff changeset
1485
kono
parents:
diff changeset
1486 /* Generate lower and upper bound checks for memory access
kono
parents:
diff changeset
1487 to memory slot [FIRST, LAST] againsr BOUNDS. Checks
kono
parents:
diff changeset
1488 are inserted before the position pointed by ITER.
kono
parents:
diff changeset
1489 DIRFLAG indicates whether memory access is load or store. */
kono
parents:
diff changeset
1490 void
kono
parents:
diff changeset
1491 chkp_check_mem_access (tree first, tree last, tree bounds,
kono
parents:
diff changeset
1492 gimple_stmt_iterator iter,
kono
parents:
diff changeset
1493 location_t location,
kono
parents:
diff changeset
1494 tree dirflag)
kono
parents:
diff changeset
1495 {
kono
parents:
diff changeset
1496 chkp_check_lower (first, bounds, iter, location, dirflag);
kono
parents:
diff changeset
1497 chkp_check_upper (last, bounds, iter, location, dirflag);
kono
parents:
diff changeset
1498 }
kono
parents:
diff changeset
1499
kono
parents:
diff changeset
1500 /* Replace call to _bnd_chk_* pointed by GSI with
kono
parents:
diff changeset
1501 bndcu and bndcl calls. DIRFLAG determines whether
kono
parents:
diff changeset
1502 check is for read or write. */
kono
parents:
diff changeset
1503
kono
parents:
diff changeset
1504 void
kono
parents:
diff changeset
1505 chkp_replace_address_check_builtin (gimple_stmt_iterator *gsi,
kono
parents:
diff changeset
1506 tree dirflag)
kono
parents:
diff changeset
1507 {
kono
parents:
diff changeset
1508 gimple_stmt_iterator call_iter = *gsi;
kono
parents:
diff changeset
1509 gimple *call = gsi_stmt (*gsi);
kono
parents:
diff changeset
1510 tree fndecl = gimple_call_fndecl (call);
kono
parents:
diff changeset
1511 tree addr = gimple_call_arg (call, 0);
kono
parents:
diff changeset
1512 tree bounds = chkp_find_bounds (addr, gsi);
kono
parents:
diff changeset
1513
kono
parents:
diff changeset
1514 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_LBOUNDS
kono
parents:
diff changeset
1515 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_BOUNDS)
kono
parents:
diff changeset
1516 chkp_check_lower (addr, bounds, *gsi, gimple_location (call), dirflag);
kono
parents:
diff changeset
1517
kono
parents:
diff changeset
1518 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_UBOUNDS)
kono
parents:
diff changeset
1519 chkp_check_upper (addr, bounds, *gsi, gimple_location (call), dirflag);
kono
parents:
diff changeset
1520
kono
parents:
diff changeset
1521 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_BOUNDS)
kono
parents:
diff changeset
1522 {
kono
parents:
diff changeset
1523 tree size = gimple_call_arg (call, 1);
kono
parents:
diff changeset
1524 addr = fold_build_pointer_plus (addr, size);
kono
parents:
diff changeset
1525 addr = fold_build_pointer_plus_hwi (addr, -1);
kono
parents:
diff changeset
1526 chkp_check_upper (addr, bounds, *gsi, gimple_location (call), dirflag);
kono
parents:
diff changeset
1527 }
kono
parents:
diff changeset
1528
kono
parents:
diff changeset
1529 gsi_remove (&call_iter, true);
kono
parents:
diff changeset
1530 }
kono
parents:
diff changeset
1531
kono
parents:
diff changeset
1532 /* Replace call to _bnd_get_ptr_* pointed by GSI with
kono
parents:
diff changeset
1533 corresponding bounds extract call. */
kono
parents:
diff changeset
1534
kono
parents:
diff changeset
1535 void
kono
parents:
diff changeset
1536 chkp_replace_extract_builtin (gimple_stmt_iterator *gsi)
kono
parents:
diff changeset
1537 {
kono
parents:
diff changeset
1538 gimple *call = gsi_stmt (*gsi);
kono
parents:
diff changeset
1539 tree fndecl = gimple_call_fndecl (call);
kono
parents:
diff changeset
1540 tree addr = gimple_call_arg (call, 0);
kono
parents:
diff changeset
1541 tree bounds = chkp_find_bounds (addr, gsi);
kono
parents:
diff changeset
1542 gimple *extract;
kono
parents:
diff changeset
1543
kono
parents:
diff changeset
1544 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_GET_PTR_LBOUND)
kono
parents:
diff changeset
1545 fndecl = chkp_extract_lower_fndecl;
kono
parents:
diff changeset
1546 else if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_GET_PTR_UBOUND)
kono
parents:
diff changeset
1547 fndecl = chkp_extract_upper_fndecl;
kono
parents:
diff changeset
1548 else
kono
parents:
diff changeset
1549 gcc_unreachable ();
kono
parents:
diff changeset
1550
kono
parents:
diff changeset
1551 extract = gimple_build_call (fndecl, 1, bounds);
kono
parents:
diff changeset
1552 gimple_call_set_lhs (extract, gimple_call_lhs (call));
kono
parents:
diff changeset
1553 chkp_mark_stmt (extract);
kono
parents:
diff changeset
1554
kono
parents:
diff changeset
1555 gsi_replace (gsi, extract, false);
kono
parents:
diff changeset
1556 }
kono
parents:
diff changeset
1557
kono
parents:
diff changeset
1558 /* Return COMPONENT_REF accessing FIELD in OBJ. */
kono
parents:
diff changeset
1559 static tree
kono
parents:
diff changeset
1560 chkp_build_component_ref (tree obj, tree field)
kono
parents:
diff changeset
1561 {
kono
parents:
diff changeset
1562 tree res;
kono
parents:
diff changeset
1563
kono
parents:
diff changeset
1564 /* If object is TMR then we do not use component_ref but
kono
parents:
diff changeset
1565 add offset instead. We need it to be able to get addr
kono
parents:
diff changeset
1566 of the reasult later. */
kono
parents:
diff changeset
1567 if (TREE_CODE (obj) == TARGET_MEM_REF)
kono
parents:
diff changeset
1568 {
kono
parents:
diff changeset
1569 tree offs = TMR_OFFSET (obj);
kono
parents:
diff changeset
1570 offs = fold_binary_to_constant (PLUS_EXPR, TREE_TYPE (offs),
kono
parents:
diff changeset
1571 offs, DECL_FIELD_OFFSET (field));
kono
parents:
diff changeset
1572
kono
parents:
diff changeset
1573 gcc_assert (offs);
kono
parents:
diff changeset
1574
kono
parents:
diff changeset
1575 res = copy_node (obj);
kono
parents:
diff changeset
1576 TREE_TYPE (res) = TREE_TYPE (field);
kono
parents:
diff changeset
1577 TMR_OFFSET (res) = offs;
kono
parents:
diff changeset
1578 }
kono
parents:
diff changeset
1579 else
kono
parents:
diff changeset
1580 res = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL_TREE);
kono
parents:
diff changeset
1581
kono
parents:
diff changeset
1582 return res;
kono
parents:
diff changeset
1583 }
kono
parents:
diff changeset
1584
kono
parents:
diff changeset
1585 /* Return ARRAY_REF for array ARR and index IDX with
kono
parents:
diff changeset
1586 specified element type ETYPE and element size ESIZE. */
kono
parents:
diff changeset
1587 static tree
kono
parents:
diff changeset
1588 chkp_build_array_ref (tree arr, tree etype, tree esize,
kono
parents:
diff changeset
1589 unsigned HOST_WIDE_INT idx)
kono
parents:
diff changeset
1590 {
kono
parents:
diff changeset
1591 tree index = build_int_cst (size_type_node, idx);
kono
parents:
diff changeset
1592 tree res;
kono
parents:
diff changeset
1593
kono
parents:
diff changeset
1594 /* If object is TMR then we do not use array_ref but
kono
parents:
diff changeset
1595 add offset instead. We need it to be able to get addr
kono
parents:
diff changeset
1596 of the reasult later. */
kono
parents:
diff changeset
1597 if (TREE_CODE (arr) == TARGET_MEM_REF)
kono
parents:
diff changeset
1598 {
kono
parents:
diff changeset
1599 tree offs = TMR_OFFSET (arr);
kono
parents:
diff changeset
1600
kono
parents:
diff changeset
1601 esize = fold_binary_to_constant (MULT_EXPR, TREE_TYPE (esize),
kono
parents:
diff changeset
1602 esize, index);
kono
parents:
diff changeset
1603 gcc_assert(esize);
kono
parents:
diff changeset
1604
kono
parents:
diff changeset
1605 offs = fold_binary_to_constant (PLUS_EXPR, TREE_TYPE (offs),
kono
parents:
diff changeset
1606 offs, esize);
kono
parents:
diff changeset
1607 gcc_assert (offs);
kono
parents:
diff changeset
1608
kono
parents:
diff changeset
1609 res = copy_node (arr);
kono
parents:
diff changeset
1610 TREE_TYPE (res) = etype;
kono
parents:
diff changeset
1611 TMR_OFFSET (res) = offs;
kono
parents:
diff changeset
1612 }
kono
parents:
diff changeset
1613 else
kono
parents:
diff changeset
1614 res = build4 (ARRAY_REF, etype, arr, index, NULL_TREE, NULL_TREE);
kono
parents:
diff changeset
1615
kono
parents:
diff changeset
1616 return res;
kono
parents:
diff changeset
1617 }
kono
parents:
diff changeset
1618
kono
parents:
diff changeset
1619 /* Helper function for chkp_add_bounds_to_call_stmt.
kono
parents:
diff changeset
1620 Fill ALL_BOUNDS output array with created bounds.
kono
parents:
diff changeset
1621
kono
parents:
diff changeset
1622 OFFS is used for recursive calls and holds basic
kono
parents:
diff changeset
1623 offset of TYPE in outer structure in bits.
kono
parents:
diff changeset
1624
kono
parents:
diff changeset
1625 ITER points a position where bounds are searched.
kono
parents:
diff changeset
1626
kono
parents:
diff changeset
1627 ALL_BOUNDS[i] is filled with elem bounds if there
kono
parents:
diff changeset
1628 is a field in TYPE which has pointer type and offset
kono
parents:
diff changeset
1629 equal to i * POINTER_SIZE in bits. */
kono
parents:
diff changeset
1630 static void
kono
parents:
diff changeset
1631 chkp_find_bounds_for_elem (tree elem, tree *all_bounds,
kono
parents:
diff changeset
1632 HOST_WIDE_INT offs,
kono
parents:
diff changeset
1633 gimple_stmt_iterator *iter)
kono
parents:
diff changeset
1634 {
kono
parents:
diff changeset
1635 tree type = TREE_TYPE (elem);
kono
parents:
diff changeset
1636
kono
parents:
diff changeset
1637 if (BOUNDED_TYPE_P (type))
kono
parents:
diff changeset
1638 {
kono
parents:
diff changeset
1639 if (!all_bounds[offs / POINTER_SIZE])
kono
parents:
diff changeset
1640 {
kono
parents:
diff changeset
1641 tree temp = make_temp_ssa_name (type, NULL, "");
kono
parents:
diff changeset
1642 gimple *assign = gimple_build_assign (temp, elem);
kono
parents:
diff changeset
1643 gimple_stmt_iterator gsi;
kono
parents:
diff changeset
1644
kono
parents:
diff changeset
1645 gsi_insert_before (iter, assign, GSI_SAME_STMT);
kono
parents:
diff changeset
1646 gsi = gsi_for_stmt (assign);
kono
parents:
diff changeset
1647
kono
parents:
diff changeset
1648 all_bounds[offs / POINTER_SIZE] = chkp_find_bounds (temp, &gsi);
kono
parents:
diff changeset
1649 }
kono
parents:
diff changeset
1650 }
kono
parents:
diff changeset
1651 else if (RECORD_OR_UNION_TYPE_P (type))
kono
parents:
diff changeset
1652 {
kono
parents:
diff changeset
1653 tree field;
kono
parents:
diff changeset
1654
kono
parents:
diff changeset
1655 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
kono
parents:
diff changeset
1656 if (TREE_CODE (field) == FIELD_DECL)
kono
parents:
diff changeset
1657 {
kono
parents:
diff changeset
1658 tree base = unshare_expr (elem);
kono
parents:
diff changeset
1659 tree field_ref = chkp_build_component_ref (base, field);
kono
parents:
diff changeset
1660 HOST_WIDE_INT field_offs
kono
parents:
diff changeset
1661 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
kono
parents:
diff changeset
1662 if (DECL_FIELD_OFFSET (field))
kono
parents:
diff changeset
1663 field_offs += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field)) * 8;
kono
parents:
diff changeset
1664
kono
parents:
diff changeset
1665 chkp_find_bounds_for_elem (field_ref, all_bounds,
kono
parents:
diff changeset
1666 offs + field_offs, iter);
kono
parents:
diff changeset
1667 }
kono
parents:
diff changeset
1668 }
kono
parents:
diff changeset
1669 else if (TREE_CODE (type) == ARRAY_TYPE)
kono
parents:
diff changeset
1670 {
kono
parents:
diff changeset
1671 tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
kono
parents:
diff changeset
1672 tree etype = TREE_TYPE (type);
kono
parents:
diff changeset
1673 HOST_WIDE_INT esize = TREE_INT_CST_LOW (TYPE_SIZE (etype));
kono
parents:
diff changeset
1674 unsigned HOST_WIDE_INT cur;
kono
parents:
diff changeset
1675
kono
parents:
diff changeset
1676 if (!maxval || integer_minus_onep (maxval))
kono
parents:
diff changeset
1677 return;
kono
parents:
diff changeset
1678
kono
parents:
diff changeset
1679 for (cur = 0; cur <= TREE_INT_CST_LOW (maxval); cur++)
kono
parents:
diff changeset
1680 {
kono
parents:
diff changeset
1681 tree base = unshare_expr (elem);
kono
parents:
diff changeset
1682 tree arr_elem = chkp_build_array_ref (base, etype,
kono
parents:
diff changeset
1683 TYPE_SIZE (etype),
kono
parents:
diff changeset
1684 cur);
kono
parents:
diff changeset
1685 chkp_find_bounds_for_elem (arr_elem, all_bounds, offs + cur * esize,
kono
parents:
diff changeset
1686 iter);
kono
parents:
diff changeset
1687 }
kono
parents:
diff changeset
1688 }
kono
parents:
diff changeset
1689 }
kono
parents:
diff changeset
1690
kono
parents:
diff changeset
1691 /* Fill HAVE_BOUND output bitmap with information about
kono
parents:
diff changeset
1692 bounds requred for object of type TYPE.
kono
parents:
diff changeset
1693
kono
parents:
diff changeset
1694 OFFS is used for recursive calls and holds basic
kono
parents:
diff changeset
1695 offset of TYPE in outer structure in bits.
kono
parents:
diff changeset
1696
kono
parents:
diff changeset
1697 HAVE_BOUND[i] is set to 1 if there is a field
kono
parents:
diff changeset
1698 in TYPE which has pointer type and offset
kono
parents:
diff changeset
1699 equal to i * POINTER_SIZE - OFFS in bits. */
kono
parents:
diff changeset
1700 void
kono
parents:
diff changeset
1701 chkp_find_bound_slots_1 (const_tree type, bitmap have_bound,
kono
parents:
diff changeset
1702 HOST_WIDE_INT offs)
kono
parents:
diff changeset
1703 {
kono
parents:
diff changeset
1704 if (BOUNDED_TYPE_P (type))
kono
parents:
diff changeset
1705 bitmap_set_bit (have_bound, offs / POINTER_SIZE);
kono
parents:
diff changeset
1706 else if (RECORD_OR_UNION_TYPE_P (type))
kono
parents:
diff changeset
1707 {
kono
parents:
diff changeset
1708 tree field;
kono
parents:
diff changeset
1709
kono
parents:
diff changeset
1710 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
kono
parents:
diff changeset
1711 if (TREE_CODE (field) == FIELD_DECL)
kono
parents:
diff changeset
1712 {
kono
parents:
diff changeset
1713 HOST_WIDE_INT field_offs = 0;
kono
parents:
diff changeset
1714 if (DECL_FIELD_BIT_OFFSET (field))
kono
parents:
diff changeset
1715 field_offs += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
kono
parents:
diff changeset
1716 if (DECL_FIELD_OFFSET (field))
kono
parents:
diff changeset
1717 field_offs += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field)) * 8;
kono
parents:
diff changeset
1718 chkp_find_bound_slots_1 (TREE_TYPE (field), have_bound,
kono
parents:
diff changeset
1719 offs + field_offs);
kono
parents:
diff changeset
1720 }
kono
parents:
diff changeset
1721 }
kono
parents:
diff changeset
1722 else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
kono
parents:
diff changeset
1723 {
kono
parents:
diff changeset
1724 /* The object type is an array of complete type, i.e., other
kono
parents:
diff changeset
1725 than a flexible array. */
kono
parents:
diff changeset
1726 tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
kono
parents:
diff changeset
1727 tree etype = TREE_TYPE (type);
kono
parents:
diff changeset
1728 HOST_WIDE_INT esize = TREE_INT_CST_LOW (TYPE_SIZE (etype));
kono
parents:
diff changeset
1729 unsigned HOST_WIDE_INT cur;
kono
parents:
diff changeset
1730
kono
parents:
diff changeset
1731 if (!maxval
kono
parents:
diff changeset
1732 || TREE_CODE (maxval) != INTEGER_CST
kono
parents:
diff changeset
1733 || integer_minus_onep (maxval))
kono
parents:
diff changeset
1734 return;
kono
parents:
diff changeset
1735
kono
parents:
diff changeset
1736 for (cur = 0; cur <= TREE_INT_CST_LOW (maxval); cur++)
kono
parents:
diff changeset
1737 chkp_find_bound_slots_1 (etype, have_bound, offs + cur * esize);
kono
parents:
diff changeset
1738 }
kono
parents:
diff changeset
1739 }
kono
parents:
diff changeset
1740
kono
parents:
diff changeset
1741 /* Fill bitmap RES with information about bounds for
kono
parents:
diff changeset
1742 type TYPE. See chkp_find_bound_slots_1 for more
kono
parents:
diff changeset
1743 details. */
kono
parents:
diff changeset
1744 void
kono
parents:
diff changeset
1745 chkp_find_bound_slots (const_tree type, bitmap res)
kono
parents:
diff changeset
1746 {
kono
parents:
diff changeset
1747 bitmap_clear (res);
kono
parents:
diff changeset
1748 chkp_find_bound_slots_1 (type, res, 0);
kono
parents:
diff changeset
1749 }
kono
parents:
diff changeset
1750
kono
parents:
diff changeset
1751 /* Return 1 if call to FNDECL should be instrumented
kono
parents:
diff changeset
1752 and 0 otherwise. */
kono
parents:
diff changeset
1753
kono
parents:
diff changeset
1754 static bool
kono
parents:
diff changeset
1755 chkp_instrument_normal_builtin (tree fndecl)
kono
parents:
diff changeset
1756 {
kono
parents:
diff changeset
1757 switch (DECL_FUNCTION_CODE (fndecl))
kono
parents:
diff changeset
1758 {
kono
parents:
diff changeset
1759 case BUILT_IN_STRLEN:
kono
parents:
diff changeset
1760 case BUILT_IN_STRCPY:
kono
parents:
diff changeset
1761 case BUILT_IN_STRNCPY:
kono
parents:
diff changeset
1762 case BUILT_IN_STPCPY:
kono
parents:
diff changeset
1763 case BUILT_IN_STPNCPY:
kono
parents:
diff changeset
1764 case BUILT_IN_STRCAT:
kono
parents:
diff changeset
1765 case BUILT_IN_STRNCAT:
kono
parents:
diff changeset
1766 case BUILT_IN_MEMCPY:
kono
parents:
diff changeset
1767 case BUILT_IN_MEMPCPY:
kono
parents:
diff changeset
1768 case BUILT_IN_MEMSET:
kono
parents:
diff changeset
1769 case BUILT_IN_MEMMOVE:
kono
parents:
diff changeset
1770 case BUILT_IN_BZERO:
kono
parents:
diff changeset
1771 case BUILT_IN_STRCMP:
kono
parents:
diff changeset
1772 case BUILT_IN_STRNCMP:
kono
parents:
diff changeset
1773 case BUILT_IN_BCMP:
kono
parents:
diff changeset
1774 case BUILT_IN_MEMCMP:
kono
parents:
diff changeset
1775 case BUILT_IN_MEMCPY_CHK:
kono
parents:
diff changeset
1776 case BUILT_IN_MEMPCPY_CHK:
kono
parents:
diff changeset
1777 case BUILT_IN_MEMMOVE_CHK:
kono
parents:
diff changeset
1778 case BUILT_IN_MEMSET_CHK:
kono
parents:
diff changeset
1779 case BUILT_IN_STRCPY_CHK:
kono
parents:
diff changeset
1780 case BUILT_IN_STRNCPY_CHK:
kono
parents:
diff changeset
1781 case BUILT_IN_STPCPY_CHK:
kono
parents:
diff changeset
1782 case BUILT_IN_STPNCPY_CHK:
kono
parents:
diff changeset
1783 case BUILT_IN_STRCAT_CHK:
kono
parents:
diff changeset
1784 case BUILT_IN_STRNCAT_CHK:
kono
parents:
diff changeset
1785 case BUILT_IN_MALLOC:
kono
parents:
diff changeset
1786 case BUILT_IN_CALLOC:
kono
parents:
diff changeset
1787 case BUILT_IN_REALLOC:
kono
parents:
diff changeset
1788 return 1;
kono
parents:
diff changeset
1789
kono
parents:
diff changeset
1790 default:
kono
parents:
diff changeset
1791 return 0;
kono
parents:
diff changeset
1792 }
kono
parents:
diff changeset
1793 }
kono
parents:
diff changeset
1794
kono
parents:
diff changeset
1795 /* Add bound arguments to call statement pointed by GSI.
kono
parents:
diff changeset
1796 Also performs a replacement of user checker builtins calls
kono
parents:
diff changeset
1797 with internal ones. */
kono
parents:
diff changeset
1798
kono
parents:
diff changeset
1799 static void
kono
parents:
diff changeset
1800 chkp_add_bounds_to_call_stmt (gimple_stmt_iterator *gsi)
kono
parents:
diff changeset
1801 {
kono
parents:
diff changeset
1802 gcall *call = as_a <gcall *> (gsi_stmt (*gsi));
kono
parents:
diff changeset
1803 unsigned arg_no = 0;
kono
parents:
diff changeset
1804 tree fndecl = gimple_call_fndecl (call);
kono
parents:
diff changeset
1805 tree fntype;
kono
parents:
diff changeset
1806 tree first_formal_arg;
kono
parents:
diff changeset
1807 tree arg;
kono
parents:
diff changeset
1808 bool use_fntype = false;
kono
parents:
diff changeset
1809 tree op;
kono
parents:
diff changeset
1810 ssa_op_iter iter;
kono
parents:
diff changeset
1811 gcall *new_call;
kono
parents:
diff changeset
1812
kono
parents:
diff changeset
1813 /* Do nothing for internal functions. */
kono
parents:
diff changeset
1814 if (gimple_call_internal_p (call))
kono
parents:
diff changeset
1815 return;
kono
parents:
diff changeset
1816
kono
parents:
diff changeset
1817 fntype = TREE_TYPE (TREE_TYPE (gimple_call_fn (call)));
kono
parents:
diff changeset
1818
kono
parents:
diff changeset
1819 /* Do nothing if back-end builtin is called. */
kono
parents:
diff changeset
1820 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
kono
parents:
diff changeset
1821 return;
kono
parents:
diff changeset
1822
kono
parents:
diff changeset
1823 /* Do nothing for some middle-end builtins. */
kono
parents:
diff changeset
1824 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
1825 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE)
kono
parents:
diff changeset
1826 return;
kono
parents:
diff changeset
1827
kono
parents:
diff changeset
1828 /* Do nothing for calls to not instrumentable functions. */
kono
parents:
diff changeset
1829 if (fndecl && !chkp_instrumentable_p (fndecl))
kono
parents:
diff changeset
1830 return;
kono
parents:
diff changeset
1831
kono
parents:
diff changeset
1832 /* Ignore CHKP_INIT_PTR_BOUNDS, CHKP_NULL_PTR_BOUNDS
kono
parents:
diff changeset
1833 and CHKP_COPY_PTR_BOUNDS. */
kono
parents:
diff changeset
1834 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
1835 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_INIT_PTR_BOUNDS
kono
parents:
diff changeset
1836 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_NULL_PTR_BOUNDS
kono
parents:
diff changeset
1837 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_COPY_PTR_BOUNDS
kono
parents:
diff changeset
1838 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_SET_PTR_BOUNDS))
kono
parents:
diff changeset
1839 return;
kono
parents:
diff changeset
1840
kono
parents:
diff changeset
1841 /* Check user builtins are replaced with checks. */
kono
parents:
diff changeset
1842 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
1843 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_LBOUNDS
kono
parents:
diff changeset
1844 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_UBOUNDS
kono
parents:
diff changeset
1845 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_CHECK_PTR_BOUNDS))
kono
parents:
diff changeset
1846 {
kono
parents:
diff changeset
1847 chkp_replace_address_check_builtin (gsi, integer_minus_one_node);
kono
parents:
diff changeset
1848 return;
kono
parents:
diff changeset
1849 }
kono
parents:
diff changeset
1850
kono
parents:
diff changeset
1851 /* Check user builtins are replaced with bound extract. */
kono
parents:
diff changeset
1852 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
1853 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_GET_PTR_LBOUND
kono
parents:
diff changeset
1854 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_GET_PTR_UBOUND))
kono
parents:
diff changeset
1855 {
kono
parents:
diff changeset
1856 chkp_replace_extract_builtin (gsi);
kono
parents:
diff changeset
1857 return;
kono
parents:
diff changeset
1858 }
kono
parents:
diff changeset
1859
kono
parents:
diff changeset
1860 /* BUILT_IN_CHKP_NARROW_PTR_BOUNDS call is replaced with
kono
parents:
diff changeset
1861 target narrow bounds call. */
kono
parents:
diff changeset
1862 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
1863 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_NARROW_PTR_BOUNDS)
kono
parents:
diff changeset
1864 {
kono
parents:
diff changeset
1865 tree arg = gimple_call_arg (call, 1);
kono
parents:
diff changeset
1866 tree bounds = chkp_find_bounds (arg, gsi);
kono
parents:
diff changeset
1867
kono
parents:
diff changeset
1868 gimple_call_set_fndecl (call, chkp_narrow_bounds_fndecl);
kono
parents:
diff changeset
1869 gimple_call_set_arg (call, 1, bounds);
kono
parents:
diff changeset
1870 update_stmt (call);
kono
parents:
diff changeset
1871
kono
parents:
diff changeset
1872 return;
kono
parents:
diff changeset
1873 }
kono
parents:
diff changeset
1874
kono
parents:
diff changeset
1875 /* BUILT_IN_CHKP_STORE_PTR_BOUNDS call is replaced with
kono
parents:
diff changeset
1876 bndstx call. */
kono
parents:
diff changeset
1877 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
1878 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_STORE_PTR_BOUNDS)
kono
parents:
diff changeset
1879 {
kono
parents:
diff changeset
1880 tree addr = gimple_call_arg (call, 0);
kono
parents:
diff changeset
1881 tree ptr = gimple_call_arg (call, 1);
kono
parents:
diff changeset
1882 tree bounds = chkp_find_bounds (ptr, gsi);
kono
parents:
diff changeset
1883 gimple_stmt_iterator iter = gsi_for_stmt (call);
kono
parents:
diff changeset
1884
kono
parents:
diff changeset
1885 chkp_build_bndstx (addr, ptr, bounds, gsi);
kono
parents:
diff changeset
1886 gsi_remove (&iter, true);
kono
parents:
diff changeset
1887
kono
parents:
diff changeset
1888 return;
kono
parents:
diff changeset
1889 }
kono
parents:
diff changeset
1890
kono
parents:
diff changeset
1891 if (!flag_chkp_instrument_calls)
kono
parents:
diff changeset
1892 return;
kono
parents:
diff changeset
1893
kono
parents:
diff changeset
1894 /* We instrument only some subset of builtins. We also instrument
kono
parents:
diff changeset
1895 builtin calls to be inlined. */
kono
parents:
diff changeset
1896 if (fndecl
kono
parents:
diff changeset
1897 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
1898 && !chkp_instrument_normal_builtin (fndecl))
kono
parents:
diff changeset
1899 {
kono
parents:
diff changeset
1900 if (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)))
kono
parents:
diff changeset
1901 return;
kono
parents:
diff changeset
1902
kono
parents:
diff changeset
1903 struct cgraph_node *clone = chkp_maybe_create_clone (fndecl);
kono
parents:
diff changeset
1904 if (!clone
kono
parents:
diff changeset
1905 || !gimple_has_body_p (clone->decl))
kono
parents:
diff changeset
1906 return;
kono
parents:
diff changeset
1907 }
kono
parents:
diff changeset
1908
kono
parents:
diff changeset
1909 /* If function decl is available then use it for
kono
parents:
diff changeset
1910 formal arguments list. Otherwise use function type. */
kono
parents:
diff changeset
1911 if (fndecl
kono
parents:
diff changeset
1912 && DECL_ARGUMENTS (fndecl)
kono
parents:
diff changeset
1913 && gimple_call_fntype (call) == TREE_TYPE (fndecl))
kono
parents:
diff changeset
1914 first_formal_arg = DECL_ARGUMENTS (fndecl);
kono
parents:
diff changeset
1915 else
kono
parents:
diff changeset
1916 {
kono
parents:
diff changeset
1917 first_formal_arg = TYPE_ARG_TYPES (fntype);
kono
parents:
diff changeset
1918 use_fntype = true;
kono
parents:
diff changeset
1919 }
kono
parents:
diff changeset
1920
kono
parents:
diff changeset
1921 /* Fill vector of new call args. */
kono
parents:
diff changeset
1922 vec<tree> new_args = vNULL;
kono
parents:
diff changeset
1923 new_args.create (gimple_call_num_args (call));
kono
parents:
diff changeset
1924 arg = first_formal_arg;
kono
parents:
diff changeset
1925 for (arg_no = 0; arg_no < gimple_call_num_args (call); arg_no++)
kono
parents:
diff changeset
1926 {
kono
parents:
diff changeset
1927 tree call_arg = gimple_call_arg (call, arg_no);
kono
parents:
diff changeset
1928 tree type;
kono
parents:
diff changeset
1929
kono
parents:
diff changeset
1930 /* Get arg type using formal argument description
kono
parents:
diff changeset
1931 or actual argument type. */
kono
parents:
diff changeset
1932 if (arg)
kono
parents:
diff changeset
1933 if (use_fntype)
kono
parents:
diff changeset
1934 if (TREE_VALUE (arg) != void_type_node)
kono
parents:
diff changeset
1935 {
kono
parents:
diff changeset
1936 type = TREE_VALUE (arg);
kono
parents:
diff changeset
1937 arg = TREE_CHAIN (arg);
kono
parents:
diff changeset
1938 }
kono
parents:
diff changeset
1939 else
kono
parents:
diff changeset
1940 type = TREE_TYPE (call_arg);
kono
parents:
diff changeset
1941 else
kono
parents:
diff changeset
1942 {
kono
parents:
diff changeset
1943 type = TREE_TYPE (arg);
kono
parents:
diff changeset
1944 arg = TREE_CHAIN (arg);
kono
parents:
diff changeset
1945 }
kono
parents:
diff changeset
1946 else
kono
parents:
diff changeset
1947 type = TREE_TYPE (call_arg);
kono
parents:
diff changeset
1948
kono
parents:
diff changeset
1949 new_args.safe_push (call_arg);
kono
parents:
diff changeset
1950
kono
parents:
diff changeset
1951 if (BOUNDED_TYPE_P (type)
kono
parents:
diff changeset
1952 || pass_by_reference (NULL, TYPE_MODE (type), type, true))
kono
parents:
diff changeset
1953 new_args.safe_push (chkp_find_bounds (call_arg, gsi));
kono
parents:
diff changeset
1954 else if (chkp_type_has_pointer (type))
kono
parents:
diff changeset
1955 {
kono
parents:
diff changeset
1956 HOST_WIDE_INT max_bounds
kono
parents:
diff changeset
1957 = TREE_INT_CST_LOW (TYPE_SIZE (type)) / POINTER_SIZE;
kono
parents:
diff changeset
1958 tree *all_bounds = (tree *)xmalloc (sizeof (tree) * max_bounds);
kono
parents:
diff changeset
1959 HOST_WIDE_INT bnd_no;
kono
parents:
diff changeset
1960
kono
parents:
diff changeset
1961 memset (all_bounds, 0, sizeof (tree) * max_bounds);
kono
parents:
diff changeset
1962
kono
parents:
diff changeset
1963 chkp_find_bounds_for_elem (call_arg, all_bounds, 0, gsi);
kono
parents:
diff changeset
1964
kono
parents:
diff changeset
1965 for (bnd_no = 0; bnd_no < max_bounds; bnd_no++)
kono
parents:
diff changeset
1966 if (all_bounds[bnd_no])
kono
parents:
diff changeset
1967 new_args.safe_push (all_bounds[bnd_no]);
kono
parents:
diff changeset
1968
kono
parents:
diff changeset
1969 free (all_bounds);
kono
parents:
diff changeset
1970 }
kono
parents:
diff changeset
1971 }
kono
parents:
diff changeset
1972
kono
parents:
diff changeset
1973 if (new_args.length () == gimple_call_num_args (call))
kono
parents:
diff changeset
1974 new_call = call;
kono
parents:
diff changeset
1975 else
kono
parents:
diff changeset
1976 {
kono
parents:
diff changeset
1977 new_call = gimple_build_call_vec (gimple_op (call, 1), new_args);
kono
parents:
diff changeset
1978 gimple_call_set_lhs (new_call, gimple_call_lhs (call));
kono
parents:
diff changeset
1979 gimple_call_copy_flags (new_call, call);
kono
parents:
diff changeset
1980 gimple_call_set_chain (new_call, gimple_call_chain (call));
kono
parents:
diff changeset
1981 }
kono
parents:
diff changeset
1982 new_args.release ();
kono
parents:
diff changeset
1983
kono
parents:
diff changeset
1984 /* For direct calls fndecl is replaced with instrumented version. */
kono
parents:
diff changeset
1985 if (fndecl)
kono
parents:
diff changeset
1986 {
kono
parents:
diff changeset
1987 tree new_decl = chkp_maybe_create_clone (fndecl)->decl;
kono
parents:
diff changeset
1988 gimple_call_set_fndecl (new_call, new_decl);
kono
parents:
diff changeset
1989 /* In case of a type cast we should modify used function
kono
parents:
diff changeset
1990 type instead of using type of new fndecl. */
kono
parents:
diff changeset
1991 if (gimple_call_fntype (call) != TREE_TYPE (fndecl))
kono
parents:
diff changeset
1992 {
kono
parents:
diff changeset
1993 tree type = gimple_call_fntype (call);
kono
parents:
diff changeset
1994 type = chkp_copy_function_type_adding_bounds (type);
kono
parents:
diff changeset
1995 gimple_call_set_fntype (new_call, type);
kono
parents:
diff changeset
1996 }
kono
parents:
diff changeset
1997 else
kono
parents:
diff changeset
1998 gimple_call_set_fntype (new_call, TREE_TYPE (new_decl));
kono
parents:
diff changeset
1999 }
kono
parents:
diff changeset
2000 /* For indirect call we should fix function pointer type if
kono
parents:
diff changeset
2001 pass some bounds. */
kono
parents:
diff changeset
2002 else if (new_call != call)
kono
parents:
diff changeset
2003 {
kono
parents:
diff changeset
2004 tree type = gimple_call_fntype (call);
kono
parents:
diff changeset
2005 type = chkp_copy_function_type_adding_bounds (type);
kono
parents:
diff changeset
2006 gimple_call_set_fntype (new_call, type);
kono
parents:
diff changeset
2007 }
kono
parents:
diff changeset
2008
kono
parents:
diff changeset
2009 /* replace old call statement with the new one. */
kono
parents:
diff changeset
2010 if (call != new_call)
kono
parents:
diff changeset
2011 {
kono
parents:
diff changeset
2012 FOR_EACH_SSA_TREE_OPERAND (op, call, iter, SSA_OP_ALL_DEFS)
kono
parents:
diff changeset
2013 {
kono
parents:
diff changeset
2014 SSA_NAME_DEF_STMT (op) = new_call;
kono
parents:
diff changeset
2015 }
kono
parents:
diff changeset
2016 gsi_replace (gsi, new_call, true);
kono
parents:
diff changeset
2017 }
kono
parents:
diff changeset
2018 else
kono
parents:
diff changeset
2019 update_stmt (new_call);
kono
parents:
diff changeset
2020
kono
parents:
diff changeset
2021 gimple_call_set_with_bounds (new_call, true);
kono
parents:
diff changeset
2022 }
kono
parents:
diff changeset
2023
kono
parents:
diff changeset
2024 /* Return constant static bounds var with specified bounds LB and UB.
kono
parents:
diff changeset
2025 If such var does not exists then new var is created with specified NAME. */
kono
parents:
diff changeset
2026 static tree
kono
parents:
diff changeset
2027 chkp_make_static_const_bounds (HOST_WIDE_INT lb,
kono
parents:
diff changeset
2028 HOST_WIDE_INT ub,
kono
parents:
diff changeset
2029 const char *name)
kono
parents:
diff changeset
2030 {
kono
parents:
diff changeset
2031 tree id = get_identifier (name);
kono
parents:
diff changeset
2032 tree var;
kono
parents:
diff changeset
2033 varpool_node *node;
kono
parents:
diff changeset
2034 symtab_node *snode;
kono
parents:
diff changeset
2035
kono
parents:
diff changeset
2036 var = build_decl (UNKNOWN_LOCATION, VAR_DECL, id,
kono
parents:
diff changeset
2037 pointer_bounds_type_node);
kono
parents:
diff changeset
2038 TREE_STATIC (var) = 1;
kono
parents:
diff changeset
2039 TREE_PUBLIC (var) = 1;
kono
parents:
diff changeset
2040
kono
parents:
diff changeset
2041 /* With LTO we may have constant bounds already in varpool.
kono
parents:
diff changeset
2042 Try to find it. */
kono
parents:
diff changeset
2043 if ((snode = symtab_node::get_for_asmname (DECL_ASSEMBLER_NAME (var))))
kono
parents:
diff changeset
2044 {
kono
parents:
diff changeset
2045 /* We don't allow this symbol usage for non bounds. */
kono
parents:
diff changeset
2046 if (snode->type != SYMTAB_VARIABLE
kono
parents:
diff changeset
2047 || !POINTER_BOUNDS_P (snode->decl))
kono
parents:
diff changeset
2048 sorry ("-fcheck-pointer-bounds requires %qs "
kono
parents:
diff changeset
2049 "name for internal usage",
kono
parents:
diff changeset
2050 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (var)));
kono
parents:
diff changeset
2051
kono
parents:
diff changeset
2052 return snode->decl;
kono
parents:
diff changeset
2053 }
kono
parents:
diff changeset
2054
kono
parents:
diff changeset
2055 TREE_USED (var) = 1;
kono
parents:
diff changeset
2056 TREE_READONLY (var) = 1;
kono
parents:
diff changeset
2057 TREE_ADDRESSABLE (var) = 0;
kono
parents:
diff changeset
2058 DECL_ARTIFICIAL (var) = 1;
kono
parents:
diff changeset
2059 DECL_READ_P (var) = 1;
kono
parents:
diff changeset
2060 DECL_INITIAL (var) = targetm.chkp_make_bounds_constant (lb, ub);
kono
parents:
diff changeset
2061 make_decl_one_only (var, DECL_ASSEMBLER_NAME (var));
kono
parents:
diff changeset
2062 /* We may use this symbol during ctors generation in chkp_finish_file
kono
parents:
diff changeset
2063 when all symbols are emitted. Force output to avoid undefined
kono
parents:
diff changeset
2064 symbols in ctors. */
kono
parents:
diff changeset
2065 node = varpool_node::get_create (var);
kono
parents:
diff changeset
2066 node->force_output = 1;
kono
parents:
diff changeset
2067
kono
parents:
diff changeset
2068 varpool_node::finalize_decl (var);
kono
parents:
diff changeset
2069
kono
parents:
diff changeset
2070 return var;
kono
parents:
diff changeset
2071 }
kono
parents:
diff changeset
2072
kono
parents:
diff changeset
2073 /* Generate code to make bounds with specified lower bound LB and SIZE.
kono
parents:
diff changeset
2074 if AFTER is 1 then code is inserted after position pointed by ITER
kono
parents:
diff changeset
2075 otherwise code is inserted before position pointed by ITER.
kono
parents:
diff changeset
2076 If ITER is NULL then code is added to entry block. */
kono
parents:
diff changeset
2077 static tree
kono
parents:
diff changeset
2078 chkp_make_bounds (tree lb, tree size, gimple_stmt_iterator *iter, bool after)
kono
parents:
diff changeset
2079 {
kono
parents:
diff changeset
2080 gimple_seq seq;
kono
parents:
diff changeset
2081 gimple_stmt_iterator gsi;
kono
parents:
diff changeset
2082 gimple *stmt;
kono
parents:
diff changeset
2083 tree bounds;
kono
parents:
diff changeset
2084
kono
parents:
diff changeset
2085 if (iter)
kono
parents:
diff changeset
2086 gsi = *iter;
kono
parents:
diff changeset
2087 else
kono
parents:
diff changeset
2088 gsi = gsi_start_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
2089
kono
parents:
diff changeset
2090 seq = NULL;
kono
parents:
diff changeset
2091
kono
parents:
diff changeset
2092 lb = chkp_force_gimple_call_op (lb, &seq);
kono
parents:
diff changeset
2093 size = chkp_force_gimple_call_op (size, &seq);
kono
parents:
diff changeset
2094
kono
parents:
diff changeset
2095 stmt = gimple_build_call (chkp_bndmk_fndecl, 2, lb, size);
kono
parents:
diff changeset
2096 chkp_mark_stmt (stmt);
kono
parents:
diff changeset
2097
kono
parents:
diff changeset
2098 bounds = chkp_get_tmp_reg (stmt);
kono
parents:
diff changeset
2099 gimple_call_set_lhs (stmt, bounds);
kono
parents:
diff changeset
2100
kono
parents:
diff changeset
2101 gimple_seq_add_stmt (&seq, stmt);
kono
parents:
diff changeset
2102
kono
parents:
diff changeset
2103 if (iter && after)
kono
parents:
diff changeset
2104 gsi_insert_seq_after (&gsi, seq, GSI_SAME_STMT);
kono
parents:
diff changeset
2105 else
kono
parents:
diff changeset
2106 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
kono
parents:
diff changeset
2107
kono
parents:
diff changeset
2108 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2109 {
kono
parents:
diff changeset
2110 fprintf (dump_file, "Made bounds: ");
kono
parents:
diff changeset
2111 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
2112 if (iter)
kono
parents:
diff changeset
2113 {
kono
parents:
diff changeset
2114 fprintf (dump_file, " inserted before statement: ");
kono
parents:
diff changeset
2115 print_gimple_stmt (dump_file, gsi_stmt (*iter), 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
2116 }
kono
parents:
diff changeset
2117 else
kono
parents:
diff changeset
2118 fprintf (dump_file, " at function entry\n");
kono
parents:
diff changeset
2119 }
kono
parents:
diff changeset
2120
kono
parents:
diff changeset
2121 /* update_stmt (stmt); */
kono
parents:
diff changeset
2122
kono
parents:
diff changeset
2123 return bounds;
kono
parents:
diff changeset
2124 }
kono
parents:
diff changeset
2125
kono
parents:
diff changeset
2126 /* Return var holding zero bounds. */
kono
parents:
diff changeset
2127 tree
kono
parents:
diff changeset
2128 chkp_get_zero_bounds_var (void)
kono
parents:
diff changeset
2129 {
kono
parents:
diff changeset
2130 if (!chkp_zero_bounds_var)
kono
parents:
diff changeset
2131 chkp_zero_bounds_var
kono
parents:
diff changeset
2132 = chkp_make_static_const_bounds (0, -1,
kono
parents:
diff changeset
2133 CHKP_ZERO_BOUNDS_VAR_NAME);
kono
parents:
diff changeset
2134 return chkp_zero_bounds_var;
kono
parents:
diff changeset
2135 }
kono
parents:
diff changeset
2136
kono
parents:
diff changeset
2137 /* Return var holding none bounds. */
kono
parents:
diff changeset
2138 tree
kono
parents:
diff changeset
2139 chkp_get_none_bounds_var (void)
kono
parents:
diff changeset
2140 {
kono
parents:
diff changeset
2141 if (!chkp_none_bounds_var)
kono
parents:
diff changeset
2142 chkp_none_bounds_var
kono
parents:
diff changeset
2143 = chkp_make_static_const_bounds (-1, 0,
kono
parents:
diff changeset
2144 CHKP_NONE_BOUNDS_VAR_NAME);
kono
parents:
diff changeset
2145 return chkp_none_bounds_var;
kono
parents:
diff changeset
2146 }
kono
parents:
diff changeset
2147
kono
parents:
diff changeset
2148 /* Return SSA_NAME used to represent zero bounds. */
kono
parents:
diff changeset
2149 static tree
kono
parents:
diff changeset
2150 chkp_get_zero_bounds (void)
kono
parents:
diff changeset
2151 {
kono
parents:
diff changeset
2152 if (zero_bounds)
kono
parents:
diff changeset
2153 return zero_bounds;
kono
parents:
diff changeset
2154
kono
parents:
diff changeset
2155 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2156 fprintf (dump_file, "Creating zero bounds...");
kono
parents:
diff changeset
2157
kono
parents:
diff changeset
2158 if ((flag_chkp_use_static_bounds && flag_chkp_use_static_const_bounds)
kono
parents:
diff changeset
2159 || flag_chkp_use_static_const_bounds > 0)
kono
parents:
diff changeset
2160 {
kono
parents:
diff changeset
2161 gimple_stmt_iterator gsi = gsi_start_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
2162 gimple *stmt;
kono
parents:
diff changeset
2163
kono
parents:
diff changeset
2164 zero_bounds = chkp_get_tmp_reg (NULL);
kono
parents:
diff changeset
2165 stmt = gimple_build_assign (zero_bounds, chkp_get_zero_bounds_var ());
kono
parents:
diff changeset
2166 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
2167 }
kono
parents:
diff changeset
2168 else
kono
parents:
diff changeset
2169 zero_bounds = chkp_make_bounds (integer_zero_node,
kono
parents:
diff changeset
2170 integer_zero_node,
kono
parents:
diff changeset
2171 NULL,
kono
parents:
diff changeset
2172 false);
kono
parents:
diff changeset
2173
kono
parents:
diff changeset
2174 return zero_bounds;
kono
parents:
diff changeset
2175 }
kono
parents:
diff changeset
2176
kono
parents:
diff changeset
2177 /* Return SSA_NAME used to represent none bounds. */
kono
parents:
diff changeset
2178 static tree
kono
parents:
diff changeset
2179 chkp_get_none_bounds (void)
kono
parents:
diff changeset
2180 {
kono
parents:
diff changeset
2181 if (none_bounds)
kono
parents:
diff changeset
2182 return none_bounds;
kono
parents:
diff changeset
2183
kono
parents:
diff changeset
2184 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2185 fprintf (dump_file, "Creating none bounds...");
kono
parents:
diff changeset
2186
kono
parents:
diff changeset
2187
kono
parents:
diff changeset
2188 if ((flag_chkp_use_static_bounds && flag_chkp_use_static_const_bounds)
kono
parents:
diff changeset
2189 || flag_chkp_use_static_const_bounds > 0)
kono
parents:
diff changeset
2190 {
kono
parents:
diff changeset
2191 gimple_stmt_iterator gsi = gsi_start_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
2192 gimple *stmt;
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 none_bounds = chkp_get_tmp_reg (NULL);
kono
parents:
diff changeset
2195 stmt = gimple_build_assign (none_bounds, chkp_get_none_bounds_var ());
kono
parents:
diff changeset
2196 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
2197 }
kono
parents:
diff changeset
2198 else
kono
parents:
diff changeset
2199 none_bounds = chkp_make_bounds (integer_minus_one_node,
kono
parents:
diff changeset
2200 build_int_cst (size_type_node, 2),
kono
parents:
diff changeset
2201 NULL,
kono
parents:
diff changeset
2202 false);
kono
parents:
diff changeset
2203
kono
parents:
diff changeset
2204 return none_bounds;
kono
parents:
diff changeset
2205 }
kono
parents:
diff changeset
2206
kono
parents:
diff changeset
2207 /* Return bounds to be used as a result of operation which
kono
parents:
diff changeset
2208 should not create poiunter (e.g. MULT_EXPR). */
kono
parents:
diff changeset
2209 static tree
kono
parents:
diff changeset
2210 chkp_get_invalid_op_bounds (void)
kono
parents:
diff changeset
2211 {
kono
parents:
diff changeset
2212 return chkp_get_zero_bounds ();
kono
parents:
diff changeset
2213 }
kono
parents:
diff changeset
2214
kono
parents:
diff changeset
2215 /* Return bounds to be used for loads of non-pointer values. */
kono
parents:
diff changeset
2216 static tree
kono
parents:
diff changeset
2217 chkp_get_nonpointer_load_bounds (void)
kono
parents:
diff changeset
2218 {
kono
parents:
diff changeset
2219 return chkp_get_zero_bounds ();
kono
parents:
diff changeset
2220 }
kono
parents:
diff changeset
2221
kono
parents:
diff changeset
2222 /* Return 1 if may use bndret call to get bounds for pointer
kono
parents:
diff changeset
2223 returned by CALL. */
kono
parents:
diff changeset
2224 static bool
kono
parents:
diff changeset
2225 chkp_call_returns_bounds_p (gcall *call)
kono
parents:
diff changeset
2226 {
kono
parents:
diff changeset
2227 if (gimple_call_internal_p (call))
kono
parents:
diff changeset
2228 {
kono
parents:
diff changeset
2229 if (gimple_call_internal_fn (call) == IFN_VA_ARG)
kono
parents:
diff changeset
2230 return true;
kono
parents:
diff changeset
2231 return false;
kono
parents:
diff changeset
2232 }
kono
parents:
diff changeset
2233
kono
parents:
diff changeset
2234 if (gimple_call_builtin_p (call, BUILT_IN_CHKP_NARROW_PTR_BOUNDS)
kono
parents:
diff changeset
2235 || chkp_gimple_call_builtin_p (call, BUILT_IN_CHKP_NARROW))
kono
parents:
diff changeset
2236 return true;
kono
parents:
diff changeset
2237
kono
parents:
diff changeset
2238 if (gimple_call_with_bounds_p (call))
kono
parents:
diff changeset
2239 return true;
kono
parents:
diff changeset
2240
kono
parents:
diff changeset
2241 tree fndecl = gimple_call_fndecl (call);
kono
parents:
diff changeset
2242
kono
parents:
diff changeset
2243 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
kono
parents:
diff changeset
2244 return false;
kono
parents:
diff changeset
2245
kono
parents:
diff changeset
2246 if (fndecl && !chkp_instrumentable_p (fndecl))
kono
parents:
diff changeset
2247 return false;
kono
parents:
diff changeset
2248
kono
parents:
diff changeset
2249 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
kono
parents:
diff changeset
2250 {
kono
parents:
diff changeset
2251 if (chkp_instrument_normal_builtin (fndecl))
kono
parents:
diff changeset
2252 return true;
kono
parents:
diff changeset
2253
kono
parents:
diff changeset
2254 if (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)))
kono
parents:
diff changeset
2255 return false;
kono
parents:
diff changeset
2256
kono
parents:
diff changeset
2257 struct cgraph_node *clone = chkp_maybe_create_clone (fndecl);
kono
parents:
diff changeset
2258 return (clone && gimple_has_body_p (clone->decl));
kono
parents:
diff changeset
2259 }
kono
parents:
diff changeset
2260
kono
parents:
diff changeset
2261 return true;
kono
parents:
diff changeset
2262 }
kono
parents:
diff changeset
2263
kono
parents:
diff changeset
2264 /* Build bounds returned by CALL. */
kono
parents:
diff changeset
2265 static tree
kono
parents:
diff changeset
2266 chkp_build_returned_bound (gcall *call)
kono
parents:
diff changeset
2267 {
kono
parents:
diff changeset
2268 gimple_stmt_iterator gsi;
kono
parents:
diff changeset
2269 tree bounds;
kono
parents:
diff changeset
2270 gimple *stmt;
kono
parents:
diff changeset
2271 tree fndecl = gimple_call_fndecl (call);
kono
parents:
diff changeset
2272 unsigned int retflags;
kono
parents:
diff changeset
2273 tree lhs = gimple_call_lhs (call);
kono
parents:
diff changeset
2274
kono
parents:
diff changeset
2275 /* To avoid fixing alloca expands in targets we handle
kono
parents:
diff changeset
2276 it separately. */
kono
parents:
diff changeset
2277 if (fndecl
kono
parents:
diff changeset
2278 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
2279 && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (fndecl)))
kono
parents:
diff changeset
2280 {
kono
parents:
diff changeset
2281 tree size = gimple_call_arg (call, 0);
kono
parents:
diff changeset
2282 gimple_stmt_iterator iter = gsi_for_stmt (call);
kono
parents:
diff changeset
2283 bounds = chkp_make_bounds (lhs, size, &iter, true);
kono
parents:
diff changeset
2284 }
kono
parents:
diff changeset
2285 /* We know bounds returned by set_bounds builtin call. */
kono
parents:
diff changeset
2286 else if (fndecl
kono
parents:
diff changeset
2287 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
2288 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_SET_PTR_BOUNDS)
kono
parents:
diff changeset
2289 {
kono
parents:
diff changeset
2290 tree lb = gimple_call_arg (call, 0);
kono
parents:
diff changeset
2291 tree size = gimple_call_arg (call, 1);
kono
parents:
diff changeset
2292 gimple_stmt_iterator iter = gsi_for_stmt (call);
kono
parents:
diff changeset
2293 bounds = chkp_make_bounds (lb, size, &iter, true);
kono
parents:
diff changeset
2294 }
kono
parents:
diff changeset
2295 /* Detect bounds initialization calls. */
kono
parents:
diff changeset
2296 else if (fndecl
kono
parents:
diff changeset
2297 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
2298 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_INIT_PTR_BOUNDS)
kono
parents:
diff changeset
2299 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
2300 /* Detect bounds nullification calls. */
kono
parents:
diff changeset
2301 else if (fndecl
kono
parents:
diff changeset
2302 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
2303 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_NULL_PTR_BOUNDS)
kono
parents:
diff changeset
2304 bounds = chkp_get_none_bounds ();
kono
parents:
diff changeset
2305 /* Detect bounds copy calls. */
kono
parents:
diff changeset
2306 else if (fndecl
kono
parents:
diff changeset
2307 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
2308 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_COPY_PTR_BOUNDS)
kono
parents:
diff changeset
2309 {
kono
parents:
diff changeset
2310 gimple_stmt_iterator iter = gsi_for_stmt (call);
kono
parents:
diff changeset
2311 bounds = chkp_find_bounds (gimple_call_arg (call, 1), &iter);
kono
parents:
diff changeset
2312 }
kono
parents:
diff changeset
2313 /* Do not use retbnd when returned bounds are equal to some
kono
parents:
diff changeset
2314 of passed bounds. */
kono
parents:
diff changeset
2315 else if (((retflags = gimple_call_return_flags (call)) & ERF_RETURNS_ARG)
kono
parents:
diff changeset
2316 && (retflags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (call))
kono
parents:
diff changeset
2317 {
kono
parents:
diff changeset
2318 gimple_stmt_iterator iter = gsi_for_stmt (call);
kono
parents:
diff changeset
2319 unsigned int retarg = retflags & ERF_RETURN_ARG_MASK, argno;
kono
parents:
diff changeset
2320 if (gimple_call_with_bounds_p (call))
kono
parents:
diff changeset
2321 {
kono
parents:
diff changeset
2322 for (argno = 0; argno < gimple_call_num_args (call); argno++)
kono
parents:
diff changeset
2323 if (!POINTER_BOUNDS_P (gimple_call_arg (call, argno)))
kono
parents:
diff changeset
2324 {
kono
parents:
diff changeset
2325 if (retarg)
kono
parents:
diff changeset
2326 retarg--;
kono
parents:
diff changeset
2327 else
kono
parents:
diff changeset
2328 break;
kono
parents:
diff changeset
2329 }
kono
parents:
diff changeset
2330 }
kono
parents:
diff changeset
2331 else
kono
parents:
diff changeset
2332 argno = retarg;
kono
parents:
diff changeset
2333
kono
parents:
diff changeset
2334 bounds = chkp_find_bounds (gimple_call_arg (call, argno), &iter);
kono
parents:
diff changeset
2335 }
kono
parents:
diff changeset
2336 else if (chkp_call_returns_bounds_p (call)
kono
parents:
diff changeset
2337 && BOUNDED_P (lhs))
kono
parents:
diff changeset
2338 {
kono
parents:
diff changeset
2339 gcc_assert (TREE_CODE (lhs) == SSA_NAME);
kono
parents:
diff changeset
2340
kono
parents:
diff changeset
2341 /* In general case build checker builtin call to
kono
parents:
diff changeset
2342 obtain returned bounds. */
kono
parents:
diff changeset
2343 stmt = gimple_build_call (chkp_ret_bnd_fndecl, 1,
kono
parents:
diff changeset
2344 gimple_call_lhs (call));
kono
parents:
diff changeset
2345 chkp_mark_stmt (stmt);
kono
parents:
diff changeset
2346
kono
parents:
diff changeset
2347 gsi = gsi_for_stmt (call);
kono
parents:
diff changeset
2348 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
2349
kono
parents:
diff changeset
2350 bounds = chkp_get_tmp_reg (stmt);
kono
parents:
diff changeset
2351 gimple_call_set_lhs (stmt, bounds);
kono
parents:
diff changeset
2352
kono
parents:
diff changeset
2353 update_stmt (stmt);
kono
parents:
diff changeset
2354 }
kono
parents:
diff changeset
2355 else
kono
parents:
diff changeset
2356 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
2357
kono
parents:
diff changeset
2358 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2359 {
kono
parents:
diff changeset
2360 fprintf (dump_file, "Built returned bounds (");
kono
parents:
diff changeset
2361 print_generic_expr (dump_file, bounds);
kono
parents:
diff changeset
2362 fprintf (dump_file, ") for call: ");
kono
parents:
diff changeset
2363 print_gimple_stmt (dump_file, call, 0, TDF_VOPS | TDF_MEMSYMS);
kono
parents:
diff changeset
2364 }
kono
parents:
diff changeset
2365
kono
parents:
diff changeset
2366 bounds = chkp_maybe_copy_and_register_bounds (lhs, bounds);
kono
parents:
diff changeset
2367
kono
parents:
diff changeset
2368 return bounds;
kono
parents:
diff changeset
2369 }
kono
parents:
diff changeset
2370
kono
parents:
diff changeset
2371 /* Return bounds used as returned by call
kono
parents:
diff changeset
2372 which produced SSA name VAL. */
kono
parents:
diff changeset
2373 gcall *
kono
parents:
diff changeset
2374 chkp_retbnd_call_by_val (tree val)
kono
parents:
diff changeset
2375 {
kono
parents:
diff changeset
2376 if (TREE_CODE (val) != SSA_NAME)
kono
parents:
diff changeset
2377 return NULL;
kono
parents:
diff changeset
2378
kono
parents:
diff changeset
2379 gcc_assert (gimple_code (SSA_NAME_DEF_STMT (val)) == GIMPLE_CALL);
kono
parents:
diff changeset
2380
kono
parents:
diff changeset
2381 imm_use_iterator use_iter;
kono
parents:
diff changeset
2382 use_operand_p use_p;
kono
parents:
diff changeset
2383 FOR_EACH_IMM_USE_FAST (use_p, use_iter, val)
kono
parents:
diff changeset
2384 if (chkp_gimple_call_builtin_p (USE_STMT (use_p), BUILT_IN_CHKP_BNDRET))
kono
parents:
diff changeset
2385 return as_a <gcall *> (USE_STMT (use_p));
kono
parents:
diff changeset
2386
kono
parents:
diff changeset
2387 return NULL;
kono
parents:
diff changeset
2388 }
kono
parents:
diff changeset
2389
kono
parents:
diff changeset
2390 /* Check the next parameter for the given PARM is bounds
kono
parents:
diff changeset
2391 and return it's default SSA_NAME (create if required). */
kono
parents:
diff changeset
2392 static tree
kono
parents:
diff changeset
2393 chkp_get_next_bounds_parm (tree parm)
kono
parents:
diff changeset
2394 {
kono
parents:
diff changeset
2395 tree bounds = TREE_CHAIN (parm);
kono
parents:
diff changeset
2396 gcc_assert (POINTER_BOUNDS_P (bounds));
kono
parents:
diff changeset
2397 bounds = ssa_default_def (cfun, bounds);
kono
parents:
diff changeset
2398 if (!bounds)
kono
parents:
diff changeset
2399 {
kono
parents:
diff changeset
2400 bounds = make_ssa_name (TREE_CHAIN (parm), gimple_build_nop ());
kono
parents:
diff changeset
2401 set_ssa_default_def (cfun, TREE_CHAIN (parm), bounds);
kono
parents:
diff changeset
2402 }
kono
parents:
diff changeset
2403 return bounds;
kono
parents:
diff changeset
2404 }
kono
parents:
diff changeset
2405
kono
parents:
diff changeset
2406 /* Return bounds to be used for input argument PARM. */
kono
parents:
diff changeset
2407 static tree
kono
parents:
diff changeset
2408 chkp_get_bound_for_parm (tree parm)
kono
parents:
diff changeset
2409 {
kono
parents:
diff changeset
2410 tree decl = SSA_NAME_VAR (parm);
kono
parents:
diff changeset
2411 tree bounds;
kono
parents:
diff changeset
2412
kono
parents:
diff changeset
2413 gcc_assert (TREE_CODE (decl) == PARM_DECL);
kono
parents:
diff changeset
2414
kono
parents:
diff changeset
2415 bounds = chkp_get_registered_bounds (parm);
kono
parents:
diff changeset
2416
kono
parents:
diff changeset
2417 if (!bounds)
kono
parents:
diff changeset
2418 bounds = chkp_get_registered_bounds (decl);
kono
parents:
diff changeset
2419
kono
parents:
diff changeset
2420 if (!bounds)
kono
parents:
diff changeset
2421 {
kono
parents:
diff changeset
2422 tree orig_decl = cgraph_node::get (cfun->decl)->orig_decl;
kono
parents:
diff changeset
2423
kono
parents:
diff changeset
2424 /* For static chain param we return zero bounds
kono
parents:
diff changeset
2425 because currently we do not check dereferences
kono
parents:
diff changeset
2426 of this pointer. */
kono
parents:
diff changeset
2427 if (cfun->static_chain_decl == decl)
kono
parents:
diff changeset
2428 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
2429 /* If non instrumented runtime is used then it may be useful
kono
parents:
diff changeset
2430 to use zero bounds for input arguments of main
kono
parents:
diff changeset
2431 function. */
kono
parents:
diff changeset
2432 else if (flag_chkp_zero_input_bounds_for_main
kono
parents:
diff changeset
2433 && id_equal (DECL_ASSEMBLER_NAME (orig_decl), "main"))
kono
parents:
diff changeset
2434 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
2435 else if (BOUNDED_P (parm))
kono
parents:
diff changeset
2436 {
kono
parents:
diff changeset
2437 bounds = chkp_get_next_bounds_parm (decl);
kono
parents:
diff changeset
2438 bounds = chkp_maybe_copy_and_register_bounds (decl, bounds);
kono
parents:
diff changeset
2439
kono
parents:
diff changeset
2440 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2441 {
kono
parents:
diff changeset
2442 fprintf (dump_file, "Built arg bounds (");
kono
parents:
diff changeset
2443 print_generic_expr (dump_file, bounds);
kono
parents:
diff changeset
2444 fprintf (dump_file, ") for arg: ");
kono
parents:
diff changeset
2445 print_node (dump_file, "", decl, 0);
kono
parents:
diff changeset
2446 }
kono
parents:
diff changeset
2447 }
kono
parents:
diff changeset
2448 else
kono
parents:
diff changeset
2449 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
2450 }
kono
parents:
diff changeset
2451
kono
parents:
diff changeset
2452 if (!chkp_get_registered_bounds (parm))
kono
parents:
diff changeset
2453 bounds = chkp_maybe_copy_and_register_bounds (parm, bounds);
kono
parents:
diff changeset
2454
kono
parents:
diff changeset
2455 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2456 {
kono
parents:
diff changeset
2457 fprintf (dump_file, "Using bounds ");
kono
parents:
diff changeset
2458 print_generic_expr (dump_file, bounds);
kono
parents:
diff changeset
2459 fprintf (dump_file, " for parm ");
kono
parents:
diff changeset
2460 print_generic_expr (dump_file, parm);
kono
parents:
diff changeset
2461 fprintf (dump_file, " of type ");
kono
parents:
diff changeset
2462 print_generic_expr (dump_file, TREE_TYPE (parm));
kono
parents:
diff changeset
2463 fprintf (dump_file, ".\n");
kono
parents:
diff changeset
2464 }
kono
parents:
diff changeset
2465
kono
parents:
diff changeset
2466 return bounds;
kono
parents:
diff changeset
2467 }
kono
parents:
diff changeset
2468
kono
parents:
diff changeset
2469 /* Build and return CALL_EXPR for bndstx builtin with specified
kono
parents:
diff changeset
2470 arguments. */
kono
parents:
diff changeset
2471 tree
kono
parents:
diff changeset
2472 chkp_build_bndldx_call (tree addr, tree ptr)
kono
parents:
diff changeset
2473 {
kono
parents:
diff changeset
2474 tree fn = build1 (ADDR_EXPR,
kono
parents:
diff changeset
2475 build_pointer_type (TREE_TYPE (chkp_bndldx_fndecl)),
kono
parents:
diff changeset
2476 chkp_bndldx_fndecl);
kono
parents:
diff changeset
2477 tree call = build_call_nary (TREE_TYPE (TREE_TYPE (chkp_bndldx_fndecl)),
kono
parents:
diff changeset
2478 fn, 2, addr, ptr);
kono
parents:
diff changeset
2479 CALL_WITH_BOUNDS_P (call) = true;
kono
parents:
diff changeset
2480 return call;
kono
parents:
diff changeset
2481 }
kono
parents:
diff changeset
2482
kono
parents:
diff changeset
2483 /* Insert code to load bounds for PTR located by ADDR.
kono
parents:
diff changeset
2484 Code is inserted after position pointed by GSI.
kono
parents:
diff changeset
2485 Loaded bounds are returned. */
kono
parents:
diff changeset
2486 static tree
kono
parents:
diff changeset
2487 chkp_build_bndldx (tree addr, tree ptr, gimple_stmt_iterator *gsi)
kono
parents:
diff changeset
2488 {
kono
parents:
diff changeset
2489 gimple_seq seq;
kono
parents:
diff changeset
2490 gimple *stmt;
kono
parents:
diff changeset
2491 tree bounds;
kono
parents:
diff changeset
2492
kono
parents:
diff changeset
2493 seq = NULL;
kono
parents:
diff changeset
2494
kono
parents:
diff changeset
2495 addr = chkp_force_gimple_call_op (addr, &seq);
kono
parents:
diff changeset
2496 ptr = chkp_force_gimple_call_op (ptr, &seq);
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 stmt = gimple_build_call (chkp_bndldx_fndecl, 2, addr, ptr);
kono
parents:
diff changeset
2499 chkp_mark_stmt (stmt);
kono
parents:
diff changeset
2500 bounds = chkp_get_tmp_reg (stmt);
kono
parents:
diff changeset
2501 gimple_call_set_lhs (stmt, bounds);
kono
parents:
diff changeset
2502
kono
parents:
diff changeset
2503 gimple_seq_add_stmt (&seq, stmt);
kono
parents:
diff changeset
2504
kono
parents:
diff changeset
2505 gsi_insert_seq_after (gsi, seq, GSI_CONTINUE_LINKING);
kono
parents:
diff changeset
2506
kono
parents:
diff changeset
2507 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2508 {
kono
parents:
diff changeset
2509 fprintf (dump_file, "Generated bndldx for pointer ");
kono
parents:
diff changeset
2510 print_generic_expr (dump_file, ptr);
kono
parents:
diff changeset
2511 fprintf (dump_file, ": ");
kono
parents:
diff changeset
2512 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS | TDF_MEMSYMS);
kono
parents:
diff changeset
2513 }
kono
parents:
diff changeset
2514
kono
parents:
diff changeset
2515 return bounds;
kono
parents:
diff changeset
2516 }
kono
parents:
diff changeset
2517
kono
parents:
diff changeset
2518 /* Build and return CALL_EXPR for bndstx builtin with specified
kono
parents:
diff changeset
2519 arguments. */
kono
parents:
diff changeset
2520 tree
kono
parents:
diff changeset
2521 chkp_build_bndstx_call (tree addr, tree ptr, tree bounds)
kono
parents:
diff changeset
2522 {
kono
parents:
diff changeset
2523 tree fn = build1 (ADDR_EXPR,
kono
parents:
diff changeset
2524 build_pointer_type (TREE_TYPE (chkp_bndstx_fndecl)),
kono
parents:
diff changeset
2525 chkp_bndstx_fndecl);
kono
parents:
diff changeset
2526 tree call = build_call_nary (TREE_TYPE (TREE_TYPE (chkp_bndstx_fndecl)),
kono
parents:
diff changeset
2527 fn, 3, ptr, bounds, addr);
kono
parents:
diff changeset
2528 CALL_WITH_BOUNDS_P (call) = true;
kono
parents:
diff changeset
2529 return call;
kono
parents:
diff changeset
2530 }
kono
parents:
diff changeset
2531
kono
parents:
diff changeset
2532 /* Insert code to store BOUNDS for PTR stored by ADDR.
kono
parents:
diff changeset
2533 New statements are inserted after position pointed
kono
parents:
diff changeset
2534 by GSI. */
kono
parents:
diff changeset
2535 void
kono
parents:
diff changeset
2536 chkp_build_bndstx (tree addr, tree ptr, tree bounds,
kono
parents:
diff changeset
2537 gimple_stmt_iterator *gsi)
kono
parents:
diff changeset
2538 {
kono
parents:
diff changeset
2539 gimple_seq seq;
kono
parents:
diff changeset
2540 gimple *stmt;
kono
parents:
diff changeset
2541
kono
parents:
diff changeset
2542 seq = NULL;
kono
parents:
diff changeset
2543
kono
parents:
diff changeset
2544 addr = chkp_force_gimple_call_op (addr, &seq);
kono
parents:
diff changeset
2545 ptr = chkp_force_gimple_call_op (ptr, &seq);
kono
parents:
diff changeset
2546
kono
parents:
diff changeset
2547 stmt = gimple_build_call (chkp_bndstx_fndecl, 3, ptr, bounds, addr);
kono
parents:
diff changeset
2548 chkp_mark_stmt (stmt);
kono
parents:
diff changeset
2549 gimple_call_set_with_bounds (stmt, true);
kono
parents:
diff changeset
2550
kono
parents:
diff changeset
2551 gimple_seq_add_stmt (&seq, stmt);
kono
parents:
diff changeset
2552
kono
parents:
diff changeset
2553 gsi_insert_seq_after (gsi, seq, GSI_CONTINUE_LINKING);
kono
parents:
diff changeset
2554
kono
parents:
diff changeset
2555 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2556 {
kono
parents:
diff changeset
2557 fprintf (dump_file, "Generated bndstx for pointer store ");
kono
parents:
diff changeset
2558 print_gimple_stmt (dump_file, gsi_stmt (*gsi), 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
2559 print_gimple_stmt (dump_file, stmt, 2, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
2560 }
kono
parents:
diff changeset
2561 }
kono
parents:
diff changeset
2562
kono
parents:
diff changeset
2563 /* This function is called when call statement
kono
parents:
diff changeset
2564 is inlined and therefore we can't use bndret
kono
parents:
diff changeset
2565 for its LHS anymore. Function fixes bndret
kono
parents:
diff changeset
2566 call using new RHS value if possible. */
kono
parents:
diff changeset
2567 void
kono
parents:
diff changeset
2568 chkp_fixup_inlined_call (tree lhs, tree rhs)
kono
parents:
diff changeset
2569 {
kono
parents:
diff changeset
2570 tree addr, bounds;
kono
parents:
diff changeset
2571 gcall *retbnd, *bndldx;
kono
parents:
diff changeset
2572
kono
parents:
diff changeset
2573 if (!BOUNDED_P (lhs))
kono
parents:
diff changeset
2574 return;
kono
parents:
diff changeset
2575
kono
parents:
diff changeset
2576 /* Search for retbnd call. */
kono
parents:
diff changeset
2577 retbnd = chkp_retbnd_call_by_val (lhs);
kono
parents:
diff changeset
2578 if (!retbnd)
kono
parents:
diff changeset
2579 return;
kono
parents:
diff changeset
2580
kono
parents:
diff changeset
2581 /* Currently only handle cases when call is replaced
kono
parents:
diff changeset
2582 with a memory access. In this case bndret call
kono
parents:
diff changeset
2583 may be replaced with bndldx call. Otherwise we
kono
parents:
diff changeset
2584 have to search for bounds which may cause wrong
kono
parents:
diff changeset
2585 result due to various optimizations applied. */
kono
parents:
diff changeset
2586 switch (TREE_CODE (rhs))
kono
parents:
diff changeset
2587 {
kono
parents:
diff changeset
2588 case VAR_DECL:
kono
parents:
diff changeset
2589 if (DECL_REGISTER (rhs))
kono
parents:
diff changeset
2590 return;
kono
parents:
diff changeset
2591 break;
kono
parents:
diff changeset
2592
kono
parents:
diff changeset
2593 case MEM_REF:
kono
parents:
diff changeset
2594 break;
kono
parents:
diff changeset
2595
kono
parents:
diff changeset
2596 case ARRAY_REF:
kono
parents:
diff changeset
2597 case COMPONENT_REF:
kono
parents:
diff changeset
2598 addr = get_base_address (rhs);
kono
parents:
diff changeset
2599 if (!DECL_P (addr)
kono
parents:
diff changeset
2600 && TREE_CODE (addr) != MEM_REF)
kono
parents:
diff changeset
2601 return;
kono
parents:
diff changeset
2602 if (DECL_P (addr) && DECL_REGISTER (addr))
kono
parents:
diff changeset
2603 return;
kono
parents:
diff changeset
2604 break;
kono
parents:
diff changeset
2605
kono
parents:
diff changeset
2606 default:
kono
parents:
diff changeset
2607 return;
kono
parents:
diff changeset
2608 }
kono
parents:
diff changeset
2609
kono
parents:
diff changeset
2610 /* Create a new statements sequence with bndldx call. */
kono
parents:
diff changeset
2611 gimple_stmt_iterator gsi = gsi_for_stmt (retbnd);
kono
parents:
diff changeset
2612 addr = build_fold_addr_expr (rhs);
kono
parents:
diff changeset
2613 chkp_build_bndldx (addr, lhs, &gsi);
kono
parents:
diff changeset
2614 bndldx = as_a <gcall *> (gsi_stmt (gsi));
kono
parents:
diff changeset
2615
kono
parents:
diff changeset
2616 /* Remove bndret call. */
kono
parents:
diff changeset
2617 bounds = gimple_call_lhs (retbnd);
kono
parents:
diff changeset
2618 gsi = gsi_for_stmt (retbnd);
kono
parents:
diff changeset
2619 gsi_remove (&gsi, true);
kono
parents:
diff changeset
2620
kono
parents:
diff changeset
2621 /* Link new bndldx call. */
kono
parents:
diff changeset
2622 gimple_call_set_lhs (bndldx, bounds);
kono
parents:
diff changeset
2623 update_stmt (bndldx);
kono
parents:
diff changeset
2624 }
kono
parents:
diff changeset
2625
kono
parents:
diff changeset
2626 /* Compute bounds for pointer NODE which was assigned in
kono
parents:
diff changeset
2627 assignment statement ASSIGN. Return computed bounds. */
kono
parents:
diff changeset
2628 static tree
kono
parents:
diff changeset
2629 chkp_compute_bounds_for_assignment (tree node, gimple *assign)
kono
parents:
diff changeset
2630 {
kono
parents:
diff changeset
2631 enum tree_code rhs_code = gimple_assign_rhs_code (assign);
kono
parents:
diff changeset
2632 tree rhs1 = gimple_assign_rhs1 (assign);
kono
parents:
diff changeset
2633 tree bounds = NULL_TREE;
kono
parents:
diff changeset
2634 gimple_stmt_iterator iter = gsi_for_stmt (assign);
kono
parents:
diff changeset
2635 tree base = NULL;
kono
parents:
diff changeset
2636
kono
parents:
diff changeset
2637 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2638 {
kono
parents:
diff changeset
2639 fprintf (dump_file, "Computing bounds for assignment: ");
kono
parents:
diff changeset
2640 print_gimple_stmt (dump_file, assign, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
2641 }
kono
parents:
diff changeset
2642
kono
parents:
diff changeset
2643 switch (rhs_code)
kono
parents:
diff changeset
2644 {
kono
parents:
diff changeset
2645 case MEM_REF:
kono
parents:
diff changeset
2646 case TARGET_MEM_REF:
kono
parents:
diff changeset
2647 case COMPONENT_REF:
kono
parents:
diff changeset
2648 case ARRAY_REF:
kono
parents:
diff changeset
2649 /* We need to load bounds from the bounds table. */
kono
parents:
diff changeset
2650 bounds = chkp_find_bounds_loaded (node, rhs1, &iter);
kono
parents:
diff changeset
2651 break;
kono
parents:
diff changeset
2652
kono
parents:
diff changeset
2653 case VAR_DECL:
kono
parents:
diff changeset
2654 case SSA_NAME:
kono
parents:
diff changeset
2655 case ADDR_EXPR:
kono
parents:
diff changeset
2656 case POINTER_PLUS_EXPR:
kono
parents:
diff changeset
2657 case NOP_EXPR:
kono
parents:
diff changeset
2658 case CONVERT_EXPR:
kono
parents:
diff changeset
2659 case INTEGER_CST:
kono
parents:
diff changeset
2660 /* Bounds are just propagated from RHS. */
kono
parents:
diff changeset
2661 bounds = chkp_find_bounds (rhs1, &iter);
kono
parents:
diff changeset
2662 base = rhs1;
kono
parents:
diff changeset
2663 break;
kono
parents:
diff changeset
2664
kono
parents:
diff changeset
2665 case VIEW_CONVERT_EXPR:
kono
parents:
diff changeset
2666 /* Bounds are just propagated from RHS. */
kono
parents:
diff changeset
2667 bounds = chkp_find_bounds (TREE_OPERAND (rhs1, 0), &iter);
kono
parents:
diff changeset
2668 break;
kono
parents:
diff changeset
2669
kono
parents:
diff changeset
2670 case PARM_DECL:
kono
parents:
diff changeset
2671 if (BOUNDED_P (rhs1))
kono
parents:
diff changeset
2672 {
kono
parents:
diff changeset
2673 /* We need to load bounds from the bounds table. */
kono
parents:
diff changeset
2674 bounds = chkp_build_bndldx (chkp_build_addr_expr (rhs1),
kono
parents:
diff changeset
2675 node, &iter);
kono
parents:
diff changeset
2676 TREE_ADDRESSABLE (rhs1) = 1;
kono
parents:
diff changeset
2677 }
kono
parents:
diff changeset
2678 else
kono
parents:
diff changeset
2679 bounds = chkp_get_nonpointer_load_bounds ();
kono
parents:
diff changeset
2680 break;
kono
parents:
diff changeset
2681
kono
parents:
diff changeset
2682 case MINUS_EXPR:
kono
parents:
diff changeset
2683 case PLUS_EXPR:
kono
parents:
diff changeset
2684 case BIT_AND_EXPR:
kono
parents:
diff changeset
2685 case BIT_IOR_EXPR:
kono
parents:
diff changeset
2686 case BIT_XOR_EXPR:
kono
parents:
diff changeset
2687 {
kono
parents:
diff changeset
2688 tree rhs2 = gimple_assign_rhs2 (assign);
kono
parents:
diff changeset
2689 tree bnd1 = chkp_find_bounds (rhs1, &iter);
kono
parents:
diff changeset
2690 tree bnd2 = chkp_find_bounds (rhs2, &iter);
kono
parents:
diff changeset
2691
kono
parents:
diff changeset
2692 /* First we try to check types of operands. If it
kono
parents:
diff changeset
2693 does not help then look at bound values.
kono
parents:
diff changeset
2694
kono
parents:
diff changeset
2695 If some bounds are incomplete and other are
kono
parents:
diff changeset
2696 not proven to be valid (i.e. also incomplete
kono
parents:
diff changeset
2697 or invalid because value is not pointer) then
kono
parents:
diff changeset
2698 resulting value is incomplete and will be
kono
parents:
diff changeset
2699 recomputed later in chkp_finish_incomplete_bounds. */
kono
parents:
diff changeset
2700 if (BOUNDED_P (rhs1)
kono
parents:
diff changeset
2701 && !BOUNDED_P (rhs2))
kono
parents:
diff changeset
2702 bounds = bnd1;
kono
parents:
diff changeset
2703 else if (BOUNDED_P (rhs2)
kono
parents:
diff changeset
2704 && !BOUNDED_P (rhs1)
kono
parents:
diff changeset
2705 && rhs_code != MINUS_EXPR)
kono
parents:
diff changeset
2706 bounds = bnd2;
kono
parents:
diff changeset
2707 else if (chkp_incomplete_bounds (bnd1))
kono
parents:
diff changeset
2708 if (chkp_valid_bounds (bnd2) && rhs_code != MINUS_EXPR
kono
parents:
diff changeset
2709 && !chkp_incomplete_bounds (bnd2))
kono
parents:
diff changeset
2710 bounds = bnd2;
kono
parents:
diff changeset
2711 else
kono
parents:
diff changeset
2712 bounds = incomplete_bounds;
kono
parents:
diff changeset
2713 else if (chkp_incomplete_bounds (bnd2))
kono
parents:
diff changeset
2714 if (chkp_valid_bounds (bnd1)
kono
parents:
diff changeset
2715 && !chkp_incomplete_bounds (bnd1))
kono
parents:
diff changeset
2716 bounds = bnd1;
kono
parents:
diff changeset
2717 else
kono
parents:
diff changeset
2718 bounds = incomplete_bounds;
kono
parents:
diff changeset
2719 else if (!chkp_valid_bounds (bnd1))
kono
parents:
diff changeset
2720 if (chkp_valid_bounds (bnd2) && rhs_code != MINUS_EXPR)
kono
parents:
diff changeset
2721 bounds = bnd2;
kono
parents:
diff changeset
2722 else if (bnd2 == chkp_get_zero_bounds ())
kono
parents:
diff changeset
2723 bounds = bnd2;
kono
parents:
diff changeset
2724 else
kono
parents:
diff changeset
2725 bounds = bnd1;
kono
parents:
diff changeset
2726 else if (!chkp_valid_bounds (bnd2))
kono
parents:
diff changeset
2727 bounds = bnd1;
kono
parents:
diff changeset
2728 else
kono
parents:
diff changeset
2729 /* Seems both operands may have valid bounds
kono
parents:
diff changeset
2730 (e.g. pointer minus pointer). In such case
kono
parents:
diff changeset
2731 use default invalid op bounds. */
kono
parents:
diff changeset
2732 bounds = chkp_get_invalid_op_bounds ();
kono
parents:
diff changeset
2733
kono
parents:
diff changeset
2734 base = (bounds == bnd1) ? rhs1 : (bounds == bnd2) ? rhs2 : NULL;
kono
parents:
diff changeset
2735 }
kono
parents:
diff changeset
2736 break;
kono
parents:
diff changeset
2737
kono
parents:
diff changeset
2738 case BIT_NOT_EXPR:
kono
parents:
diff changeset
2739 case NEGATE_EXPR:
kono
parents:
diff changeset
2740 case LSHIFT_EXPR:
kono
parents:
diff changeset
2741 case RSHIFT_EXPR:
kono
parents:
diff changeset
2742 case LROTATE_EXPR:
kono
parents:
diff changeset
2743 case RROTATE_EXPR:
kono
parents:
diff changeset
2744 case EQ_EXPR:
kono
parents:
diff changeset
2745 case NE_EXPR:
kono
parents:
diff changeset
2746 case LT_EXPR:
kono
parents:
diff changeset
2747 case LE_EXPR:
kono
parents:
diff changeset
2748 case GT_EXPR:
kono
parents:
diff changeset
2749 case GE_EXPR:
kono
parents:
diff changeset
2750 case MULT_EXPR:
kono
parents:
diff changeset
2751 case RDIV_EXPR:
kono
parents:
diff changeset
2752 case TRUNC_DIV_EXPR:
kono
parents:
diff changeset
2753 case FLOOR_DIV_EXPR:
kono
parents:
diff changeset
2754 case CEIL_DIV_EXPR:
kono
parents:
diff changeset
2755 case ROUND_DIV_EXPR:
kono
parents:
diff changeset
2756 case TRUNC_MOD_EXPR:
kono
parents:
diff changeset
2757 case FLOOR_MOD_EXPR:
kono
parents:
diff changeset
2758 case CEIL_MOD_EXPR:
kono
parents:
diff changeset
2759 case ROUND_MOD_EXPR:
kono
parents:
diff changeset
2760 case EXACT_DIV_EXPR:
kono
parents:
diff changeset
2761 case FIX_TRUNC_EXPR:
kono
parents:
diff changeset
2762 case FLOAT_EXPR:
kono
parents:
diff changeset
2763 case REALPART_EXPR:
kono
parents:
diff changeset
2764 case IMAGPART_EXPR:
kono
parents:
diff changeset
2765 /* No valid bounds may be produced by these exprs. */
kono
parents:
diff changeset
2766 bounds = chkp_get_invalid_op_bounds ();
kono
parents:
diff changeset
2767 break;
kono
parents:
diff changeset
2768
kono
parents:
diff changeset
2769 case COND_EXPR:
kono
parents:
diff changeset
2770 {
kono
parents:
diff changeset
2771 tree val1 = gimple_assign_rhs2 (assign);
kono
parents:
diff changeset
2772 tree val2 = gimple_assign_rhs3 (assign);
kono
parents:
diff changeset
2773 tree bnd1 = chkp_find_bounds (val1, &iter);
kono
parents:
diff changeset
2774 tree bnd2 = chkp_find_bounds (val2, &iter);
kono
parents:
diff changeset
2775 gimple *stmt;
kono
parents:
diff changeset
2776
kono
parents:
diff changeset
2777 if (chkp_incomplete_bounds (bnd1) || chkp_incomplete_bounds (bnd2))
kono
parents:
diff changeset
2778 bounds = incomplete_bounds;
kono
parents:
diff changeset
2779 else if (bnd1 == bnd2)
kono
parents:
diff changeset
2780 bounds = bnd1;
kono
parents:
diff changeset
2781 else
kono
parents:
diff changeset
2782 {
kono
parents:
diff changeset
2783 rhs1 = unshare_expr (rhs1);
kono
parents:
diff changeset
2784
kono
parents:
diff changeset
2785 bounds = chkp_get_tmp_reg (assign);
kono
parents:
diff changeset
2786 stmt = gimple_build_assign (bounds, COND_EXPR, rhs1, bnd1, bnd2);
kono
parents:
diff changeset
2787 gsi_insert_after (&iter, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
2788
kono
parents:
diff changeset
2789 if (!chkp_valid_bounds (bnd1) && !chkp_valid_bounds (bnd2))
kono
parents:
diff changeset
2790 chkp_mark_invalid_bounds (bounds);
kono
parents:
diff changeset
2791 }
kono
parents:
diff changeset
2792 }
kono
parents:
diff changeset
2793 break;
kono
parents:
diff changeset
2794
kono
parents:
diff changeset
2795 case MAX_EXPR:
kono
parents:
diff changeset
2796 case MIN_EXPR:
kono
parents:
diff changeset
2797 {
kono
parents:
diff changeset
2798 tree rhs2 = gimple_assign_rhs2 (assign);
kono
parents:
diff changeset
2799 tree bnd1 = chkp_find_bounds (rhs1, &iter);
kono
parents:
diff changeset
2800 tree bnd2 = chkp_find_bounds (rhs2, &iter);
kono
parents:
diff changeset
2801
kono
parents:
diff changeset
2802 if (chkp_incomplete_bounds (bnd1) || chkp_incomplete_bounds (bnd2))
kono
parents:
diff changeset
2803 bounds = incomplete_bounds;
kono
parents:
diff changeset
2804 else if (bnd1 == bnd2)
kono
parents:
diff changeset
2805 bounds = bnd1;
kono
parents:
diff changeset
2806 else
kono
parents:
diff changeset
2807 {
kono
parents:
diff changeset
2808 gimple *stmt;
kono
parents:
diff changeset
2809 tree cond = build2 (rhs_code == MAX_EXPR ? GT_EXPR : LT_EXPR,
kono
parents:
diff changeset
2810 boolean_type_node, rhs1, rhs2);
kono
parents:
diff changeset
2811 bounds = chkp_get_tmp_reg (assign);
kono
parents:
diff changeset
2812 stmt = gimple_build_assign (bounds, COND_EXPR, cond, bnd1, bnd2);
kono
parents:
diff changeset
2813
kono
parents:
diff changeset
2814 gsi_insert_after (&iter, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
2815
kono
parents:
diff changeset
2816 if (!chkp_valid_bounds (bnd1) && !chkp_valid_bounds (bnd2))
kono
parents:
diff changeset
2817 chkp_mark_invalid_bounds (bounds);
kono
parents:
diff changeset
2818 }
kono
parents:
diff changeset
2819 }
kono
parents:
diff changeset
2820 break;
kono
parents:
diff changeset
2821
kono
parents:
diff changeset
2822 default:
kono
parents:
diff changeset
2823 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
2824 warning (0, "pointer bounds were lost due to unexpected expression %s",
kono
parents:
diff changeset
2825 get_tree_code_name (rhs_code));
kono
parents:
diff changeset
2826 }
kono
parents:
diff changeset
2827
kono
parents:
diff changeset
2828 gcc_assert (bounds);
kono
parents:
diff changeset
2829
kono
parents:
diff changeset
2830 /* We may reuse bounds of other pointer we copy/modify. But it is not
kono
parents:
diff changeset
2831 allowed for abnormal ssa names. If we produced a pointer using
kono
parents:
diff changeset
2832 abnormal ssa name, we better make a bounds copy to avoid coalescing
kono
parents:
diff changeset
2833 issues. */
kono
parents:
diff changeset
2834 if (base
kono
parents:
diff changeset
2835 && TREE_CODE (base) == SSA_NAME
kono
parents:
diff changeset
2836 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (base))
kono
parents:
diff changeset
2837 {
kono
parents:
diff changeset
2838 gimple *stmt = gimple_build_assign (chkp_get_tmp_reg (NULL), bounds);
kono
parents:
diff changeset
2839 gsi_insert_after (&iter, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
2840 bounds = gimple_assign_lhs (stmt);
kono
parents:
diff changeset
2841 }
kono
parents:
diff changeset
2842
kono
parents:
diff changeset
2843 if (node)
kono
parents:
diff changeset
2844 bounds = chkp_maybe_copy_and_register_bounds (node, bounds);
kono
parents:
diff changeset
2845
kono
parents:
diff changeset
2846 return bounds;
kono
parents:
diff changeset
2847 }
kono
parents:
diff changeset
2848
kono
parents:
diff changeset
2849 /* Compute bounds for ssa name NODE defined by DEF_STMT pointed by ITER.
kono
parents:
diff changeset
2850
kono
parents:
diff changeset
2851 There are just few statement codes allowed: NOP (for default ssa names),
kono
parents:
diff changeset
2852 ASSIGN, CALL, PHI, ASM.
kono
parents:
diff changeset
2853
kono
parents:
diff changeset
2854 Return computed bounds. */
kono
parents:
diff changeset
2855 static tree
kono
parents:
diff changeset
2856 chkp_get_bounds_by_definition (tree node, gimple *def_stmt,
kono
parents:
diff changeset
2857 gphi_iterator *iter)
kono
parents:
diff changeset
2858 {
kono
parents:
diff changeset
2859 tree var, bounds;
kono
parents:
diff changeset
2860 enum gimple_code code = gimple_code (def_stmt);
kono
parents:
diff changeset
2861 gphi *stmt;
kono
parents:
diff changeset
2862
kono
parents:
diff changeset
2863 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2864 {
kono
parents:
diff changeset
2865 fprintf (dump_file, "Searching for bounds for node: ");
kono
parents:
diff changeset
2866 print_generic_expr (dump_file, node);
kono
parents:
diff changeset
2867
kono
parents:
diff changeset
2868 fprintf (dump_file, " using its definition: ");
kono
parents:
diff changeset
2869 print_gimple_stmt (dump_file, def_stmt, 0, TDF_VOPS | TDF_MEMSYMS);
kono
parents:
diff changeset
2870 }
kono
parents:
diff changeset
2871
kono
parents:
diff changeset
2872 switch (code)
kono
parents:
diff changeset
2873 {
kono
parents:
diff changeset
2874 case GIMPLE_NOP:
kono
parents:
diff changeset
2875 var = SSA_NAME_VAR (node);
kono
parents:
diff changeset
2876 switch (TREE_CODE (var))
kono
parents:
diff changeset
2877 {
kono
parents:
diff changeset
2878 case PARM_DECL:
kono
parents:
diff changeset
2879 bounds = chkp_get_bound_for_parm (node);
kono
parents:
diff changeset
2880 break;
kono
parents:
diff changeset
2881
kono
parents:
diff changeset
2882 case VAR_DECL:
kono
parents:
diff changeset
2883 /* For uninitialized pointers use none bounds. */
kono
parents:
diff changeset
2884 bounds = chkp_get_none_bounds ();
kono
parents:
diff changeset
2885 bounds = chkp_maybe_copy_and_register_bounds (node, bounds);
kono
parents:
diff changeset
2886 break;
kono
parents:
diff changeset
2887
kono
parents:
diff changeset
2888 case RESULT_DECL:
kono
parents:
diff changeset
2889 {
kono
parents:
diff changeset
2890 tree base_type;
kono
parents:
diff changeset
2891
kono
parents:
diff changeset
2892 gcc_assert (TREE_CODE (TREE_TYPE (node)) == REFERENCE_TYPE);
kono
parents:
diff changeset
2893
kono
parents:
diff changeset
2894 base_type = TREE_TYPE (TREE_TYPE (node));
kono
parents:
diff changeset
2895
kono
parents:
diff changeset
2896 gcc_assert (TYPE_SIZE (base_type)
kono
parents:
diff changeset
2897 && TREE_CODE (TYPE_SIZE (base_type)) == INTEGER_CST
kono
parents:
diff changeset
2898 && tree_to_uhwi (TYPE_SIZE (base_type)) != 0);
kono
parents:
diff changeset
2899
kono
parents:
diff changeset
2900 bounds = chkp_make_bounds (node, TYPE_SIZE_UNIT (base_type),
kono
parents:
diff changeset
2901 NULL, false);
kono
parents:
diff changeset
2902 bounds = chkp_maybe_copy_and_register_bounds (node, bounds);
kono
parents:
diff changeset
2903 }
kono
parents:
diff changeset
2904 break;
kono
parents:
diff changeset
2905
kono
parents:
diff changeset
2906 default:
kono
parents:
diff changeset
2907 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2908 {
kono
parents:
diff changeset
2909 fprintf (dump_file, "Unexpected var with no definition\n");
kono
parents:
diff changeset
2910 print_generic_expr (dump_file, var);
kono
parents:
diff changeset
2911 }
kono
parents:
diff changeset
2912 internal_error ("chkp_get_bounds_by_definition: Unexpected var of type %s",
kono
parents:
diff changeset
2913 get_tree_code_name (TREE_CODE (var)));
kono
parents:
diff changeset
2914 }
kono
parents:
diff changeset
2915 break;
kono
parents:
diff changeset
2916
kono
parents:
diff changeset
2917 case GIMPLE_ASSIGN:
kono
parents:
diff changeset
2918 bounds = chkp_compute_bounds_for_assignment (node, def_stmt);
kono
parents:
diff changeset
2919 break;
kono
parents:
diff changeset
2920
kono
parents:
diff changeset
2921 case GIMPLE_CALL:
kono
parents:
diff changeset
2922 bounds = chkp_build_returned_bound (as_a <gcall *> (def_stmt));
kono
parents:
diff changeset
2923 break;
kono
parents:
diff changeset
2924
kono
parents:
diff changeset
2925 case GIMPLE_PHI:
kono
parents:
diff changeset
2926 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (node))
kono
parents:
diff changeset
2927 if (SSA_NAME_VAR (node))
kono
parents:
diff changeset
2928 var = chkp_get_bounds_var (SSA_NAME_VAR (node));
kono
parents:
diff changeset
2929 else
kono
parents:
diff changeset
2930 var = make_temp_ssa_name (pointer_bounds_type_node,
kono
parents:
diff changeset
2931 NULL,
kono
parents:
diff changeset
2932 CHKP_BOUND_TMP_NAME);
kono
parents:
diff changeset
2933 else
kono
parents:
diff changeset
2934 var = chkp_get_tmp_var ();
kono
parents:
diff changeset
2935 stmt = create_phi_node (var, gimple_bb (def_stmt));
kono
parents:
diff changeset
2936 bounds = gimple_phi_result (stmt);
kono
parents:
diff changeset
2937 *iter = gsi_for_phi (stmt);
kono
parents:
diff changeset
2938
kono
parents:
diff changeset
2939 bounds = chkp_maybe_copy_and_register_bounds (node, bounds);
kono
parents:
diff changeset
2940
kono
parents:
diff changeset
2941 /* Created bounds do not have all phi args computed and
kono
parents:
diff changeset
2942 therefore we do not know if there is a valid source
kono
parents:
diff changeset
2943 of bounds for that node. Therefore we mark bounds
kono
parents:
diff changeset
2944 as incomplete and then recompute them when all phi
kono
parents:
diff changeset
2945 args are computed. */
kono
parents:
diff changeset
2946 chkp_register_incomplete_bounds (bounds, node);
kono
parents:
diff changeset
2947 break;
kono
parents:
diff changeset
2948
kono
parents:
diff changeset
2949 case GIMPLE_ASM:
kono
parents:
diff changeset
2950 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
2951 bounds = chkp_maybe_copy_and_register_bounds (node, bounds);
kono
parents:
diff changeset
2952 break;
kono
parents:
diff changeset
2953
kono
parents:
diff changeset
2954 default:
kono
parents:
diff changeset
2955 internal_error ("chkp_get_bounds_by_definition: Unexpected GIMPLE code %s",
kono
parents:
diff changeset
2956 gimple_code_name[code]);
kono
parents:
diff changeset
2957 }
kono
parents:
diff changeset
2958
kono
parents:
diff changeset
2959 return bounds;
kono
parents:
diff changeset
2960 }
kono
parents:
diff changeset
2961
kono
parents:
diff changeset
2962 /* Return CALL_EXPR for bndmk with specified LOWER_BOUND and SIZE. */
kono
parents:
diff changeset
2963 tree
kono
parents:
diff changeset
2964 chkp_build_make_bounds_call (tree lower_bound, tree size)
kono
parents:
diff changeset
2965 {
kono
parents:
diff changeset
2966 tree call = build1 (ADDR_EXPR,
kono
parents:
diff changeset
2967 build_pointer_type (TREE_TYPE (chkp_bndmk_fndecl)),
kono
parents:
diff changeset
2968 chkp_bndmk_fndecl);
kono
parents:
diff changeset
2969 return build_call_nary (TREE_TYPE (TREE_TYPE (chkp_bndmk_fndecl)),
kono
parents:
diff changeset
2970 call, 2, lower_bound, size);
kono
parents:
diff changeset
2971 }
kono
parents:
diff changeset
2972
kono
parents:
diff changeset
2973 /* Create static bounds var of specfified OBJ which is
kono
parents:
diff changeset
2974 is either VAR_DECL or string constant. */
kono
parents:
diff changeset
2975 static tree
kono
parents:
diff changeset
2976 chkp_make_static_bounds (tree obj)
kono
parents:
diff changeset
2977 {
kono
parents:
diff changeset
2978 static int string_id = 1;
kono
parents:
diff changeset
2979 static int var_id = 1;
kono
parents:
diff changeset
2980 tree *slot;
kono
parents:
diff changeset
2981 const char *var_name;
kono
parents:
diff changeset
2982 char *bnd_var_name;
kono
parents:
diff changeset
2983 tree bnd_var;
kono
parents:
diff changeset
2984
kono
parents:
diff changeset
2985 /* First check if we already have required var. */
kono
parents:
diff changeset
2986 if (chkp_static_var_bounds)
kono
parents:
diff changeset
2987 {
kono
parents:
diff changeset
2988 /* For vars we use assembler name as a key in
kono
parents:
diff changeset
2989 chkp_static_var_bounds map. It allows to
kono
parents:
diff changeset
2990 avoid duplicating bound vars for decls
kono
parents:
diff changeset
2991 sharing assembler name. */
kono
parents:
diff changeset
2992 if (VAR_P (obj))
kono
parents:
diff changeset
2993 {
kono
parents:
diff changeset
2994 tree name = DECL_ASSEMBLER_NAME (obj);
kono
parents:
diff changeset
2995 slot = chkp_static_var_bounds->get (name);
kono
parents:
diff changeset
2996 if (slot)
kono
parents:
diff changeset
2997 return *slot;
kono
parents:
diff changeset
2998 }
kono
parents:
diff changeset
2999 else
kono
parents:
diff changeset
3000 {
kono
parents:
diff changeset
3001 slot = chkp_static_var_bounds->get (obj);
kono
parents:
diff changeset
3002 if (slot)
kono
parents:
diff changeset
3003 return *slot;
kono
parents:
diff changeset
3004 }
kono
parents:
diff changeset
3005 }
kono
parents:
diff changeset
3006
kono
parents:
diff changeset
3007 /* Build decl for bounds var. */
kono
parents:
diff changeset
3008 if (VAR_P (obj))
kono
parents:
diff changeset
3009 {
kono
parents:
diff changeset
3010 if (DECL_IGNORED_P (obj))
kono
parents:
diff changeset
3011 {
kono
parents:
diff changeset
3012 bnd_var_name = (char *) xmalloc (strlen (CHKP_VAR_BOUNDS_PREFIX) + 10);
kono
parents:
diff changeset
3013 sprintf (bnd_var_name, "%s%d", CHKP_VAR_BOUNDS_PREFIX, var_id++);
kono
parents:
diff changeset
3014 }
kono
parents:
diff changeset
3015 else
kono
parents:
diff changeset
3016 {
kono
parents:
diff changeset
3017 var_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (obj));
kono
parents:
diff changeset
3018
kono
parents:
diff changeset
3019 /* For hidden symbols we want to skip first '*' char. */
kono
parents:
diff changeset
3020 if (*var_name == '*')
kono
parents:
diff changeset
3021 var_name++;
kono
parents:
diff changeset
3022
kono
parents:
diff changeset
3023 bnd_var_name = (char *) xmalloc (strlen (var_name)
kono
parents:
diff changeset
3024 + strlen (CHKP_BOUNDS_OF_SYMBOL_PREFIX) + 1);
kono
parents:
diff changeset
3025 strcpy (bnd_var_name, CHKP_BOUNDS_OF_SYMBOL_PREFIX);
kono
parents:
diff changeset
3026 strcat (bnd_var_name, var_name);
kono
parents:
diff changeset
3027 }
kono
parents:
diff changeset
3028
kono
parents:
diff changeset
3029 bnd_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
kono
parents:
diff changeset
3030 get_identifier (bnd_var_name),
kono
parents:
diff changeset
3031 pointer_bounds_type_node);
kono
parents:
diff changeset
3032
kono
parents:
diff changeset
3033 /* Address of the obj will be used as lower bound. */
kono
parents:
diff changeset
3034 TREE_ADDRESSABLE (obj) = 1;
kono
parents:
diff changeset
3035 }
kono
parents:
diff changeset
3036 else
kono
parents:
diff changeset
3037 {
kono
parents:
diff changeset
3038 bnd_var_name = (char *) xmalloc (strlen (CHKP_STRING_BOUNDS_PREFIX) + 10);
kono
parents:
diff changeset
3039 sprintf (bnd_var_name, "%s%d", CHKP_STRING_BOUNDS_PREFIX, string_id++);
kono
parents:
diff changeset
3040
kono
parents:
diff changeset
3041 bnd_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
kono
parents:
diff changeset
3042 get_identifier (bnd_var_name),
kono
parents:
diff changeset
3043 pointer_bounds_type_node);
kono
parents:
diff changeset
3044 }
kono
parents:
diff changeset
3045
kono
parents:
diff changeset
3046 free (bnd_var_name);
kono
parents:
diff changeset
3047
kono
parents:
diff changeset
3048 TREE_PUBLIC (bnd_var) = 0;
kono
parents:
diff changeset
3049 TREE_USED (bnd_var) = 1;
kono
parents:
diff changeset
3050 TREE_READONLY (bnd_var) = 0;
kono
parents:
diff changeset
3051 TREE_STATIC (bnd_var) = 1;
kono
parents:
diff changeset
3052 TREE_ADDRESSABLE (bnd_var) = 0;
kono
parents:
diff changeset
3053 DECL_ARTIFICIAL (bnd_var) = 1;
kono
parents:
diff changeset
3054 DECL_COMMON (bnd_var) = 1;
kono
parents:
diff changeset
3055 DECL_COMDAT (bnd_var) = 1;
kono
parents:
diff changeset
3056 DECL_READ_P (bnd_var) = 1;
kono
parents:
diff changeset
3057 DECL_INITIAL (bnd_var) = chkp_build_addr_expr (obj);
kono
parents:
diff changeset
3058 /* Force output similar to constant bounds.
kono
parents:
diff changeset
3059 See chkp_make_static_const_bounds. */
kono
parents:
diff changeset
3060 varpool_node::get_create (bnd_var)->force_output = 1;
kono
parents:
diff changeset
3061 /* Mark symbol as requiring bounds initialization. */
kono
parents:
diff changeset
3062 varpool_node::get_create (bnd_var)->need_bounds_init = 1;
kono
parents:
diff changeset
3063 varpool_node::finalize_decl (bnd_var);
kono
parents:
diff changeset
3064
kono
parents:
diff changeset
3065 /* Add created var to the map to use it for other references
kono
parents:
diff changeset
3066 to obj. */
kono
parents:
diff changeset
3067 if (!chkp_static_var_bounds)
kono
parents:
diff changeset
3068 chkp_static_var_bounds = new hash_map<tree, tree>;
kono
parents:
diff changeset
3069
kono
parents:
diff changeset
3070 if (VAR_P (obj))
kono
parents:
diff changeset
3071 {
kono
parents:
diff changeset
3072 tree name = DECL_ASSEMBLER_NAME (obj);
kono
parents:
diff changeset
3073 chkp_static_var_bounds->put (name, bnd_var);
kono
parents:
diff changeset
3074 }
kono
parents:
diff changeset
3075 else
kono
parents:
diff changeset
3076 chkp_static_var_bounds->put (obj, bnd_var);
kono
parents:
diff changeset
3077
kono
parents:
diff changeset
3078 return bnd_var;
kono
parents:
diff changeset
3079 }
kono
parents:
diff changeset
3080
kono
parents:
diff changeset
3081 /* When var has incomplete type we cannot get size to
kono
parents:
diff changeset
3082 compute its bounds. In such cases we use checker
kono
parents:
diff changeset
3083 builtin call which determines object size at runtime. */
kono
parents:
diff changeset
3084 static tree
kono
parents:
diff changeset
3085 chkp_generate_extern_var_bounds (tree var)
kono
parents:
diff changeset
3086 {
kono
parents:
diff changeset
3087 tree bounds, size_reloc, lb, size, max_size, cond;
kono
parents:
diff changeset
3088 gimple_stmt_iterator gsi;
kono
parents:
diff changeset
3089 gimple_seq seq = NULL;
kono
parents:
diff changeset
3090 gimple *stmt;
kono
parents:
diff changeset
3091
kono
parents:
diff changeset
3092 /* If instrumentation is not enabled for vars having
kono
parents:
diff changeset
3093 incomplete type then just return zero bounds to avoid
kono
parents:
diff changeset
3094 checks for this var. */
kono
parents:
diff changeset
3095 if (!flag_chkp_incomplete_type)
kono
parents:
diff changeset
3096 return chkp_get_zero_bounds ();
kono
parents:
diff changeset
3097
kono
parents:
diff changeset
3098 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3099 {
kono
parents:
diff changeset
3100 fprintf (dump_file, "Generating bounds for extern symbol '");
kono
parents:
diff changeset
3101 print_generic_expr (dump_file, var);
kono
parents:
diff changeset
3102 fprintf (dump_file, "'\n");
kono
parents:
diff changeset
3103 }
kono
parents:
diff changeset
3104
kono
parents:
diff changeset
3105 stmt = gimple_build_call (chkp_sizeof_fndecl, 1, var);
kono
parents:
diff changeset
3106
kono
parents:
diff changeset
3107 size_reloc = create_tmp_reg (chkp_uintptr_type, CHKP_SIZE_TMP_NAME);
kono
parents:
diff changeset
3108 gimple_call_set_lhs (stmt, size_reloc);
kono
parents:
diff changeset
3109
kono
parents:
diff changeset
3110 gimple_seq_add_stmt (&seq, stmt);
kono
parents:
diff changeset
3111
kono
parents:
diff changeset
3112 lb = chkp_build_addr_expr (var);
kono
parents:
diff changeset
3113 size = make_ssa_name (chkp_get_size_tmp_var ());
kono
parents:
diff changeset
3114
kono
parents:
diff changeset
3115 if (flag_chkp_zero_dynamic_size_as_infinite)
kono
parents:
diff changeset
3116 {
kono
parents:
diff changeset
3117 /* We should check that size relocation was resolved.
kono
parents:
diff changeset
3118 If it was not then use maximum possible size for the var. */
kono
parents:
diff changeset
3119 max_size = build2 (MINUS_EXPR, chkp_uintptr_type, integer_zero_node,
kono
parents:
diff changeset
3120 fold_convert (chkp_uintptr_type, lb));
kono
parents:
diff changeset
3121 max_size = chkp_force_gimple_call_op (max_size, &seq);
kono
parents:
diff changeset
3122
kono
parents:
diff changeset
3123 cond = build2 (NE_EXPR, boolean_type_node,
kono
parents:
diff changeset
3124 size_reloc, integer_zero_node);
kono
parents:
diff changeset
3125 stmt = gimple_build_assign (size, COND_EXPR, cond, size_reloc, max_size);
kono
parents:
diff changeset
3126 gimple_seq_add_stmt (&seq, stmt);
kono
parents:
diff changeset
3127 }
kono
parents:
diff changeset
3128 else
kono
parents:
diff changeset
3129 {
kono
parents:
diff changeset
3130 stmt = gimple_build_assign (size, size_reloc);
kono
parents:
diff changeset
3131 gimple_seq_add_stmt (&seq, stmt);
kono
parents:
diff changeset
3132 }
kono
parents:
diff changeset
3133
kono
parents:
diff changeset
3134 gsi = gsi_start_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
3135 gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
kono
parents:
diff changeset
3136
kono
parents:
diff changeset
3137 bounds = chkp_make_bounds (lb, size, &gsi, true);
kono
parents:
diff changeset
3138
kono
parents:
diff changeset
3139 return bounds;
kono
parents:
diff changeset
3140 }
kono
parents:
diff changeset
3141
kono
parents:
diff changeset
3142 /* Return 1 if TYPE has fields with zero size or fields
kono
parents:
diff changeset
3143 marked with chkp_variable_size attribute. */
kono
parents:
diff changeset
3144 bool
kono
parents:
diff changeset
3145 chkp_variable_size_type (tree type)
kono
parents:
diff changeset
3146 {
kono
parents:
diff changeset
3147 bool res = false;
kono
parents:
diff changeset
3148 tree field;
kono
parents:
diff changeset
3149
kono
parents:
diff changeset
3150 if (RECORD_OR_UNION_TYPE_P (type))
kono
parents:
diff changeset
3151 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
kono
parents:
diff changeset
3152 {
kono
parents:
diff changeset
3153 if (TREE_CODE (field) == FIELD_DECL)
kono
parents:
diff changeset
3154 res = res
kono
parents:
diff changeset
3155 || lookup_attribute ("bnd_variable_size", DECL_ATTRIBUTES (field))
kono
parents:
diff changeset
3156 || chkp_variable_size_type (TREE_TYPE (field));
kono
parents:
diff changeset
3157 }
kono
parents:
diff changeset
3158 else
kono
parents:
diff changeset
3159 res = !TYPE_SIZE (type)
kono
parents:
diff changeset
3160 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
kono
parents:
diff changeset
3161 || tree_to_uhwi (TYPE_SIZE (type)) == 0;
kono
parents:
diff changeset
3162
kono
parents:
diff changeset
3163 return res;
kono
parents:
diff changeset
3164 }
kono
parents:
diff changeset
3165
kono
parents:
diff changeset
3166 /* Compute and return bounds for address of DECL which is
kono
parents:
diff changeset
3167 one of VAR_DECL, PARM_DECL, RESULT_DECL. */
kono
parents:
diff changeset
3168 static tree
kono
parents:
diff changeset
3169 chkp_get_bounds_for_decl_addr (tree decl)
kono
parents:
diff changeset
3170 {
kono
parents:
diff changeset
3171 tree bounds;
kono
parents:
diff changeset
3172
kono
parents:
diff changeset
3173 gcc_assert (VAR_P (decl)
kono
parents:
diff changeset
3174 || TREE_CODE (decl) == PARM_DECL
kono
parents:
diff changeset
3175 || TREE_CODE (decl) == RESULT_DECL);
kono
parents:
diff changeset
3176
kono
parents:
diff changeset
3177 bounds = chkp_get_registered_addr_bounds (decl);
kono
parents:
diff changeset
3178
kono
parents:
diff changeset
3179 if (bounds)
kono
parents:
diff changeset
3180 return bounds;
kono
parents:
diff changeset
3181
kono
parents:
diff changeset
3182 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3183 {
kono
parents:
diff changeset
3184 fprintf (dump_file, "Building bounds for address of decl ");
kono
parents:
diff changeset
3185 print_generic_expr (dump_file, decl);
kono
parents:
diff changeset
3186 fprintf (dump_file, "\n");
kono
parents:
diff changeset
3187 }
kono
parents:
diff changeset
3188
kono
parents:
diff changeset
3189 /* Use zero bounds if size is unknown and checks for
kono
parents:
diff changeset
3190 unknown sizes are restricted. */
kono
parents:
diff changeset
3191 if ((!DECL_SIZE (decl)
kono
parents:
diff changeset
3192 || (chkp_variable_size_type (TREE_TYPE (decl))
kono
parents:
diff changeset
3193 && (TREE_STATIC (decl)
kono
parents:
diff changeset
3194 || DECL_EXTERNAL (decl)
kono
parents:
diff changeset
3195 || TREE_PUBLIC (decl))))
kono
parents:
diff changeset
3196 && !flag_chkp_incomplete_type)
kono
parents:
diff changeset
3197 return chkp_get_zero_bounds ();
kono
parents:
diff changeset
3198
kono
parents:
diff changeset
3199 if (VOID_TYPE_P (TREE_TYPE (decl)))
kono
parents:
diff changeset
3200 return chkp_get_zero_bounds ();
kono
parents:
diff changeset
3201
kono
parents:
diff changeset
3202 if (flag_chkp_use_static_bounds
kono
parents:
diff changeset
3203 && VAR_P (decl)
kono
parents:
diff changeset
3204 && (TREE_STATIC (decl)
kono
parents:
diff changeset
3205 || DECL_EXTERNAL (decl)
kono
parents:
diff changeset
3206 || TREE_PUBLIC (decl))
kono
parents:
diff changeset
3207 && !DECL_THREAD_LOCAL_P (decl))
kono
parents:
diff changeset
3208 {
kono
parents:
diff changeset
3209 tree bnd_var = chkp_make_static_bounds (decl);
kono
parents:
diff changeset
3210 gimple_stmt_iterator gsi = gsi_start_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
3211 gimple *stmt;
kono
parents:
diff changeset
3212
kono
parents:
diff changeset
3213 bounds = chkp_get_tmp_reg (NULL);
kono
parents:
diff changeset
3214 stmt = gimple_build_assign (bounds, bnd_var);
kono
parents:
diff changeset
3215 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3216 }
kono
parents:
diff changeset
3217 else if (!DECL_SIZE (decl)
kono
parents:
diff changeset
3218 || (chkp_variable_size_type (TREE_TYPE (decl))
kono
parents:
diff changeset
3219 && (TREE_STATIC (decl)
kono
parents:
diff changeset
3220 || DECL_EXTERNAL (decl)
kono
parents:
diff changeset
3221 || TREE_PUBLIC (decl))))
kono
parents:
diff changeset
3222 {
kono
parents:
diff changeset
3223 gcc_assert (VAR_P (decl));
kono
parents:
diff changeset
3224 bounds = chkp_generate_extern_var_bounds (decl);
kono
parents:
diff changeset
3225 }
kono
parents:
diff changeset
3226 else
kono
parents:
diff changeset
3227 {
kono
parents:
diff changeset
3228 tree lb = chkp_build_addr_expr (decl);
kono
parents:
diff changeset
3229 bounds = chkp_make_bounds (lb, DECL_SIZE_UNIT (decl), NULL, false);
kono
parents:
diff changeset
3230 }
kono
parents:
diff changeset
3231
kono
parents:
diff changeset
3232 return bounds;
kono
parents:
diff changeset
3233 }
kono
parents:
diff changeset
3234
kono
parents:
diff changeset
3235 /* Compute and return bounds for constant string. */
kono
parents:
diff changeset
3236 static tree
kono
parents:
diff changeset
3237 chkp_get_bounds_for_string_cst (tree cst)
kono
parents:
diff changeset
3238 {
kono
parents:
diff changeset
3239 tree bounds;
kono
parents:
diff changeset
3240 tree lb;
kono
parents:
diff changeset
3241 tree size;
kono
parents:
diff changeset
3242
kono
parents:
diff changeset
3243 gcc_assert (TREE_CODE (cst) == STRING_CST);
kono
parents:
diff changeset
3244
kono
parents:
diff changeset
3245 bounds = chkp_get_registered_bounds (cst);
kono
parents:
diff changeset
3246
kono
parents:
diff changeset
3247 if (bounds)
kono
parents:
diff changeset
3248 return bounds;
kono
parents:
diff changeset
3249
kono
parents:
diff changeset
3250 if ((flag_chkp_use_static_bounds && flag_chkp_use_static_const_bounds)
kono
parents:
diff changeset
3251 || flag_chkp_use_static_const_bounds > 0)
kono
parents:
diff changeset
3252 {
kono
parents:
diff changeset
3253 tree bnd_var = chkp_make_static_bounds (cst);
kono
parents:
diff changeset
3254 gimple_stmt_iterator gsi = gsi_start_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
3255 gimple *stmt;
kono
parents:
diff changeset
3256
kono
parents:
diff changeset
3257 bounds = chkp_get_tmp_reg (NULL);
kono
parents:
diff changeset
3258 stmt = gimple_build_assign (bounds, bnd_var);
kono
parents:
diff changeset
3259 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3260 }
kono
parents:
diff changeset
3261 else
kono
parents:
diff changeset
3262 {
kono
parents:
diff changeset
3263 lb = chkp_build_addr_expr (cst);
kono
parents:
diff changeset
3264 size = build_int_cst (chkp_uintptr_type, TREE_STRING_LENGTH (cst));
kono
parents:
diff changeset
3265 bounds = chkp_make_bounds (lb, size, NULL, false);
kono
parents:
diff changeset
3266 }
kono
parents:
diff changeset
3267
kono
parents:
diff changeset
3268 bounds = chkp_maybe_copy_and_register_bounds (cst, bounds);
kono
parents:
diff changeset
3269
kono
parents:
diff changeset
3270 return bounds;
kono
parents:
diff changeset
3271 }
kono
parents:
diff changeset
3272
kono
parents:
diff changeset
3273 /* Generate code to instersect bounds BOUNDS1 and BOUNDS2 and
kono
parents:
diff changeset
3274 return the result. if ITER is not NULL then Code is inserted
kono
parents:
diff changeset
3275 before position pointed by ITER. Otherwise code is added to
kono
parents:
diff changeset
3276 entry block. */
kono
parents:
diff changeset
3277 static tree
kono
parents:
diff changeset
3278 chkp_intersect_bounds (tree bounds1, tree bounds2, gimple_stmt_iterator *iter)
kono
parents:
diff changeset
3279 {
kono
parents:
diff changeset
3280 if (!bounds1 || bounds1 == chkp_get_zero_bounds ())
kono
parents:
diff changeset
3281 return bounds2 ? bounds2 : bounds1;
kono
parents:
diff changeset
3282 else if (!bounds2 || bounds2 == chkp_get_zero_bounds ())
kono
parents:
diff changeset
3283 return bounds1;
kono
parents:
diff changeset
3284 else
kono
parents:
diff changeset
3285 {
kono
parents:
diff changeset
3286 gimple_seq seq;
kono
parents:
diff changeset
3287 gimple *stmt;
kono
parents:
diff changeset
3288 tree bounds;
kono
parents:
diff changeset
3289
kono
parents:
diff changeset
3290 seq = NULL;
kono
parents:
diff changeset
3291
kono
parents:
diff changeset
3292 stmt = gimple_build_call (chkp_intersect_fndecl, 2, bounds1, bounds2);
kono
parents:
diff changeset
3293 chkp_mark_stmt (stmt);
kono
parents:
diff changeset
3294
kono
parents:
diff changeset
3295 bounds = chkp_get_tmp_reg (stmt);
kono
parents:
diff changeset
3296 gimple_call_set_lhs (stmt, bounds);
kono
parents:
diff changeset
3297
kono
parents:
diff changeset
3298 gimple_seq_add_stmt (&seq, stmt);
kono
parents:
diff changeset
3299
kono
parents:
diff changeset
3300 /* We are probably doing narrowing for constant expression.
kono
parents:
diff changeset
3301 In such case iter may be undefined. */
kono
parents:
diff changeset
3302 if (!iter)
kono
parents:
diff changeset
3303 {
kono
parents:
diff changeset
3304 gimple_stmt_iterator gsi = gsi_last_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
3305 iter = &gsi;
kono
parents:
diff changeset
3306 gsi_insert_seq_after (iter, seq, GSI_SAME_STMT);
kono
parents:
diff changeset
3307 }
kono
parents:
diff changeset
3308 else
kono
parents:
diff changeset
3309 gsi_insert_seq_before (iter, seq, GSI_SAME_STMT);
kono
parents:
diff changeset
3310
kono
parents:
diff changeset
3311 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3312 {
kono
parents:
diff changeset
3313 fprintf (dump_file, "Bounds intersection: ");
kono
parents:
diff changeset
3314 print_gimple_stmt (dump_file, stmt, 0, TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
3315 fprintf (dump_file, " inserted before statement: ");
kono
parents:
diff changeset
3316 print_gimple_stmt (dump_file, gsi_stmt (*iter), 0,
kono
parents:
diff changeset
3317 TDF_VOPS|TDF_MEMSYMS);
kono
parents:
diff changeset
3318 }
kono
parents:
diff changeset
3319
kono
parents:
diff changeset
3320 return bounds;
kono
parents:
diff changeset
3321 }
kono
parents:
diff changeset
3322 }
kono
parents:
diff changeset
3323
kono
parents:
diff changeset
3324 /* Return 1 if we are allowed to narrow bounds for addressed FIELD
kono
parents:
diff changeset
3325 and 0 othersize. REF is reference to the field. */
kono
parents:
diff changeset
3326
kono
parents:
diff changeset
3327 static bool
kono
parents:
diff changeset
3328 chkp_may_narrow_to_field (tree ref, tree field)
kono
parents:
diff changeset
3329 {
kono
parents:
diff changeset
3330 return DECL_SIZE (field) && TREE_CODE (DECL_SIZE (field)) == INTEGER_CST
kono
parents:
diff changeset
3331 && tree_to_uhwi (DECL_SIZE (field)) != 0
kono
parents:
diff changeset
3332 && !(flag_chkp_flexible_struct_trailing_arrays
kono
parents:
diff changeset
3333 && array_at_struct_end_p (ref))
kono
parents:
diff changeset
3334 && (!DECL_FIELD_OFFSET (field)
kono
parents:
diff changeset
3335 || TREE_CODE (DECL_FIELD_OFFSET (field)) == INTEGER_CST)
kono
parents:
diff changeset
3336 && (!DECL_FIELD_BIT_OFFSET (field)
kono
parents:
diff changeset
3337 || TREE_CODE (DECL_FIELD_BIT_OFFSET (field)) == INTEGER_CST)
kono
parents:
diff changeset
3338 && !lookup_attribute ("bnd_variable_size", DECL_ATTRIBUTES (field))
kono
parents:
diff changeset
3339 && !chkp_variable_size_type (TREE_TYPE (field));
kono
parents:
diff changeset
3340 }
kono
parents:
diff changeset
3341
kono
parents:
diff changeset
3342 /* Return 1 if bounds for FIELD should be narrowed to
kono
parents:
diff changeset
3343 field's own size. REF is reference to the field. */
kono
parents:
diff changeset
3344
kono
parents:
diff changeset
3345 static bool
kono
parents:
diff changeset
3346 chkp_narrow_bounds_for_field (tree ref, tree field)
kono
parents:
diff changeset
3347 {
kono
parents:
diff changeset
3348 HOST_WIDE_INT offs;
kono
parents:
diff changeset
3349 HOST_WIDE_INT bit_offs;
kono
parents:
diff changeset
3350
kono
parents:
diff changeset
3351 if (!chkp_may_narrow_to_field (ref, field))
kono
parents:
diff changeset
3352 return false;
kono
parents:
diff changeset
3353
kono
parents:
diff changeset
3354 /* Access to compiler generated fields should not cause
kono
parents:
diff changeset
3355 bounds narrowing. */
kono
parents:
diff changeset
3356 if (DECL_ARTIFICIAL (field))
kono
parents:
diff changeset
3357 return false;
kono
parents:
diff changeset
3358
kono
parents:
diff changeset
3359 offs = tree_to_uhwi (DECL_FIELD_OFFSET (field));
kono
parents:
diff changeset
3360 bit_offs = tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field));
kono
parents:
diff changeset
3361
kono
parents:
diff changeset
3362 return (flag_chkp_narrow_bounds
kono
parents:
diff changeset
3363 && (flag_chkp_first_field_has_own_bounds
kono
parents:
diff changeset
3364 || offs
kono
parents:
diff changeset
3365 || bit_offs));
kono
parents:
diff changeset
3366 }
kono
parents:
diff changeset
3367
kono
parents:
diff changeset
3368 /* Perform narrowing for BOUNDS of an INNER reference. Shift boundary
kono
parents:
diff changeset
3369 by OFFSET bytes and limit to SIZE bytes. Newly created statements are
kono
parents:
diff changeset
3370 added to ITER. */
kono
parents:
diff changeset
3371
kono
parents:
diff changeset
3372 static tree
kono
parents:
diff changeset
3373 chkp_narrow_size_and_offset (tree bounds, tree inner, tree offset,
kono
parents:
diff changeset
3374 tree size, gimple_stmt_iterator *iter)
kono
parents:
diff changeset
3375 {
kono
parents:
diff changeset
3376 tree addr = chkp_build_addr_expr (unshare_expr (inner));
kono
parents:
diff changeset
3377 tree t = TREE_TYPE (addr);
kono
parents:
diff changeset
3378
kono
parents:
diff changeset
3379 gimple *stmt = gimple_build_assign (NULL_TREE, addr);
kono
parents:
diff changeset
3380 addr = make_temp_ssa_name (t, stmt, CHKP_BOUND_TMP_NAME);
kono
parents:
diff changeset
3381 gimple_assign_set_lhs (stmt, addr);
kono
parents:
diff changeset
3382 gsi_insert_seq_before (iter, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3383
kono
parents:
diff changeset
3384 stmt = gimple_build_assign (NULL_TREE, POINTER_PLUS_EXPR, addr, offset);
kono
parents:
diff changeset
3385 tree shifted = make_temp_ssa_name (t, stmt, CHKP_BOUND_TMP_NAME);
kono
parents:
diff changeset
3386 gimple_assign_set_lhs (stmt, shifted);
kono
parents:
diff changeset
3387 gsi_insert_seq_before (iter, stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3388
kono
parents:
diff changeset
3389 tree bounds2 = chkp_make_bounds (shifted, size, iter, false);
kono
parents:
diff changeset
3390
kono
parents:
diff changeset
3391 return chkp_intersect_bounds (bounds, bounds2, iter);
kono
parents:
diff changeset
3392 }
kono
parents:
diff changeset
3393
kono
parents:
diff changeset
3394 /* Perform narrowing for BOUNDS using bounds computed for field
kono
parents:
diff changeset
3395 access COMPONENT. ITER meaning is the same as for
kono
parents:
diff changeset
3396 chkp_intersect_bounds. */
kono
parents:
diff changeset
3397
kono
parents:
diff changeset
3398 static tree
kono
parents:
diff changeset
3399 chkp_narrow_bounds_to_field (tree bounds, tree component,
kono
parents:
diff changeset
3400 gimple_stmt_iterator *iter)
kono
parents:
diff changeset
3401 {
kono
parents:
diff changeset
3402 tree field = TREE_OPERAND (component, 1);
kono
parents:
diff changeset
3403 tree size = DECL_SIZE_UNIT (field);
kono
parents:
diff changeset
3404 tree field_ptr = chkp_build_addr_expr (component);
kono
parents:
diff changeset
3405 tree field_bounds;
kono
parents:
diff changeset
3406
kono
parents:
diff changeset
3407 field_bounds = chkp_make_bounds (field_ptr, size, iter, false);
kono
parents:
diff changeset
3408
kono
parents:
diff changeset
3409 return chkp_intersect_bounds (field_bounds, bounds, iter);
kono
parents:
diff changeset
3410 }
kono
parents:
diff changeset
3411
kono
parents:
diff changeset
3412 /* Parse field or array access NODE.
kono
parents:
diff changeset
3413
kono
parents:
diff changeset
3414 PTR ouput parameter holds a pointer to the outermost
kono
parents:
diff changeset
3415 object.
kono
parents:
diff changeset
3416
kono
parents:
diff changeset
3417 BITFIELD output parameter is set to 1 if bitfield is
kono
parents:
diff changeset
3418 accessed and to 0 otherwise. If it is 1 then ELT holds
kono
parents:
diff changeset
3419 outer component for accessed bit field.
kono
parents:
diff changeset
3420
kono
parents:
diff changeset
3421 SAFE outer parameter is set to 1 if access is safe and
kono
parents:
diff changeset
3422 checks are not required.
kono
parents:
diff changeset
3423
kono
parents:
diff changeset
3424 BOUNDS outer parameter holds bounds to be used to check
kono
parents:
diff changeset
3425 access (may be NULL).
kono
parents:
diff changeset
3426
kono
parents:
diff changeset
3427 If INNERMOST_BOUNDS is 1 then try to narrow bounds to the
kono
parents:
diff changeset
3428 innermost accessed component. */
kono
parents:
diff changeset
3429 static void
kono
parents:
diff changeset
3430 chkp_parse_array_and_component_ref (tree node, tree *ptr,
kono
parents:
diff changeset
3431 tree *elt, bool *safe,
kono
parents:
diff changeset
3432 bool *bitfield,
kono
parents:
diff changeset
3433 tree *bounds,
kono
parents:
diff changeset
3434 gimple_stmt_iterator *iter,
kono
parents:
diff changeset
3435 bool innermost_bounds)
kono
parents:
diff changeset
3436 {
kono
parents:
diff changeset
3437 tree comp_to_narrow = NULL_TREE;
kono
parents:
diff changeset
3438 tree last_comp = NULL_TREE;
kono
parents:
diff changeset
3439 bool array_ref_found = false;
kono
parents:
diff changeset
3440 tree *nodes;
kono
parents:
diff changeset
3441 tree var;
kono
parents:
diff changeset
3442 int len;
kono
parents:
diff changeset
3443 int i;
kono
parents:
diff changeset
3444
kono
parents:
diff changeset
3445 /* Compute tree height for expression. */
kono
parents:
diff changeset
3446 var = node;
kono
parents:
diff changeset
3447 len = 1;
kono
parents:
diff changeset
3448 while (TREE_CODE (var) == COMPONENT_REF
kono
parents:
diff changeset
3449 || TREE_CODE (var) == ARRAY_REF
kono
parents:
diff changeset
3450 || TREE_CODE (var) == VIEW_CONVERT_EXPR
kono
parents:
diff changeset
3451 || TREE_CODE (var) == BIT_FIELD_REF)
kono
parents:
diff changeset
3452 {
kono
parents:
diff changeset
3453 var = TREE_OPERAND (var, 0);
kono
parents:
diff changeset
3454 len++;
kono
parents:
diff changeset
3455 }
kono
parents:
diff changeset
3456
kono
parents:
diff changeset
3457 gcc_assert (len > 1);
kono
parents:
diff changeset
3458
kono
parents:
diff changeset
3459 /* It is more convenient for us to scan left-to-right,
kono
parents:
diff changeset
3460 so walk tree again and put all node to nodes vector
kono
parents:
diff changeset
3461 in reversed order. */
kono
parents:
diff changeset
3462 nodes = XALLOCAVEC (tree, len);
kono
parents:
diff changeset
3463 nodes[len - 1] = node;
kono
parents:
diff changeset
3464 for (i = len - 2; i >= 0; i--)
kono
parents:
diff changeset
3465 nodes[i] = TREE_OPERAND (nodes[i + 1], 0);
kono
parents:
diff changeset
3466
kono
parents:
diff changeset
3467 if (bounds)
kono
parents:
diff changeset
3468 *bounds = NULL;
kono
parents:
diff changeset
3469 *safe = true;
kono
parents:
diff changeset
3470 *bitfield = ((TREE_CODE (node) == COMPONENT_REF
kono
parents:
diff changeset
3471 && DECL_BIT_FIELD_TYPE (TREE_OPERAND (node, 1)))
kono
parents:
diff changeset
3472 || TREE_CODE (node) == BIT_FIELD_REF);
kono
parents:
diff changeset
3473 /* To get bitfield address we will need outer element. */
kono
parents:
diff changeset
3474 if (*bitfield)
kono
parents:
diff changeset
3475 *elt = nodes[len - 2];
kono
parents:
diff changeset
3476 else
kono
parents:
diff changeset
3477 *elt = NULL_TREE;
kono
parents:
diff changeset
3478
kono
parents:
diff changeset
3479 /* If we have indirection in expression then compute
kono
parents:
diff changeset
3480 outermost structure bounds. Computed bounds may be
kono
parents:
diff changeset
3481 narrowed later. */
kono
parents:
diff changeset
3482 if (TREE_CODE (nodes[0]) == MEM_REF || INDIRECT_REF_P (nodes[0]))
kono
parents:
diff changeset
3483 {
kono
parents:
diff changeset
3484 *safe = false;
kono
parents:
diff changeset
3485 *ptr = TREE_OPERAND (nodes[0], 0);
kono
parents:
diff changeset
3486 if (bounds)
kono
parents:
diff changeset
3487 *bounds = chkp_find_bounds (*ptr, iter);
kono
parents:
diff changeset
3488 }
kono
parents:
diff changeset
3489 else
kono
parents:
diff changeset
3490 {
kono
parents:
diff changeset
3491 gcc_assert (VAR_P (var)
kono
parents:
diff changeset
3492 || TREE_CODE (var) == PARM_DECL
kono
parents:
diff changeset
3493 || TREE_CODE (var) == RESULT_DECL
kono
parents:
diff changeset
3494 || TREE_CODE (var) == STRING_CST
kono
parents:
diff changeset
3495 || TREE_CODE (var) == SSA_NAME);
kono
parents:
diff changeset
3496
kono
parents:
diff changeset
3497 *ptr = chkp_build_addr_expr (var);
kono
parents:
diff changeset
3498
kono
parents:
diff changeset
3499 /* For hard register cases chkp_build_addr_expr returns INTEGER_CST
kono
parents:
diff changeset
3500 and later on chkp_find_bounds will fail to find proper bounds.
kono
parents:
diff changeset
3501 In order to avoid that, we find/create bounds right aways using
kono
parents:
diff changeset
3502 the var itself. */
kono
parents:
diff changeset
3503 if (VAR_P (var) && DECL_HARD_REGISTER (var))
kono
parents:
diff changeset
3504 *bounds = chkp_make_addressed_object_bounds (var, iter);
kono
parents:
diff changeset
3505 }
kono
parents:
diff changeset
3506
kono
parents:
diff changeset
3507 /* In this loop we are trying to find a field access
kono
parents:
diff changeset
3508 requiring narrowing. There are two simple rules
kono
parents:
diff changeset
3509 for search:
kono
parents:
diff changeset
3510 1. Leftmost array_ref is chosen if any.
kono
parents:
diff changeset
3511 2. Rightmost suitable component_ref is chosen if innermost
kono
parents:
diff changeset
3512 bounds are required and no array_ref exists. */
kono
parents:
diff changeset
3513 for (i = 1; i < len; i++)
kono
parents:
diff changeset
3514 {
kono
parents:
diff changeset
3515 var = nodes[i];
kono
parents:
diff changeset
3516
kono
parents:
diff changeset
3517 if (TREE_CODE (var) == ARRAY_REF)
kono
parents:
diff changeset
3518 {
kono
parents:
diff changeset
3519 *safe = false;
kono
parents:
diff changeset
3520 array_ref_found = true;
kono
parents:
diff changeset
3521 if (flag_chkp_narrow_bounds
kono
parents:
diff changeset
3522 && !flag_chkp_narrow_to_innermost_arrray
kono
parents:
diff changeset
3523 && (!last_comp
kono
parents:
diff changeset
3524 || chkp_may_narrow_to_field (var,
kono
parents:
diff changeset
3525 TREE_OPERAND (last_comp, 1))))
kono
parents:
diff changeset
3526 {
kono
parents:
diff changeset
3527 comp_to_narrow = last_comp;
kono
parents:
diff changeset
3528 break;
kono
parents:
diff changeset
3529 }
kono
parents:
diff changeset
3530 }
kono
parents:
diff changeset
3531 else if (TREE_CODE (var) == COMPONENT_REF)
kono
parents:
diff changeset
3532 {
kono
parents:
diff changeset
3533 tree field = TREE_OPERAND (var, 1);
kono
parents:
diff changeset
3534
kono
parents:
diff changeset
3535 if (innermost_bounds
kono
parents:
diff changeset
3536 && !array_ref_found
kono
parents:
diff changeset
3537 && chkp_narrow_bounds_for_field (var, field))
kono
parents:
diff changeset
3538 comp_to_narrow = var;
kono
parents:
diff changeset
3539 last_comp = var;
kono
parents:
diff changeset
3540
kono
parents:
diff changeset
3541 if (flag_chkp_narrow_bounds
kono
parents:
diff changeset
3542 && flag_chkp_narrow_to_innermost_arrray
kono
parents:
diff changeset
3543 && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
kono
parents:
diff changeset
3544 {
kono
parents:
diff changeset
3545 if (bounds)
kono
parents:
diff changeset
3546 *bounds = chkp_narrow_bounds_to_field (*bounds, var, iter);
kono
parents:
diff changeset
3547 comp_to_narrow = NULL;
kono
parents:
diff changeset
3548 }
kono
parents:
diff changeset
3549 }
kono
parents:
diff changeset
3550 else if (TREE_CODE (var) == BIT_FIELD_REF)
kono
parents:
diff changeset
3551 {
kono
parents:
diff changeset
3552 if (flag_chkp_narrow_bounds && bounds)
kono
parents:
diff changeset
3553 {
kono
parents:
diff changeset
3554 tree offset, size;
kono
parents:
diff changeset
3555 chkp_parse_bit_field_ref (var, UNKNOWN_LOCATION, &offset, &size);
kono
parents:
diff changeset
3556 *bounds
kono
parents:
diff changeset
3557 = chkp_narrow_size_and_offset (*bounds, TREE_OPERAND (var, 0),
kono
parents:
diff changeset
3558 offset, size, iter);
kono
parents:
diff changeset
3559 }
kono
parents:
diff changeset
3560 }
kono
parents:
diff changeset
3561 else if (TREE_CODE (var) == VIEW_CONVERT_EXPR)
kono
parents:
diff changeset
3562 /* Nothing to do for it. */
kono
parents:
diff changeset
3563 ;
kono
parents:
diff changeset
3564 else
kono
parents:
diff changeset
3565 gcc_unreachable ();
kono
parents:
diff changeset
3566 }
kono
parents:
diff changeset
3567
kono
parents:
diff changeset
3568 if (comp_to_narrow && DECL_SIZE (TREE_OPERAND (comp_to_narrow, 1)) && bounds)
kono
parents:
diff changeset
3569 *bounds = chkp_narrow_bounds_to_field (*bounds, comp_to_narrow, iter);
kono
parents:
diff changeset
3570
kono
parents:
diff changeset
3571 if (innermost_bounds && bounds && !*bounds)
kono
parents:
diff changeset
3572 *bounds = chkp_find_bounds (*ptr, iter);
kono
parents:
diff changeset
3573 }
kono
parents:
diff changeset
3574
kono
parents:
diff changeset
3575 /* Parse BIT_FIELD_REF to a NODE for a given location LOC. Return OFFSET
kono
parents:
diff changeset
3576 and SIZE in bytes. */
kono
parents:
diff changeset
3577
kono
parents:
diff changeset
3578 static
kono
parents:
diff changeset
3579 void chkp_parse_bit_field_ref (tree node, location_t loc, tree *offset,
kono
parents:
diff changeset
3580 tree *size)
kono
parents:
diff changeset
3581 {
kono
parents:
diff changeset
3582 tree bpu = fold_convert (size_type_node, bitsize_int (BITS_PER_UNIT));
kono
parents:
diff changeset
3583 tree offs = fold_convert (size_type_node, TREE_OPERAND (node, 2));
kono
parents:
diff changeset
3584 tree rem = size_binop_loc (loc, TRUNC_MOD_EXPR, offs, bpu);
kono
parents:
diff changeset
3585 offs = size_binop_loc (loc, TRUNC_DIV_EXPR, offs, bpu);
kono
parents:
diff changeset
3586
kono
parents:
diff changeset
3587 tree s = fold_convert (size_type_node, TREE_OPERAND (node, 1));
kono
parents:
diff changeset
3588 s = size_binop_loc (loc, PLUS_EXPR, s, rem);
kono
parents:
diff changeset
3589 s = size_binop_loc (loc, CEIL_DIV_EXPR, s, bpu);
kono
parents:
diff changeset
3590 s = fold_convert (size_type_node, s);
kono
parents:
diff changeset
3591
kono
parents:
diff changeset
3592 *offset = offs;
kono
parents:
diff changeset
3593 *size = s;
kono
parents:
diff changeset
3594 }
kono
parents:
diff changeset
3595
kono
parents:
diff changeset
3596 /* Compute and return bounds for address of OBJ. */
kono
parents:
diff changeset
3597 static tree
kono
parents:
diff changeset
3598 chkp_make_addressed_object_bounds (tree obj, gimple_stmt_iterator *iter)
kono
parents:
diff changeset
3599 {
kono
parents:
diff changeset
3600 tree bounds = chkp_get_registered_addr_bounds (obj);
kono
parents:
diff changeset
3601
kono
parents:
diff changeset
3602 if (bounds)
kono
parents:
diff changeset
3603 return bounds;
kono
parents:
diff changeset
3604
kono
parents:
diff changeset
3605 switch (TREE_CODE (obj))
kono
parents:
diff changeset
3606 {
kono
parents:
diff changeset
3607 case VAR_DECL:
kono
parents:
diff changeset
3608 case PARM_DECL:
kono
parents:
diff changeset
3609 case RESULT_DECL:
kono
parents:
diff changeset
3610 bounds = chkp_get_bounds_for_decl_addr (obj);
kono
parents:
diff changeset
3611 break;
kono
parents:
diff changeset
3612
kono
parents:
diff changeset
3613 case STRING_CST:
kono
parents:
diff changeset
3614 bounds = chkp_get_bounds_for_string_cst (obj);
kono
parents:
diff changeset
3615 break;
kono
parents:
diff changeset
3616
kono
parents:
diff changeset
3617 case ARRAY_REF:
kono
parents:
diff changeset
3618 case COMPONENT_REF:
kono
parents:
diff changeset
3619 case BIT_FIELD_REF:
kono
parents:
diff changeset
3620 {
kono
parents:
diff changeset
3621 tree elt;
kono
parents:
diff changeset
3622 tree ptr;
kono
parents:
diff changeset
3623 bool safe;
kono
parents:
diff changeset
3624 bool bitfield;
kono
parents:
diff changeset
3625
kono
parents:
diff changeset
3626 chkp_parse_array_and_component_ref (obj, &ptr, &elt, &safe,
kono
parents:
diff changeset
3627 &bitfield, &bounds, iter, true);
kono
parents:
diff changeset
3628
kono
parents:
diff changeset
3629 gcc_assert (bounds);
kono
parents:
diff changeset
3630 }
kono
parents:
diff changeset
3631 break;
kono
parents:
diff changeset
3632
kono
parents:
diff changeset
3633 case FUNCTION_DECL:
kono
parents:
diff changeset
3634 case LABEL_DECL:
kono
parents:
diff changeset
3635 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
3636 break;
kono
parents:
diff changeset
3637
kono
parents:
diff changeset
3638 case MEM_REF:
kono
parents:
diff changeset
3639 bounds = chkp_find_bounds (TREE_OPERAND (obj, 0), iter);
kono
parents:
diff changeset
3640 break;
kono
parents:
diff changeset
3641
kono
parents:
diff changeset
3642 case REALPART_EXPR:
kono
parents:
diff changeset
3643 case IMAGPART_EXPR:
kono
parents:
diff changeset
3644 bounds = chkp_make_addressed_object_bounds (TREE_OPERAND (obj, 0), iter);
kono
parents:
diff changeset
3645 break;
kono
parents:
diff changeset
3646
kono
parents:
diff changeset
3647 default:
kono
parents:
diff changeset
3648 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3649 {
kono
parents:
diff changeset
3650 fprintf (dump_file, "chkp_make_addressed_object_bounds: "
kono
parents:
diff changeset
3651 "unexpected object of type %s\n",
kono
parents:
diff changeset
3652 get_tree_code_name (TREE_CODE (obj)));
kono
parents:
diff changeset
3653 print_node (dump_file, "", obj, 0);
kono
parents:
diff changeset
3654 }
kono
parents:
diff changeset
3655 internal_error ("chkp_make_addressed_object_bounds: "
kono
parents:
diff changeset
3656 "Unexpected tree code %s",
kono
parents:
diff changeset
3657 get_tree_code_name (TREE_CODE (obj)));
kono
parents:
diff changeset
3658 }
kono
parents:
diff changeset
3659
kono
parents:
diff changeset
3660 chkp_register_addr_bounds (obj, bounds);
kono
parents:
diff changeset
3661
kono
parents:
diff changeset
3662 return bounds;
kono
parents:
diff changeset
3663 }
kono
parents:
diff changeset
3664
kono
parents:
diff changeset
3665 /* Compute bounds for pointer PTR loaded from PTR_SRC. Generate statements
kono
parents:
diff changeset
3666 to compute bounds if required. Computed bounds should be available at
kono
parents:
diff changeset
3667 position pointed by ITER.
kono
parents:
diff changeset
3668
kono
parents:
diff changeset
3669 If PTR_SRC is NULL_TREE then pointer definition is identified.
kono
parents:
diff changeset
3670
kono
parents:
diff changeset
3671 If PTR_SRC is not NULL_TREE then ITER points to statements which loads
kono
parents:
diff changeset
3672 PTR. If PTR is a any memory reference then ITER points to a statement
kono
parents:
diff changeset
3673 after which bndldx will be inserterd. In both cases ITER will be updated
kono
parents:
diff changeset
3674 to point to the inserted bndldx statement. */
kono
parents:
diff changeset
3675
kono
parents:
diff changeset
3676 static tree
kono
parents:
diff changeset
3677 chkp_find_bounds_1 (tree ptr, tree ptr_src, gimple_stmt_iterator *iter)
kono
parents:
diff changeset
3678 {
kono
parents:
diff changeset
3679 tree addr = NULL_TREE;
kono
parents:
diff changeset
3680 tree bounds = NULL_TREE;
kono
parents:
diff changeset
3681
kono
parents:
diff changeset
3682 if (!ptr_src)
kono
parents:
diff changeset
3683 ptr_src = ptr;
kono
parents:
diff changeset
3684
kono
parents:
diff changeset
3685 bounds = chkp_get_registered_bounds (ptr_src);
kono
parents:
diff changeset
3686
kono
parents:
diff changeset
3687 if (bounds)
kono
parents:
diff changeset
3688 return bounds;
kono
parents:
diff changeset
3689
kono
parents:
diff changeset
3690 switch (TREE_CODE (ptr_src))
kono
parents:
diff changeset
3691 {
kono
parents:
diff changeset
3692 case MEM_REF:
kono
parents:
diff changeset
3693 case VAR_DECL:
kono
parents:
diff changeset
3694 if (BOUNDED_P (ptr_src))
kono
parents:
diff changeset
3695 if (VAR_P (ptr) && DECL_REGISTER (ptr))
kono
parents:
diff changeset
3696 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
3697 else
kono
parents:
diff changeset
3698 {
kono
parents:
diff changeset
3699 addr = chkp_build_addr_expr (ptr_src);
kono
parents:
diff changeset
3700 bounds = chkp_build_bndldx (addr, ptr, iter);
kono
parents:
diff changeset
3701 }
kono
parents:
diff changeset
3702 else
kono
parents:
diff changeset
3703 bounds = chkp_get_nonpointer_load_bounds ();
kono
parents:
diff changeset
3704 break;
kono
parents:
diff changeset
3705
kono
parents:
diff changeset
3706 case ARRAY_REF:
kono
parents:
diff changeset
3707 case COMPONENT_REF:
kono
parents:
diff changeset
3708 addr = get_base_address (ptr_src);
kono
parents:
diff changeset
3709 if (VAR_P (addr) && DECL_HARD_REGISTER (addr))
kono
parents:
diff changeset
3710 {
kono
parents:
diff changeset
3711 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
3712 break;
kono
parents:
diff changeset
3713 }
kono
parents:
diff changeset
3714 if (DECL_P (addr)
kono
parents:
diff changeset
3715 || TREE_CODE (addr) == MEM_REF
kono
parents:
diff changeset
3716 || TREE_CODE (addr) == TARGET_MEM_REF)
kono
parents:
diff changeset
3717 {
kono
parents:
diff changeset
3718 if (BOUNDED_P (ptr_src))
kono
parents:
diff changeset
3719 if (VAR_P (ptr) && DECL_REGISTER (ptr))
kono
parents:
diff changeset
3720 bounds = chkp_get_zero_bounds ();
kono
parents:
diff changeset
3721 else
kono
parents:
diff changeset
3722 {
kono
parents:
diff changeset
3723 addr = chkp_build_addr_expr (ptr_src);
kono
parents:
diff changeset
3724 bounds = chkp_build_bndldx (addr, ptr, iter);
kono
parents:
diff changeset
3725 }
kono
parents:
diff changeset
3726 else
kono
parents:
diff changeset
3727 bounds = chkp_get_nonpointer_load_bounds ();
kono
parents:
diff changeset
3728 }
kono
parents:
diff changeset
3729 else
kono
parents:
diff changeset
3730 {
kono
parents:
diff changeset
3731 gcc_assert (TREE_CODE (addr) == SSA_NAME);
kono
parents:
diff changeset
3732 bounds = chkp_find_bounds (addr, iter);
kono
parents:
diff changeset
3733 }
kono
parents:
diff changeset
3734 break;
kono
parents:
diff changeset
3735
kono
parents:
diff changeset
3736 case PARM_DECL:
kono
parents:
diff changeset
3737 /* Handled above but failed. */
kono
parents:
diff changeset
3738 bounds = chkp_get_invalid_op_bounds ();
kono
parents:
diff changeset
3739 break;
kono
parents:
diff changeset
3740
kono
parents:
diff changeset
3741 case TARGET_MEM_REF:
kono
parents:
diff changeset
3742 addr = chkp_build_addr_expr (ptr_src);
kono
parents:
diff changeset
3743 bounds = chkp_build_bndldx (addr, ptr, iter);
kono
parents:
diff changeset
3744 break;
kono
parents:
diff changeset
3745
kono
parents:
diff changeset
3746 case SSA_NAME:
kono
parents:
diff changeset
3747 bounds = chkp_get_registered_bounds (ptr_src);
kono
parents:
diff changeset
3748 if (!bounds)
kono
parents:
diff changeset
3749 {
kono
parents:
diff changeset
3750 gimple *def_stmt = SSA_NAME_DEF_STMT (ptr_src);
kono
parents:
diff changeset
3751 gphi_iterator phi_iter;
kono
parents:
diff changeset
3752
kono
parents:
diff changeset
3753 bounds = chkp_get_bounds_by_definition (ptr_src, def_stmt, &phi_iter);
kono
parents:
diff changeset
3754
kono
parents:
diff changeset
3755 gcc_assert (bounds);
kono
parents:
diff changeset
3756
kono
parents:
diff changeset
3757 if (gphi *def_phi = dyn_cast <gphi *> (def_stmt))
kono
parents:
diff changeset
3758 {
kono
parents:
diff changeset
3759 unsigned i;
kono
parents:
diff changeset
3760
kono
parents:
diff changeset
3761 for (i = 0; i < gimple_phi_num_args (def_phi); i++)
kono
parents:
diff changeset
3762 {
kono
parents:
diff changeset
3763 tree arg = gimple_phi_arg_def (def_phi, i);
kono
parents:
diff changeset
3764 tree arg_bnd;
kono
parents:
diff changeset
3765 gphi *phi_bnd;
kono
parents:
diff changeset
3766
kono
parents:
diff changeset
3767 arg_bnd = chkp_find_bounds (arg, NULL);
kono
parents:
diff changeset
3768
kono
parents:
diff changeset
3769 /* chkp_get_bounds_by_definition created new phi
kono
parents:
diff changeset
3770 statement and phi_iter points to it.
kono
parents:
diff changeset
3771
kono
parents:
diff changeset
3772 Previous call to chkp_find_bounds could create
kono
parents:
diff changeset
3773 new basic block and therefore change phi statement
kono
parents:
diff changeset
3774 phi_iter points to. */
kono
parents:
diff changeset
3775 phi_bnd = phi_iter.phi ();
kono
parents:
diff changeset
3776
kono
parents:
diff changeset
3777 add_phi_arg (phi_bnd, arg_bnd,
kono
parents:
diff changeset
3778 gimple_phi_arg_edge (def_phi, i),
kono
parents:
diff changeset
3779 UNKNOWN_LOCATION);
kono
parents:
diff changeset
3780 }
kono
parents:
diff changeset
3781
kono
parents:
diff changeset
3782 /* If all bound phi nodes have their arg computed
kono
parents:
diff changeset
3783 then we may finish its computation. See
kono
parents:
diff changeset
3784 chkp_finish_incomplete_bounds for more details. */
kono
parents:
diff changeset
3785 if (chkp_may_finish_incomplete_bounds ())
kono
parents:
diff changeset
3786 chkp_finish_incomplete_bounds ();
kono
parents:
diff changeset
3787 }
kono
parents:
diff changeset
3788
kono
parents:
diff changeset
3789 gcc_assert (bounds == chkp_get_registered_bounds (ptr_src)
kono
parents:
diff changeset
3790 || chkp_incomplete_bounds (bounds));
kono
parents:
diff changeset
3791 }
kono
parents:
diff changeset
3792 break;
kono
parents:
diff changeset
3793
kono
parents:
diff changeset
3794 case ADDR_EXPR:
kono
parents:
diff changeset
3795 case WITH_SIZE_EXPR:
kono
parents:
diff changeset
3796 bounds = chkp_make_addressed_object_bounds (TREE_OPERAND (ptr_src, 0), iter);
kono
parents:
diff changeset
3797 break;
kono
parents:
diff changeset
3798
kono
parents:
diff changeset
3799 case INTEGER_CST:
kono
parents:
diff changeset
3800 case COMPLEX_CST:
kono
parents:
diff changeset
3801 case VECTOR_CST:
kono
parents:
diff changeset
3802 if (integer_zerop (ptr_src))
kono
parents:
diff changeset
3803 bounds = chkp_get_none_bounds ();
kono
parents:
diff changeset
3804 else
kono
parents:
diff changeset
3805 bounds = chkp_get_invalid_op_bounds ();
kono
parents:
diff changeset
3806 break;
kono
parents:
diff changeset
3807
kono
parents:
diff changeset
3808 default:
kono
parents:
diff changeset
3809 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3810 {
kono
parents:
diff changeset
3811 fprintf (dump_file, "chkp_find_bounds: unexpected ptr of type %s\n",
kono
parents:
diff changeset
3812 get_tree_code_name (TREE_CODE (ptr_src)));
kono
parents:
diff changeset
3813 print_node (dump_file, "", ptr_src, 0);
kono
parents:
diff changeset
3814 }
kono
parents:
diff changeset
3815 internal_error ("chkp_find_bounds: Unexpected tree code %s",
kono
parents:
diff changeset
3816 get_tree_code_name (TREE_CODE (ptr_src)));
kono
parents:
diff changeset
3817 }
kono
parents:
diff changeset
3818
kono
parents:
diff changeset
3819 if (!bounds)
kono
parents:
diff changeset
3820 {
kono
parents:
diff changeset
3821 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3822 {
kono
parents:
diff changeset
3823 fprintf (stderr, "chkp_find_bounds: cannot find bounds for pointer\n");
kono
parents:
diff changeset
3824 print_node (dump_file, "", ptr_src, 0);
kono
parents:
diff changeset
3825 }
kono
parents:
diff changeset
3826 internal_error ("chkp_find_bounds: Cannot find bounds for pointer");
kono
parents:
diff changeset
3827 }
kono
parents:
diff changeset
3828
kono
parents:
diff changeset
3829 return bounds;
kono
parents:
diff changeset
3830 }
kono
parents:
diff changeset
3831
kono
parents:
diff changeset
3832 /* Normal case for bounds search without forced narrowing. */
kono
parents:
diff changeset
3833 static tree
kono
parents:
diff changeset
3834 chkp_find_bounds (tree ptr, gimple_stmt_iterator *iter)
kono
parents:
diff changeset
3835 {
kono
parents:
diff changeset
3836 return chkp_find_bounds_1 (ptr, NULL_TREE, iter);
kono
parents:
diff changeset
3837 }
kono
parents:
diff changeset
3838
kono
parents:
diff changeset
3839 /* Search bounds for pointer PTR loaded from PTR_SRC
kono
parents:
diff changeset
3840 by statement *ITER points to. */
kono
parents:
diff changeset
3841 static tree
kono
parents:
diff changeset
3842 chkp_find_bounds_loaded (tree ptr, tree ptr_src, gimple_stmt_iterator *iter)
kono
parents:
diff changeset
3843 {
kono
parents:
diff changeset
3844 return chkp_find_bounds_1 (ptr, ptr_src, iter);
kono
parents:
diff changeset
3845 }
kono
parents:
diff changeset
3846
kono
parents:
diff changeset
3847 /* Helper function which checks type of RHS and finds all pointers in
kono
parents:
diff changeset
3848 it. For each found pointer we build it's accesses in LHS and RHS
kono
parents:
diff changeset
3849 objects and then call HANDLER for them. Function is used to copy
kono
parents:
diff changeset
3850 or initilize bounds for copied object. */
kono
parents:
diff changeset
3851 static void
kono
parents:
diff changeset
3852 chkp_walk_pointer_assignments (tree lhs, tree rhs, void *arg,
kono
parents:
diff changeset
3853 assign_handler handler)
kono
parents:
diff changeset
3854 {
kono
parents:
diff changeset
3855 tree type = TREE_TYPE (lhs);
kono
parents:
diff changeset
3856
kono
parents:
diff changeset
3857 /* We have nothing to do with clobbers. */
kono
parents:
diff changeset
3858 if (TREE_CLOBBER_P (rhs))
kono
parents:
diff changeset
3859 return;
kono
parents:
diff changeset
3860
kono
parents:
diff changeset
3861 if (BOUNDED_TYPE_P (type))
kono
parents:
diff changeset
3862 handler (lhs, rhs, arg);
kono
parents:
diff changeset
3863 else if (RECORD_OR_UNION_TYPE_P (type))
kono
parents:
diff changeset
3864 {
kono
parents:
diff changeset
3865 tree field;
kono
parents:
diff changeset
3866
kono
parents:
diff changeset
3867 if (TREE_CODE (rhs) == CONSTRUCTOR)
kono
parents:
diff changeset
3868 {
kono
parents:
diff changeset
3869 unsigned HOST_WIDE_INT cnt;
kono
parents:
diff changeset
3870 tree val;
kono
parents:
diff changeset
3871
kono
parents:
diff changeset
3872 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs), cnt, field, val)
kono
parents:
diff changeset
3873 {
kono
parents:
diff changeset
3874 if (field && chkp_type_has_pointer (TREE_TYPE (field)))
kono
parents:
diff changeset
3875 {
kono
parents:
diff changeset
3876 tree lhs_field = chkp_build_component_ref (lhs, field);
kono
parents:
diff changeset
3877 chkp_walk_pointer_assignments (lhs_field, val, arg, handler);
kono
parents:
diff changeset
3878 }
kono
parents:
diff changeset
3879 }
kono
parents:
diff changeset
3880 }
kono
parents:
diff changeset
3881 else
kono
parents:
diff changeset
3882 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
kono
parents:
diff changeset
3883 if (TREE_CODE (field) == FIELD_DECL
kono
parents:
diff changeset
3884 && chkp_type_has_pointer (TREE_TYPE (field)))
kono
parents:
diff changeset
3885 {
kono
parents:
diff changeset
3886 tree rhs_field = chkp_build_component_ref (rhs, field);
kono
parents:
diff changeset
3887 tree lhs_field = chkp_build_component_ref (lhs, field);
kono
parents:
diff changeset
3888 chkp_walk_pointer_assignments (lhs_field, rhs_field, arg, handler);
kono
parents:
diff changeset
3889 }
kono
parents:
diff changeset
3890 }
kono
parents:
diff changeset
3891 else if (TREE_CODE (type) == ARRAY_TYPE)
kono
parents:
diff changeset
3892 {
kono
parents:
diff changeset
3893 unsigned HOST_WIDE_INT cur = 0;
kono
parents:
diff changeset
3894 tree maxval = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
kono
parents:
diff changeset
3895 tree etype = TREE_TYPE (type);
kono
parents:
diff changeset
3896 tree esize = TYPE_SIZE (etype);
kono
parents:
diff changeset
3897
kono
parents:
diff changeset
3898 if (TREE_CODE (rhs) == CONSTRUCTOR)
kono
parents:
diff changeset
3899 {
kono
parents:
diff changeset
3900 unsigned HOST_WIDE_INT cnt;
kono
parents:
diff changeset
3901 tree purp, val, lhs_elem;
kono
parents:
diff changeset
3902
kono
parents:
diff changeset
3903 FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs), cnt, purp, val)
kono
parents:
diff changeset
3904 {
kono
parents:
diff changeset
3905 if (purp && TREE_CODE (purp) == RANGE_EXPR)
kono
parents:
diff changeset
3906 {
kono
parents:
diff changeset
3907 tree lo_index = TREE_OPERAND (purp, 0);
kono
parents:
diff changeset
3908 tree hi_index = TREE_OPERAND (purp, 1);
kono
parents:
diff changeset
3909
kono
parents:
diff changeset
3910 for (cur = (unsigned)tree_to_uhwi (lo_index);
kono
parents:
diff changeset
3911 cur <= (unsigned)tree_to_uhwi (hi_index);
kono
parents:
diff changeset
3912 cur++)
kono
parents:
diff changeset
3913 {
kono
parents:
diff changeset
3914 lhs_elem = chkp_build_array_ref (lhs, etype, esize, cur);
kono
parents:
diff changeset
3915 chkp_walk_pointer_assignments (lhs_elem, val, arg, handler);
kono
parents:
diff changeset
3916 }
kono
parents:
diff changeset
3917 }
kono
parents:
diff changeset
3918 else
kono
parents:
diff changeset
3919 {
kono
parents:
diff changeset
3920 if (purp)
kono
parents:
diff changeset
3921 {
kono
parents:
diff changeset
3922 gcc_assert (TREE_CODE (purp) == INTEGER_CST);
kono
parents:
diff changeset
3923 cur = tree_to_uhwi (purp);
kono
parents:
diff changeset
3924 }
kono
parents:
diff changeset
3925
kono
parents:
diff changeset
3926 lhs_elem = chkp_build_array_ref (lhs, etype, esize, cur++);
kono
parents:
diff changeset
3927
kono
parents:
diff changeset
3928 chkp_walk_pointer_assignments (lhs_elem, val, arg, handler);
kono
parents:
diff changeset
3929 }
kono
parents:
diff changeset
3930 }
kono
parents:
diff changeset
3931 }
kono
parents:
diff changeset
3932 /* Copy array only when size is known. */
kono
parents:
diff changeset
3933 else if (maxval && !integer_minus_onep (maxval))
kono
parents:
diff changeset
3934 for (cur = 0; cur <= TREE_INT_CST_LOW (maxval); cur++)
kono
parents:
diff changeset
3935 {
kono
parents:
diff changeset
3936 tree lhs_elem = chkp_build_array_ref (lhs, etype, esize, cur);
kono
parents:
diff changeset
3937 tree rhs_elem = chkp_build_array_ref (rhs, etype, esize, cur);
kono
parents:
diff changeset
3938 chkp_walk_pointer_assignments (lhs_elem, rhs_elem, arg, handler);
kono
parents:
diff changeset
3939 }
kono
parents:
diff changeset
3940 }
kono
parents:
diff changeset
3941 else
kono
parents:
diff changeset
3942 internal_error("chkp_walk_pointer_assignments: unexpected RHS type: %s",
kono
parents:
diff changeset
3943 get_tree_code_name (TREE_CODE (type)));
kono
parents:
diff changeset
3944 }
kono
parents:
diff changeset
3945
kono
parents:
diff changeset
3946 /* Add code to copy bounds for assignment of RHS to LHS.
kono
parents:
diff changeset
3947 ARG is an iterator pointing ne code position. */
kono
parents:
diff changeset
3948 static void
kono
parents:
diff changeset
3949 chkp_copy_bounds_for_elem (tree lhs, tree rhs, void *arg)
kono
parents:
diff changeset
3950 {
kono
parents:
diff changeset
3951 gimple_stmt_iterator *iter = (gimple_stmt_iterator *)arg;
kono
parents:
diff changeset
3952 tree bounds = chkp_find_bounds (rhs, iter);
kono
parents:
diff changeset
3953 tree addr = chkp_build_addr_expr(lhs);
kono
parents:
diff changeset
3954
kono
parents:
diff changeset
3955 chkp_build_bndstx (addr, rhs, bounds, iter);
kono
parents:
diff changeset
3956 }
kono
parents:
diff changeset
3957
kono
parents:
diff changeset
3958 /* Emit static bound initilizers and size vars. */
kono
parents:
diff changeset
3959 void
kono
parents:
diff changeset
3960 chkp_finish_file (void)
kono
parents:
diff changeset
3961 {
kono
parents:
diff changeset
3962 struct varpool_node *node;
kono
parents:
diff changeset
3963 struct chkp_ctor_stmt_list stmts;
kono
parents:
diff changeset
3964
kono
parents:
diff changeset
3965 if (seen_error ())
kono
parents:
diff changeset
3966 return;
kono
parents:
diff changeset
3967
kono
parents:
diff changeset
3968 /* Iterate through varpool and generate bounds initialization
kono
parents:
diff changeset
3969 constructors for all statically initialized pointers. */
kono
parents:
diff changeset
3970 stmts.avail = MAX_STMTS_IN_STATIC_CHKP_CTOR;
kono
parents:
diff changeset
3971 stmts.stmts = NULL;
kono
parents:
diff changeset
3972 FOR_EACH_VARIABLE (node)
kono
parents:
diff changeset
3973 /* Check that var is actually emitted and we need and may initialize
kono
parents:
diff changeset
3974 its bounds. */
kono
parents:
diff changeset
3975 if (node->need_bounds_init
kono
parents:
diff changeset
3976 && !POINTER_BOUNDS_P (node->decl)
kono
parents:
diff changeset
3977 && DECL_RTL (node->decl)
kono
parents:
diff changeset
3978 && MEM_P (DECL_RTL (node->decl))
kono
parents:
diff changeset
3979 && TREE_ASM_WRITTEN (node->decl))
kono
parents:
diff changeset
3980 {
kono
parents:
diff changeset
3981 chkp_walk_pointer_assignments (node->decl,
kono
parents:
diff changeset
3982 DECL_INITIAL (node->decl),
kono
parents:
diff changeset
3983 &stmts,
kono
parents:
diff changeset
3984 chkp_add_modification_to_stmt_list);
kono
parents:
diff changeset
3985
kono
parents:
diff changeset
3986 if (stmts.avail <= 0)
kono
parents:
diff changeset
3987 {
kono
parents:
diff changeset
3988 cgraph_build_static_cdtor ('P', stmts.stmts,
kono
parents:
diff changeset
3989 MAX_RESERVED_INIT_PRIORITY + 3);
kono
parents:
diff changeset
3990 stmts.avail = MAX_STMTS_IN_STATIC_CHKP_CTOR;
kono
parents:
diff changeset
3991 stmts.stmts = NULL;
kono
parents:
diff changeset
3992 }
kono
parents:
diff changeset
3993 }
kono
parents:
diff changeset
3994
kono
parents:
diff changeset
3995 if (stmts.stmts)
kono
parents:
diff changeset
3996 cgraph_build_static_cdtor ('P', stmts.stmts,
kono
parents:
diff changeset
3997 MAX_RESERVED_INIT_PRIORITY + 3);
kono
parents:
diff changeset
3998
kono
parents:
diff changeset
3999 /* Iterate through varpool and generate bounds initialization
kono
parents:
diff changeset
4000 constructors for all static bounds vars. */
kono
parents:
diff changeset
4001 stmts.avail = MAX_STMTS_IN_STATIC_CHKP_CTOR;
kono
parents:
diff changeset
4002 stmts.stmts = NULL;
kono
parents:
diff changeset
4003 FOR_EACH_VARIABLE (node)
kono
parents:
diff changeset
4004 if (node->need_bounds_init
kono
parents:
diff changeset
4005 && POINTER_BOUNDS_P (node->decl)
kono
parents:
diff changeset
4006 && TREE_ASM_WRITTEN (node->decl))
kono
parents:
diff changeset
4007 {
kono
parents:
diff changeset
4008 tree bnd = node->decl;
kono
parents:
diff changeset
4009 tree var;
kono
parents:
diff changeset
4010
kono
parents:
diff changeset
4011 gcc_assert (DECL_INITIAL (bnd)
kono
parents:
diff changeset
4012 && TREE_CODE (DECL_INITIAL (bnd)) == ADDR_EXPR);
kono
parents:
diff changeset
4013
kono
parents:
diff changeset
4014 var = TREE_OPERAND (DECL_INITIAL (bnd), 0);
kono
parents:
diff changeset
4015 chkp_output_static_bounds (bnd, var, &stmts);
kono
parents:
diff changeset
4016 }
kono
parents:
diff changeset
4017
kono
parents:
diff changeset
4018 if (stmts.stmts)
kono
parents:
diff changeset
4019 cgraph_build_static_cdtor ('B', stmts.stmts,
kono
parents:
diff changeset
4020 MAX_RESERVED_INIT_PRIORITY + 2);
kono
parents:
diff changeset
4021
kono
parents:
diff changeset
4022 delete chkp_static_var_bounds;
kono
parents:
diff changeset
4023 delete chkp_bounds_map;
kono
parents:
diff changeset
4024 }
kono
parents:
diff changeset
4025
kono
parents:
diff changeset
4026 /* An instrumentation function which is called for each statement
kono
parents:
diff changeset
4027 having memory access we want to instrument. It inserts check
kono
parents:
diff changeset
4028 code and bounds copy code.
kono
parents:
diff changeset
4029
kono
parents:
diff changeset
4030 ITER points to statement to instrument.
kono
parents:
diff changeset
4031
kono
parents:
diff changeset
4032 NODE holds memory access in statement to check.
kono
parents:
diff changeset
4033
kono
parents:
diff changeset
4034 LOC holds the location information for statement.
kono
parents:
diff changeset
4035
kono
parents:
diff changeset
4036 DIRFLAGS determines whether access is read or write.
kono
parents:
diff changeset
4037
kono
parents:
diff changeset
4038 ACCESS_OFFS should be added to address used in NODE
kono
parents:
diff changeset
4039 before check.
kono
parents:
diff changeset
4040
kono
parents:
diff changeset
4041 ACCESS_SIZE holds size of checked access.
kono
parents:
diff changeset
4042
kono
parents:
diff changeset
4043 SAFE indicates if NODE access is safe and should not be
kono
parents:
diff changeset
4044 checked. */
kono
parents:
diff changeset
4045 static void
kono
parents:
diff changeset
4046 chkp_process_stmt (gimple_stmt_iterator *iter, tree node,
kono
parents:
diff changeset
4047 location_t loc, tree dirflag,
kono
parents:
diff changeset
4048 tree access_offs, tree access_size,
kono
parents:
diff changeset
4049 bool safe)
kono
parents:
diff changeset
4050 {
kono
parents:
diff changeset
4051 tree node_type = TREE_TYPE (node);
kono
parents:
diff changeset
4052 tree size = access_size ? access_size : TYPE_SIZE_UNIT (node_type);
kono
parents:
diff changeset
4053 tree addr_first = NULL_TREE; /* address of the first accessed byte */
kono
parents:
diff changeset
4054 tree addr_last = NULL_TREE; /* address of the last accessed byte */
kono
parents:
diff changeset
4055 tree ptr = NULL_TREE; /* a pointer used for dereference */
kono
parents:
diff changeset
4056 tree bounds = NULL_TREE;
kono
parents:
diff changeset
4057 bool reg_store = false;
kono
parents:
diff changeset
4058
kono
parents:
diff changeset
4059 /* We do not need instrumentation for clobbers. */
kono
parents:
diff changeset
4060 if (dirflag == integer_one_node
kono
parents:
diff changeset
4061 && gimple_code (gsi_stmt (*iter)) == GIMPLE_ASSIGN
kono
parents:
diff changeset
4062 && TREE_CLOBBER_P (gimple_assign_rhs1 (gsi_stmt (*iter))))
kono
parents:
diff changeset
4063 return;
kono
parents:
diff changeset
4064
kono
parents:
diff changeset
4065 switch (TREE_CODE (node))
kono
parents:
diff changeset
4066 {
kono
parents:
diff changeset
4067 case ARRAY_REF:
kono
parents:
diff changeset
4068 case COMPONENT_REF:
kono
parents:
diff changeset
4069 {
kono
parents:
diff changeset
4070 bool bitfield;
kono
parents:
diff changeset
4071 tree elt;
kono
parents:
diff changeset
4072
kono
parents:
diff changeset
4073 if (safe)
kono
parents:
diff changeset
4074 {
kono
parents:
diff changeset
4075 /* We are not going to generate any checks, so do not
kono
parents:
diff changeset
4076 generate bounds as well. */
kono
parents:
diff changeset
4077 addr_first = chkp_build_addr_expr (node);
kono
parents:
diff changeset
4078 break;
kono
parents:
diff changeset
4079 }
kono
parents:
diff changeset
4080
kono
parents:
diff changeset
4081 chkp_parse_array_and_component_ref (node, &ptr, &elt, &safe,
kono
parents:
diff changeset
4082 &bitfield, &bounds, iter, false);
kono
parents:
diff changeset
4083
kono
parents:
diff changeset
4084 /* Break if there is no dereference and operation is safe. */
kono
parents:
diff changeset
4085
kono
parents:
diff changeset
4086 if (bitfield)
kono
parents:
diff changeset
4087 {
kono
parents:
diff changeset
4088 tree field = TREE_OPERAND (node, 1);
kono
parents:
diff changeset
4089
kono
parents:
diff changeset
4090 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
kono
parents:
diff changeset
4091 size = DECL_SIZE_UNIT (field);
kono
parents:
diff changeset
4092
kono
parents:
diff changeset
4093 if (elt)
kono
parents:
diff changeset
4094 elt = chkp_build_addr_expr (elt);
kono
parents:
diff changeset
4095 addr_first = fold_convert_loc (loc, ptr_type_node, elt ? elt : ptr);
kono
parents:
diff changeset
4096 addr_first = fold_build_pointer_plus_loc (loc,
kono
parents:
diff changeset
4097 addr_first,
kono
parents:
diff changeset
4098 byte_position (field));
kono
parents:
diff changeset
4099 }
kono
parents:
diff changeset
4100 else
kono
parents:
diff changeset
4101 addr_first = chkp_build_addr_expr (node);
kono
parents:
diff changeset
4102 }
kono
parents:
diff changeset
4103 break;
kono
parents:
diff changeset
4104
kono
parents:
diff changeset
4105 case INDIRECT_REF:
kono
parents:
diff changeset
4106 ptr = TREE_OPERAND (node, 0);
kono
parents:
diff changeset
4107 addr_first = ptr;
kono
parents:
diff changeset
4108 break;
kono
parents:
diff changeset
4109
kono
parents:
diff changeset
4110 case MEM_REF:
kono
parents:
diff changeset
4111 ptr = TREE_OPERAND (node, 0);
kono
parents:
diff changeset
4112 addr_first = chkp_build_addr_expr (node);
kono
parents:
diff changeset
4113 break;
kono
parents:
diff changeset
4114
kono
parents:
diff changeset
4115 case TARGET_MEM_REF:
kono
parents:
diff changeset
4116 ptr = TMR_BASE (node);
kono
parents:
diff changeset
4117 addr_first = chkp_build_addr_expr (node);
kono
parents:
diff changeset
4118 break;
kono
parents:
diff changeset
4119
kono
parents:
diff changeset
4120 case ARRAY_RANGE_REF:
kono
parents:
diff changeset
4121 printf("ARRAY_RANGE_REF\n");
kono
parents:
diff changeset
4122 debug_gimple_stmt(gsi_stmt(*iter));
kono
parents:
diff changeset
4123 debug_tree(node);
kono
parents:
diff changeset
4124 gcc_unreachable ();
kono
parents:
diff changeset
4125 break;
kono
parents:
diff changeset
4126
kono
parents:
diff changeset
4127 case BIT_FIELD_REF:
kono
parents:
diff changeset
4128 {
kono
parents:
diff changeset
4129 tree offset, size;
kono
parents:
diff changeset
4130
kono
parents:
diff changeset
4131 gcc_assert (!access_offs);
kono
parents:
diff changeset
4132 gcc_assert (!access_size);
kono
parents:
diff changeset
4133
kono
parents:
diff changeset
4134 chkp_parse_bit_field_ref (node, loc, &offset, &size);
kono
parents:
diff changeset
4135
kono
parents:
diff changeset
4136 chkp_process_stmt (iter, TREE_OPERAND (node, 0), loc,
kono
parents:
diff changeset
4137 dirflag, offset, size, safe);
kono
parents:
diff changeset
4138 return;
kono
parents:
diff changeset
4139 }
kono
parents:
diff changeset
4140 break;
kono
parents:
diff changeset
4141
kono
parents:
diff changeset
4142 case VAR_DECL:
kono
parents:
diff changeset
4143 case RESULT_DECL:
kono
parents:
diff changeset
4144 case PARM_DECL:
kono
parents:
diff changeset
4145 if (dirflag != integer_one_node
kono
parents:
diff changeset
4146 || DECL_REGISTER (node))
kono
parents:
diff changeset
4147 return;
kono
parents:
diff changeset
4148
kono
parents:
diff changeset
4149 safe = true;
kono
parents:
diff changeset
4150 addr_first = chkp_build_addr_expr (node);
kono
parents:
diff changeset
4151 break;
kono
parents:
diff changeset
4152
kono
parents:
diff changeset
4153 default:
kono
parents:
diff changeset
4154 return;
kono
parents:
diff changeset
4155 }
kono
parents:
diff changeset
4156
kono
parents:
diff changeset
4157 /* If addr_last was not computed then use (addr_first + size - 1)
kono
parents:
diff changeset
4158 expression to compute it. */
kono
parents:
diff changeset
4159 if (!addr_last)
kono
parents:
diff changeset
4160 {
kono
parents:
diff changeset
4161 addr_last = fold_build_pointer_plus_loc (loc, addr_first, size);
kono
parents:
diff changeset
4162 addr_last = fold_build_pointer_plus_hwi_loc (loc, addr_last, -1);
kono
parents:
diff changeset
4163 }
kono
parents:
diff changeset
4164
kono
parents:
diff changeset
4165 /* Shift both first_addr and last_addr by access_offs if specified. */
kono
parents:
diff changeset
4166 if (access_offs)
kono
parents:
diff changeset
4167 {
kono
parents:
diff changeset
4168 addr_first = fold_build_pointer_plus_loc (loc, addr_first, access_offs);
kono
parents:
diff changeset
4169 addr_last = fold_build_pointer_plus_loc (loc, addr_last, access_offs);
kono
parents:
diff changeset
4170 }
kono
parents:
diff changeset
4171
kono
parents:
diff changeset
4172 if (dirflag == integer_one_node)
kono
parents:
diff changeset
4173 {
kono
parents:
diff changeset
4174 tree base = get_base_address (node);
kono
parents:
diff changeset
4175 if (VAR_P (base) && DECL_HARD_REGISTER (base))
kono
parents:
diff changeset
4176 reg_store = true;
kono
parents:
diff changeset
4177 }
kono
parents:
diff changeset
4178
kono
parents:
diff changeset
4179 /* Generate bndcl/bndcu checks if memory access is not safe. */
kono
parents:
diff changeset
4180 if (!safe)
kono
parents:
diff changeset
4181 {
kono
parents:
diff changeset
4182 gimple_stmt_iterator stmt_iter = *iter;
kono
parents:
diff changeset
4183
kono
parents:
diff changeset
4184 if (!bounds)
kono
parents:
diff changeset
4185 bounds = chkp_find_bounds (ptr, iter);
kono
parents:
diff changeset
4186
kono
parents:
diff changeset
4187 chkp_check_mem_access (addr_first, addr_last, bounds,
kono
parents:
diff changeset
4188 stmt_iter, loc, dirflag);
kono
parents:
diff changeset
4189 }
kono
parents:
diff changeset
4190
kono
parents:
diff changeset
4191 /* We need to store bounds in case pointer is stored. */
kono
parents:
diff changeset
4192 if (dirflag == integer_one_node
kono
parents:
diff changeset
4193 && !reg_store
kono
parents:
diff changeset
4194 && chkp_type_has_pointer (node_type)
kono
parents:
diff changeset
4195 && flag_chkp_store_bounds)
kono
parents:
diff changeset
4196 {
kono
parents:
diff changeset
4197 gimple *stmt = gsi_stmt (*iter);
kono
parents:
diff changeset
4198 tree rhs1 = gimple_assign_rhs1 (stmt);
kono
parents:
diff changeset
4199 enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
kono
parents:
diff changeset
4200
kono
parents:
diff changeset
4201 if (get_gimple_rhs_class (rhs_code) == GIMPLE_SINGLE_RHS)
kono
parents:
diff changeset
4202 chkp_walk_pointer_assignments (node, rhs1, iter,
kono
parents:
diff changeset
4203 chkp_copy_bounds_for_elem);
kono
parents:
diff changeset
4204 else
kono
parents:
diff changeset
4205 {
kono
parents:
diff changeset
4206 bounds = chkp_compute_bounds_for_assignment (NULL_TREE, stmt);
kono
parents:
diff changeset
4207 chkp_build_bndstx (addr_first, rhs1, bounds, iter);
kono
parents:
diff changeset
4208 }
kono
parents:
diff changeset
4209 }
kono
parents:
diff changeset
4210 }
kono
parents:
diff changeset
4211
kono
parents:
diff changeset
4212 /* Add code to copy bounds for all pointers copied
kono
parents:
diff changeset
4213 in ASSIGN created during inline of EDGE. */
kono
parents:
diff changeset
4214 void
kono
parents:
diff changeset
4215 chkp_copy_bounds_for_assign (gimple *assign, struct cgraph_edge *edge)
kono
parents:
diff changeset
4216 {
kono
parents:
diff changeset
4217 tree lhs = gimple_assign_lhs (assign);
kono
parents:
diff changeset
4218 tree rhs = gimple_assign_rhs1 (assign);
kono
parents:
diff changeset
4219 gimple_stmt_iterator iter = gsi_for_stmt (assign);
kono
parents:
diff changeset
4220
kono
parents:
diff changeset
4221 if (!flag_chkp_store_bounds)
kono
parents:
diff changeset
4222 return;
kono
parents:
diff changeset
4223
kono
parents:
diff changeset
4224 chkp_walk_pointer_assignments (lhs, rhs, &iter, chkp_copy_bounds_for_elem);
kono
parents:
diff changeset
4225
kono
parents:
diff changeset
4226 /* We should create edges for all created calls to bndldx and bndstx. */
kono
parents:
diff changeset
4227 while (gsi_stmt (iter) != assign)
kono
parents:
diff changeset
4228 {
kono
parents:
diff changeset
4229 gimple *stmt = gsi_stmt (iter);
kono
parents:
diff changeset
4230 if (gimple_code (stmt) == GIMPLE_CALL)
kono
parents:
diff changeset
4231 {
kono
parents:
diff changeset
4232 tree fndecl = gimple_call_fndecl (stmt);
kono
parents:
diff changeset
4233 struct cgraph_node *callee = cgraph_node::get_create (fndecl);
kono
parents:
diff changeset
4234 struct cgraph_edge *new_edge;
kono
parents:
diff changeset
4235
kono
parents:
diff changeset
4236 gcc_assert (chkp_gimple_call_builtin_p (stmt, BUILT_IN_CHKP_BNDSTX)
kono
parents:
diff changeset
4237 || chkp_gimple_call_builtin_p (stmt, BUILT_IN_CHKP_BNDLDX)
kono
parents:
diff changeset
4238 || chkp_gimple_call_builtin_p (stmt, BUILT_IN_CHKP_BNDRET));
kono
parents:
diff changeset
4239
kono
parents:
diff changeset
4240 new_edge = edge->caller->create_edge (callee,
kono
parents:
diff changeset
4241 as_a <gcall *> (stmt),
kono
parents:
diff changeset
4242 edge->count,
kono
parents:
diff changeset
4243 edge->frequency);
kono
parents:
diff changeset
4244 new_edge->frequency = compute_call_stmt_bb_frequency
kono
parents:
diff changeset
4245 (edge->caller->decl, gimple_bb (stmt));
kono
parents:
diff changeset
4246 }
kono
parents:
diff changeset
4247 gsi_prev (&iter);
kono
parents:
diff changeset
4248 }
kono
parents:
diff changeset
4249 }
kono
parents:
diff changeset
4250
kono
parents:
diff changeset
4251 /* Some code transformation made during instrumentation pass
kono
parents:
diff changeset
4252 may put code into inconsistent state. Here we find and fix
kono
parents:
diff changeset
4253 such flaws. */
kono
parents:
diff changeset
4254 void
kono
parents:
diff changeset
4255 chkp_fix_cfg ()
kono
parents:
diff changeset
4256 {
kono
parents:
diff changeset
4257 basic_block bb;
kono
parents:
diff changeset
4258 gimple_stmt_iterator i;
kono
parents:
diff changeset
4259
kono
parents:
diff changeset
4260 /* We could insert some code right after stmt which ends bb.
kono
parents:
diff changeset
4261 We wanted to put this code on fallthru edge but did not
kono
parents:
diff changeset
4262 add new edges from the beginning because it may cause new
kono
parents:
diff changeset
4263 phi node creation which may be incorrect due to incomplete
kono
parents:
diff changeset
4264 bound phi nodes. */
kono
parents:
diff changeset
4265 FOR_ALL_BB_FN (bb, cfun)
kono
parents:
diff changeset
4266 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
kono
parents:
diff changeset
4267 {
kono
parents:
diff changeset
4268 gimple *stmt = gsi_stmt (i);
kono
parents:
diff changeset
4269 gimple_stmt_iterator next = i;
kono
parents:
diff changeset
4270
kono
parents:
diff changeset
4271 gsi_next (&next);
kono
parents:
diff changeset
4272
kono
parents:
diff changeset
4273 if (stmt_ends_bb_p (stmt)
kono
parents:
diff changeset
4274 && !gsi_end_p (next))
kono
parents:
diff changeset
4275 {
kono
parents:
diff changeset
4276 edge fall = find_fallthru_edge (bb->succs);
kono
parents:
diff changeset
4277 basic_block dest = NULL;
kono
parents:
diff changeset
4278 int flags = 0;
kono
parents:
diff changeset
4279
kono
parents:
diff changeset
4280 gcc_assert (fall);
kono
parents:
diff changeset
4281
kono
parents:
diff changeset
4282 /* We cannot split abnormal edge. Therefore we
kono
parents:
diff changeset
4283 store its params, make it regular and then
kono
parents:
diff changeset
4284 rebuild abnormal edge after split. */
kono
parents:
diff changeset
4285 if (fall->flags & EDGE_ABNORMAL)
kono
parents:
diff changeset
4286 {
kono
parents:
diff changeset
4287 flags = fall->flags & ~EDGE_FALLTHRU;
kono
parents:
diff changeset
4288 dest = fall->dest;
kono
parents:
diff changeset
4289
kono
parents:
diff changeset
4290 fall->flags &= ~EDGE_COMPLEX;
kono
parents:
diff changeset
4291 }
kono
parents:
diff changeset
4292
kono
parents:
diff changeset
4293 while (!gsi_end_p (next))
kono
parents:
diff changeset
4294 {
kono
parents:
diff changeset
4295 gimple *next_stmt = gsi_stmt (next);
kono
parents:
diff changeset
4296 gsi_remove (&next, false);
kono
parents:
diff changeset
4297 gsi_insert_on_edge (fall, next_stmt);
kono
parents:
diff changeset
4298 }
kono
parents:
diff changeset
4299
kono
parents:
diff changeset
4300 gsi_commit_edge_inserts ();
kono
parents:
diff changeset
4301
kono
parents:
diff changeset
4302 /* Re-create abnormal edge. */
kono
parents:
diff changeset
4303 if (dest)
kono
parents:
diff changeset
4304 make_edge (bb, dest, flags);
kono
parents:
diff changeset
4305 }
kono
parents:
diff changeset
4306 }
kono
parents:
diff changeset
4307 }
kono
parents:
diff changeset
4308
kono
parents:
diff changeset
4309 /* Walker callback for chkp_replace_function_pointers. Replaces
kono
parents:
diff changeset
4310 function pointer in the specified operand with pointer to the
kono
parents:
diff changeset
4311 instrumented function version. */
kono
parents:
diff changeset
4312 static tree
kono
parents:
diff changeset
4313 chkp_replace_function_pointer (tree *op, int *walk_subtrees,
kono
parents:
diff changeset
4314 void *data ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
4315 {
kono
parents:
diff changeset
4316 if (TREE_CODE (*op) == FUNCTION_DECL
kono
parents:
diff changeset
4317 && chkp_instrumentable_p (*op)
kono
parents:
diff changeset
4318 && (DECL_BUILT_IN_CLASS (*op) == NOT_BUILT_IN
kono
parents:
diff changeset
4319 /* For builtins we replace pointers only for selected
kono
parents:
diff changeset
4320 function and functions having definitions. */
kono
parents:
diff changeset
4321 || (DECL_BUILT_IN_CLASS (*op) == BUILT_IN_NORMAL
kono
parents:
diff changeset
4322 && (chkp_instrument_normal_builtin (*op)
kono
parents:
diff changeset
4323 || gimple_has_body_p (*op)))))
kono
parents:
diff changeset
4324 {
kono
parents:
diff changeset
4325 struct cgraph_node *node = cgraph_node::get_create (*op);
kono
parents:
diff changeset
4326 struct cgraph_node *clone = NULL;
kono
parents:
diff changeset
4327
kono
parents:
diff changeset
4328 if (!node->instrumentation_clone)
kono
parents:
diff changeset
4329 clone = chkp_maybe_create_clone (*op);
kono
parents:
diff changeset
4330
kono
parents:
diff changeset
4331 if (clone)
kono
parents:
diff changeset
4332 *op = clone->decl;
kono
parents:
diff changeset
4333 *walk_subtrees = 0;
kono
parents:
diff changeset
4334 }
kono
parents:
diff changeset
4335
kono
parents:
diff changeset
4336 return NULL;
kono
parents:
diff changeset
4337 }
kono
parents:
diff changeset
4338
kono
parents:
diff changeset
4339 /* This function searches for function pointers in statement
kono
parents:
diff changeset
4340 pointed by GSI and replaces them with pointers to instrumented
kono
parents:
diff changeset
4341 function versions. */
kono
parents:
diff changeset
4342 static void
kono
parents:
diff changeset
4343 chkp_replace_function_pointers (gimple_stmt_iterator *gsi)
kono
parents:
diff changeset
4344 {
kono
parents:
diff changeset
4345 gimple *stmt = gsi_stmt (*gsi);
kono
parents:
diff changeset
4346 /* For calls we want to walk call args only. */
kono
parents:
diff changeset
4347 if (gimple_code (stmt) == GIMPLE_CALL)
kono
parents:
diff changeset
4348 {
kono
parents:
diff changeset
4349 unsigned i;
kono
parents:
diff changeset
4350 for (i = 0; i < gimple_call_num_args (stmt); i++)
kono
parents:
diff changeset
4351 walk_tree (gimple_call_arg_ptr (stmt, i),
kono
parents:
diff changeset
4352 chkp_replace_function_pointer, NULL, NULL);
kono
parents:
diff changeset
4353 }
kono
parents:
diff changeset
4354 else
kono
parents:
diff changeset
4355 walk_gimple_stmt (gsi, NULL, chkp_replace_function_pointer, NULL);
kono
parents:
diff changeset
4356 }
kono
parents:
diff changeset
4357
kono
parents:
diff changeset
4358 /* This function instruments all statements working with memory,
kono
parents:
diff changeset
4359 calls and rets.
kono
parents:
diff changeset
4360
kono
parents:
diff changeset
4361 It also removes excess statements from static initializers. */
kono
parents:
diff changeset
4362 static void
kono
parents:
diff changeset
4363 chkp_instrument_function (void)
kono
parents:
diff changeset
4364 {
kono
parents:
diff changeset
4365 basic_block bb, next;
kono
parents:
diff changeset
4366 gimple_stmt_iterator i;
kono
parents:
diff changeset
4367 enum gimple_rhs_class grhs_class;
kono
parents:
diff changeset
4368 bool safe = lookup_attribute ("chkp ctor", DECL_ATTRIBUTES (cfun->decl));
kono
parents:
diff changeset
4369
kono
parents:
diff changeset
4370 bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb;
kono
parents:
diff changeset
4371 do
kono
parents:
diff changeset
4372 {
kono
parents:
diff changeset
4373 next = bb->next_bb;
kono
parents:
diff changeset
4374 for (i = gsi_start_bb (bb); !gsi_end_p (i); )
kono
parents:
diff changeset
4375 {
kono
parents:
diff changeset
4376 gimple *s = gsi_stmt (i);
kono
parents:
diff changeset
4377
kono
parents:
diff changeset
4378 /* Skip statement marked to not be instrumented. */
kono
parents:
diff changeset
4379 if (chkp_marked_stmt_p (s))
kono
parents:
diff changeset
4380 {
kono
parents:
diff changeset
4381 gsi_next (&i);
kono
parents:
diff changeset
4382 continue;
kono
parents:
diff changeset
4383 }
kono
parents:
diff changeset
4384
kono
parents:
diff changeset
4385 chkp_replace_function_pointers (&i);
kono
parents:
diff changeset
4386
kono
parents:
diff changeset
4387 switch (gimple_code (s))
kono
parents:
diff changeset
4388 {
kono
parents:
diff changeset
4389 case GIMPLE_ASSIGN:
kono
parents:
diff changeset
4390 chkp_process_stmt (&i, gimple_assign_lhs (s),
kono
parents:
diff changeset
4391 gimple_location (s), integer_one_node,
kono
parents:
diff changeset
4392 NULL_TREE, NULL_TREE, safe);
kono
parents:
diff changeset
4393 chkp_process_stmt (&i, gimple_assign_rhs1 (s),
kono
parents:
diff changeset
4394 gimple_location (s), integer_zero_node,
kono
parents:
diff changeset
4395 NULL_TREE, NULL_TREE, safe);
kono
parents:
diff changeset
4396 grhs_class = get_gimple_rhs_class (gimple_assign_rhs_code (s));
kono
parents:
diff changeset
4397 if (grhs_class == GIMPLE_BINARY_RHS)
kono
parents:
diff changeset
4398 chkp_process_stmt (&i, gimple_assign_rhs2 (s),
kono
parents:
diff changeset
4399 gimple_location (s), integer_zero_node,
kono
parents:
diff changeset
4400 NULL_TREE, NULL_TREE, safe);
kono
parents:
diff changeset
4401 break;
kono
parents:
diff changeset
4402
kono
parents:
diff changeset
4403 case GIMPLE_RETURN:
kono
parents:
diff changeset
4404 {
kono
parents:
diff changeset
4405 greturn *r = as_a <greturn *> (s);
kono
parents:
diff changeset
4406 if (gimple_return_retval (r) != NULL_TREE)
kono
parents:
diff changeset
4407 {
kono
parents:
diff changeset
4408 chkp_process_stmt (&i, gimple_return_retval (r),
kono
parents:
diff changeset
4409 gimple_location (r),
kono
parents:
diff changeset
4410 integer_zero_node,
kono
parents:
diff changeset
4411 NULL_TREE, NULL_TREE, safe);
kono
parents:
diff changeset
4412
kono
parents:
diff changeset
4413 /* Additionally we need to add bounds
kono
parents:
diff changeset
4414 to return statement. */
kono
parents:
diff changeset
4415 chkp_add_bounds_to_ret_stmt (&i);
kono
parents:
diff changeset
4416 }
kono
parents:
diff changeset
4417 }
kono
parents:
diff changeset
4418 break;
kono
parents:
diff changeset
4419
kono
parents:
diff changeset
4420 case GIMPLE_CALL:
kono
parents:
diff changeset
4421 chkp_add_bounds_to_call_stmt (&i);
kono
parents:
diff changeset
4422 break;
kono
parents:
diff changeset
4423
kono
parents:
diff changeset
4424 default:
kono
parents:
diff changeset
4425 ;
kono
parents:
diff changeset
4426 }
kono
parents:
diff changeset
4427
kono
parents:
diff changeset
4428 gsi_next (&i);
kono
parents:
diff changeset
4429
kono
parents:
diff changeset
4430 /* We do not need any actual pointer stores in checker
kono
parents:
diff changeset
4431 static initializer. */
kono
parents:
diff changeset
4432 if (lookup_attribute ("chkp ctor", DECL_ATTRIBUTES (cfun->decl))
kono
parents:
diff changeset
4433 && gimple_code (s) == GIMPLE_ASSIGN
kono
parents:
diff changeset
4434 && gimple_store_p (s))
kono
parents:
diff changeset
4435 {
kono
parents:
diff changeset
4436 gimple_stmt_iterator del_iter = gsi_for_stmt (s);
kono
parents:
diff changeset
4437 gsi_remove (&del_iter, true);
kono
parents:
diff changeset
4438 unlink_stmt_vdef (s);
kono
parents:
diff changeset
4439 release_defs(s);
kono
parents:
diff changeset
4440 }
kono
parents:
diff changeset
4441 }
kono
parents:
diff changeset
4442 bb = next;
kono
parents:
diff changeset
4443 }
kono
parents:
diff changeset
4444 while (bb);
kono
parents:
diff changeset
4445
kono
parents:
diff changeset
4446 /* Some input params may have bounds and be address taken. In this case
kono
parents:
diff changeset
4447 we should store incoming bounds into bounds table. */
kono
parents:
diff changeset
4448 tree arg;
kono
parents:
diff changeset
4449 if (flag_chkp_store_bounds)
kono
parents:
diff changeset
4450 for (arg = DECL_ARGUMENTS (cfun->decl); arg; arg = DECL_CHAIN (arg))
kono
parents:
diff changeset
4451 if (TREE_ADDRESSABLE (arg))
kono
parents:
diff changeset
4452 {
kono
parents:
diff changeset
4453 if (BOUNDED_P (arg))
kono
parents:
diff changeset
4454 {
kono
parents:
diff changeset
4455 tree bounds = chkp_get_next_bounds_parm (arg);
kono
parents:
diff changeset
4456 tree def_ptr = ssa_default_def (cfun, arg);
kono
parents:
diff changeset
4457 gimple_stmt_iterator iter
kono
parents:
diff changeset
4458 = gsi_start_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
4459 chkp_build_bndstx (chkp_build_addr_expr (arg),
kono
parents:
diff changeset
4460 def_ptr ? def_ptr : arg,
kono
parents:
diff changeset
4461 bounds, &iter);
kono
parents:
diff changeset
4462
kono
parents:
diff changeset
4463 /* Skip bounds arg. */
kono
parents:
diff changeset
4464 arg = TREE_CHAIN (arg);
kono
parents:
diff changeset
4465 }
kono
parents:
diff changeset
4466 else if (chkp_type_has_pointer (TREE_TYPE (arg)))
kono
parents:
diff changeset
4467 {
kono
parents:
diff changeset
4468 tree orig_arg = arg;
kono
parents:
diff changeset
4469 bitmap slots = BITMAP_ALLOC (NULL);
kono
parents:
diff changeset
4470 gimple_stmt_iterator iter
kono
parents:
diff changeset
4471 = gsi_start_bb (chkp_get_entry_block ());
kono
parents:
diff changeset
4472 bitmap_iterator bi;
kono
parents:
diff changeset
4473 unsigned bnd_no;
kono
parents:
diff changeset
4474
kono
parents:
diff changeset
4475 chkp_find_bound_slots (TREE_TYPE (arg), slots);
kono
parents:
diff changeset
4476
kono
parents:
diff changeset
4477 EXECUTE_IF_SET_IN_BITMAP (slots, 0, bnd_no, bi)
kono
parents:
diff changeset
4478 {
kono
parents:
diff changeset
4479 tree bounds = chkp_get_next_bounds_parm (arg);
kono
parents:
diff changeset
4480 HOST_WIDE_INT offs = bnd_no * POINTER_SIZE / BITS_PER_UNIT;
kono
parents:
diff changeset
4481 tree addr = chkp_build_addr_expr (orig_arg);
kono
parents:
diff changeset
4482 tree ptr = build2 (MEM_REF, ptr_type_node, addr,
kono
parents:
diff changeset
4483 build_int_cst (ptr_type_node, offs));
kono
parents:
diff changeset
4484 chkp_build_bndstx (chkp_build_addr_expr (ptr), ptr,
kono
parents:
diff changeset
4485 bounds, &iter);
kono
parents:
diff changeset
4486
kono
parents:
diff changeset
4487 arg = DECL_CHAIN (arg);
kono
parents:
diff changeset
4488 }
kono
parents:
diff changeset
4489 BITMAP_FREE (slots);
kono
parents:
diff changeset
4490 }
kono
parents:
diff changeset
4491 }
kono
parents:
diff changeset
4492 }
kono
parents:
diff changeset
4493
kono
parents:
diff changeset
4494 /* Find init/null/copy_ptr_bounds calls and replace them
kono
parents:
diff changeset
4495 with assignments. It should allow better code
kono
parents:
diff changeset
4496 optimization. */
kono
parents:
diff changeset
4497
kono
parents:
diff changeset
4498 static void
kono
parents:
diff changeset
4499 chkp_remove_useless_builtins ()
kono
parents:
diff changeset
4500 {
kono
parents:
diff changeset
4501 basic_block bb;
kono
parents:
diff changeset
4502 gimple_stmt_iterator gsi;
kono
parents:
diff changeset
4503
kono
parents:
diff changeset
4504 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
4505 {
kono
parents:
diff changeset
4506 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
kono
parents:
diff changeset
4507 {
kono
parents:
diff changeset
4508 gimple *stmt = gsi_stmt (gsi);
kono
parents:
diff changeset
4509 tree fndecl;
kono
parents:
diff changeset
4510 enum built_in_function fcode;
kono
parents:
diff changeset
4511
kono
parents:
diff changeset
4512 /* Find builtins returning first arg and replace
kono
parents:
diff changeset
4513 them with assignments. */
kono
parents:
diff changeset
4514 if (gimple_code (stmt) == GIMPLE_CALL
kono
parents:
diff changeset
4515 && (fndecl = gimple_call_fndecl (stmt))
kono
parents:
diff changeset
4516 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
4517 && (fcode = DECL_FUNCTION_CODE (fndecl))
kono
parents:
diff changeset
4518 && (fcode == BUILT_IN_CHKP_INIT_PTR_BOUNDS
kono
parents:
diff changeset
4519 || fcode == BUILT_IN_CHKP_NULL_PTR_BOUNDS
kono
parents:
diff changeset
4520 || fcode == BUILT_IN_CHKP_COPY_PTR_BOUNDS
kono
parents:
diff changeset
4521 || fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS))
kono
parents:
diff changeset
4522 {
kono
parents:
diff changeset
4523 tree res = gimple_call_arg (stmt, 0);
kono
parents:
diff changeset
4524 update_call_from_tree (&gsi, res);
kono
parents:
diff changeset
4525 stmt = gsi_stmt (gsi);
kono
parents:
diff changeset
4526 update_stmt (stmt);
kono
parents:
diff changeset
4527 }
kono
parents:
diff changeset
4528 }
kono
parents:
diff changeset
4529 }
kono
parents:
diff changeset
4530 }
kono
parents:
diff changeset
4531
kono
parents:
diff changeset
4532 /* Initialize pass. */
kono
parents:
diff changeset
4533 static void
kono
parents:
diff changeset
4534 chkp_init (void)
kono
parents:
diff changeset
4535 {
kono
parents:
diff changeset
4536 basic_block bb;
kono
parents:
diff changeset
4537 gimple_stmt_iterator i;
kono
parents:
diff changeset
4538
kono
parents:
diff changeset
4539 in_chkp_pass = true;
kono
parents:
diff changeset
4540
kono
parents:
diff changeset
4541 for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb; bb = bb->next_bb)
kono
parents:
diff changeset
4542 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i))
kono
parents:
diff changeset
4543 chkp_unmark_stmt (gsi_stmt (i));
kono
parents:
diff changeset
4544
kono
parents:
diff changeset
4545 chkp_invalid_bounds = new hash_set<tree>;
kono
parents:
diff changeset
4546 chkp_completed_bounds_set = new hash_set<tree>;
kono
parents:
diff changeset
4547 delete chkp_reg_bounds;
kono
parents:
diff changeset
4548 chkp_reg_bounds = new hash_map<tree, tree>;
kono
parents:
diff changeset
4549 delete chkp_bound_vars;
kono
parents:
diff changeset
4550 chkp_bound_vars = new hash_map<tree, tree>;
kono
parents:
diff changeset
4551 chkp_reg_addr_bounds = new hash_map<tree, tree>;
kono
parents:
diff changeset
4552 chkp_incomplete_bounds_map = new hash_map<tree, tree>;
kono
parents:
diff changeset
4553 delete chkp_bounds_map;
kono
parents:
diff changeset
4554 chkp_bounds_map = new hash_map<tree, tree>;
kono
parents:
diff changeset
4555 chkp_abnormal_copies = BITMAP_GGC_ALLOC ();
kono
parents:
diff changeset
4556
kono
parents:
diff changeset
4557 entry_block = NULL;
kono
parents:
diff changeset
4558 zero_bounds = NULL_TREE;
kono
parents:
diff changeset
4559 none_bounds = NULL_TREE;
kono
parents:
diff changeset
4560 incomplete_bounds = integer_zero_node;
kono
parents:
diff changeset
4561 tmp_var = NULL_TREE;
kono
parents:
diff changeset
4562 size_tmp_var = NULL_TREE;
kono
parents:
diff changeset
4563
kono
parents:
diff changeset
4564 chkp_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode, true);
kono
parents:
diff changeset
4565
kono
parents:
diff changeset
4566 /* We create these constant bounds once for each object file.
kono
parents:
diff changeset
4567 These symbols go to comdat section and result in single copy
kono
parents:
diff changeset
4568 of each one in the final binary. */
kono
parents:
diff changeset
4569 chkp_get_zero_bounds_var ();
kono
parents:
diff changeset
4570 chkp_get_none_bounds_var ();
kono
parents:
diff changeset
4571
kono
parents:
diff changeset
4572 calculate_dominance_info (CDI_DOMINATORS);
kono
parents:
diff changeset
4573 calculate_dominance_info (CDI_POST_DOMINATORS);
kono
parents:
diff changeset
4574
kono
parents:
diff changeset
4575 bitmap_obstack_initialize (NULL);
kono
parents:
diff changeset
4576 }
kono
parents:
diff changeset
4577
kono
parents:
diff changeset
4578 /* Finalize instrumentation pass. */
kono
parents:
diff changeset
4579 static void
kono
parents:
diff changeset
4580 chkp_fini (void)
kono
parents:
diff changeset
4581 {
kono
parents:
diff changeset
4582 in_chkp_pass = false;
kono
parents:
diff changeset
4583
kono
parents:
diff changeset
4584 delete chkp_invalid_bounds;
kono
parents:
diff changeset
4585 delete chkp_completed_bounds_set;
kono
parents:
diff changeset
4586 delete chkp_reg_addr_bounds;
kono
parents:
diff changeset
4587 delete chkp_incomplete_bounds_map;
kono
parents:
diff changeset
4588
kono
parents:
diff changeset
4589 free_dominance_info (CDI_DOMINATORS);
kono
parents:
diff changeset
4590 free_dominance_info (CDI_POST_DOMINATORS);
kono
parents:
diff changeset
4591
kono
parents:
diff changeset
4592 bitmap_obstack_release (NULL);
kono
parents:
diff changeset
4593
kono
parents:
diff changeset
4594 entry_block = NULL;
kono
parents:
diff changeset
4595 zero_bounds = NULL_TREE;
kono
parents:
diff changeset
4596 none_bounds = NULL_TREE;
kono
parents:
diff changeset
4597 }
kono
parents:
diff changeset
4598
kono
parents:
diff changeset
4599 /* Main instrumentation pass function. */
kono
parents:
diff changeset
4600 static unsigned int
kono
parents:
diff changeset
4601 chkp_execute (void)
kono
parents:
diff changeset
4602 {
kono
parents:
diff changeset
4603 chkp_init ();
kono
parents:
diff changeset
4604
kono
parents:
diff changeset
4605 chkp_instrument_function ();
kono
parents:
diff changeset
4606
kono
parents:
diff changeset
4607 chkp_remove_useless_builtins ();
kono
parents:
diff changeset
4608
kono
parents:
diff changeset
4609 chkp_function_mark_instrumented (cfun->decl);
kono
parents:
diff changeset
4610
kono
parents:
diff changeset
4611 chkp_fix_cfg ();
kono
parents:
diff changeset
4612
kono
parents:
diff changeset
4613 chkp_fini ();
kono
parents:
diff changeset
4614
kono
parents:
diff changeset
4615 return 0;
kono
parents:
diff changeset
4616 }
kono
parents:
diff changeset
4617
kono
parents:
diff changeset
4618 /* Instrumentation pass gate. */
kono
parents:
diff changeset
4619 static bool
kono
parents:
diff changeset
4620 chkp_gate (void)
kono
parents:
diff changeset
4621 {
kono
parents:
diff changeset
4622 cgraph_node *node = cgraph_node::get (cfun->decl);
kono
parents:
diff changeset
4623 return ((node != NULL
kono
parents:
diff changeset
4624 && node->instrumentation_clone)
kono
parents:
diff changeset
4625 || lookup_attribute ("chkp ctor", DECL_ATTRIBUTES (cfun->decl)));
kono
parents:
diff changeset
4626 }
kono
parents:
diff changeset
4627
kono
parents:
diff changeset
4628 namespace {
kono
parents:
diff changeset
4629
kono
parents:
diff changeset
4630 const pass_data pass_data_chkp =
kono
parents:
diff changeset
4631 {
kono
parents:
diff changeset
4632 GIMPLE_PASS, /* type */
kono
parents:
diff changeset
4633 "chkp", /* name */
kono
parents:
diff changeset
4634 OPTGROUP_NONE, /* optinfo_flags */
kono
parents:
diff changeset
4635 TV_NONE, /* tv_id */
kono
parents:
diff changeset
4636 PROP_ssa | PROP_cfg, /* properties_required */
kono
parents:
diff changeset
4637 0, /* properties_provided */
kono
parents:
diff changeset
4638 0, /* properties_destroyed */
kono
parents:
diff changeset
4639 0, /* todo_flags_start */
kono
parents:
diff changeset
4640 TODO_verify_il
kono
parents:
diff changeset
4641 | TODO_update_ssa /* todo_flags_finish */
kono
parents:
diff changeset
4642 };
kono
parents:
diff changeset
4643
kono
parents:
diff changeset
4644 class pass_chkp : public gimple_opt_pass
kono
parents:
diff changeset
4645 {
kono
parents:
diff changeset
4646 public:
kono
parents:
diff changeset
4647 pass_chkp (gcc::context *ctxt)
kono
parents:
diff changeset
4648 : gimple_opt_pass (pass_data_chkp, ctxt)
kono
parents:
diff changeset
4649 {}
kono
parents:
diff changeset
4650
kono
parents:
diff changeset
4651 /* opt_pass methods: */
kono
parents:
diff changeset
4652 virtual opt_pass * clone ()
kono
parents:
diff changeset
4653 {
kono
parents:
diff changeset
4654 return new pass_chkp (m_ctxt);
kono
parents:
diff changeset
4655 }
kono
parents:
diff changeset
4656
kono
parents:
diff changeset
4657 virtual bool gate (function *)
kono
parents:
diff changeset
4658 {
kono
parents:
diff changeset
4659 return chkp_gate ();
kono
parents:
diff changeset
4660 }
kono
parents:
diff changeset
4661
kono
parents:
diff changeset
4662 virtual unsigned int execute (function *)
kono
parents:
diff changeset
4663 {
kono
parents:
diff changeset
4664 return chkp_execute ();
kono
parents:
diff changeset
4665 }
kono
parents:
diff changeset
4666
kono
parents:
diff changeset
4667 }; // class pass_chkp
kono
parents:
diff changeset
4668
kono
parents:
diff changeset
4669 } // anon namespace
kono
parents:
diff changeset
4670
kono
parents:
diff changeset
4671 gimple_opt_pass *
kono
parents:
diff changeset
4672 make_pass_chkp (gcc::context *ctxt)
kono
parents:
diff changeset
4673 {
kono
parents:
diff changeset
4674 return new pass_chkp (ctxt);
kono
parents:
diff changeset
4675 }
kono
parents:
diff changeset
4676
kono
parents:
diff changeset
4677 #include "gt-tree-chkp.h"