1 /* Copyright (C) 2012-2013 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)
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
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
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
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. */
115 #include "coretypes.h"
119 #include "tree-iterator.h"
120 #include "vtable-verify.h"
122 #include "gimplify.h"
123 #include "stringpool.h"
124 #include "stor-layout.h"
126 static int num_calls_to_regset
= 0;
127 static int num_calls_to_regpair
= 0;
128 static int current_set_size
;
130 /* Mark these specially since they need to be stored in precompiled
132 static GTY (()) vec
<tree
, va_gc
> *vlt_saved_class_info
;
133 static GTY (()) tree vlt_register_pairs_fndecl
= NULL_TREE
;
134 static GTY (()) tree vlt_register_set_fndecl
= NULL_TREE
;
137 struct vtv_graph_node
*node
;
138 struct work_node
*next
;
141 struct vtbl_map_node
*vtable_find_or_create_map_decl (tree
);
143 /* As part of vtable verification the compiler generates and inserts
144 calls to __VLTVerifyVtablePointer, which is in libstdc++. This
145 function builds and initializes the function decl that is used
146 in generating those function calls.
148 In addition to __VLTVerifyVtablePointer there is also
149 __VLTVerifyVtablePointerDebug which can be used in place of
150 __VLTVerifyVtablePointer, and which takes extra parameters and
151 outputs extra information, to help debug problems. The debug
152 version of this function is generated and used if flag_vtv_debug is
155 The signatures for these functions are:
157 void * __VLTVerifyVtablePointer (void **, void*);
158 void * __VLTVerifyVtablePointerDebug (void**, void *, char *, char *);
162 vtv_build_vtable_verify_fndecl (void)
164 tree func_type
= NULL_TREE
;
166 if (verify_vtbl_ptr_fndecl
!= NULL_TREE
167 && TREE_CODE (verify_vtbl_ptr_fndecl
) != ERROR_MARK
)
172 func_type
= build_function_type_list (const_ptr_type_node
,
173 build_pointer_type (ptr_type_node
),
175 const_string_type_node
,
176 const_string_type_node
,
178 verify_vtbl_ptr_fndecl
=
179 build_lang_decl (FUNCTION_DECL
,
180 get_identifier ("__VLTVerifyVtablePointerDebug"),
185 func_type
= build_function_type_list (const_ptr_type_node
,
186 build_pointer_type (ptr_type_node
),
189 verify_vtbl_ptr_fndecl
=
190 build_lang_decl (FUNCTION_DECL
,
191 get_identifier ("__VLTVerifyVtablePointer"),
195 TREE_NOTHROW (verify_vtbl_ptr_fndecl
) = 1;
196 DECL_ATTRIBUTES (verify_vtbl_ptr_fndecl
)
197 = tree_cons (get_identifier ("leaf"), NULL
,
198 DECL_ATTRIBUTES (verify_vtbl_ptr_fndecl
));
199 DECL_PURE_P (verify_vtbl_ptr_fndecl
) = 1;
200 TREE_PUBLIC (verify_vtbl_ptr_fndecl
) = 1;
201 DECL_PRESERVE_P (verify_vtbl_ptr_fndecl
) = 1;
204 /* As part of vtable verification the compiler generates and inserts
205 calls to __VLTRegisterSet and __VLTRegisterPair, which are in
206 libsupc++. This function builds and initializes the function decls
207 that are used in generating those function calls.
209 The signatures for these functions are:
211 void __VLTRegisterSetDebug (void **, const void *, std::size_t,
214 void __VLTRegisterSet (void **, const void *, std::size_t,
217 void __VLTRegisterPairDebug (void **, const void *, size_t,
218 const void *, const char *, const char *);
220 void __VLTRegisterPair (void **, const void *, size_t, const void *);
224 init_functions (void)
226 tree register_set_type
;
227 tree register_pairs_type
;
229 if (vlt_register_set_fndecl
!= NULL_TREE
)
232 gcc_assert (vlt_register_pairs_fndecl
== NULL_TREE
);
233 gcc_assert (vlt_register_set_fndecl
== NULL_TREE
);
235 /* Build function decl for __VLTRegisterSet*. */
237 register_set_type
= build_function_type_list
239 build_pointer_type (ptr_type_node
),
243 build_pointer_type (ptr_type_node
),
247 vlt_register_set_fndecl
= build_lang_decl
249 get_identifier ("__VLTRegisterSetDebug"),
252 vlt_register_set_fndecl
= build_lang_decl
254 get_identifier ("__VLTRegisterSet"),
258 TREE_NOTHROW (vlt_register_set_fndecl
) = 1;
259 DECL_ATTRIBUTES (vlt_register_set_fndecl
) =
260 tree_cons (get_identifier ("leaf"), NULL
,
261 DECL_ATTRIBUTES (vlt_register_set_fndecl
));
262 TREE_PUBLIC (vlt_register_set_fndecl
) = 1;
263 DECL_PRESERVE_P (vlt_register_set_fndecl
) = 1;
264 SET_DECL_LANGUAGE (vlt_register_set_fndecl
, lang_cplusplus
);
266 /* Build function decl for __VLTRegisterPair*. */
270 register_pairs_type
= build_function_type_list (void_type_node
,
276 const_string_type_node
,
277 const_string_type_node
,
280 vlt_register_pairs_fndecl
= build_lang_decl
282 get_identifier ("__VLTRegisterPairDebug"),
283 register_pairs_type
);
287 register_pairs_type
= build_function_type_list (void_type_node
,
295 vlt_register_pairs_fndecl
= build_lang_decl
297 get_identifier ("__VLTRegisterPair"),
298 register_pairs_type
);
301 TREE_NOTHROW (vlt_register_pairs_fndecl
) = 1;
302 DECL_ATTRIBUTES (vlt_register_pairs_fndecl
) =
303 tree_cons (get_identifier ("leaf"), NULL
,
304 DECL_ATTRIBUTES (vlt_register_pairs_fndecl
));
305 TREE_PUBLIC (vlt_register_pairs_fndecl
) = 1;
306 DECL_PRESERVE_P (vlt_register_pairs_fndecl
) = 1;
307 SET_DECL_LANGUAGE (vlt_register_pairs_fndecl
, lang_cplusplus
);
311 /* This is a helper function for
312 vtv_compute_class_hierarchy_transitive_closure. It adds a
313 vtv_graph_node to the WORKLIST, which is a linked list of
314 seen-but-not-yet-processed nodes. INSERTED is a bitmap, one bit
315 per node, to help make sure that we don't insert a node into the
316 worklist more than once. Each node represents a class somewhere in
317 our class hierarchy information. Every node in the graph gets added
318 to the worklist exactly once and removed from the worklist exactly
319 once (when all of its children have been processed). */
322 add_to_worklist (struct work_node
**worklist
, struct vtv_graph_node
*node
,
325 struct work_node
*new_work_node
;
327 if (bitmap_bit_p (inserted
, node
->class_uid
))
330 new_work_node
= XNEW (struct work_node
);
331 new_work_node
->next
= *worklist
;
332 new_work_node
->node
= node
;
333 *worklist
= new_work_node
;
335 bitmap_set_bit (inserted
, node
->class_uid
);
338 /* This is a helper function for
339 vtv_compute_class_hierarchy_transitive_closure. It goes through
340 the WORKLIST of class hierarchy nodes looking for a "leaf" node,
341 i.e. a node whose children in the hierarchy have all been
342 processed. When it finds the next leaf node, it removes it from
343 the linked list (WORKLIST) and returns the node. */
345 static struct vtv_graph_node
*
346 find_and_remove_next_leaf_node (struct work_node
**worklist
)
348 struct work_node
*prev
, *cur
;
349 struct vtv_graph_node
*ret_val
= NULL
;
351 for (prev
= NULL
, cur
= *worklist
; cur
; prev
= cur
, cur
= cur
->next
)
353 if ((cur
->node
->children
).length() == cur
->node
->num_processed_children
)
356 (*worklist
) = cur
->next
;
358 prev
->next
= cur
->next
;
370 /* In our class hierarchy graph, each class node contains a bitmap,
371 with one bit for each class in the hierarchy. The bits are set for
372 classes that are descendants in the graph of the current node.
373 Initially the descendants bitmap is only set for immediate
374 descendants. This function traverses the class hierarchy graph,
375 bottom up, filling in the transitive closures for the descendants
376 as we rise up the graph. */
379 vtv_compute_class_hierarchy_transitive_closure (void)
381 struct work_node
*worklist
= NULL
;
382 sbitmap inserted
= sbitmap_alloc (num_vtable_map_nodes
);
386 /* Note: Every node in the graph gets added to the worklist exactly
387 once and removed from the worklist exactly once (when all of its
388 children have been processed). Each node's children edges are
389 followed exactly once, and each node's parent edges are followed
390 exactly once. So this algorithm is roughly O(V + 2E), i.e.
394 /* Find all the "leaf" nodes in the graph, and add them to the worklist. */
395 bitmap_clear (inserted
);
396 for (j
= 0; j
< num_vtable_map_nodes
; ++j
)
398 struct vtbl_map_node
*cur
= vtbl_map_nodes_vec
[j
];
400 && ((cur
->class_info
->children
).length() == 0)
401 && ! (bitmap_bit_p (inserted
, cur
->class_info
->class_uid
)))
402 add_to_worklist (&worklist
, cur
->class_info
, inserted
);
405 /* Main work: pull next leaf node off work list, process it, add its
406 parents to the worklist, where a 'leaf' node is one that has no
407 children, or all of its children have been processed. */
410 struct vtv_graph_node
*temp_node
=
411 find_and_remove_next_leaf_node (&worklist
);
413 gcc_assert (temp_node
!= NULL
);
414 temp_node
->descendants
= sbitmap_alloc (num_vtable_map_nodes
);
415 bitmap_clear (temp_node
->descendants
);
416 bitmap_set_bit (temp_node
->descendants
, temp_node
->class_uid
);
417 for (i
= 0; i
< (temp_node
->children
).length(); ++i
)
418 bitmap_ior (temp_node
->descendants
, temp_node
->descendants
,
419 temp_node
->children
[i
]->descendants
);
420 for (i
= 0; i
< (temp_node
->parents
).length(); ++i
)
422 temp_node
->parents
[i
]->num_processed_children
=
423 temp_node
->parents
[i
]->num_processed_children
+ 1;
424 if (!bitmap_bit_p (inserted
, temp_node
->parents
[i
]->class_uid
))
425 add_to_worklist (&worklist
, temp_node
->parents
[i
], inserted
);
430 /* Keep track of which pairs we have already created __VLTRegisterPair
431 calls for, to prevent creating duplicate calls within the same
432 compilation unit. VTABLE_DECL is the var decl for the vtable of
433 the (descendant) class that we are adding to our class hierarchy
434 data. VPTR_ADDRESS is an expression for calculating the correct
435 offset into the vtable (VTABLE_DECL). It is the actual vtable
436 pointer address that will be stored in our list of valid vtable
437 pointers for BASE_CLASS. BASE_CLASS is the record_type node for
438 the base class to whose hiearchy we want to add
439 VPTR_ADDRESS. (VTABLE_DECL should be the vtable for BASE_CLASS or
440 one of BASE_CLASS' descendents. */
443 check_and_record_registered_pairs (tree vtable_decl
, tree vptr_address
,
447 struct vtbl_map_node
*base_vtable_map_node
;
448 bool inserted_something
= false;
451 if (TREE_CODE (vptr_address
) == ADDR_EXPR
452 && TREE_CODE (TREE_OPERAND (vptr_address
, 0)) == MEM_REF
)
453 vptr_address
= TREE_OPERAND (vptr_address
, 0);
455 if (TREE_OPERAND_LENGTH (vptr_address
) > 1)
456 offset
= TREE_INT_CST_LOW (TREE_OPERAND (vptr_address
, 1));
460 base_vtable_map_node
= vtbl_map_get_node (TYPE_MAIN_VARIANT (base_class
));
462 inserted_something
= vtbl_map_node_registration_insert
463 (base_vtable_map_node
,
466 return !inserted_something
;
469 /* Given an IDENTIFIER_NODE, build and return a string literal based on it. */
472 build_string_from_id (tree identifier
)
476 gcc_assert (TREE_CODE (identifier
) == IDENTIFIER_NODE
);
478 len
= IDENTIFIER_LENGTH (identifier
);
479 return build_string_literal (len
+ 1, IDENTIFIER_POINTER (identifier
));
482 /* A class may contain secondary vtables in it, for various reasons.
483 This function goes through the decl chain of a class record looking
484 for any fields that point to secondary vtables, and adding calls to
485 __VLTRegisterPair for the secondary vtable pointers.
487 BASE_CLASS_DECL_ARG is an expression for the address of the vtable
488 map variable for the BASE_CLASS (whose hierarchy we are currently
489 updating). BASE_CLASS is the record_type node for the base class.
490 RECORD_TYPE is the record_type node for the descendant class that
491 we are possibly adding to BASE_CLASS's hierarchy. BODY is the
492 function body for the constructor init function to which we are
493 adding our calls to __VLTRegisterPair. */
496 register_construction_vtables (tree base_class
, tree record_type
,
497 vec
<tree
> *vtable_ptr_array
)
501 if (TREE_CODE (record_type
) != RECORD_TYPE
)
504 vtbl_var_decl
= CLASSTYPE_VTABLES (record_type
);
506 if (CLASSTYPE_VBASECLASSES (record_type
))
509 bool already_registered
= false;
510 tree val_vtbl_decl
= NULL_TREE
;
512 vtt_decl
= DECL_CHAIN (vtbl_var_decl
);
514 /* Check to see if we have found a VTT. Add its data if appropriate. */
517 tree values
= DECL_INITIAL (vtt_decl
);
518 if (TREE_ASM_WRITTEN (vtt_decl
)
519 && values
!= NULL_TREE
520 && TREE_CODE (values
) == CONSTRUCTOR
521 && TREE_CODE (TREE_TYPE (values
)) == ARRAY_TYPE
)
523 unsigned HOST_WIDE_INT cnt
;
526 /* Loop through the initialization values for this
527 vtable to get all the correct vtable pointer
528 addresses that we need to add to our set of valid
529 vtable pointers for the current base class. This may
530 result in adding more than just the element assigned
531 to the primary vptr of the class, so we may end up
532 with more vtable pointers than are strictly
536 vec_safe_iterate (CONSTRUCTOR_ELTS (values
),
540 tree value
= ce
->value
;
542 /* Search for the ADDR_EXPR operand within the value. */
545 && TREE_OPERAND (value
, 0)
546 && TREE_CODE (TREE_OPERAND (value
, 0)) == ADDR_EXPR
)
547 value
= TREE_OPERAND (value
, 0);
549 /* The VAR_DECL for the vtable should be the first
550 argument of the ADDR_EXPR, which is the first
553 if (TREE_OPERAND (value
, 0))
554 val_vtbl_decl
= TREE_OPERAND (value
, 0);
556 while (TREE_CODE (val_vtbl_decl
) != VAR_DECL
557 && TREE_OPERAND (val_vtbl_decl
, 0))
558 val_vtbl_decl
= TREE_OPERAND (val_vtbl_decl
, 0);
560 gcc_assert (TREE_CODE (val_vtbl_decl
) == VAR_DECL
);
562 /* Check to see if we already have this vtable pointer in
563 our valid set for this base class. */
565 already_registered
= check_and_record_registered_pairs
570 if (already_registered
)
573 /* Add this vtable pointer to our set of valid
574 pointers for the base class. */
576 vtable_ptr_array
->safe_push (value
);
584 /* This function iterates through all the vtables it can find from the
585 BINFO of a class, to make sure we have found ALL of the vtables
586 that an object of that class could point to. Generate calls to
587 __VLTRegisterPair for those vtable pointers that we find.
589 BINFO is the tree_binfo node for the BASE_CLASS. BODY is the
590 function body for the constructor init function to which we are
591 adding calls to __VLTRegisterPair. ARG1 is an expression for the
592 address of the vtable map variable (for the BASE_CLASS), that will
593 point to the updated data set. BASE_CLASS is the record_type node
594 for the base class whose set of valid vtable pointers we are
595 updating. STR1 and STR2 are all debugging information, to be passed
596 as parameters to __VLTRegisterPairDebug. STR1 represents the name
597 of the vtable map variable to be updated by the call. Similarly,
598 STR2 represents the name of the class whose vtable pointer is being
599 added to the hierarchy. */
602 register_other_binfo_vtables (tree binfo
, tree base_class
,
603 vec
<tree
> *vtable_ptr_array
)
608 bool already_registered
;
610 if (binfo
== NULL_TREE
)
613 for (ix
= 0; BINFO_BASE_ITERATE (binfo
, ix
, base_binfo
); ix
++)
615 if ((!BINFO_PRIMARY_P (base_binfo
)
616 || BINFO_VIRTUAL_P (base_binfo
))
617 && (vtable_decl
= get_vtbl_decl_for_binfo (base_binfo
)))
619 tree vtable_address
= build_vtbl_address (base_binfo
);
621 already_registered
= check_and_record_registered_pairs
625 if (!already_registered
)
627 vtable_ptr_array
->safe_push (vtable_address
);
632 register_other_binfo_vtables (base_binfo
, base_class
, vtable_ptr_array
);
636 /* The set of valid vtable pointers for any given class are stored in
637 a hash table. For reasons of efficiency, that hash table size is
638 always a power of two. In order to try to prevent re-sizing the
639 hash tables very often, we pass __VLTRegisterPair an initial guess
640 as to the number of entries the hashtable will eventually need
641 (rounded up to the nearest power of two). This function takes the
642 class information we have collected for a particular class,
643 CLASS_NODE, and calculates the hash table size guess. */
646 guess_num_vtable_pointers (struct vtv_graph_node
*class_node
)
649 int total_num_vtbls
= 0;
650 int num_vtbls_power_of_two
= 1;
653 for (i
= 0; i
< num_vtable_map_nodes
; ++i
)
654 if (bitmap_bit_p (class_node
->descendants
, i
))
656 tree class_type
= vtbl_map_nodes_vec
[i
]->class_info
->class_type
;
657 for (vtbl
= CLASSTYPE_VTABLES (class_type
); vtbl
;
658 vtbl
= DECL_CHAIN (vtbl
))
661 if (total_num_vtbls
> num_vtbls_power_of_two
)
662 num_vtbls_power_of_two
<<= 1;
665 return num_vtbls_power_of_two
;
668 /* A simple hash function on strings */
669 /* Be careful about changing this routine. The values generated will
670 be stored in the calls to InitSet. So, changing this routine may
671 cause a binary incompatibility. */
674 vtv_string_hash (const char *in
)
679 gcc_assert (in
!= NULL
);
686 get_log_file_name (const char *fname
)
688 const char *tmp_dir
= concat (dump_dir_name
, NULL
);
693 dir_len
= strlen (tmp_dir
);
694 fname_len
= strlen (fname
);
696 full_name
= XNEWVEC (char, dir_len
+ fname_len
+ 1);
697 strcpy (full_name
, tmp_dir
);
698 strcpy (full_name
+ dir_len
, fname
);
704 write_out_current_set_data (tree base_class
, int set_size
)
706 static int class_data_log_fd
= -1;
708 int bytes_written
__attribute__ ((unused
));
709 char *file_name
= get_log_file_name ("vtv_class_set_sizes.log");
711 if (class_data_log_fd
== -1)
712 class_data_log_fd
= open (file_name
,
713 O_WRONLY
| O_APPEND
| O_CREAT
, S_IRWXU
);
715 if (class_data_log_fd
== -1)
717 warning_at (UNKNOWN_LOCATION
, 0,
718 "unable to open log file %<vtv_class_set_sizes.log%>: %m");
722 snprintf (buffer
, sizeof (buffer
), "%s %d\n",
723 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (base_class
))),
725 bytes_written
= write (class_data_log_fd
, buffer
, strlen (buffer
));
729 build_key_buffer_arg (tree base_ptr_var_decl
)
731 const int key_type_fixed_size
= 8;
732 uint32_t len1
= IDENTIFIER_LENGTH (DECL_NAME (base_ptr_var_decl
));
733 uint32_t hash_value
= vtv_string_hash (IDENTIFIER_POINTER
734 (DECL_NAME (base_ptr_var_decl
)));
735 void *key_buffer
= xmalloc (len1
+ key_type_fixed_size
);
736 uint32_t *value_ptr
= (uint32_t *) key_buffer
;
739 /* Set the len and hash for the string. */
742 *value_ptr
= hash_value
;
744 /* Now copy the string representation of the vtbl map name... */
745 memcpy ((char *) key_buffer
+ key_type_fixed_size
,
746 IDENTIFIER_POINTER (DECL_NAME (base_ptr_var_decl
)),
749 /* ... and build a string literal from it. This will make a copy
750 so the key_bufffer is not needed anymore after this. */
751 ret_value
= build_string_literal (len1
+ key_type_fixed_size
,
752 (char *) key_buffer
);
758 insert_call_to_register_set (tree class_name
,
759 vec
<tree
> *vtbl_ptr_array
, tree body
, tree arg1
,
760 tree arg2
, tree size_hint_arg
)
763 int num_args
= vtbl_ptr_array
->length();
764 char *array_arg_name
= ACONCAT (("__vptr_array_",
765 IDENTIFIER_POINTER (class_name
), NULL
));
766 tree array_arg_type
= build_array_type_nelts (build_pointer_type
770 tree array_arg
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
771 get_identifier (array_arg_name
),
775 vec
<constructor_elt
, va_gc
> *array_elements
;
776 vec_alloc (array_elements
, num_args
);
778 tree initial
= NULL_TREE
;
779 tree arg3
= NULL_TREE
;
781 TREE_PUBLIC (array_arg
) = 0;
782 DECL_EXTERNAL (array_arg
) = 0;
783 TREE_STATIC (array_arg
) = 1;
784 DECL_ARTIFICIAL (array_arg
) = 0;
785 TREE_READONLY (array_arg
) = 1;
786 DECL_IGNORED_P (array_arg
) = 0;
787 DECL_PRESERVE_P (array_arg
) = 0;
788 DECL_VISIBILITY (array_arg
) = VISIBILITY_HIDDEN
;
790 for (k
= 0; k
< num_args
; ++k
)
792 CONSTRUCTOR_APPEND_ELT (array_elements
, NULL_TREE
, (*vtbl_ptr_array
)[k
]);
795 initial
= build_constructor (TREE_TYPE (array_arg
), array_elements
);
797 TREE_CONSTANT (initial
) = 1;
798 TREE_STATIC (initial
) = 1;
799 DECL_INITIAL (array_arg
) = initial
;
800 relayout_decl (array_arg
);
801 varpool_finalize_decl (array_arg
);
803 arg3
= build1 (ADDR_EXPR
, TYPE_POINTER_TO (TREE_TYPE (array_arg
)), array_arg
);
805 TREE_TYPE (arg3
) = build_pointer_type (TREE_TYPE (array_arg
));
807 call_expr
= build_call_expr (vlt_register_set_fndecl
, 5, arg1
,
808 arg2
, /* set_symbol_key */
809 size_hint_arg
, build_int_cst (size_type_node
,
812 append_to_statement_list (call_expr
, &body
);
813 num_calls_to_regset
++;
817 insert_call_to_register_pair (vec
<tree
> *vtbl_ptr_array
, tree arg1
,
818 tree arg2
, tree size_hint_arg
, tree str1
,
819 tree str2
, tree body
)
822 int num_args
= vtbl_ptr_array
->length();
823 tree vtable_address
= NULL_TREE
;
826 vtable_address
= build_int_cst (build_pointer_type (void_type_node
), 0);
828 vtable_address
= (*vtbl_ptr_array
)[0];
831 call_expr
= build_call_expr (vlt_register_pairs_fndecl
, 6, arg1
, arg2
,
832 size_hint_arg
, vtable_address
, str1
, str2
);
834 call_expr
= build_call_expr (vlt_register_pairs_fndecl
, 4, arg1
, arg2
,
835 size_hint_arg
, vtable_address
);
837 append_to_statement_list (call_expr
, &body
);
838 num_calls_to_regpair
++;
842 output_set_info (tree record_type
, vec
<tree
> vtbl_ptr_array
)
844 static int vtv_debug_log_fd
= -1;
846 int bytes_written
__attribute__ ((unused
));
847 int array_len
= vtbl_ptr_array
.length();
848 const char *class_name
=
849 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (record_type
)));
850 char *file_name
= get_log_file_name ("vtv_set_ptr_data.log");
852 if (vtv_debug_log_fd
== -1)
853 vtv_debug_log_fd
= open (file_name
,
854 O_WRONLY
| O_APPEND
| O_CREAT
, S_IRWXU
);
855 if (vtv_debug_log_fd
== -1)
857 warning_at (UNKNOWN_LOCATION
, 0,
858 "unable to open log file %<vtv_set_ptr_data.log%>: %m");
862 for (int i
= 0; i
< array_len
; ++i
)
864 const char *vptr_name
= "unknown";
867 if (TREE_CODE (vtbl_ptr_array
[i
]) == POINTER_PLUS_EXPR
)
869 tree arg0
= TREE_OPERAND (vtbl_ptr_array
[i
], 0);
870 tree arg1
= TREE_OPERAND (vtbl_ptr_array
[i
], 1);
872 if (TREE_CODE (arg0
) == ADDR_EXPR
)
873 arg0
= TREE_OPERAND (arg0
, 0);
875 if (TREE_CODE (arg0
) == VAR_DECL
)
876 vptr_name
= IDENTIFIER_POINTER (DECL_NAME (arg0
));
878 if (TREE_CODE (arg1
) == INTEGER_CST
)
879 vptr_offset
= TREE_INT_CST_LOW (arg1
);
882 snprintf (buffer
, sizeof (buffer
), "%s %s %s + %d\n",
883 main_input_filename
, class_name
, vptr_name
, vptr_offset
);
884 bytes_written
= write (vtv_debug_log_fd
, buffer
, strlen(buffer
));
889 /* This function goes through our internal class hierarchy & vtable
890 pointer data structure and outputs calls to __VLTRegisterPair for
891 every class-vptr pair (for those classes whose vtable would be
892 output in the current compilation unit). These calls get put into
893 our constructor initialization function. BODY is the function
894 body, so far, of our constructor initialization function, to which we
898 register_all_pairs (tree body
)
900 bool registered_at_least_one
= false;
901 vec
<tree
> *vtbl_ptr_array
= NULL
;
904 for (j
= 0; j
< num_vtable_map_nodes
; ++j
)
906 struct vtbl_map_node
*current
= vtbl_map_nodes_vec
[j
];
908 tree base_class
= current
->class_info
->class_type
;
909 tree base_ptr_var_decl
= current
->vtbl_map_decl
;
913 tree str1
= NULL_TREE
;
914 tree str2
= NULL_TREE
;
918 gcc_assert (current
->class_info
!= NULL
);
922 str1
= build_string_from_id (DECL_NAME (base_ptr_var_decl
));
924 new_type
= build_pointer_type (TREE_TYPE (base_ptr_var_decl
));
925 arg1
= build1 (ADDR_EXPR
, new_type
, base_ptr_var_decl
);
927 /* We need a fresh vector for each iteration. */
929 vec_free (vtbl_ptr_array
);
931 vec_alloc (vtbl_ptr_array
, 10);
933 for (i
= 0; i
< num_vtable_map_nodes
; ++i
)
934 if (bitmap_bit_p (current
->class_info
->descendants
, i
))
936 struct vtbl_map_node
*vtbl_class_node
= vtbl_map_nodes_vec
[i
];
937 tree class_type
= vtbl_class_node
->class_info
->class_type
;
940 && (TREE_CODE (class_type
) == RECORD_TYPE
))
942 bool already_registered
;
944 tree binfo
= TYPE_BINFO (class_type
);
946 bool vtable_should_be_output
= false;
948 vtable_decl
= CLASSTYPE_VTABLES (class_type
);
950 /* Handle main vtable for this class. */
954 vtable_should_be_output
= TREE_ASM_WRITTEN (vtable_decl
);
955 str2
= build_string_from_id (DECL_NAME (vtable_decl
));
958 if (vtable_decl
&& vtable_should_be_output
)
960 tree vtable_address
= build_vtbl_address (binfo
);
962 already_registered
= check_and_record_registered_pairs
968 if (!already_registered
)
970 vtbl_ptr_array
->safe_push (vtable_address
);
972 /* Find and handle any 'extra' vtables associated
973 with this class, via virtual inheritance. */
974 register_construction_vtables (base_class
, class_type
,
977 /* Find and handle any 'extra' vtables associated
978 with this class, via multiple inheritance. */
979 register_other_binfo_vtables (binfo
, base_class
,
985 current_set_size
= vtbl_ptr_array
->length();
987 /* Sometimes we need to initialize the set symbol even if we are
988 not adding any vtable pointers to the set in the current
989 compilation unit. In that case, we need to initialize the
990 set to our best guess as to what the eventual size of the set
991 hash table will be (to prevent having to re-size the hash
994 size_hint
= guess_num_vtable_pointers (current
->class_info
);
996 /* If we have added vtable pointers to the set in this
997 compilation unit, adjust the size hint for the set's hash
998 table appropriately. */
999 if (vtbl_ptr_array
->length() > 0)
1001 unsigned len
= vtbl_ptr_array
->length();
1002 while ((size_t) len
> size_hint
)
1005 size_hint_arg
= build_int_cst (size_type_node
, size_hint
);
1007 /* Get the key-buffer argument. */
1008 arg2
= build_key_buffer_arg (base_ptr_var_decl
);
1010 if (str2
== NULL_TREE
)
1011 str2
= build_string_literal (strlen ("unknown") + 1,
1015 output_set_info (current
->class_info
->class_type
,
1018 if (vtbl_ptr_array
->length() > 1)
1020 insert_call_to_register_set (current
->class_name
,
1021 vtbl_ptr_array
, body
, arg1
, arg2
,
1023 registered_at_least_one
= true;
1028 if (vtbl_ptr_array
->length() > 0
1029 || (current
->is_used
1030 || (current
->registered
.size() > 0)))
1032 insert_call_to_register_pair (vtbl_ptr_array
,
1033 arg1
, arg2
, size_hint_arg
, str1
,
1035 registered_at_least_one
= true;
1039 if (flag_vtv_counts
&& current_set_size
> 0)
1040 write_out_current_set_data (base_class
, current_set_size
);
1044 return registered_at_least_one
;
1047 /* Given a tree containing a class type (CLASS_TYPE), this function
1048 finds and returns the class hierarchy node for that class in our
1051 static struct vtv_graph_node
*
1052 find_graph_node (tree class_type
)
1054 struct vtbl_map_node
*vtbl_node
;
1056 vtbl_node
= vtbl_map_get_node (TYPE_MAIN_VARIANT (class_type
));
1058 return vtbl_node
->class_info
;
1063 /* Add base class/derived class pair to our internal class hierarchy
1064 data structure. BASE_NODE is our vtv_graph_node that corresponds
1065 to a base class. DERIVED_NODE is our vtv_graph_node that
1066 corresponds to a class that is a descendant of the base class
1067 (possibly the base class itself). */
1070 add_hierarchy_pair (struct vtv_graph_node
*base_node
,
1071 struct vtv_graph_node
*derived_node
)
1073 (base_node
->children
).safe_push (derived_node
);
1074 (derived_node
->parents
).safe_push (base_node
);
1077 /* This functions adds a new base class/derived class relationship to
1078 our class hierarchy data structure. Both parameters are trees
1079 representing the class types, i.e. RECORD_TYPE trees.
1080 DERIVED_CLASS can be the same as BASE_CLASS. */
1083 update_class_hierarchy_information (tree base_class
,
1086 struct vtv_graph_node
*base_node
= find_graph_node (base_class
);
1087 struct vtv_graph_node
*derived_node
= find_graph_node (derived_class
);
1089 add_hierarchy_pair (base_node
, derived_node
);
1094 write_out_vtv_count_data (void)
1096 static int vtv_count_log_fd
= -1;
1098 int unused_vtbl_map_vars
= 0;
1099 int bytes_written
__attribute__ ((unused
));
1100 char *file_name
= get_log_file_name ("vtv_count_data.log");
1102 if (vtv_count_log_fd
== -1)
1103 vtv_count_log_fd
= open (file_name
,
1104 O_WRONLY
| O_APPEND
| O_CREAT
, S_IRWXU
);
1105 if (vtv_count_log_fd
== -1)
1107 warning_at (UNKNOWN_LOCATION
, 0,
1108 "unable to open log file %<vtv_count_data.log%>: %m");
1112 for (unsigned i
= 0; i
< num_vtable_map_nodes
; ++i
)
1114 struct vtbl_map_node
*current
= vtbl_map_nodes_vec
[i
];
1115 if (!current
->is_used
1116 && current
->registered
.size() == 0)
1117 unused_vtbl_map_vars
++;
1120 snprintf (buffer
, sizeof (buffer
), "%s %d %d %d %d %d\n",
1121 main_input_filename
, total_num_virtual_calls
,
1122 total_num_verified_vcalls
, num_calls_to_regset
,
1123 num_calls_to_regpair
, unused_vtbl_map_vars
);
1125 bytes_written
= write (vtv_count_log_fd
, buffer
, strlen (buffer
));
1128 /* This function calls register_all_pairs, which actually generates
1129 all the calls to __VLTRegisterPair (in the verification constructor
1130 init function). It also generates the calls to
1131 __VLTChangePermission, if the verification constructor init
1132 function is going into the preinit array. INIT_ROUTINE_BODY is
1133 the body of our constructior initialization function, to which we
1134 add our function calls.*/
1137 vtv_register_class_hierarchy_information (tree init_routine_body
)
1139 bool registered_something
= false;
1143 if (num_vtable_map_nodes
== 0)
1146 /* Add class hierarchy pairs to the vtable map data structure. */
1147 registered_something
= register_all_pairs (init_routine_body
);
1149 if (flag_vtv_counts
)
1150 write_out_vtv_count_data ();
1152 return registered_something
;
1156 /* Generate the special constructor function that calls
1157 __VLTChangePermission and __VLTRegisterPairs, and give it a very
1158 high initialization priority. */
1161 vtv_generate_init_routine (void)
1163 tree init_routine_body
;
1164 bool vtable_classes_found
= false;
1166 push_lang_context (lang_name_c
);
1168 /* The priority for this init function (constructor) is carefully
1169 chosen so that it will happen after the calls to unprotect the
1170 memory used for vtable verification and before the memory is
1172 init_routine_body
= vtv_start_verification_constructor_init_function ();
1174 vtable_classes_found
=
1175 vtv_register_class_hierarchy_information (init_routine_body
);
1177 if (vtable_classes_found
)
1180 vtv_finish_verification_constructor_init_function (init_routine_body
);
1181 TREE_STATIC (vtv_fndecl
) = 1;
1182 TREE_USED (vtv_fndecl
) = 1;
1183 DECL_PRESERVE_P (vtv_fndecl
) = 1;
1184 if (flag_vtable_verify
== VTV_PREINIT_PRIORITY
)
1185 DECL_STATIC_CONSTRUCTOR (vtv_fndecl
) = 0;
1187 gimplify_function_tree (vtv_fndecl
);
1188 cgraph_add_new_function (vtv_fndecl
, false);
1190 cgraph_process_new_functions ();
1192 if (flag_vtable_verify
== VTV_PREINIT_PRIORITY
)
1193 assemble_vtv_preinit_initializer (vtv_fndecl
);
1196 pop_lang_context ();
1199 /* This funtion takes a tree containing a class type (BASE_TYPE), and
1200 it either finds the existing vtbl_map_node for that class in our
1201 data structure, or it creates a new node and adds it to the data
1202 structure if there is not one for the class already. As part of
1203 this process it also creates the global vtable map variable for the
1206 struct vtbl_map_node
*
1207 vtable_find_or_create_map_decl (tree base_type
)
1209 char *var_name
= NULL
;
1210 struct vtbl_map_node
*vtable_map_node
= NULL
;
1212 /* Verify the type has an associated vtable. */
1213 if (!TYPE_BINFO (base_type
) || !BINFO_VTABLE (TYPE_BINFO (base_type
)))
1216 /* Create map lookup symbol for base class */
1217 var_name
= get_mangled_vtable_map_var_name (base_type
);
1219 /* We've already created the variable; just look it. */
1220 vtable_map_node
= vtbl_map_get_node (TYPE_MAIN_VARIANT (base_type
));
1222 if (!vtable_map_node
|| (vtable_map_node
->vtbl_map_decl
== NULL_TREE
))
1224 /* If we haven't already created the *__vtable_map global
1225 variable for this class, do so now, and add it to the
1226 varpool, to make sure it gets saved and written out. */
1228 tree var_decl
= NULL
;
1229 tree var_type
= build_pointer_type (void_type_node
);
1230 tree initial_value
= integer_zero_node
;
1232 var_decl
= build_decl (UNKNOWN_LOCATION
, VAR_DECL
,
1233 get_identifier (var_name
), var_type
);
1235 DECL_EXTERNAL (var_decl
) = 0;
1236 TREE_STATIC (var_decl
) = 1;
1237 DECL_VISIBILITY (var_decl
) = VISIBILITY_HIDDEN
;
1238 SET_DECL_ASSEMBLER_NAME (var_decl
, get_identifier (var_name
));
1239 DECL_ARTIFICIAL (var_decl
) = 1;
1240 /* We cannot mark this variable as read-only because we want to be
1241 able to write to it at runtime. */
1242 TREE_READONLY (var_decl
) = 0;
1243 DECL_IGNORED_P (var_decl
) = 1;
1244 DECL_PRESERVE_P (var_decl
) = 1;
1246 /* Put these mmap variables in thr .vtable_map_vars section, so
1247 we can find and protect them. */
1249 DECL_SECTION_NAME (var_decl
) = build_string (strlen (".vtable_map_vars"),
1250 ".vtable_map_vars");
1251 DECL_HAS_IMPLICIT_SECTION_NAME_P (var_decl
) = true;
1252 DECL_INITIAL (var_decl
) = initial_value
;
1254 comdat_linkage (var_decl
);
1256 varpool_finalize_decl (var_decl
);
1257 if (!vtable_map_node
)
1259 find_or_create_vtbl_map_node (TYPE_MAIN_VARIANT (base_type
));
1260 if (vtable_map_node
->vtbl_map_decl
== NULL_TREE
)
1261 vtable_map_node
->vtbl_map_decl
= var_decl
;
1264 gcc_assert (vtable_map_node
);
1265 return vtable_map_node
;
1268 /* This function is used to build up our class hierarchy data for a
1269 particular class. TYPE is the record_type tree node for the
1273 vtv_insert_single_class_info (tree type
)
1275 if (flag_vtable_verify
)
1277 tree binfo
= TYPE_BINFO (type
);
1279 struct vtbl_map_node
*own_map
;
1282 /* First make sure to create the map for this record type. */
1283 own_map
= vtable_find_or_create_map_decl (type
);
1284 if (own_map
== NULL
)
1287 /* Go through the list of all base classes for the current
1288 (derived) type, make sure the *__vtable_map global variable
1289 for the base class exists, and add the base class/derived
1290 class pair to the class hierarchy information we are
1291 accumulating (for vtable pointer verification). */
1292 for (i
= 0; BINFO_BASE_ITERATE (binfo
, i
, base_binfo
); i
++)
1294 tree tree_val
= BINFO_TYPE (base_binfo
);
1295 struct vtbl_map_node
*vtable_map_node
= NULL
;
1297 vtable_map_node
= vtable_find_or_create_map_decl (tree_val
);
1299 if (vtable_map_node
!= NULL
)
1300 update_class_hierarchy_information (tree_val
, type
);
1305 /* This function adds classes we are interested in to a list of
1306 classes. RECORD is the record_type node for the class we are
1307 adding to the list. */
1310 vtv_save_class_info (tree record
)
1312 if (!flag_vtable_verify
|| TREE_CODE (record
) == UNION_TYPE
)
1315 if (!vlt_saved_class_info
)
1316 vec_alloc (vlt_saved_class_info
, 10);
1318 gcc_assert (TREE_CODE (record
) == RECORD_TYPE
);
1320 vec_safe_push (vlt_saved_class_info
, record
);
1324 /* This function goes through the list of classes we saved and calls
1325 vtv_insert_single_class_info on each one, to build up our class
1326 hierarchy data structure. */
1329 vtv_recover_class_info (void)
1334 if (vlt_saved_class_info
)
1336 for (i
= 0; i
< vlt_saved_class_info
->length(); ++i
)
1338 current_class
= (*vlt_saved_class_info
)[i
];
1339 gcc_assert (TREE_CODE (current_class
) == RECORD_TYPE
);
1340 vtv_insert_single_class_info (current_class
);
1345 #include "gt-cp-vtable-class-hierarchy.h"