annotate gcc/ipa-chkp.c @ 144:8f4e72ab4e11

fix segmentation fault caused by nothing next cur_op to end
author Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sun, 23 Dec 2018 21:23:56 +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 IPA passes.
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 #define INCLUDE_STRING
kono
parents:
diff changeset
23 #include "system.h"
kono
parents:
diff changeset
24 #include "coretypes.h"
kono
parents:
diff changeset
25 #include "backend.h"
kono
parents:
diff changeset
26 #include "tree.h"
kono
parents:
diff changeset
27 #include "gimple.h"
kono
parents:
diff changeset
28 #include "tree-pass.h"
kono
parents:
diff changeset
29 #include "stringpool.h"
kono
parents:
diff changeset
30 #include "lto-streamer.h"
kono
parents:
diff changeset
31 #include "stor-layout.h"
kono
parents:
diff changeset
32 #include "calls.h"
kono
parents:
diff changeset
33 #include "cgraph.h"
kono
parents:
diff changeset
34 #include "tree-chkp.h"
kono
parents:
diff changeset
35 #include "tree-inline.h"
kono
parents:
diff changeset
36 #include "ipa-chkp.h"
kono
parents:
diff changeset
37 #include "stringpool.h"
kono
parents:
diff changeset
38 #include "attribs.h"
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 /* Pointer Bounds Checker has two IPA passes to support code instrumentation.
kono
parents:
diff changeset
41
kono
parents:
diff changeset
42 In instrumented code each pointer is provided with bounds. For input
kono
parents:
diff changeset
43 pointer parameters it means we also have bounds passed. For calls it
kono
parents:
diff changeset
44 means we have additional bounds arguments for pointer arguments.
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 To have all IPA optimizations working correctly we have to express
kono
parents:
diff changeset
47 dataflow between passed and received bounds explicitly via additional
kono
parents:
diff changeset
48 entries in function declaration arguments list and in function type.
kono
parents:
diff changeset
49 Since we may have both instrumented and not instrumented code at the
kono
parents:
diff changeset
50 same time, we cannot replace all original functions with their
kono
parents:
diff changeset
51 instrumented variants. Therefore we create clones (versions) instead.
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 Instrumentation clones creation is a separate IPA pass which is a part
kono
parents:
diff changeset
54 of early local passes. Clones are created after SSA is built (because
kono
parents:
diff changeset
55 instrumentation pass works on SSA) and before any transformations
kono
parents:
diff changeset
56 which may change pointer flow and therefore lead to incorrect code
kono
parents:
diff changeset
57 instrumentation (possibly causing false bounds check failures).
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 Instrumentation clones have pointer bounds arguments added right after
kono
parents:
diff changeset
60 pointer arguments. Clones have assembler name of the original
kono
parents:
diff changeset
61 function with suffix added. New assembler name is in transparent
kono
parents:
diff changeset
62 alias chain with the original name. Thus we expect all calls to the
kono
parents:
diff changeset
63 original and instrumented functions look similar in assembler.
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 During instrumentation versioning pass we create instrumented versions
kono
parents:
diff changeset
66 of all function with body and also for all their aliases and thunks.
kono
parents:
diff changeset
67 Clones for functions with no body are created on demand (usually
kono
parents:
diff changeset
68 during call instrumentation).
kono
parents:
diff changeset
69
kono
parents:
diff changeset
70 Original and instrumented function nodes are connected with IPA
kono
parents:
diff changeset
71 reference IPA_REF_CHKP. It is mostly done to have reachability
kono
parents:
diff changeset
72 analysis working correctly. We may have no references to the
kono
parents:
diff changeset
73 instrumented function in the code but it still should be counted
kono
parents:
diff changeset
74 as reachable if the original function is reachable.
kono
parents:
diff changeset
75
kono
parents:
diff changeset
76 When original function bodies are not needed anymore we release
kono
parents:
diff changeset
77 them and transform functions into a special kind of thunks. Each
kono
parents:
diff changeset
78 thunk has a call edge to the instrumented version. These thunks
kono
parents:
diff changeset
79 help to keep externally visible instrumented functions visible
kono
parents:
diff changeset
80 when linker resolution files are used. Linker has no info about
kono
parents:
diff changeset
81 connection between original and instrumented function and
kono
parents:
diff changeset
82 therefore we may wrongly decide (due to difference in assembler
kono
parents:
diff changeset
83 names) that instrumented function version is local and can be
kono
parents:
diff changeset
84 removed. */
kono
parents:
diff changeset
85
kono
parents:
diff changeset
86 #define CHKP_BOUNDS_OF_SYMBOL_PREFIX "__chkp_bounds_of_"
kono
parents:
diff changeset
87 #define CHKP_WRAPPER_SYMBOL_PREFIX "__mpx_wrapper_"
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 /* Return 1 calls to FNDECL should be replaced with
kono
parents:
diff changeset
90 a call to wrapper function. */
kono
parents:
diff changeset
91 bool
kono
parents:
diff changeset
92 chkp_wrap_function (tree fndecl)
kono
parents:
diff changeset
93 {
kono
parents:
diff changeset
94 if (!flag_chkp_use_wrappers)
kono
parents:
diff changeset
95 return false;
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
kono
parents:
diff changeset
98 {
kono
parents:
diff changeset
99 switch (DECL_FUNCTION_CODE (fndecl))
kono
parents:
diff changeset
100 {
kono
parents:
diff changeset
101 case BUILT_IN_STRLEN:
kono
parents:
diff changeset
102 case BUILT_IN_STRCPY:
kono
parents:
diff changeset
103 case BUILT_IN_STRNCPY:
kono
parents:
diff changeset
104 case BUILT_IN_STPCPY:
kono
parents:
diff changeset
105 case BUILT_IN_STPNCPY:
kono
parents:
diff changeset
106 case BUILT_IN_STRCAT:
kono
parents:
diff changeset
107 case BUILT_IN_STRNCAT:
kono
parents:
diff changeset
108 case BUILT_IN_MEMCPY:
kono
parents:
diff changeset
109 case BUILT_IN_MEMPCPY:
kono
parents:
diff changeset
110 case BUILT_IN_MEMSET:
kono
parents:
diff changeset
111 case BUILT_IN_MEMMOVE:
kono
parents:
diff changeset
112 case BUILT_IN_BZERO:
kono
parents:
diff changeset
113 case BUILT_IN_MALLOC:
kono
parents:
diff changeset
114 case BUILT_IN_CALLOC:
kono
parents:
diff changeset
115 case BUILT_IN_REALLOC:
kono
parents:
diff changeset
116 return 1;
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 default:
kono
parents:
diff changeset
119 return 0;
kono
parents:
diff changeset
120 }
kono
parents:
diff changeset
121 }
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 return false;
kono
parents:
diff changeset
124 }
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 static const char *
kono
parents:
diff changeset
127 chkp_wrap_function_name (tree fndecl)
kono
parents:
diff changeset
128 {
kono
parents:
diff changeset
129 gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 switch (DECL_FUNCTION_CODE (fndecl))
kono
parents:
diff changeset
132 {
kono
parents:
diff changeset
133 case BUILT_IN_STRLEN:
kono
parents:
diff changeset
134 return CHKP_WRAPPER_SYMBOL_PREFIX "strlen";
kono
parents:
diff changeset
135 case BUILT_IN_STRCPY:
kono
parents:
diff changeset
136 return CHKP_WRAPPER_SYMBOL_PREFIX "strcpy";
kono
parents:
diff changeset
137 case BUILT_IN_STRNCPY:
kono
parents:
diff changeset
138 return CHKP_WRAPPER_SYMBOL_PREFIX "strncpy";
kono
parents:
diff changeset
139 case BUILT_IN_STPCPY:
kono
parents:
diff changeset
140 return CHKP_WRAPPER_SYMBOL_PREFIX "stpcpy";
kono
parents:
diff changeset
141 case BUILT_IN_STPNCPY:
kono
parents:
diff changeset
142 return CHKP_WRAPPER_SYMBOL_PREFIX "stpncpy";
kono
parents:
diff changeset
143 case BUILT_IN_STRCAT:
kono
parents:
diff changeset
144 return CHKP_WRAPPER_SYMBOL_PREFIX "strcat";
kono
parents:
diff changeset
145 case BUILT_IN_STRNCAT:
kono
parents:
diff changeset
146 return CHKP_WRAPPER_SYMBOL_PREFIX "strncat";
kono
parents:
diff changeset
147 case BUILT_IN_MEMCPY:
kono
parents:
diff changeset
148 return CHKP_WRAPPER_SYMBOL_PREFIX "memcpy";
kono
parents:
diff changeset
149 case BUILT_IN_MEMPCPY:
kono
parents:
diff changeset
150 return CHKP_WRAPPER_SYMBOL_PREFIX "mempcpy";
kono
parents:
diff changeset
151 case BUILT_IN_MEMSET:
kono
parents:
diff changeset
152 return CHKP_WRAPPER_SYMBOL_PREFIX "memset";
kono
parents:
diff changeset
153 case BUILT_IN_MEMMOVE:
kono
parents:
diff changeset
154 return CHKP_WRAPPER_SYMBOL_PREFIX "memmove";
kono
parents:
diff changeset
155 case BUILT_IN_BZERO:
kono
parents:
diff changeset
156 return CHKP_WRAPPER_SYMBOL_PREFIX "bzero";
kono
parents:
diff changeset
157 case BUILT_IN_MALLOC:
kono
parents:
diff changeset
158 return CHKP_WRAPPER_SYMBOL_PREFIX "malloc";
kono
parents:
diff changeset
159 case BUILT_IN_CALLOC:
kono
parents:
diff changeset
160 return CHKP_WRAPPER_SYMBOL_PREFIX "calloc";
kono
parents:
diff changeset
161 case BUILT_IN_REALLOC:
kono
parents:
diff changeset
162 return CHKP_WRAPPER_SYMBOL_PREFIX "realloc";
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 default:
kono
parents:
diff changeset
165 gcc_unreachable ();
kono
parents:
diff changeset
166 }
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 return "";
kono
parents:
diff changeset
169 }
kono
parents:
diff changeset
170
kono
parents:
diff changeset
171 /* Build a clone of FNDECL with a modified name. */
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 static tree
kono
parents:
diff changeset
174 chkp_build_instrumented_fndecl (tree fndecl)
kono
parents:
diff changeset
175 {
kono
parents:
diff changeset
176 tree new_decl = copy_node (fndecl);
kono
parents:
diff changeset
177 tree new_name;
kono
parents:
diff changeset
178 std::string s;
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 /* called_as_built_in checks DECL_NAME to identify calls to
kono
parents:
diff changeset
181 builtins. We want instrumented calls to builtins to be
kono
parents:
diff changeset
182 recognized by called_as_built_in. Therefore use original
kono
parents:
diff changeset
183 DECL_NAME for cloning with no prefixes. */
kono
parents:
diff changeset
184 s = IDENTIFIER_POINTER (DECL_NAME (fndecl));
kono
parents:
diff changeset
185 s += ".chkp";
kono
parents:
diff changeset
186 DECL_NAME (new_decl) = get_identifier (s.c_str ());
kono
parents:
diff changeset
187
kono
parents:
diff changeset
188 /* References to the original and to the instrumented version
kono
parents:
diff changeset
189 should look the same in the output assembly. And we cannot
kono
parents:
diff changeset
190 use the same assembler name for the instrumented version
kono
parents:
diff changeset
191 because it conflicts with decl merging algorithms in LTO.
kono
parents:
diff changeset
192 Achieve the result by using transparent alias name for the
kono
parents:
diff changeset
193 instrumented version. */
kono
parents:
diff changeset
194 if (chkp_wrap_function(fndecl))
kono
parents:
diff changeset
195 {
kono
parents:
diff changeset
196 new_name = get_identifier (chkp_wrap_function_name (fndecl));
kono
parents:
diff changeset
197 DECL_VISIBILITY (new_decl) = VISIBILITY_DEFAULT;
kono
parents:
diff changeset
198 }
kono
parents:
diff changeset
199 else
kono
parents:
diff changeset
200 {
kono
parents:
diff changeset
201 s = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
kono
parents:
diff changeset
202 s += ".chkp";
kono
parents:
diff changeset
203 new_name = get_identifier (s.c_str ());
kono
parents:
diff changeset
204 IDENTIFIER_TRANSPARENT_ALIAS (new_name) = 1;
kono
parents:
diff changeset
205 TREE_CHAIN (new_name) = DECL_ASSEMBLER_NAME (fndecl);
kono
parents:
diff changeset
206 }
kono
parents:
diff changeset
207 SET_DECL_ASSEMBLER_NAME (new_decl, new_name);
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 /* For functions with body versioning will make a copy of arguments.
kono
parents:
diff changeset
210 For functions with no body we need to do it here. */
kono
parents:
diff changeset
211 if (!gimple_has_body_p (fndecl))
kono
parents:
diff changeset
212 {
kono
parents:
diff changeset
213 tree arg;
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 DECL_ARGUMENTS (new_decl) = copy_list (DECL_ARGUMENTS (fndecl));
kono
parents:
diff changeset
216 for (arg = DECL_ARGUMENTS (new_decl); arg; arg = DECL_CHAIN (arg))
kono
parents:
diff changeset
217 DECL_CONTEXT (arg) = new_decl;
kono
parents:
diff changeset
218 }
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 /* We are going to modify attributes list and therefore should
kono
parents:
diff changeset
221 make own copy. */
kono
parents:
diff changeset
222 DECL_ATTRIBUTES (new_decl) = copy_list (DECL_ATTRIBUTES (fndecl));
kono
parents:
diff changeset
223
kono
parents:
diff changeset
224 /* Change builtin function code. */
kono
parents:
diff changeset
225 if (DECL_BUILT_IN (new_decl))
kono
parents:
diff changeset
226 {
kono
parents:
diff changeset
227 gcc_assert (DECL_BUILT_IN_CLASS (new_decl) == BUILT_IN_NORMAL);
kono
parents:
diff changeset
228 gcc_assert (DECL_FUNCTION_CODE (new_decl) < BEGIN_CHKP_BUILTINS);
kono
parents:
diff changeset
229 DECL_FUNCTION_CODE (new_decl)
kono
parents:
diff changeset
230 = (enum built_in_function)(DECL_FUNCTION_CODE (new_decl)
kono
parents:
diff changeset
231 + BEGIN_CHKP_BUILTINS + 1);
kono
parents:
diff changeset
232 }
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 return new_decl;
kono
parents:
diff changeset
235 }
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 /* Fix operands of attribute from ATTRS list named ATTR_NAME.
kono
parents:
diff changeset
239 Integer operands are replaced with values according to
kono
parents:
diff changeset
240 INDEXES map having LEN elements. For operands out of len
kono
parents:
diff changeset
241 we just add DELTA. */
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 static void
kono
parents:
diff changeset
244 chkp_map_attr_arg_indexes (tree attrs, const char *attr_name,
kono
parents:
diff changeset
245 unsigned *indexes, int len, int delta)
kono
parents:
diff changeset
246 {
kono
parents:
diff changeset
247 tree attr = lookup_attribute (attr_name, attrs);
kono
parents:
diff changeset
248 tree op;
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 if (!attr)
kono
parents:
diff changeset
251 return;
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 TREE_VALUE (attr) = copy_list (TREE_VALUE (attr));
kono
parents:
diff changeset
254 for (op = TREE_VALUE (attr); op; op = TREE_CHAIN (op))
kono
parents:
diff changeset
255 {
kono
parents:
diff changeset
256 int idx;
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 if (TREE_CODE (TREE_VALUE (op)) != INTEGER_CST)
kono
parents:
diff changeset
259 continue;
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 idx = TREE_INT_CST_LOW (TREE_VALUE (op));
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 /* If idx exceeds indexes length then we just
kono
parents:
diff changeset
264 keep it at the same distance from the last
kono
parents:
diff changeset
265 known arg. */
kono
parents:
diff changeset
266 if (idx > len)
kono
parents:
diff changeset
267 idx += delta;
kono
parents:
diff changeset
268 else
kono
parents:
diff changeset
269 idx = indexes[idx - 1] + 1;
kono
parents:
diff changeset
270 TREE_VALUE (op) = build_int_cst (TREE_TYPE (TREE_VALUE (op)), idx);
kono
parents:
diff changeset
271 }
kono
parents:
diff changeset
272 }
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 /* Make a copy of function type ORIG_TYPE adding pointer
kono
parents:
diff changeset
275 bounds as additional arguments. */
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 tree
kono
parents:
diff changeset
278 chkp_copy_function_type_adding_bounds (tree orig_type)
kono
parents:
diff changeset
279 {
kono
parents:
diff changeset
280 tree type;
kono
parents:
diff changeset
281 tree arg_type, attrs;
kono
parents:
diff changeset
282 unsigned len = list_length (TYPE_ARG_TYPES (orig_type));
kono
parents:
diff changeset
283 unsigned *indexes = XALLOCAVEC (unsigned, len);
kono
parents:
diff changeset
284 unsigned idx = 0, new_idx = 0;
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 for (arg_type = TYPE_ARG_TYPES (orig_type);
kono
parents:
diff changeset
287 arg_type;
kono
parents:
diff changeset
288 arg_type = TREE_CHAIN (arg_type))
kono
parents:
diff changeset
289 if (TREE_VALUE (arg_type) == void_type_node)
kono
parents:
diff changeset
290 continue;
kono
parents:
diff changeset
291 else if (BOUNDED_TYPE_P (TREE_VALUE (arg_type))
kono
parents:
diff changeset
292 || pass_by_reference (NULL, TYPE_MODE (TREE_VALUE (arg_type)),
kono
parents:
diff changeset
293 TREE_VALUE (arg_type), true)
kono
parents:
diff changeset
294 || chkp_type_has_pointer (TREE_VALUE (arg_type)))
kono
parents:
diff changeset
295 break;
kono
parents:
diff changeset
296
kono
parents:
diff changeset
297 /* We may use original type if there are no bounds passed. */
kono
parents:
diff changeset
298 if (!arg_type)
kono
parents:
diff changeset
299 return orig_type;
kono
parents:
diff changeset
300
kono
parents:
diff changeset
301 type = build_distinct_type_copy (orig_type);
kono
parents:
diff changeset
302 TYPE_ARG_TYPES (type) = copy_list (TYPE_ARG_TYPES (type));
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 for (arg_type = TYPE_ARG_TYPES (type);
kono
parents:
diff changeset
305 arg_type;
kono
parents:
diff changeset
306 arg_type = TREE_CHAIN (arg_type))
kono
parents:
diff changeset
307 {
kono
parents:
diff changeset
308 indexes[idx++] = new_idx++;
kono
parents:
diff changeset
309
kono
parents:
diff changeset
310 /* pass_by_reference returns 1 for void type,
kono
parents:
diff changeset
311 so check for it first. */
kono
parents:
diff changeset
312 if (TREE_VALUE (arg_type) == void_type_node)
kono
parents:
diff changeset
313 continue;
kono
parents:
diff changeset
314 else if (BOUNDED_TYPE_P (TREE_VALUE (arg_type))
kono
parents:
diff changeset
315 || pass_by_reference (NULL, TYPE_MODE (TREE_VALUE (arg_type)),
kono
parents:
diff changeset
316 TREE_VALUE (arg_type), true))
kono
parents:
diff changeset
317 {
kono
parents:
diff changeset
318 tree new_type = build_tree_list (NULL_TREE,
kono
parents:
diff changeset
319 pointer_bounds_type_node);
kono
parents:
diff changeset
320 TREE_CHAIN (new_type) = TREE_CHAIN (arg_type);
kono
parents:
diff changeset
321 TREE_CHAIN (arg_type) = new_type;
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 arg_type = TREE_CHAIN (arg_type);
kono
parents:
diff changeset
324 new_idx++;
kono
parents:
diff changeset
325 }
kono
parents:
diff changeset
326 else if (chkp_type_has_pointer (TREE_VALUE (arg_type)))
kono
parents:
diff changeset
327 {
kono
parents:
diff changeset
328 bitmap slots = BITMAP_ALLOC (NULL);
kono
parents:
diff changeset
329 bitmap_iterator bi;
kono
parents:
diff changeset
330 unsigned bnd_no;
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 chkp_find_bound_slots (TREE_VALUE (arg_type), slots);
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 EXECUTE_IF_SET_IN_BITMAP (slots, 0, bnd_no, bi)
kono
parents:
diff changeset
335 {
kono
parents:
diff changeset
336 tree new_type = build_tree_list (NULL_TREE,
kono
parents:
diff changeset
337 pointer_bounds_type_node);
kono
parents:
diff changeset
338 TREE_CHAIN (new_type) = TREE_CHAIN (arg_type);
kono
parents:
diff changeset
339 TREE_CHAIN (arg_type) = new_type;
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 arg_type = TREE_CHAIN (arg_type);
kono
parents:
diff changeset
342 new_idx++;
kono
parents:
diff changeset
343 }
kono
parents:
diff changeset
344 BITMAP_FREE (slots);
kono
parents:
diff changeset
345 }
kono
parents:
diff changeset
346 }
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 /* If function type has attribute with arg indexes then
kono
parents:
diff changeset
349 we have to copy it fixing attribute ops. Map for
kono
parents:
diff changeset
350 fixing is in indexes array. */
kono
parents:
diff changeset
351 attrs = TYPE_ATTRIBUTES (type);
kono
parents:
diff changeset
352 if (lookup_attribute ("nonnull", attrs)
kono
parents:
diff changeset
353 || lookup_attribute ("format", attrs)
kono
parents:
diff changeset
354 || lookup_attribute ("format_arg", attrs))
kono
parents:
diff changeset
355 {
kono
parents:
diff changeset
356 int delta = new_idx - len;
kono
parents:
diff changeset
357 attrs = copy_list (TYPE_ATTRIBUTES (type));
kono
parents:
diff changeset
358 chkp_map_attr_arg_indexes (attrs, "nonnull", indexes, len, delta);
kono
parents:
diff changeset
359 chkp_map_attr_arg_indexes (attrs, "format", indexes, len, delta);
kono
parents:
diff changeset
360 chkp_map_attr_arg_indexes (attrs, "format_arg", indexes, len, delta);
kono
parents:
diff changeset
361 TYPE_ATTRIBUTES (type) = attrs;
kono
parents:
diff changeset
362 }
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 return type;
kono
parents:
diff changeset
365 }
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 /* For given function FNDECL add bounds arguments to arguments
kono
parents:
diff changeset
368 list. */
kono
parents:
diff changeset
369
kono
parents:
diff changeset
370 static void
kono
parents:
diff changeset
371 chkp_add_bounds_params_to_function (tree fndecl)
kono
parents:
diff changeset
372 {
kono
parents:
diff changeset
373 tree arg;
kono
parents:
diff changeset
374
kono
parents:
diff changeset
375 for (arg = DECL_ARGUMENTS (fndecl); arg; arg = DECL_CHAIN (arg))
kono
parents:
diff changeset
376 if (BOUNDED_P (arg))
kono
parents:
diff changeset
377 {
kono
parents:
diff changeset
378 std::string new_name = CHKP_BOUNDS_OF_SYMBOL_PREFIX;
kono
parents:
diff changeset
379 tree new_arg;
kono
parents:
diff changeset
380
kono
parents:
diff changeset
381 if (DECL_NAME (arg))
kono
parents:
diff changeset
382 new_name += IDENTIFIER_POINTER (DECL_NAME (arg));
kono
parents:
diff changeset
383 else
kono
parents:
diff changeset
384 {
kono
parents:
diff changeset
385 char uid[25];
kono
parents:
diff changeset
386 snprintf (uid, 25, "D.%u", DECL_UID (arg));
kono
parents:
diff changeset
387 new_name += uid;
kono
parents:
diff changeset
388 }
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 new_arg = build_decl (DECL_SOURCE_LOCATION (arg), PARM_DECL,
kono
parents:
diff changeset
391 get_identifier (new_name.c_str ()),
kono
parents:
diff changeset
392 pointer_bounds_type_node);
kono
parents:
diff changeset
393 DECL_ARG_TYPE (new_arg) = pointer_bounds_type_node;
kono
parents:
diff changeset
394 DECL_CONTEXT (new_arg) = DECL_CONTEXT (arg);
kono
parents:
diff changeset
395 DECL_ARTIFICIAL (new_arg) = 1;
kono
parents:
diff changeset
396 DECL_CHAIN (new_arg) = DECL_CHAIN (arg);
kono
parents:
diff changeset
397 DECL_CHAIN (arg) = new_arg;
kono
parents:
diff changeset
398
kono
parents:
diff changeset
399 arg = DECL_CHAIN (arg);
kono
parents:
diff changeset
400
kono
parents:
diff changeset
401 }
kono
parents:
diff changeset
402 else if (chkp_type_has_pointer (TREE_TYPE (arg)))
kono
parents:
diff changeset
403 {
kono
parents:
diff changeset
404 tree orig_arg = arg;
kono
parents:
diff changeset
405 bitmap slots = BITMAP_ALLOC (NULL);
kono
parents:
diff changeset
406 bitmap_iterator bi;
kono
parents:
diff changeset
407 unsigned bnd_no;
kono
parents:
diff changeset
408
kono
parents:
diff changeset
409 chkp_find_bound_slots (TREE_TYPE (arg), slots);
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 EXECUTE_IF_SET_IN_BITMAP (slots, 0, bnd_no, bi)
kono
parents:
diff changeset
412 {
kono
parents:
diff changeset
413 std::string new_name = CHKP_BOUNDS_OF_SYMBOL_PREFIX;
kono
parents:
diff changeset
414 tree new_arg;
kono
parents:
diff changeset
415 char offs[25];
kono
parents:
diff changeset
416
kono
parents:
diff changeset
417 if (DECL_NAME (orig_arg))
kono
parents:
diff changeset
418 new_name += IDENTIFIER_POINTER (DECL_NAME (orig_arg));
kono
parents:
diff changeset
419 else
kono
parents:
diff changeset
420 {
kono
parents:
diff changeset
421 snprintf (offs, 25, "D.%u", DECL_UID (arg));
kono
parents:
diff changeset
422 new_name += offs;
kono
parents:
diff changeset
423 }
kono
parents:
diff changeset
424 snprintf (offs, 25, "__%u", bnd_no * POINTER_SIZE / BITS_PER_UNIT);
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 new_arg = build_decl (DECL_SOURCE_LOCATION (orig_arg),
kono
parents:
diff changeset
427 PARM_DECL,
kono
parents:
diff changeset
428 get_identifier (new_name.c_str ()),
kono
parents:
diff changeset
429 pointer_bounds_type_node);
kono
parents:
diff changeset
430 DECL_ARG_TYPE (new_arg) = pointer_bounds_type_node;
kono
parents:
diff changeset
431 DECL_CONTEXT (new_arg) = DECL_CONTEXT (orig_arg);
kono
parents:
diff changeset
432 DECL_ARTIFICIAL (new_arg) = 1;
kono
parents:
diff changeset
433 DECL_CHAIN (new_arg) = DECL_CHAIN (arg);
kono
parents:
diff changeset
434 DECL_CHAIN (arg) = new_arg;
kono
parents:
diff changeset
435
kono
parents:
diff changeset
436 arg = DECL_CHAIN (arg);
kono
parents:
diff changeset
437 }
kono
parents:
diff changeset
438 BITMAP_FREE (slots);
kono
parents:
diff changeset
439 }
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 TREE_TYPE (fndecl) =
kono
parents:
diff changeset
442 chkp_copy_function_type_adding_bounds (TREE_TYPE (fndecl));
kono
parents:
diff changeset
443 }
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 /* Return an instrumentation clone for builtin function
kono
parents:
diff changeset
446 FNDECL. Create one if needed. */
kono
parents:
diff changeset
447
kono
parents:
diff changeset
448 tree
kono
parents:
diff changeset
449 chkp_maybe_clone_builtin_fndecl (tree fndecl)
kono
parents:
diff changeset
450 {
kono
parents:
diff changeset
451 tree clone;
kono
parents:
diff changeset
452 enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
455 && fcode < BEGIN_CHKP_BUILTINS);
kono
parents:
diff changeset
456
kono
parents:
diff changeset
457 fcode = (enum built_in_function) (fcode + BEGIN_CHKP_BUILTINS + 1);
kono
parents:
diff changeset
458 clone = builtin_decl_explicit (fcode);
kono
parents:
diff changeset
459 if (clone)
kono
parents:
diff changeset
460 return clone;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 clone = chkp_build_instrumented_fndecl (fndecl);
kono
parents:
diff changeset
463 chkp_add_bounds_params_to_function (clone);
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 gcc_assert (DECL_FUNCTION_CODE (clone) == fcode);
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 set_builtin_decl (fcode, clone, false);
kono
parents:
diff changeset
468
kono
parents:
diff changeset
469 return clone;
kono
parents:
diff changeset
470 }
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 /* Return 1 if function FNDECL should be instrumented. */
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 bool
kono
parents:
diff changeset
475 chkp_instrumentable_p (tree fndecl)
kono
parents:
diff changeset
476 {
kono
parents:
diff changeset
477 struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
kono
parents:
diff changeset
478 return (!lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (fndecl))
kono
parents:
diff changeset
479 && (!flag_chkp_instrument_marked_only
kono
parents:
diff changeset
480 || lookup_attribute ("bnd_instrument", DECL_ATTRIBUTES (fndecl)))
kono
parents:
diff changeset
481 && (!fn || !copy_forbidden (fn)));
kono
parents:
diff changeset
482 }
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 /* Return clone created for instrumentation of NODE or NULL. */
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 cgraph_node *
kono
parents:
diff changeset
487 chkp_maybe_create_clone (tree fndecl)
kono
parents:
diff changeset
488 {
kono
parents:
diff changeset
489 cgraph_node *node = cgraph_node::get_create (fndecl);
kono
parents:
diff changeset
490 cgraph_node *clone = node->instrumented_version;
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 gcc_assert (!node->instrumentation_clone);
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 if (DECL_BUILT_IN (fndecl)
kono
parents:
diff changeset
495 && (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL
kono
parents:
diff changeset
496 || DECL_FUNCTION_CODE (fndecl) >= BEGIN_CHKP_BUILTINS))
kono
parents:
diff changeset
497 return NULL;
kono
parents:
diff changeset
498
kono
parents:
diff changeset
499 clone = node->instrumented_version;
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 /* Some instrumented builtin function calls may be optimized and
kono
parents:
diff changeset
502 cgraph nodes may be removed as unreachable. Later optimizations
kono
parents:
diff changeset
503 may generate new calls to removed functions and in this case
kono
parents:
diff changeset
504 we have to recreate cgraph node. FUNCTION_DECL for instrumented
kono
parents:
diff changeset
505 builtin still exists and should be reused in such case. */
kono
parents:
diff changeset
506 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
507 && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl))
kono
parents:
diff changeset
508 && !clone)
kono
parents:
diff changeset
509 {
kono
parents:
diff changeset
510 enum built_in_function fncode = DECL_FUNCTION_CODE (fndecl);
kono
parents:
diff changeset
511 tree new_decl;
kono
parents:
diff changeset
512
kono
parents:
diff changeset
513 fncode = (enum built_in_function) (fncode + BEGIN_CHKP_BUILTINS + 1);
kono
parents:
diff changeset
514 new_decl = builtin_decl_explicit (fncode);
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 /* We've actually already created an instrumented clone once.
kono
parents:
diff changeset
517 Restore it. */
kono
parents:
diff changeset
518 if (new_decl)
kono
parents:
diff changeset
519 {
kono
parents:
diff changeset
520 clone = cgraph_node::get (new_decl);
kono
parents:
diff changeset
521
kono
parents:
diff changeset
522 if (!clone)
kono
parents:
diff changeset
523 {
kono
parents:
diff changeset
524 gcc_assert (!gimple_has_body_p (fndecl));
kono
parents:
diff changeset
525 clone = cgraph_node::get_create (new_decl);
kono
parents:
diff changeset
526 clone->externally_visible = node->externally_visible;
kono
parents:
diff changeset
527 clone->local = node->local;
kono
parents:
diff changeset
528 clone->address_taken = node->address_taken;
kono
parents:
diff changeset
529 clone->thunk = node->thunk;
kono
parents:
diff changeset
530 clone->alias = node->alias;
kono
parents:
diff changeset
531 clone->weakref = node->weakref;
kono
parents:
diff changeset
532 clone->cpp_implicit_alias = node->cpp_implicit_alias;
kono
parents:
diff changeset
533 clone->orig_decl = fndecl;
kono
parents:
diff changeset
534 clone->instrumentation_clone = true;
kono
parents:
diff changeset
535 }
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 clone->instrumented_version = node;
kono
parents:
diff changeset
538 node->instrumented_version = clone;
kono
parents:
diff changeset
539 }
kono
parents:
diff changeset
540 }
kono
parents:
diff changeset
541
kono
parents:
diff changeset
542 if (!clone)
kono
parents:
diff changeset
543 {
kono
parents:
diff changeset
544 tree new_decl = chkp_build_instrumented_fndecl (fndecl);
kono
parents:
diff changeset
545 struct cgraph_edge *e;
kono
parents:
diff changeset
546 struct ipa_ref *ref;
kono
parents:
diff changeset
547 int i;
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 clone = node->create_version_clone (new_decl, vNULL, NULL);
kono
parents:
diff changeset
550 clone->externally_visible = node->externally_visible;
kono
parents:
diff changeset
551 clone->local = node->local;
kono
parents:
diff changeset
552 clone->address_taken = node->address_taken;
kono
parents:
diff changeset
553 clone->thunk = node->thunk;
kono
parents:
diff changeset
554 clone->alias = node->alias;
kono
parents:
diff changeset
555 clone->weakref = node->weakref;
kono
parents:
diff changeset
556 clone->cpp_implicit_alias = node->cpp_implicit_alias;
kono
parents:
diff changeset
557 clone->instrumented_version = node;
kono
parents:
diff changeset
558 clone->orig_decl = fndecl;
kono
parents:
diff changeset
559 clone->instrumentation_clone = true;
kono
parents:
diff changeset
560 node->instrumented_version = clone;
kono
parents:
diff changeset
561
kono
parents:
diff changeset
562 if (gimple_has_body_p (fndecl))
kono
parents:
diff changeset
563 {
kono
parents:
diff changeset
564 gcc_assert (chkp_instrumentable_p (fndecl));
kono
parents:
diff changeset
565 tree_function_versioning (fndecl, new_decl, NULL, false,
kono
parents:
diff changeset
566 NULL, false, NULL, NULL);
kono
parents:
diff changeset
567 clone->lowered = true;
kono
parents:
diff changeset
568 }
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 /* New params are inserted after versioning because it
kono
parents:
diff changeset
571 actually copies args list from the original decl. */
kono
parents:
diff changeset
572 chkp_add_bounds_params_to_function (new_decl);
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 /* Remember builtin fndecl. */
kono
parents:
diff changeset
575 if (DECL_BUILT_IN_CLASS (clone->decl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
576 && fndecl == builtin_decl_explicit (DECL_FUNCTION_CODE (fndecl)))
kono
parents:
diff changeset
577 {
kono
parents:
diff changeset
578 gcc_assert (!builtin_decl_explicit (DECL_FUNCTION_CODE (clone->decl)));
kono
parents:
diff changeset
579 set_builtin_decl (DECL_FUNCTION_CODE (clone->decl),
kono
parents:
diff changeset
580 clone->decl, false);
kono
parents:
diff changeset
581 }
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583 /* Clones have the same comdat group as originals. */
kono
parents:
diff changeset
584 if (node->same_comdat_group
kono
parents:
diff changeset
585 || (DECL_ONE_ONLY (node->decl)
kono
parents:
diff changeset
586 && !DECL_EXTERNAL (node->decl)))
kono
parents:
diff changeset
587 clone->add_to_same_comdat_group (node);
kono
parents:
diff changeset
588
kono
parents:
diff changeset
589 if (gimple_has_body_p (fndecl))
kono
parents:
diff changeset
590 symtab->call_cgraph_insertion_hooks (clone);
kono
parents:
diff changeset
591
kono
parents:
diff changeset
592 /* Clone all aliases. */
kono
parents:
diff changeset
593 for (i = 0; node->iterate_direct_aliases (i, ref); i++)
kono
parents:
diff changeset
594 chkp_maybe_create_clone (ref->referring->decl);
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 /* Clone all thunks. */
kono
parents:
diff changeset
597 for (e = node->callers; e; e = e->next_caller)
kono
parents:
diff changeset
598 if (e->caller->thunk.thunk_p
kono
parents:
diff changeset
599 && !e->caller->thunk.add_pointer_bounds_args
kono
parents:
diff changeset
600 && !e->caller->instrumentation_clone)
kono
parents:
diff changeset
601 {
kono
parents:
diff changeset
602 struct cgraph_node *thunk
kono
parents:
diff changeset
603 = chkp_maybe_create_clone (e->caller->decl);
kono
parents:
diff changeset
604 /* Redirect thunk clone edge to the node clone. */
kono
parents:
diff changeset
605 thunk->callees->redirect_callee (clone);
kono
parents:
diff changeset
606 }
kono
parents:
diff changeset
607
kono
parents:
diff changeset
608 /* For aliases and thunks we should make sure target is cloned
kono
parents:
diff changeset
609 to have proper references and edges. */
kono
parents:
diff changeset
610 if (node->thunk.thunk_p)
kono
parents:
diff changeset
611 chkp_maybe_create_clone (node->callees->callee->decl);
kono
parents:
diff changeset
612 else if (node->alias)
kono
parents:
diff changeset
613 {
kono
parents:
diff changeset
614 struct cgraph_node *target;
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 ref = node->ref_list.first_reference ();
kono
parents:
diff changeset
617 if (ref)
kono
parents:
diff changeset
618 {
kono
parents:
diff changeset
619 target = chkp_maybe_create_clone (ref->referred->decl);
kono
parents:
diff changeset
620 clone->create_reference (target, IPA_REF_ALIAS);
kono
parents:
diff changeset
621 }
kono
parents:
diff changeset
622
kono
parents:
diff changeset
623 if (node->alias_target)
kono
parents:
diff changeset
624 {
kono
parents:
diff changeset
625 if (TREE_CODE (node->alias_target) == FUNCTION_DECL)
kono
parents:
diff changeset
626 {
kono
parents:
diff changeset
627 target = chkp_maybe_create_clone (node->alias_target);
kono
parents:
diff changeset
628 clone->alias_target = target->decl;
kono
parents:
diff changeset
629 }
kono
parents:
diff changeset
630 else
kono
parents:
diff changeset
631 clone->alias_target = node->alias_target;
kono
parents:
diff changeset
632 }
kono
parents:
diff changeset
633 }
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 /* Add IPA reference. It's main role is to keep instrumented
kono
parents:
diff changeset
636 version reachable while original node is reachable. */
kono
parents:
diff changeset
637 ref = node->create_reference (clone, IPA_REF_CHKP, NULL);
kono
parents:
diff changeset
638 }
kono
parents:
diff changeset
639
kono
parents:
diff changeset
640 return clone;
kono
parents:
diff changeset
641 }
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 /* Create clone for all functions to be instrumented. */
kono
parents:
diff changeset
644
kono
parents:
diff changeset
645 static unsigned int
kono
parents:
diff changeset
646 chkp_versioning (void)
kono
parents:
diff changeset
647 {
kono
parents:
diff changeset
648 struct cgraph_node *node;
kono
parents:
diff changeset
649 const char *reason;
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 bitmap_obstack_initialize (NULL);
kono
parents:
diff changeset
652
kono
parents:
diff changeset
653 FOR_EACH_DEFINED_FUNCTION (node)
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 tree decl = node->decl;
kono
parents:
diff changeset
656 if (!node->instrumentation_clone
kono
parents:
diff changeset
657 && !node->instrumented_version
kono
parents:
diff changeset
658 && !node->alias
kono
parents:
diff changeset
659 && !node->thunk.thunk_p
kono
parents:
diff changeset
660 && (!DECL_BUILT_IN (decl)
kono
parents:
diff changeset
661 || (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
kono
parents:
diff changeset
662 && DECL_FUNCTION_CODE (decl) < BEGIN_CHKP_BUILTINS)))
kono
parents:
diff changeset
663 {
kono
parents:
diff changeset
664 if (chkp_instrumentable_p (decl))
kono
parents:
diff changeset
665 chkp_maybe_create_clone (decl);
kono
parents:
diff changeset
666 else if ((reason = copy_forbidden (DECL_STRUCT_FUNCTION (decl))))
kono
parents:
diff changeset
667 {
kono
parents:
diff changeset
668 if (warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wchkp,
kono
parents:
diff changeset
669 "function cannot be instrumented"))
kono
parents:
diff changeset
670 inform (DECL_SOURCE_LOCATION (decl), reason, decl);
kono
parents:
diff changeset
671 }
kono
parents:
diff changeset
672 }
kono
parents:
diff changeset
673 }
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 /* Mark all aliases and thunks of functions with no instrumented
kono
parents:
diff changeset
676 version as legacy function. */
kono
parents:
diff changeset
677 FOR_EACH_DEFINED_FUNCTION (node)
kono
parents:
diff changeset
678 {
kono
parents:
diff changeset
679 if (!node->instrumentation_clone
kono
parents:
diff changeset
680 && !node->instrumented_version
kono
parents:
diff changeset
681 && (node->alias || node->thunk.thunk_p)
kono
parents:
diff changeset
682 && !lookup_attribute ("bnd_legacy", DECL_ATTRIBUTES (node->decl)))
kono
parents:
diff changeset
683 DECL_ATTRIBUTES (node->decl)
kono
parents:
diff changeset
684 = tree_cons (get_identifier ("bnd_legacy"), NULL,
kono
parents:
diff changeset
685 DECL_ATTRIBUTES (node->decl));
kono
parents:
diff changeset
686 }
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 bitmap_obstack_release (NULL);
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 return 0;
kono
parents:
diff changeset
691 }
kono
parents:
diff changeset
692
kono
parents:
diff changeset
693 /* In this pass we remove bodies of functions having
kono
parents:
diff changeset
694 instrumented version. Functions with removed bodies
kono
parents:
diff changeset
695 become a special kind of thunks to provide a connection
kono
parents:
diff changeset
696 between calls to the original version and instrumented
kono
parents:
diff changeset
697 function. */
kono
parents:
diff changeset
698
kono
parents:
diff changeset
699 static unsigned int
kono
parents:
diff changeset
700 chkp_produce_thunks (bool early)
kono
parents:
diff changeset
701 {
kono
parents:
diff changeset
702 struct cgraph_node *node;
kono
parents:
diff changeset
703
kono
parents:
diff changeset
704 FOR_EACH_DEFINED_FUNCTION (node)
kono
parents:
diff changeset
705 {
kono
parents:
diff changeset
706 if (!node->instrumentation_clone
kono
parents:
diff changeset
707 && node->instrumented_version
kono
parents:
diff changeset
708 && gimple_has_body_p (node->decl)
kono
parents:
diff changeset
709 && gimple_has_body_p (node->instrumented_version->decl)
kono
parents:
diff changeset
710 && (!lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl))
kono
parents:
diff changeset
711 || !early))
kono
parents:
diff changeset
712 {
kono
parents:
diff changeset
713 node->release_body ();
kono
parents:
diff changeset
714 node->remove_callees ();
kono
parents:
diff changeset
715 node->remove_all_references ();
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 node->thunk.thunk_p = true;
kono
parents:
diff changeset
718 node->thunk.add_pointer_bounds_args = true;
kono
parents:
diff changeset
719 node->create_edge (node->instrumented_version, NULL,
kono
parents:
diff changeset
720 node->count, CGRAPH_FREQ_BASE);
kono
parents:
diff changeset
721 node->create_reference (node->instrumented_version,
kono
parents:
diff changeset
722 IPA_REF_CHKP, NULL);
kono
parents:
diff changeset
723 /* Thunk shouldn't be a cdtor. */
kono
parents:
diff changeset
724 DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
kono
parents:
diff changeset
725 DECL_STATIC_DESTRUCTOR (node->decl) = 0;
kono
parents:
diff changeset
726 }
kono
parents:
diff changeset
727 }
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 /* Mark instrumentation clones created for aliases and thunks
kono
parents:
diff changeset
730 as insttrumented so they could be removed as unreachable
kono
parents:
diff changeset
731 now. */
kono
parents:
diff changeset
732 if (!early)
kono
parents:
diff changeset
733 {
kono
parents:
diff changeset
734 FOR_EACH_DEFINED_FUNCTION (node)
kono
parents:
diff changeset
735 {
kono
parents:
diff changeset
736 if (node->instrumentation_clone
kono
parents:
diff changeset
737 && (node->alias || node->thunk.thunk_p)
kono
parents:
diff changeset
738 && !chkp_function_instrumented_p (node->decl))
kono
parents:
diff changeset
739 chkp_function_mark_instrumented (node->decl);
kono
parents:
diff changeset
740 }
kono
parents:
diff changeset
741 }
kono
parents:
diff changeset
742
kono
parents:
diff changeset
743 return TODO_remove_functions;
kono
parents:
diff changeset
744 }
kono
parents:
diff changeset
745
kono
parents:
diff changeset
746 const pass_data pass_data_ipa_chkp_versioning =
kono
parents:
diff changeset
747 {
kono
parents:
diff changeset
748 SIMPLE_IPA_PASS, /* type */
kono
parents:
diff changeset
749 "chkp_versioning", /* name */
kono
parents:
diff changeset
750 OPTGROUP_NONE, /* optinfo_flags */
kono
parents:
diff changeset
751 TV_NONE, /* tv_id */
kono
parents:
diff changeset
752 0, /* properties_required */
kono
parents:
diff changeset
753 0, /* properties_provided */
kono
parents:
diff changeset
754 0, /* properties_destroyed */
kono
parents:
diff changeset
755 0, /* todo_flags_start */
kono
parents:
diff changeset
756 0 /* todo_flags_finish */
kono
parents:
diff changeset
757 };
kono
parents:
diff changeset
758
kono
parents:
diff changeset
759 const pass_data pass_data_ipa_chkp_early_produce_thunks =
kono
parents:
diff changeset
760 {
kono
parents:
diff changeset
761 SIMPLE_IPA_PASS, /* type */
kono
parents:
diff changeset
762 "chkp_ecleanup", /* name */
kono
parents:
diff changeset
763 OPTGROUP_NONE, /* optinfo_flags */
kono
parents:
diff changeset
764 TV_NONE, /* tv_id */
kono
parents:
diff changeset
765 0, /* properties_required */
kono
parents:
diff changeset
766 0, /* properties_provided */
kono
parents:
diff changeset
767 0, /* properties_destroyed */
kono
parents:
diff changeset
768 0, /* todo_flags_start */
kono
parents:
diff changeset
769 0 /* todo_flags_finish */
kono
parents:
diff changeset
770 };
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 const pass_data pass_data_ipa_chkp_produce_thunks =
kono
parents:
diff changeset
773 {
kono
parents:
diff changeset
774 SIMPLE_IPA_PASS, /* type */
kono
parents:
diff changeset
775 "chkp_cleanup", /* name */
kono
parents:
diff changeset
776 OPTGROUP_NONE, /* optinfo_flags */
kono
parents:
diff changeset
777 TV_NONE, /* tv_id */
kono
parents:
diff changeset
778 0, /* properties_required */
kono
parents:
diff changeset
779 0, /* properties_provided */
kono
parents:
diff changeset
780 0, /* properties_destroyed */
kono
parents:
diff changeset
781 0, /* todo_flags_start */
kono
parents:
diff changeset
782 0 /* todo_flags_finish */
kono
parents:
diff changeset
783 };
kono
parents:
diff changeset
784
kono
parents:
diff changeset
785 class pass_ipa_chkp_versioning : public simple_ipa_opt_pass
kono
parents:
diff changeset
786 {
kono
parents:
diff changeset
787 public:
kono
parents:
diff changeset
788 pass_ipa_chkp_versioning (gcc::context *ctxt)
kono
parents:
diff changeset
789 : simple_ipa_opt_pass (pass_data_ipa_chkp_versioning, ctxt)
kono
parents:
diff changeset
790 {}
kono
parents:
diff changeset
791
kono
parents:
diff changeset
792 /* opt_pass methods: */
kono
parents:
diff changeset
793 virtual opt_pass * clone ()
kono
parents:
diff changeset
794 {
kono
parents:
diff changeset
795 return new pass_ipa_chkp_versioning (m_ctxt);
kono
parents:
diff changeset
796 }
kono
parents:
diff changeset
797
kono
parents:
diff changeset
798 virtual bool gate (function *)
kono
parents:
diff changeset
799 {
kono
parents:
diff changeset
800 return flag_check_pointer_bounds;
kono
parents:
diff changeset
801 }
kono
parents:
diff changeset
802
kono
parents:
diff changeset
803 virtual unsigned int execute (function *)
kono
parents:
diff changeset
804 {
kono
parents:
diff changeset
805 return chkp_versioning ();
kono
parents:
diff changeset
806 }
kono
parents:
diff changeset
807
kono
parents:
diff changeset
808 }; // class pass_ipa_chkp_versioning
kono
parents:
diff changeset
809
kono
parents:
diff changeset
810 class pass_ipa_chkp_early_produce_thunks : public simple_ipa_opt_pass
kono
parents:
diff changeset
811 {
kono
parents:
diff changeset
812 public:
kono
parents:
diff changeset
813 pass_ipa_chkp_early_produce_thunks (gcc::context *ctxt)
kono
parents:
diff changeset
814 : simple_ipa_opt_pass (pass_data_ipa_chkp_early_produce_thunks, ctxt)
kono
parents:
diff changeset
815 {}
kono
parents:
diff changeset
816
kono
parents:
diff changeset
817 /* opt_pass methods: */
kono
parents:
diff changeset
818 virtual opt_pass * clone ()
kono
parents:
diff changeset
819 {
kono
parents:
diff changeset
820 return new pass_ipa_chkp_early_produce_thunks (m_ctxt);
kono
parents:
diff changeset
821 }
kono
parents:
diff changeset
822
kono
parents:
diff changeset
823 virtual bool gate (function *)
kono
parents:
diff changeset
824 {
kono
parents:
diff changeset
825 return flag_check_pointer_bounds;
kono
parents:
diff changeset
826 }
kono
parents:
diff changeset
827
kono
parents:
diff changeset
828 virtual unsigned int execute (function *)
kono
parents:
diff changeset
829 {
kono
parents:
diff changeset
830 return chkp_produce_thunks (true);
kono
parents:
diff changeset
831 }
kono
parents:
diff changeset
832
kono
parents:
diff changeset
833 }; // class pass_chkp_produce_thunks
kono
parents:
diff changeset
834
kono
parents:
diff changeset
835 class pass_ipa_chkp_produce_thunks : public simple_ipa_opt_pass
kono
parents:
diff changeset
836 {
kono
parents:
diff changeset
837 public:
kono
parents:
diff changeset
838 pass_ipa_chkp_produce_thunks (gcc::context *ctxt)
kono
parents:
diff changeset
839 : simple_ipa_opt_pass (pass_data_ipa_chkp_produce_thunks, ctxt)
kono
parents:
diff changeset
840 {}
kono
parents:
diff changeset
841
kono
parents:
diff changeset
842 /* opt_pass methods: */
kono
parents:
diff changeset
843 virtual opt_pass * clone ()
kono
parents:
diff changeset
844 {
kono
parents:
diff changeset
845 return new pass_ipa_chkp_produce_thunks (m_ctxt);
kono
parents:
diff changeset
846 }
kono
parents:
diff changeset
847
kono
parents:
diff changeset
848 virtual bool gate (function *)
kono
parents:
diff changeset
849 {
kono
parents:
diff changeset
850 return flag_check_pointer_bounds;
kono
parents:
diff changeset
851 }
kono
parents:
diff changeset
852
kono
parents:
diff changeset
853 virtual unsigned int execute (function *)
kono
parents:
diff changeset
854 {
kono
parents:
diff changeset
855 return chkp_produce_thunks (false);
kono
parents:
diff changeset
856 }
kono
parents:
diff changeset
857
kono
parents:
diff changeset
858 }; // class pass_chkp_produce_thunks
kono
parents:
diff changeset
859
kono
parents:
diff changeset
860 simple_ipa_opt_pass *
kono
parents:
diff changeset
861 make_pass_ipa_chkp_versioning (gcc::context *ctxt)
kono
parents:
diff changeset
862 {
kono
parents:
diff changeset
863 return new pass_ipa_chkp_versioning (ctxt);
kono
parents:
diff changeset
864 }
kono
parents:
diff changeset
865
kono
parents:
diff changeset
866 simple_ipa_opt_pass *
kono
parents:
diff changeset
867 make_pass_ipa_chkp_early_produce_thunks (gcc::context *ctxt)
kono
parents:
diff changeset
868 {
kono
parents:
diff changeset
869 return new pass_ipa_chkp_early_produce_thunks (ctxt);
kono
parents:
diff changeset
870 }
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872 simple_ipa_opt_pass *
kono
parents:
diff changeset
873 make_pass_ipa_chkp_produce_thunks (gcc::context *ctxt)
kono
parents:
diff changeset
874 {
kono
parents:
diff changeset
875 return new pass_ipa_chkp_produce_thunks (ctxt);
kono
parents:
diff changeset
876 }