PR c++/64359
[official-gcc.git] / gcc / cp / vtable-class-hierarchy.c
blob4d6de986fc54b67b922269bd289cc816183562a3
1 /* Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 This file is part of GCC.
5 GCC is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
10 GCC is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GCC; see the file COPYING3. If not see
17 <http://www.gnu.org/licenses/>. */
19 /* Virtual Table Pointer Security Pass - Detect corruption of vtable pointers
20 before using them for virtual method dispatches. */
22 /* This file is part of the vtable security feature implementation.
23 The vtable security feature is designed to detect when a virtual
24 call is about to be made through an invalid vtable pointer
25 (possibly due to data corruption or malicious attacks). The
26 compiler finds every virtual call, and inserts a verification call
27 before the virtual call. The verification call takes the actual
28 vtable pointer value in the object through which the virtual call
29 is being made, and compares the vtable pointer against a set of all
30 valid vtable pointers that the object could contain (this set is
31 based on the declared type of the object). If the pointer is in
32 the valid set, execution is allowed to continue; otherwise the
33 program is halted.
35 There are several pieces needed in order to make this work: 1. For
36 every virtual class in the program (i.e. a class that contains
37 virtual methods), we need to build the set of all possible valid
38 vtables that an object of that class could point to. This includes
39 vtables for any class(es) that inherit from the class under
40 consideration. 2. For every such data set we build up, we need a
41 way to find and reference the data set. This is complicated by the
42 fact that the real vtable addresses are not known until runtime,
43 when the program is loaded into memory, but we need to reference the
44 sets at compile time when we are inserting verification calls into
45 the program. 3. We need to find every virtual call in the program,
46 and insert the verification call (with the appropriate arguments)
47 before the virtual call. 4. We need some runtime library pieces:
48 the code to build up the data sets at runtime; the code to actually
49 perform the verification using the data sets; and some code to set
50 protections on the data sets, so they themselves do not become
51 hacker targets.
53 To find and reference the set of valid vtable pointers for any given
54 virtual class, we create a special global varible for each virtual
55 class. We refer to this as the "vtable map variable" for that
56 class. The vtable map variable has the type "void *", and is
57 initialized by the compiler to NULL. At runtime when the set of
58 valid vtable pointers for a virtual class, e.g. class Foo, is built,
59 the vtable map variable for class Foo is made to point to the set.
60 During compile time, when the compiler is inserting verification
61 calls into the program, it passes the vtable map variable for the
62 appropriate class to the verification call, so that at runtime the
63 verification call can find the appropriate data set.
65 The actual set of valid vtable pointers for a virtual class,
66 e.g. class Foo, cannot be built until runtime, when the vtables get
67 loaded into memory and their addresses are known. But the knowledge
68 about which vtables belong in which class' hierarchy is only known
69 at compile time. Therefore at compile time we collect class
70 hierarchy and vtable information about every virtual class, and we
71 generate calls to build up the data sets at runtime. To build the
72 data sets, we call one of the functions we add to the runtime
73 library, __VLTRegisterPair. __VLTRegisterPair takes two arguments,
74 a vtable map variable and the address of a vtable. If the vtable
75 map variable is currently NULL, it creates a new data set (hash
76 table), makes the vtable map variable point to the new data set, and
77 inserts the vtable address into the data set. If the vtable map
78 variable is not NULL, it just inserts the vtable address into the
79 data set. In order to make sure that our data sets are built before
80 any verification calls happen, we create a special constructor
81 initialization function for each compilation unit, give it a very
82 high initialization priority, and insert all of our calls to
83 __VLTRegisterPair into our special constructor initialization
84 function.
86 The vtable verification feature is controlled by the flag
87 '-fvtable-verify='. There are three flavors of this:
88 '-fvtable-verify=std', '-fvtable-verify=preinit', and
89 '-fvtable-verify=none'. If the option '-fvtable-verfy=preinit' is
90 used, then our constructor initialization function gets put into the
91 preinit array. This is necessary if there are data sets that need
92 to be built very early in execution. If the constructor
93 initialization function gets put into the preinit array, the we also
94 add calls to __VLTChangePermission at the beginning and end of the
95 function. The call at the beginning sets the permissions on the
96 data sets and vtable map variables to read/write, and the one at the
97 end makes them read-only. If the '-fvtable-verify=std' option is
98 used, the constructor initialization functions are executed at their
99 normal time, and the __VLTChangePermission calls are handled
100 differently (see the comments in libstdc++-v3/libsupc++/vtv_rts.cc).
101 The option '-fvtable-verify=none' turns off vtable verification.
103 This file contains code to find and record the class hierarchies for
104 the virtual classes in a program, and all the vtables associated
105 with each such class; to generate the vtable map variables; and to
106 generate the constructor initialization function (with the calls to
107 __VLTRegisterPair, and __VLTChangePermission). The main data
108 structures used for collecting the class hierarchy data and
109 building/maintaining the vtable map variable data are defined in
110 gcc/vtable-verify.h, because they are used both here and in
111 gcc/vtable-verify.c. */
113 #include "config.h"
114 #include "system.h"
115 #include "coretypes.h"
116 #include "cp-tree.h"
117 #include "output.h"
118 #include "hash-map.h"
119 #include "is-a.h"
120 #include "plugin-api.h"
121 #include "vec.h"
122 #include "hashtab.h"
123 #include "hash-set.h"
124 #include "machmode.h"
125 #include "tm.h"
126 #include "hard-reg-set.h"
127 #include "input.h"
128 #include "function.h"
129 #include "ipa-ref.h"
130 #include "cgraph.h"
131 #include "tree-iterator.h"
132 #include "vtable-verify.h"
133 #include "gimplify.h"
134 #include "stringpool.h"
135 #include "stor-layout.h"
137 static int num_calls_to_regset = 0;
138 static int num_calls_to_regpair = 0;
139 static int current_set_size;
141 /* Mark these specially since they need to be stored in precompiled
142 header IR. */
143 static GTY (()) vec<tree, va_gc> *vlt_saved_class_info;
144 static GTY (()) tree vlt_register_pairs_fndecl = NULL_TREE;
145 static GTY (()) tree vlt_register_set_fndecl = NULL_TREE;
147 struct work_node {
148 struct vtv_graph_node *node;
149 struct work_node *next;
152 struct vtbl_map_node *vtable_find_or_create_map_decl (tree);
154 /* As part of vtable verification the compiler generates and inserts
155 calls to __VLTVerifyVtablePointer, which is in libstdc++. This
156 function builds and initializes the function decl that is used
157 in generating those function calls.
159 In addition to __VLTVerifyVtablePointer there is also
160 __VLTVerifyVtablePointerDebug which can be used in place of
161 __VLTVerifyVtablePointer, and which takes extra parameters and
162 outputs extra information, to help debug problems. The debug
163 version of this function is generated and used if flag_vtv_debug is
164 true.
166 The signatures for these functions are:
168 void * __VLTVerifyVtablePointer (void **, void*);
169 void * __VLTVerifyVtablePointerDebug (void**, void *, char *, char *);
172 void
173 vtv_build_vtable_verify_fndecl (void)
175 tree func_type = NULL_TREE;
177 if (verify_vtbl_ptr_fndecl != NULL_TREE
178 && TREE_CODE (verify_vtbl_ptr_fndecl) != ERROR_MARK)
179 return;
181 if (flag_vtv_debug)
183 func_type = build_function_type_list (const_ptr_type_node,
184 build_pointer_type (ptr_type_node),
185 const_ptr_type_node,
186 const_string_type_node,
187 const_string_type_node,
188 NULL_TREE);
189 verify_vtbl_ptr_fndecl =
190 build_lang_decl (FUNCTION_DECL,
191 get_identifier ("__VLTVerifyVtablePointerDebug"),
192 func_type);
194 else
196 func_type = build_function_type_list (const_ptr_type_node,
197 build_pointer_type (ptr_type_node),
198 const_ptr_type_node,
199 NULL_TREE);
200 verify_vtbl_ptr_fndecl =
201 build_lang_decl (FUNCTION_DECL,
202 get_identifier ("__VLTVerifyVtablePointer"),
203 func_type);
206 TREE_NOTHROW (verify_vtbl_ptr_fndecl) = 1;
207 DECL_ATTRIBUTES (verify_vtbl_ptr_fndecl)
208 = tree_cons (get_identifier ("leaf"), NULL,
209 DECL_ATTRIBUTES (verify_vtbl_ptr_fndecl));
210 DECL_PURE_P (verify_vtbl_ptr_fndecl) = 1;
211 TREE_PUBLIC (verify_vtbl_ptr_fndecl) = 1;
212 DECL_PRESERVE_P (verify_vtbl_ptr_fndecl) = 1;
215 /* As part of vtable verification the compiler generates and inserts
216 calls to __VLTRegisterSet and __VLTRegisterPair, which are in
217 libsupc++. This function builds and initializes the function decls
218 that are used in generating those function calls.
220 The signatures for these functions are:
222 void __VLTRegisterSetDebug (void **, const void *, std::size_t,
223 size_t, void **);
225 void __VLTRegisterSet (void **, const void *, std::size_t,
226 size_t, void **);
228 void __VLTRegisterPairDebug (void **, const void *, size_t,
229 const void *, const char *, const char *);
231 void __VLTRegisterPair (void **, const void *, size_t, const void *);
234 static void
235 init_functions (void)
237 tree register_set_type;
238 tree register_pairs_type;
240 if (vlt_register_set_fndecl != NULL_TREE)
241 return;
243 gcc_assert (vlt_register_pairs_fndecl == NULL_TREE);
244 gcc_assert (vlt_register_set_fndecl == NULL_TREE);
246 /* Build function decl for __VLTRegisterSet*. */
248 register_set_type = build_function_type_list
249 (void_type_node,
250 build_pointer_type (ptr_type_node),
251 const_ptr_type_node,
252 size_type_node,
253 size_type_node,
254 build_pointer_type (ptr_type_node),
255 NULL_TREE);
257 if (flag_vtv_debug)
258 vlt_register_set_fndecl = build_lang_decl
259 (FUNCTION_DECL,
260 get_identifier ("__VLTRegisterSetDebug"),
261 register_set_type);
262 else
263 vlt_register_set_fndecl = build_lang_decl
264 (FUNCTION_DECL,
265 get_identifier ("__VLTRegisterSet"),
266 register_set_type);
269 TREE_NOTHROW (vlt_register_set_fndecl) = 1;
270 DECL_ATTRIBUTES (vlt_register_set_fndecl) =
271 tree_cons (get_identifier ("leaf"), NULL,
272 DECL_ATTRIBUTES (vlt_register_set_fndecl));
273 DECL_EXTERNAL(vlt_register_set_fndecl) = 1;
274 TREE_PUBLIC (vlt_register_set_fndecl) = 1;
275 DECL_PRESERVE_P (vlt_register_set_fndecl) = 1;
276 SET_DECL_LANGUAGE (vlt_register_set_fndecl, lang_cplusplus);
278 /* Build function decl for __VLTRegisterPair*. */
280 if (flag_vtv_debug)
282 register_pairs_type = build_function_type_list (void_type_node,
283 build_pointer_type
284 (ptr_type_node),
285 const_ptr_type_node,
286 size_type_node,
287 const_ptr_type_node,
288 const_string_type_node,
289 const_string_type_node,
290 NULL_TREE);
292 vlt_register_pairs_fndecl = build_lang_decl
293 (FUNCTION_DECL,
294 get_identifier ("__VLTRegisterPairDebug"),
295 register_pairs_type);
297 else
299 register_pairs_type = build_function_type_list (void_type_node,
300 build_pointer_type
301 (ptr_type_node),
302 const_ptr_type_node,
303 size_type_node,
304 const_ptr_type_node,
305 NULL_TREE);
307 vlt_register_pairs_fndecl = build_lang_decl
308 (FUNCTION_DECL,
309 get_identifier ("__VLTRegisterPair"),
310 register_pairs_type);
313 TREE_NOTHROW (vlt_register_pairs_fndecl) = 1;
314 DECL_ATTRIBUTES (vlt_register_pairs_fndecl) =
315 tree_cons (get_identifier ("leaf"), NULL,
316 DECL_ATTRIBUTES (vlt_register_pairs_fndecl));
317 DECL_EXTERNAL(vlt_register_pairs_fndecl) = 1;
318 TREE_PUBLIC (vlt_register_pairs_fndecl) = 1;
319 DECL_PRESERVE_P (vlt_register_pairs_fndecl) = 1;
320 SET_DECL_LANGUAGE (vlt_register_pairs_fndecl, lang_cplusplus);
324 /* This is a helper function for
325 vtv_compute_class_hierarchy_transitive_closure. It adds a
326 vtv_graph_node to the WORKLIST, which is a linked list of
327 seen-but-not-yet-processed nodes. INSERTED is a bitmap, one bit
328 per node, to help make sure that we don't insert a node into the
329 worklist more than once. Each node represents a class somewhere in
330 our class hierarchy information. Every node in the graph gets added
331 to the worklist exactly once and removed from the worklist exactly
332 once (when all of its children have been processed). */
334 static void
335 add_to_worklist (struct work_node **worklist, struct vtv_graph_node *node,
336 sbitmap inserted)
338 struct work_node *new_work_node;
340 if (bitmap_bit_p (inserted, node->class_uid))
341 return;
343 new_work_node = XNEW (struct work_node);
344 new_work_node->next = *worklist;
345 new_work_node->node = node;
346 *worklist = new_work_node;
348 bitmap_set_bit (inserted, node->class_uid);
351 /* This is a helper function for
352 vtv_compute_class_hierarchy_transitive_closure. It goes through
353 the WORKLIST of class hierarchy nodes looking for a "leaf" node,
354 i.e. a node whose children in the hierarchy have all been
355 processed. When it finds the next leaf node, it removes it from
356 the linked list (WORKLIST) and returns the node. */
358 static struct vtv_graph_node *
359 find_and_remove_next_leaf_node (struct work_node **worklist)
361 struct work_node *prev, *cur;
362 struct vtv_graph_node *ret_val = NULL;
364 for (prev = NULL, cur = *worklist; cur; prev = cur, cur = cur->next)
366 if ((cur->node->children).length() == cur->node->num_processed_children)
368 if (prev == NULL)
369 (*worklist) = cur->next;
370 else
371 prev->next = cur->next;
373 cur->next = NULL;
374 ret_val = cur->node;
375 free (cur);
376 return ret_val;
380 return NULL;
383 /* In our class hierarchy graph, each class node contains a bitmap,
384 with one bit for each class in the hierarchy. The bits are set for
385 classes that are descendants in the graph of the current node.
386 Initially the descendants bitmap is only set for immediate
387 descendants. This function traverses the class hierarchy graph,
388 bottom up, filling in the transitive closures for the descendants
389 as we rise up the graph. */
391 void
392 vtv_compute_class_hierarchy_transitive_closure (void)
394 struct work_node *worklist = NULL;
395 sbitmap inserted = sbitmap_alloc (num_vtable_map_nodes);
396 unsigned i;
397 unsigned j;
399 /* Note: Every node in the graph gets added to the worklist exactly
400 once and removed from the worklist exactly once (when all of its
401 children have been processed). Each node's children edges are
402 followed exactly once, and each node's parent edges are followed
403 exactly once. So this algorithm is roughly O(V + 2E), i.e.
404 O(E + V). */
406 /* Set-up: */
407 /* Find all the "leaf" nodes in the graph, and add them to the worklist. */
408 bitmap_clear (inserted);
409 for (j = 0; j < num_vtable_map_nodes; ++j)
411 struct vtbl_map_node *cur = vtbl_map_nodes_vec[j];
412 if (cur->class_info
413 && ((cur->class_info->children).length() == 0)
414 && ! (bitmap_bit_p (inserted, cur->class_info->class_uid)))
415 add_to_worklist (&worklist, cur->class_info, inserted);
418 /* Main work: pull next leaf node off work list, process it, add its
419 parents to the worklist, where a 'leaf' node is one that has no
420 children, or all of its children have been processed. */
421 while (worklist)
423 struct vtv_graph_node *temp_node =
424 find_and_remove_next_leaf_node (&worklist);
426 gcc_assert (temp_node != NULL);
427 temp_node->descendants = sbitmap_alloc (num_vtable_map_nodes);
428 bitmap_clear (temp_node->descendants);
429 bitmap_set_bit (temp_node->descendants, temp_node->class_uid);
430 for (i = 0; i < (temp_node->children).length(); ++i)
431 bitmap_ior (temp_node->descendants, temp_node->descendants,
432 temp_node->children[i]->descendants);
433 for (i = 0; i < (temp_node->parents).length(); ++i)
435 temp_node->parents[i]->num_processed_children =
436 temp_node->parents[i]->num_processed_children + 1;
437 if (!bitmap_bit_p (inserted, temp_node->parents[i]->class_uid))
438 add_to_worklist (&worklist, temp_node->parents[i], inserted);
443 /* Keep track of which pairs we have already created __VLTRegisterPair
444 calls for, to prevent creating duplicate calls within the same
445 compilation unit. VTABLE_DECL is the var decl for the vtable of
446 the (descendant) class that we are adding to our class hierarchy
447 data. VPTR_ADDRESS is an expression for calculating the correct
448 offset into the vtable (VTABLE_DECL). It is the actual vtable
449 pointer address that will be stored in our list of valid vtable
450 pointers for BASE_CLASS. BASE_CLASS is the record_type node for
451 the base class to whose hiearchy we want to add
452 VPTR_ADDRESS. (VTABLE_DECL should be the vtable for BASE_CLASS or
453 one of BASE_CLASS' descendents. */
455 static bool
456 check_and_record_registered_pairs (tree vtable_decl, tree vptr_address,
457 tree base_class)
459 unsigned offset;
460 struct vtbl_map_node *base_vtable_map_node;
461 bool inserted_something = false;
464 if (TREE_CODE (vptr_address) == ADDR_EXPR
465 && TREE_CODE (TREE_OPERAND (vptr_address, 0)) == MEM_REF)
466 vptr_address = TREE_OPERAND (vptr_address, 0);
468 if (TREE_OPERAND_LENGTH (vptr_address) > 1)
469 offset = TREE_INT_CST_LOW (TREE_OPERAND (vptr_address, 1));
470 else
471 offset = 0;
473 base_vtable_map_node = vtbl_map_get_node (TYPE_MAIN_VARIANT (base_class));
475 inserted_something = vtbl_map_node_registration_insert
476 (base_vtable_map_node,
477 vtable_decl,
478 offset);
479 return !inserted_something;
482 /* Given an IDENTIFIER_NODE, build and return a string literal based on it. */
484 static tree
485 build_string_from_id (tree identifier)
487 int len;
489 gcc_assert (TREE_CODE (identifier) == IDENTIFIER_NODE);
491 len = IDENTIFIER_LENGTH (identifier);
492 return build_string_literal (len + 1, IDENTIFIER_POINTER (identifier));
495 /* A class may contain secondary vtables in it, for various reasons.
496 This function goes through the decl chain of a class record looking
497 for any fields that point to secondary vtables, and adding calls to
498 __VLTRegisterPair for the secondary vtable pointers.
500 BASE_CLASS_DECL_ARG is an expression for the address of the vtable
501 map variable for the BASE_CLASS (whose hierarchy we are currently
502 updating). BASE_CLASS is the record_type node for the base class.
503 RECORD_TYPE is the record_type node for the descendant class that
504 we are possibly adding to BASE_CLASS's hierarchy. BODY is the
505 function body for the constructor init function to which we are
506 adding our calls to __VLTRegisterPair. */
508 static void
509 register_construction_vtables (tree base_class, tree record_type,
510 vec<tree> *vtable_ptr_array)
512 tree vtbl_var_decl;
514 if (TREE_CODE (record_type) != RECORD_TYPE)
515 return;
517 vtbl_var_decl = CLASSTYPE_VTABLES (record_type);
519 if (CLASSTYPE_VBASECLASSES (record_type))
521 tree vtt_decl;
522 bool already_registered = false;
523 tree val_vtbl_decl = NULL_TREE;
525 vtt_decl = DECL_CHAIN (vtbl_var_decl);
527 /* Check to see if we have found a VTT. Add its data if appropriate. */
528 if (vtt_decl)
530 tree values = DECL_INITIAL (vtt_decl);
531 if (TREE_ASM_WRITTEN (vtt_decl)
532 && values != NULL_TREE
533 && TREE_CODE (values) == CONSTRUCTOR
534 && TREE_CODE (TREE_TYPE (values)) == ARRAY_TYPE)
536 unsigned HOST_WIDE_INT cnt;
537 constructor_elt *ce;
539 /* Loop through the initialization values for this
540 vtable to get all the correct vtable pointer
541 addresses that we need to add to our set of valid
542 vtable pointers for the current base class. This may
543 result in adding more than just the element assigned
544 to the primary vptr of the class, so we may end up
545 with more vtable pointers than are strictly
546 necessary. */
548 for (cnt = 0;
549 vec_safe_iterate (CONSTRUCTOR_ELTS (values),
550 cnt, &ce);
551 cnt++)
553 tree value = ce->value;
555 /* Search for the ADDR_EXPR operand within the value. */
557 while (value
558 && TREE_OPERAND (value, 0)
559 && TREE_CODE (TREE_OPERAND (value, 0)) == ADDR_EXPR)
560 value = TREE_OPERAND (value, 0);
562 /* The VAR_DECL for the vtable should be the first
563 argument of the ADDR_EXPR, which is the first
564 argument of value.*/
566 if (TREE_OPERAND (value, 0))
567 val_vtbl_decl = TREE_OPERAND (value, 0);
569 while (TREE_CODE (val_vtbl_decl) != VAR_DECL
570 && TREE_OPERAND (val_vtbl_decl, 0))
571 val_vtbl_decl = TREE_OPERAND (val_vtbl_decl, 0);
573 gcc_assert (TREE_CODE (val_vtbl_decl) == VAR_DECL);
575 /* Check to see if we already have this vtable pointer in
576 our valid set for this base class. */
578 already_registered = check_and_record_registered_pairs
579 (val_vtbl_decl,
580 value,
581 base_class);
583 if (already_registered)
584 continue;
586 /* Add this vtable pointer to our set of valid
587 pointers for the base class. */
589 vtable_ptr_array->safe_push (value);
590 current_set_size++;
597 /* This function iterates through all the vtables it can find from the
598 BINFO of a class, to make sure we have found ALL of the vtables
599 that an object of that class could point to. Generate calls to
600 __VLTRegisterPair for those vtable pointers that we find.
602 BINFO is the tree_binfo node for the BASE_CLASS. BODY is the
603 function body for the constructor init function to which we are
604 adding calls to __VLTRegisterPair. ARG1 is an expression for the
605 address of the vtable map variable (for the BASE_CLASS), that will
606 point to the updated data set. BASE_CLASS is the record_type node
607 for the base class whose set of valid vtable pointers we are
608 updating. STR1 and STR2 are all debugging information, to be passed
609 as parameters to __VLTRegisterPairDebug. STR1 represents the name
610 of the vtable map variable to be updated by the call. Similarly,
611 STR2 represents the name of the class whose vtable pointer is being
612 added to the hierarchy. */
614 static void
615 register_other_binfo_vtables (tree binfo, tree base_class,
616 vec<tree> *vtable_ptr_array)
618 unsigned ix;
619 tree base_binfo;
620 tree vtable_decl;
621 bool already_registered;
623 if (binfo == NULL_TREE)
624 return;
626 for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
628 if ((!BINFO_PRIMARY_P (base_binfo)
629 || BINFO_VIRTUAL_P (base_binfo))
630 && (vtable_decl = get_vtbl_decl_for_binfo (base_binfo)))
632 tree vtable_address = build_vtbl_address (base_binfo);
634 already_registered = check_and_record_registered_pairs
635 (vtable_decl,
636 vtable_address,
637 base_class);
638 if (!already_registered)
640 vtable_ptr_array->safe_push (vtable_address);
641 current_set_size++;
645 register_other_binfo_vtables (base_binfo, base_class, vtable_ptr_array);
649 /* The set of valid vtable pointers for any given class are stored in
650 a hash table. For reasons of efficiency, that hash table size is
651 always a power of two. In order to try to prevent re-sizing the
652 hash tables very often, we pass __VLTRegisterPair an initial guess
653 as to the number of entries the hashtable will eventually need
654 (rounded up to the nearest power of two). This function takes the
655 class information we have collected for a particular class,
656 CLASS_NODE, and calculates the hash table size guess. */
658 static int
659 guess_num_vtable_pointers (struct vtv_graph_node *class_node)
661 tree vtbl;
662 int total_num_vtbls = 0;
663 int num_vtbls_power_of_two = 1;
664 unsigned i;
666 for (i = 0; i < num_vtable_map_nodes; ++i)
667 if (bitmap_bit_p (class_node->descendants, i))
669 tree class_type = vtbl_map_nodes_vec[i]->class_info->class_type;
670 for (vtbl = CLASSTYPE_VTABLES (class_type); vtbl;
671 vtbl = DECL_CHAIN (vtbl))
673 total_num_vtbls++;
674 if (total_num_vtbls > num_vtbls_power_of_two)
675 num_vtbls_power_of_two <<= 1;
678 return num_vtbls_power_of_two;
681 /* A simple hash function on strings */
682 /* Be careful about changing this routine. The values generated will
683 be stored in the calls to InitSet. So, changing this routine may
684 cause a binary incompatibility. */
686 static uint32_t
687 vtv_string_hash (const char *in)
689 const char *s = in;
690 uint32_t h = 0;
692 gcc_assert (in != NULL);
693 for ( ; *s; ++s)
694 h = 5 * h + *s;
695 return h;
698 static char *
699 get_log_file_name (const char *fname)
701 const char *tmp_dir = concat (dump_dir_name, NULL);
702 char *full_name;
703 int dir_len;
704 int fname_len;
706 dir_len = strlen (tmp_dir);
707 fname_len = strlen (fname);
709 full_name = XNEWVEC (char, dir_len + fname_len + 1);
710 strcpy (full_name, tmp_dir);
711 strcpy (full_name + dir_len, fname);
713 return full_name;
716 static void
717 write_out_current_set_data (tree base_class, int set_size)
719 static int class_data_log_fd = -1;
720 char buffer[1024];
721 int bytes_written __attribute__ ((unused));
722 char *file_name = get_log_file_name ("vtv_class_set_sizes.log");
724 if (class_data_log_fd == -1)
725 class_data_log_fd = open (file_name,
726 O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
728 if (class_data_log_fd == -1)
730 warning_at (UNKNOWN_LOCATION, 0,
731 "unable to open log file %<vtv_class_set_sizes.log%>: %m");
732 return;
735 snprintf (buffer, sizeof (buffer), "%s %d\n",
736 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (base_class))),
737 set_size);
738 bytes_written = write (class_data_log_fd, buffer, strlen (buffer));
741 static tree
742 build_key_buffer_arg (tree base_ptr_var_decl)
744 const int key_type_fixed_size = 8;
745 uint32_t len1 = IDENTIFIER_LENGTH (DECL_NAME (base_ptr_var_decl));
746 uint32_t hash_value = vtv_string_hash (IDENTIFIER_POINTER
747 (DECL_NAME (base_ptr_var_decl)));
748 void *key_buffer = xmalloc (len1 + key_type_fixed_size);
749 uint32_t *value_ptr = (uint32_t *) key_buffer;
750 tree ret_value;
752 /* Set the len and hash for the string. */
753 *value_ptr = len1;
754 value_ptr++;
755 *value_ptr = hash_value;
757 /* Now copy the string representation of the vtbl map name... */
758 memcpy ((char *) key_buffer + key_type_fixed_size,
759 IDENTIFIER_POINTER (DECL_NAME (base_ptr_var_decl)),
760 len1);
762 /* ... and build a string literal from it. This will make a copy
763 so the key_bufffer is not needed anymore after this. */
764 ret_value = build_string_literal (len1 + key_type_fixed_size,
765 (char *) key_buffer);
766 free (key_buffer);
767 return ret_value;
770 static void
771 insert_call_to_register_set (tree class_name,
772 vec<tree> *vtbl_ptr_array, tree body, tree arg1,
773 tree arg2, tree size_hint_arg)
775 tree call_expr;
776 int num_args = vtbl_ptr_array->length();
777 char *array_arg_name = ACONCAT (("__vptr_array_",
778 IDENTIFIER_POINTER (class_name), NULL));
779 tree array_arg_type = build_array_type_nelts (build_pointer_type
780 (build_pointer_type
781 (void_type_node)),
782 num_args);
783 tree array_arg = build_decl (UNKNOWN_LOCATION, VAR_DECL,
784 get_identifier (array_arg_name),
785 array_arg_type);
786 int k;
788 vec<constructor_elt, va_gc> *array_elements;
789 vec_alloc (array_elements, num_args);
791 tree initial = NULL_TREE;
792 tree arg3 = NULL_TREE;
794 TREE_PUBLIC (array_arg) = 0;
795 DECL_EXTERNAL (array_arg) = 0;
796 TREE_STATIC (array_arg) = 1;
797 DECL_ARTIFICIAL (array_arg) = 0;
798 TREE_READONLY (array_arg) = 1;
799 DECL_IGNORED_P (array_arg) = 0;
800 DECL_PRESERVE_P (array_arg) = 0;
801 DECL_VISIBILITY (array_arg) = VISIBILITY_HIDDEN;
803 for (k = 0; k < num_args; ++k)
805 CONSTRUCTOR_APPEND_ELT (array_elements, NULL_TREE, (*vtbl_ptr_array)[k]);
808 initial = build_constructor (TREE_TYPE (array_arg), array_elements);
810 TREE_CONSTANT (initial) = 1;
811 TREE_STATIC (initial) = 1;
812 DECL_INITIAL (array_arg) = initial;
813 relayout_decl (array_arg);
814 varpool_node::finalize_decl (array_arg);
816 arg3 = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (array_arg)), array_arg);
818 TREE_TYPE (arg3) = build_pointer_type (TREE_TYPE (array_arg));
820 call_expr = build_call_expr (vlt_register_set_fndecl, 5, arg1,
821 arg2, /* set_symbol_key */
822 size_hint_arg, build_int_cst (size_type_node,
823 num_args),
824 arg3);
825 append_to_statement_list (call_expr, &body);
826 num_calls_to_regset++;
829 static void
830 insert_call_to_register_pair (vec<tree> *vtbl_ptr_array, tree arg1,
831 tree arg2, tree size_hint_arg, tree str1,
832 tree str2, tree body)
834 tree call_expr;
835 int num_args = vtbl_ptr_array->length();
836 tree vtable_address = NULL_TREE;
838 if (num_args == 0)
839 vtable_address = build_int_cst (build_pointer_type (void_type_node), 0);
840 else
841 vtable_address = (*vtbl_ptr_array)[0];
843 if (flag_vtv_debug)
844 call_expr = build_call_expr (vlt_register_pairs_fndecl, 6, arg1, arg2,
845 size_hint_arg, vtable_address, str1, str2);
846 else
847 call_expr = build_call_expr (vlt_register_pairs_fndecl, 4, arg1, arg2,
848 size_hint_arg, vtable_address);
850 append_to_statement_list (call_expr, &body);
851 num_calls_to_regpair++;
854 static void
855 output_set_info (tree record_type, vec<tree> vtbl_ptr_array)
857 static int vtv_debug_log_fd = -1;
858 char buffer[1024];
859 int bytes_written __attribute__ ((unused));
860 int array_len = vtbl_ptr_array.length();
861 const char *class_name =
862 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (record_type)));
863 char *file_name = get_log_file_name ("vtv_set_ptr_data.log");
865 if (vtv_debug_log_fd == -1)
866 vtv_debug_log_fd = open (file_name,
867 O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
868 if (vtv_debug_log_fd == -1)
870 warning_at (UNKNOWN_LOCATION, 0,
871 "unable to open log file %<vtv_set_ptr_data.log%>: %m");
872 return;
875 for (int i = 0; i < array_len; ++i)
877 const char *vptr_name = "unknown";
878 int vptr_offset = 0;
880 if (TREE_CODE (vtbl_ptr_array[i]) == POINTER_PLUS_EXPR)
882 tree arg0 = TREE_OPERAND (vtbl_ptr_array[i], 0);
883 tree arg1 = TREE_OPERAND (vtbl_ptr_array[i], 1);
885 if (TREE_CODE (arg0) == ADDR_EXPR)
886 arg0 = TREE_OPERAND (arg0, 0);
888 if (TREE_CODE (arg0) == VAR_DECL)
889 vptr_name = IDENTIFIER_POINTER (DECL_NAME (arg0));
891 if (TREE_CODE (arg1) == INTEGER_CST)
892 vptr_offset = TREE_INT_CST_LOW (arg1);
895 snprintf (buffer, sizeof (buffer), "%s %s %s + %d\n",
896 main_input_filename, class_name, vptr_name, vptr_offset);
897 bytes_written = write (vtv_debug_log_fd, buffer, strlen(buffer));
902 /* This function goes through our internal class hierarchy & vtable
903 pointer data structure and outputs calls to __VLTRegisterPair for
904 every class-vptr pair (for those classes whose vtable would be
905 output in the current compilation unit). These calls get put into
906 our constructor initialization function. BODY is the function
907 body, so far, of our constructor initialization function, to which we
908 add the calls. */
910 static bool
911 register_all_pairs (tree body)
913 bool registered_at_least_one = false;
914 vec<tree> *vtbl_ptr_array = NULL;
915 unsigned j;
917 for (j = 0; j < num_vtable_map_nodes; ++j)
919 struct vtbl_map_node *current = vtbl_map_nodes_vec[j];
920 unsigned i = 0;
921 tree base_class = current->class_info->class_type;
922 tree base_ptr_var_decl = current->vtbl_map_decl;
923 tree arg1;
924 tree arg2;
925 tree new_type;
926 tree str1 = NULL_TREE;
927 tree str2 = NULL_TREE;
928 size_t size_hint;
929 tree size_hint_arg;
931 gcc_assert (current->class_info != NULL);
934 if (flag_vtv_debug)
935 str1 = build_string_from_id (DECL_NAME (base_ptr_var_decl));
937 new_type = build_pointer_type (TREE_TYPE (base_ptr_var_decl));
938 arg1 = build1 (ADDR_EXPR, new_type, base_ptr_var_decl);
940 /* We need a fresh vector for each iteration. */
941 if (vtbl_ptr_array)
942 vec_free (vtbl_ptr_array);
944 vec_alloc (vtbl_ptr_array, 10);
946 for (i = 0; i < num_vtable_map_nodes; ++i)
947 if (bitmap_bit_p (current->class_info->descendants, i))
949 struct vtbl_map_node *vtbl_class_node = vtbl_map_nodes_vec[i];
950 tree class_type = vtbl_class_node->class_info->class_type;
952 if (class_type
953 && (TREE_CODE (class_type) == RECORD_TYPE))
955 bool already_registered;
957 tree binfo = TYPE_BINFO (class_type);
958 tree vtable_decl;
959 bool vtable_should_be_output = false;
961 vtable_decl = CLASSTYPE_VTABLES (class_type);
963 /* Handle main vtable for this class. */
965 if (vtable_decl)
967 vtable_should_be_output = TREE_ASM_WRITTEN (vtable_decl);
968 str2 = build_string_from_id (DECL_NAME (vtable_decl));
971 if (vtable_decl && vtable_should_be_output)
973 tree vtable_address = build_vtbl_address (binfo);
975 already_registered = check_and_record_registered_pairs
976 (vtable_decl,
977 vtable_address,
978 base_class);
981 if (!already_registered)
983 vtbl_ptr_array->safe_push (vtable_address);
985 /* Find and handle any 'extra' vtables associated
986 with this class, via virtual inheritance. */
987 register_construction_vtables (base_class, class_type,
988 vtbl_ptr_array);
990 /* Find and handle any 'extra' vtables associated
991 with this class, via multiple inheritance. */
992 register_other_binfo_vtables (binfo, base_class,
993 vtbl_ptr_array);
998 current_set_size = vtbl_ptr_array->length();
1000 /* Sometimes we need to initialize the set symbol even if we are
1001 not adding any vtable pointers to the set in the current
1002 compilation unit. In that case, we need to initialize the
1003 set to our best guess as to what the eventual size of the set
1004 hash table will be (to prevent having to re-size the hash
1005 table later). */
1007 size_hint = guess_num_vtable_pointers (current->class_info);
1009 /* If we have added vtable pointers to the set in this
1010 compilation unit, adjust the size hint for the set's hash
1011 table appropriately. */
1012 if (vtbl_ptr_array->length() > 0)
1014 unsigned len = vtbl_ptr_array->length();
1015 while ((size_t) len > size_hint)
1016 size_hint <<= 1;
1018 size_hint_arg = build_int_cst (size_type_node, size_hint);
1020 /* Get the key-buffer argument. */
1021 arg2 = build_key_buffer_arg (base_ptr_var_decl);
1023 if (str2 == NULL_TREE)
1024 str2 = build_string_literal (strlen ("unknown") + 1,
1025 "unknown");
1027 if (flag_vtv_debug)
1028 output_set_info (current->class_info->class_type,
1029 *vtbl_ptr_array);
1031 if (vtbl_ptr_array->length() > 1)
1033 insert_call_to_register_set (current->class_name,
1034 vtbl_ptr_array, body, arg1, arg2,
1035 size_hint_arg);
1036 registered_at_least_one = true;
1038 else
1041 if (vtbl_ptr_array->length() > 0
1042 || (current->is_used
1043 || (current->registered->size() > 0)))
1045 insert_call_to_register_pair (vtbl_ptr_array,
1046 arg1, arg2, size_hint_arg, str1,
1047 str2, body);
1048 registered_at_least_one = true;
1052 if (flag_vtv_counts && current_set_size > 0)
1053 write_out_current_set_data (base_class, current_set_size);
1057 return registered_at_least_one;
1060 /* Given a tree containing a class type (CLASS_TYPE), this function
1061 finds and returns the class hierarchy node for that class in our
1062 data structure. */
1064 static struct vtv_graph_node *
1065 find_graph_node (tree class_type)
1067 struct vtbl_map_node *vtbl_node;
1069 vtbl_node = vtbl_map_get_node (TYPE_MAIN_VARIANT (class_type));
1070 if (vtbl_node)
1071 return vtbl_node->class_info;
1073 return NULL;
1076 /* Add base class/derived class pair to our internal class hierarchy
1077 data structure. BASE_NODE is our vtv_graph_node that corresponds
1078 to a base class. DERIVED_NODE is our vtv_graph_node that
1079 corresponds to a class that is a descendant of the base class
1080 (possibly the base class itself). */
1082 static void
1083 add_hierarchy_pair (struct vtv_graph_node *base_node,
1084 struct vtv_graph_node *derived_node)
1086 (base_node->children).safe_push (derived_node);
1087 (derived_node->parents).safe_push (base_node);
1090 /* This functions adds a new base class/derived class relationship to
1091 our class hierarchy data structure. Both parameters are trees
1092 representing the class types, i.e. RECORD_TYPE trees.
1093 DERIVED_CLASS can be the same as BASE_CLASS. */
1095 static void
1096 update_class_hierarchy_information (tree base_class,
1097 tree derived_class)
1099 struct vtv_graph_node *base_node = find_graph_node (base_class);
1100 struct vtv_graph_node *derived_node = find_graph_node (derived_class);
1102 add_hierarchy_pair (base_node, derived_node);
1106 static void
1107 write_out_vtv_count_data (void)
1109 static int vtv_count_log_fd = -1;
1110 char buffer[1024];
1111 int unused_vtbl_map_vars = 0;
1112 int bytes_written __attribute__ ((unused));
1113 char *file_name = get_log_file_name ("vtv_count_data.log");
1115 if (vtv_count_log_fd == -1)
1116 vtv_count_log_fd = open (file_name,
1117 O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
1118 if (vtv_count_log_fd == -1)
1120 warning_at (UNKNOWN_LOCATION, 0,
1121 "unable to open log file %<vtv_count_data.log%>: %m");
1122 return;
1125 for (unsigned i = 0; i < num_vtable_map_nodes; ++i)
1127 struct vtbl_map_node *current = vtbl_map_nodes_vec[i];
1128 if (!current->is_used
1129 && current->registered->size() == 0)
1130 unused_vtbl_map_vars++;
1133 snprintf (buffer, sizeof (buffer), "%s %d %d %d %d %d\n",
1134 main_input_filename, total_num_virtual_calls,
1135 total_num_verified_vcalls, num_calls_to_regset,
1136 num_calls_to_regpair, unused_vtbl_map_vars);
1138 bytes_written = write (vtv_count_log_fd, buffer, strlen (buffer));
1141 /* This function calls register_all_pairs, which actually generates
1142 all the calls to __VLTRegisterPair (in the verification constructor
1143 init function). It also generates the calls to
1144 __VLTChangePermission, if the verification constructor init
1145 function is going into the preinit array. INIT_ROUTINE_BODY is
1146 the body of our constructior initialization function, to which we
1147 add our function calls.*/
1149 bool
1150 vtv_register_class_hierarchy_information (tree init_routine_body)
1152 bool registered_something = false;
1154 init_functions ();
1156 if (num_vtable_map_nodes == 0)
1157 return false;
1159 /* Add class hierarchy pairs to the vtable map data structure. */
1160 registered_something = register_all_pairs (init_routine_body);
1162 if (flag_vtv_counts)
1163 write_out_vtv_count_data ();
1165 return registered_something;
1169 /* Generate the special constructor function that calls
1170 __VLTChangePermission and __VLTRegisterPairs, and give it a very
1171 high initialization priority. */
1173 void
1174 vtv_generate_init_routine (void)
1176 tree init_routine_body;
1177 bool vtable_classes_found = false;
1179 push_lang_context (lang_name_c);
1181 /* The priority for this init function (constructor) is carefully
1182 chosen so that it will happen after the calls to unprotect the
1183 memory used for vtable verification and before the memory is
1184 protected again. */
1185 init_routine_body = vtv_start_verification_constructor_init_function ();
1187 vtable_classes_found =
1188 vtv_register_class_hierarchy_information (init_routine_body);
1190 if (vtable_classes_found)
1192 tree vtv_fndecl =
1193 vtv_finish_verification_constructor_init_function (init_routine_body);
1194 TREE_STATIC (vtv_fndecl) = 1;
1195 TREE_USED (vtv_fndecl) = 1;
1196 DECL_PRESERVE_P (vtv_fndecl) = 1;
1197 if (flag_vtable_verify == VTV_PREINIT_PRIORITY)
1198 DECL_STATIC_CONSTRUCTOR (vtv_fndecl) = 0;
1200 gimplify_function_tree (vtv_fndecl);
1201 cgraph_node::add_new_function (vtv_fndecl, false);
1203 symtab->process_new_functions ();
1205 if (flag_vtable_verify == VTV_PREINIT_PRIORITY)
1206 assemble_vtv_preinit_initializer (vtv_fndecl);
1209 pop_lang_context ();
1212 /* This funtion takes a tree containing a class type (BASE_TYPE), and
1213 it either finds the existing vtbl_map_node for that class in our
1214 data structure, or it creates a new node and adds it to the data
1215 structure if there is not one for the class already. As part of
1216 this process it also creates the global vtable map variable for the
1217 class. */
1219 struct vtbl_map_node *
1220 vtable_find_or_create_map_decl (tree base_type)
1222 char *var_name = NULL;
1223 struct vtbl_map_node *vtable_map_node = NULL;
1225 /* Verify the type has an associated vtable. */
1226 if (!TYPE_BINFO (base_type) || !BINFO_VTABLE (TYPE_BINFO (base_type)))
1227 return NULL;
1229 /* Create map lookup symbol for base class */
1230 var_name = get_mangled_vtable_map_var_name (base_type);
1232 /* We've already created the variable; just look it. */
1233 vtable_map_node = vtbl_map_get_node (TYPE_MAIN_VARIANT (base_type));
1235 if (!vtable_map_node || (vtable_map_node->vtbl_map_decl == NULL_TREE))
1237 /* If we haven't already created the *__vtable_map global
1238 variable for this class, do so now, and add it to the
1239 varpool, to make sure it gets saved and written out. */
1241 tree var_decl = NULL;
1242 tree var_type = build_pointer_type (void_type_node);
1243 tree initial_value = integer_zero_node;
1245 var_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1246 get_identifier (var_name), var_type);
1248 DECL_EXTERNAL (var_decl) = 0;
1249 TREE_STATIC (var_decl) = 1;
1250 DECL_VISIBILITY (var_decl) = VISIBILITY_HIDDEN;
1251 SET_DECL_ASSEMBLER_NAME (var_decl, get_identifier (var_name));
1252 DECL_ARTIFICIAL (var_decl) = 1;
1253 /* We cannot mark this variable as read-only because we want to be
1254 able to write to it at runtime. */
1255 TREE_READONLY (var_decl) = 0;
1256 DECL_IGNORED_P (var_decl) = 1;
1257 DECL_PRESERVE_P (var_decl) = 1;
1259 /* Put these mmap variables in thr .vtable_map_vars section, so
1260 we can find and protect them. */
1262 set_decl_section_name (var_decl, ".vtable_map_vars");
1263 symtab_node::get (var_decl)->implicit_section = true;
1264 DECL_INITIAL (var_decl) = initial_value;
1266 comdat_linkage (var_decl);
1268 varpool_node::finalize_decl (var_decl);
1269 if (!vtable_map_node)
1270 vtable_map_node =
1271 find_or_create_vtbl_map_node (TYPE_MAIN_VARIANT (base_type));
1272 if (vtable_map_node->vtbl_map_decl == NULL_TREE)
1273 vtable_map_node->vtbl_map_decl = var_decl;
1276 gcc_assert (vtable_map_node);
1277 return vtable_map_node;
1280 /* This function is used to build up our class hierarchy data for a
1281 particular class. TYPE is the record_type tree node for the
1282 class. */
1284 static void
1285 vtv_insert_single_class_info (tree type)
1287 if (flag_vtable_verify)
1289 tree binfo = TYPE_BINFO (type);
1290 tree base_binfo;
1291 struct vtbl_map_node *own_map;
1292 int i;
1294 /* First make sure to create the map for this record type. */
1295 own_map = vtable_find_or_create_map_decl (type);
1296 if (own_map == NULL)
1297 return;
1299 /* Go through the list of all base classes for the current
1300 (derived) type, make sure the *__vtable_map global variable
1301 for the base class exists, and add the base class/derived
1302 class pair to the class hierarchy information we are
1303 accumulating (for vtable pointer verification). */
1304 for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
1306 tree tree_val = BINFO_TYPE (base_binfo);
1307 struct vtbl_map_node *vtable_map_node = NULL;
1309 vtable_map_node = vtable_find_or_create_map_decl (tree_val);
1311 if (vtable_map_node != NULL)
1312 update_class_hierarchy_information (tree_val, type);
1317 /* This function adds classes we are interested in to a list of
1318 classes. RECORD is the record_type node for the class we are
1319 adding to the list. */
1321 void
1322 vtv_save_class_info (tree record)
1324 if (!flag_vtable_verify || TREE_CODE (record) == UNION_TYPE)
1325 return;
1327 if (!vlt_saved_class_info)
1328 vec_alloc (vlt_saved_class_info, 10);
1330 gcc_assert (TREE_CODE (record) == RECORD_TYPE);
1332 vec_safe_push (vlt_saved_class_info, record);
1336 /* This function goes through the list of classes we saved and calls
1337 vtv_insert_single_class_info on each one, to build up our class
1338 hierarchy data structure. */
1340 void
1341 vtv_recover_class_info (void)
1343 tree current_class;
1344 unsigned i;
1346 if (vlt_saved_class_info)
1348 for (i = 0; i < vlt_saved_class_info->length(); ++i)
1350 current_class = (*vlt_saved_class_info)[i];
1351 gcc_assert (TREE_CODE (current_class) == RECORD_TYPE);
1352 vtv_insert_single_class_info (current_class);
1357 #include "gt-cp-vtable-class-hierarchy.h"