1 /* Copyright (C) 2012-2019 Free Software Foundation, Inc.
2 
3    This file is part of GCC.
4 
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.
9 
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.
14 
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/>.  */
18 
19 /* Virtual Table Pointer Security Pass - Detect corruption of vtable pointers
20    before using them for virtual method dispatches.  */
21 
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.
34 
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.
52 
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.
64 
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.
85 
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.
102 
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.  */
112 
113 #include "config.h"
114 #include "system.h"
115 #include "coretypes.h"
116 #include "vtable-verify.h"
117 #include "cp-tree.h"
118 #include "stringpool.h"
119 #include "cgraph.h"
120 #include "output.h"
121 #include "tree-iterator.h"
122 #include "gimplify.h"
123 #include "stor-layout.h"
124 
125 static int num_calls_to_regset = 0;
126 static int num_calls_to_regpair = 0;
127 static int current_set_size;
128 
129 /* Mark these specially since they need to be stored in precompiled
130    header IR.  */
131 static GTY (()) vec<tree, va_gc> *vlt_saved_class_info;
132 static GTY (()) tree vlt_register_pairs_fndecl = NULL_TREE;
133 static GTY (()) tree vlt_register_set_fndecl = NULL_TREE;
134 
135 struct work_node {
136   struct vtv_graph_node *node;
137   struct work_node *next;
138 };
139 
140 struct vtbl_map_node *vtable_find_or_create_map_decl (tree);
141 
142 /* As part of vtable verification the compiler generates and inserts
143    calls to __VLTVerifyVtablePointer, which is in libstdc++.  This
144    function builds and initializes the function decl that is used
145    in generating those function calls.
146 
147    In addition to __VLTVerifyVtablePointer there is also
148    __VLTVerifyVtablePointerDebug which can be used in place of
149    __VLTVerifyVtablePointer, and which takes extra parameters and
150    outputs extra information, to help debug problems.  The debug
151    version of this function is generated and used if flag_vtv_debug is
152    true.
153 
154    The signatures for these functions are:
155 
156    void * __VLTVerifyVtablePointer (void **, void*);
157    void * __VLTVerifyVtablePointerDebug (void**, void *, char *, char *);
158 */
159 
160 void
vtv_build_vtable_verify_fndecl(void)161 vtv_build_vtable_verify_fndecl (void)
162 {
163   tree func_type = NULL_TREE;
164 
165   if (verify_vtbl_ptr_fndecl != NULL_TREE
166       && TREE_CODE (verify_vtbl_ptr_fndecl) != ERROR_MARK)
167     return;
168 
169   if (flag_vtv_debug)
170     {
171       func_type = build_function_type_list (const_ptr_type_node,
172                                             build_pointer_type (ptr_type_node),
173                                             const_ptr_type_node,
174                                             const_string_type_node,
175                                             const_string_type_node,
176                                             NULL_TREE);
177       verify_vtbl_ptr_fndecl =
178         build_lang_decl (FUNCTION_DECL,
179                          get_identifier ("__VLTVerifyVtablePointerDebug"),
180                          func_type);
181     }
182   else
183     {
184       func_type = build_function_type_list (const_ptr_type_node,
185                                             build_pointer_type (ptr_type_node),
186                                             const_ptr_type_node,
187                                             NULL_TREE);
188       verify_vtbl_ptr_fndecl =
189         build_lang_decl (FUNCTION_DECL,
190                          get_identifier ("__VLTVerifyVtablePointer"),
191                          func_type);
192     }
193 
194   TREE_NOTHROW (verify_vtbl_ptr_fndecl) = 1;
195   DECL_ATTRIBUTES (verify_vtbl_ptr_fndecl)
196       = tree_cons (get_identifier ("leaf"), NULL,
197                    DECL_ATTRIBUTES (verify_vtbl_ptr_fndecl));
198   DECL_PURE_P (verify_vtbl_ptr_fndecl) = 1;
199   TREE_PUBLIC (verify_vtbl_ptr_fndecl) = 1;
200   DECL_PRESERVE_P (verify_vtbl_ptr_fndecl) = 1;
201 }
202 
203 /* As part of vtable verification the compiler generates and inserts
204    calls to __VLTRegisterSet and __VLTRegisterPair, which are in
205    libsupc++.  This function builds and initializes the function decls
206    that are used in generating those function calls.
207 
208    The signatures for these functions are:
209 
210    void __VLTRegisterSetDebug (void **, const void *, std::size_t,
211                                size_t, void **);
212 
213    void __VLTRegisterSet (void **, const void *, std::size_t,
214                           size_t, void **);
215 
216    void __VLTRegisterPairDebug (void **, const void *, size_t,
217                                 const void *, const char *, const char *);
218 
219    void __VLTRegisterPair (void **, const void *, size_t, const void *);
220 */
221 
222 static void
init_functions(void)223 init_functions (void)
224 {
225   tree register_set_type;
226   tree register_pairs_type;
227 
228   if (vlt_register_set_fndecl != NULL_TREE)
229     return;
230 
231   gcc_assert (vlt_register_pairs_fndecl == NULL_TREE);
232   gcc_assert (vlt_register_set_fndecl == NULL_TREE);
233 
234   /* Build function decl for __VLTRegisterSet*.  */
235 
236   register_set_type = build_function_type_list
237                                              (void_type_node,
238                                               build_pointer_type (ptr_type_node),
239                                               const_ptr_type_node,
240                                               size_type_node,
241                                               size_type_node,
242                                               build_pointer_type (ptr_type_node),
243                                               NULL_TREE);
244 
245   if (flag_vtv_debug)
246     vlt_register_set_fndecl = build_lang_decl
247                                        (FUNCTION_DECL,
248                                         get_identifier ("__VLTRegisterSetDebug"),
249                                         register_set_type);
250   else
251     vlt_register_set_fndecl = build_lang_decl
252                                        (FUNCTION_DECL,
253                                         get_identifier ("__VLTRegisterSet"),
254                                         register_set_type);
255 
256 
257   TREE_NOTHROW (vlt_register_set_fndecl) = 1;
258   DECL_ATTRIBUTES (vlt_register_set_fndecl) =
259                     tree_cons (get_identifier ("leaf"), NULL,
260                                DECL_ATTRIBUTES (vlt_register_set_fndecl));
261   DECL_EXTERNAL(vlt_register_set_fndecl) = 1;
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);
265 
266   /* Build function decl for __VLTRegisterPair*.  */
267 
268   if (flag_vtv_debug)
269     {
270       register_pairs_type = build_function_type_list (void_type_node,
271                                                       build_pointer_type
272                                                               (ptr_type_node),
273                                                       const_ptr_type_node,
274                                                       size_type_node,
275                                                       const_ptr_type_node,
276                                                       const_string_type_node,
277                                                       const_string_type_node,
278                                                       NULL_TREE);
279 
280       vlt_register_pairs_fndecl = build_lang_decl
281                                       (FUNCTION_DECL,
282                                        get_identifier ("__VLTRegisterPairDebug"),
283                                        register_pairs_type);
284     }
285   else
286     {
287       register_pairs_type = build_function_type_list (void_type_node,
288                                                       build_pointer_type
289                                                               (ptr_type_node),
290                                                       const_ptr_type_node,
291                                                       size_type_node,
292                                                       const_ptr_type_node,
293                                                       NULL_TREE);
294 
295       vlt_register_pairs_fndecl = build_lang_decl
296                                       (FUNCTION_DECL,
297                                        get_identifier ("__VLTRegisterPair"),
298                                        register_pairs_type);
299     }
300 
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   DECL_EXTERNAL(vlt_register_pairs_fndecl) = 1;
306   TREE_PUBLIC (vlt_register_pairs_fndecl) = 1;
307   DECL_PRESERVE_P (vlt_register_pairs_fndecl) = 1;
308   SET_DECL_LANGUAGE (vlt_register_pairs_fndecl, lang_cplusplus);
309 
310 }
311 
312 /* This is a helper function for
313    vtv_compute_class_hierarchy_transitive_closure.  It adds a
314    vtv_graph_node to the WORKLIST, which is a linked list of
315    seen-but-not-yet-processed nodes.  INSERTED is a bitmap, one bit
316    per node, to help make sure that we don't insert a node into the
317    worklist more than once.  Each node represents a class somewhere in
318    our class hierarchy information. Every node in the graph gets added
319    to the worklist exactly once and removed from the worklist exactly
320    once (when all of its children have been processed).  */
321 
322 static void
add_to_worklist(struct work_node ** worklist,struct vtv_graph_node * node,sbitmap inserted)323 add_to_worklist (struct work_node **worklist, struct vtv_graph_node *node,
324                  sbitmap inserted)
325 {
326   struct work_node *new_work_node;
327 
328   if (bitmap_bit_p (inserted, node->class_uid))
329     return;
330 
331   new_work_node = XNEW (struct work_node);
332   new_work_node->next = *worklist;
333   new_work_node->node = node;
334   *worklist = new_work_node;
335 
336   bitmap_set_bit (inserted, node->class_uid);
337 }
338 
339 /* This is a helper function for
340    vtv_compute_class_hierarchy_transitive_closure.  It goes through
341    the WORKLIST of class hierarchy nodes looking for a "leaf" node,
342    i.e. a node whose children in the hierarchy have all been
343    processed.  When it finds the next leaf node, it removes it from
344    the linked list (WORKLIST) and returns the node.  */
345 
346 static struct vtv_graph_node *
find_and_remove_next_leaf_node(struct work_node ** worklist)347 find_and_remove_next_leaf_node (struct work_node **worklist)
348 {
349   struct work_node *prev, *cur;
350   struct vtv_graph_node *ret_val = NULL;
351 
352   for (prev = NULL, cur = *worklist; cur; prev = cur, cur = cur->next)
353     {
354       if ((cur->node->children).length() == cur->node->num_processed_children)
355         {
356           if (prev == NULL)
357             (*worklist) = cur->next;
358           else
359             prev->next = cur->next;
360 
361           cur->next = NULL;
362           ret_val = cur->node;
363           free (cur);
364           return ret_val;
365         }
366     }
367 
368   return NULL;
369 }
370 
371 /* In our class hierarchy graph, each class node contains a bitmap,
372    with one bit for each class in the hierarchy.  The bits are set for
373    classes that are descendants in the graph of the current node.
374    Initially the descendants bitmap is only set for immediate
375    descendants.  This function traverses the class hierarchy graph,
376    bottom up, filling in the transitive closures for the descendants
377    as we rise up the graph.  */
378 
379 void
vtv_compute_class_hierarchy_transitive_closure(void)380 vtv_compute_class_hierarchy_transitive_closure (void)
381 {
382   struct work_node *worklist = NULL;
383   sbitmap inserted = sbitmap_alloc (num_vtable_map_nodes);
384   unsigned i;
385   unsigned j;
386 
387   /* Note: Every node in the graph gets added to the worklist exactly
388    once and removed from the worklist exactly once (when all of its
389    children have been processed).  Each node's children edges are
390    followed exactly once, and each node's parent edges are followed
391    exactly once.  So this algorithm is roughly O(V + 2E), i.e.
392    O(E + V).  */
393 
394   /* Set-up:                                                                */
395   /* Find all the "leaf" nodes in the graph, and add them to the worklist.  */
396   bitmap_clear (inserted);
397   for (j = 0; j < num_vtable_map_nodes; ++j)
398     {
399       struct vtbl_map_node *cur = vtbl_map_nodes_vec[j];
400       if (cur->class_info
401           && ((cur->class_info->children).length() == 0)
402           && ! (bitmap_bit_p (inserted, cur->class_info->class_uid)))
403         add_to_worklist (&worklist, cur->class_info, inserted);
404     }
405 
406   /* Main work: pull next leaf node off work list, process it, add its
407      parents to the worklist, where a 'leaf' node is one that has no
408      children, or all of its children have been processed.  */
409   while (worklist)
410     {
411       struct vtv_graph_node *temp_node =
412                                   find_and_remove_next_leaf_node (&worklist);
413 
414       gcc_assert (temp_node != NULL);
415       temp_node->descendants = sbitmap_alloc (num_vtable_map_nodes);
416       bitmap_clear (temp_node->descendants);
417       bitmap_set_bit (temp_node->descendants, temp_node->class_uid);
418       for (i = 0; i < (temp_node->children).length(); ++i)
419         bitmap_ior (temp_node->descendants, temp_node->descendants,
420                         temp_node->children[i]->descendants);
421       for (i = 0; i < (temp_node->parents).length(); ++i)
422         {
423           temp_node->parents[i]->num_processed_children =
424                     temp_node->parents[i]->num_processed_children + 1;
425           if (!bitmap_bit_p (inserted, temp_node->parents[i]->class_uid))
426             add_to_worklist (&worklist, temp_node->parents[i], inserted);
427         }
428     }
429 }
430 
431 /* Keep track of which pairs we have already created __VLTRegisterPair
432    calls for, to prevent creating duplicate calls within the same
433    compilation unit.  VTABLE_DECL is the var decl for the vtable of
434    the (descendant) class that we are adding to our class hierarchy
435    data.  VPTR_ADDRESS is an expression for calculating the correct
436    offset into the vtable (VTABLE_DECL).  It is the actual vtable
437    pointer address that will be stored in our list of valid vtable
438    pointers for BASE_CLASS.  BASE_CLASS is the record_type node for
439    the base class to whose hiearchy we want to add
440    VPTR_ADDRESS. (VTABLE_DECL should be the vtable for BASE_CLASS or
441    one of BASE_CLASS' descendents.  */
442 
443 static bool
check_and_record_registered_pairs(tree vtable_decl,tree vptr_address,tree base_class)444 check_and_record_registered_pairs (tree vtable_decl, tree vptr_address,
445                                    tree base_class)
446 {
447   unsigned offset;
448   struct vtbl_map_node *base_vtable_map_node;
449   bool inserted_something = false;
450 
451 
452   if (TREE_CODE (vptr_address) == ADDR_EXPR
453       && TREE_CODE (TREE_OPERAND (vptr_address, 0)) == MEM_REF)
454     vptr_address = TREE_OPERAND (vptr_address, 0);
455 
456   if (TREE_OPERAND_LENGTH (vptr_address) > 1)
457     offset = TREE_INT_CST_LOW (TREE_OPERAND (vptr_address, 1));
458   else
459     offset = 0;
460 
461   base_vtable_map_node = vtbl_map_get_node (TYPE_MAIN_VARIANT (base_class));
462 
463   inserted_something = vtbl_map_node_registration_insert
464                                                         (base_vtable_map_node,
465                                                          vtable_decl,
466                                                          offset);
467   return !inserted_something;
468 }
469 
470 /* Given an IDENTIFIER_NODE, build and return a string literal based on it.  */
471 
472 static tree
build_string_from_id(tree identifier)473 build_string_from_id (tree identifier)
474 {
475   int len;
476 
477   gcc_assert (TREE_CODE (identifier) == IDENTIFIER_NODE);
478 
479   len = IDENTIFIER_LENGTH (identifier);
480   return build_string_literal (len + 1, IDENTIFIER_POINTER (identifier));
481 }
482 
483 /* A class may contain secondary vtables in it, for various reasons.
484    This function goes through the decl chain of a class record looking
485    for any fields that point to secondary vtables, and adding calls to
486    __VLTRegisterPair for the secondary vtable pointers.
487 
488    BASE_CLASS_DECL_ARG is an expression for the address of the vtable
489    map variable for the BASE_CLASS (whose hierarchy we are currently
490    updating).  BASE_CLASS is the record_type node for the base class.
491    RECORD_TYPE is the record_type node for the descendant class that
492    we are possibly adding to BASE_CLASS's hierarchy.  BODY is the
493    function body for the constructor init function to which we are
494    adding our calls to __VLTRegisterPair.  */
495 
496 static void
register_construction_vtables(tree base_class,tree record_type,vec<tree> * vtable_ptr_array)497 register_construction_vtables (tree base_class, tree record_type,
498                                vec<tree> *vtable_ptr_array)
499 {
500   tree vtbl_var_decl;
501 
502   if (TREE_CODE (record_type) != RECORD_TYPE)
503     return;
504 
505   vtbl_var_decl = CLASSTYPE_VTABLES (record_type);
506 
507   if (CLASSTYPE_VBASECLASSES (record_type))
508     {
509       tree vtt_decl;
510       bool already_registered = false;
511       tree val_vtbl_decl = NULL_TREE;
512 
513       vtt_decl = DECL_CHAIN (vtbl_var_decl);
514 
515       /* Check to see if we have found a VTT.  Add its data if appropriate.  */
516       if (vtt_decl)
517         {
518           tree values = DECL_INITIAL (vtt_decl);
519           if (TREE_ASM_WRITTEN (vtt_decl)
520               && values != NULL_TREE
521               && TREE_CODE (values) == CONSTRUCTOR
522               && TREE_CODE (TREE_TYPE (values)) == ARRAY_TYPE)
523             {
524               unsigned HOST_WIDE_INT cnt;
525               constructor_elt *ce;
526 
527               /* Loop through the initialization values for this
528                  vtable to get all the correct vtable pointer
529                  addresses that we need to add to our set of valid
530                  vtable pointers for the current base class.  This may
531                  result in adding more than just the element assigned
532                  to the primary vptr of the class, so we may end up
533                  with more vtable pointers than are strictly
534                  necessary.  */
535 
536               for (cnt = 0;
537                    vec_safe_iterate (CONSTRUCTOR_ELTS (values),
538                                      cnt, &ce);
539                    cnt++)
540                 {
541                   tree value = ce->value;
542 
543                   /* Search for the ADDR_EXPR operand within the value.  */
544 
545                   while (value
546                          && TREE_OPERAND (value, 0)
547                          && TREE_CODE (TREE_OPERAND (value, 0)) == ADDR_EXPR)
548                     value = TREE_OPERAND (value, 0);
549 
550                   /* The VAR_DECL for the vtable should be the first
551                      argument of the ADDR_EXPR, which is the first
552                      argument of value.*/
553 
554                   if (TREE_OPERAND (value, 0))
555                     val_vtbl_decl = TREE_OPERAND (value, 0);
556 
557                   while (!VAR_P (val_vtbl_decl)
558                          && TREE_OPERAND (val_vtbl_decl, 0))
559                     val_vtbl_decl = TREE_OPERAND (val_vtbl_decl, 0);
560 
561 		  gcc_assert (VAR_P (val_vtbl_decl));
562 
563                   /* Check to see if we already have this vtable pointer in
564                      our valid set for this base class.  */
565 
566                   already_registered = check_and_record_registered_pairs
567                                                                (val_vtbl_decl,
568                                                                 value,
569                                                                 base_class);
570 
571                   if (already_registered)
572                     continue;
573 
574                   /* Add this vtable pointer to our set of valid
575                      pointers for the base class.  */
576 
577                   vtable_ptr_array->safe_push (value);
578                   current_set_size++;
579                 }
580             }
581         }
582     }
583 }
584 
585 /* This function iterates through all the vtables it can find from the
586    BINFO of a class, to make sure we have found ALL of the vtables
587    that an object of that class could point to.  Generate calls to
588    __VLTRegisterPair for those vtable pointers that we find.
589 
590    BINFO is the tree_binfo node for the BASE_CLASS.  BODY is the
591    function body for the constructor init function to which we are
592    adding calls to __VLTRegisterPair.  ARG1 is an expression for the
593    address of the vtable map variable (for the BASE_CLASS), that will
594    point to the updated data set.  BASE_CLASS is the record_type node
595    for the base class whose set of valid vtable pointers we are
596    updating. STR1 and STR2 are all debugging information, to be passed
597    as parameters to __VLTRegisterPairDebug.  STR1 represents the name
598    of the vtable map variable to be updated by the call.  Similarly,
599    STR2 represents the name of the class whose vtable pointer is being
600    added to the hierarchy.  */
601 
602 static void
register_other_binfo_vtables(tree binfo,tree base_class,vec<tree> * vtable_ptr_array)603 register_other_binfo_vtables (tree binfo, tree base_class,
604                               vec<tree> *vtable_ptr_array)
605 {
606   unsigned ix;
607   tree base_binfo;
608   tree vtable_decl;
609   bool already_registered;
610 
611   if (binfo == NULL_TREE)
612     return;
613 
614   for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
615     {
616       if ((!BINFO_PRIMARY_P (base_binfo)
617            || BINFO_VIRTUAL_P (base_binfo))
618           && (vtable_decl = get_vtbl_decl_for_binfo (base_binfo)))
619         {
620           tree vtable_address = build_vtbl_address (base_binfo);
621 
622           already_registered = check_and_record_registered_pairs
623                                                               (vtable_decl,
624                                                                vtable_address,
625                                                                base_class);
626           if (!already_registered)
627             {
628               vtable_ptr_array->safe_push (vtable_address);
629               current_set_size++;
630             }
631         }
632 
633       register_other_binfo_vtables (base_binfo, base_class, vtable_ptr_array);
634     }
635 }
636 
637 /* The set of valid vtable pointers for any given class are stored in
638    a hash table.  For reasons of efficiency, that hash table size is
639    always a power of two.  In order to try to prevent re-sizing the
640    hash tables very often, we pass __VLTRegisterPair an initial guess
641    as to the number of entries the hashtable will eventually need
642    (rounded up to the nearest power of two).  This function takes the
643    class information we have collected for a particular class,
644    CLASS_NODE, and calculates the hash table size guess.  */
645 
646 static int
guess_num_vtable_pointers(struct vtv_graph_node * class_node)647 guess_num_vtable_pointers (struct vtv_graph_node *class_node)
648 {
649   tree vtbl;
650   int total_num_vtbls = 0;
651   int num_vtbls_power_of_two = 1;
652   unsigned i;
653 
654   for (i = 0; i < num_vtable_map_nodes; ++i)
655     if (bitmap_bit_p (class_node->descendants, i))
656       {
657         tree class_type = vtbl_map_nodes_vec[i]->class_info->class_type;
658         for (vtbl = CLASSTYPE_VTABLES (class_type); vtbl;
659              vtbl = DECL_CHAIN (vtbl))
660           {
661             total_num_vtbls++;
662             if (total_num_vtbls > num_vtbls_power_of_two)
663               num_vtbls_power_of_two <<= 1;
664           }
665       }
666   return num_vtbls_power_of_two;
667 }
668 
669 /* A simple hash function on strings */
670 /* Be careful about changing this routine. The values generated will
671    be stored in the calls to InitSet. So, changing this routine may
672    cause a binary incompatibility.  */
673 
674 static uint32_t
vtv_string_hash(const char * in)675 vtv_string_hash (const char *in)
676 {
677   const char *s = in;
678   uint32_t h = 0;
679 
680   gcc_assert (in != NULL);
681   for ( ; *s; ++s)
682     h = 5 * h + *s;
683   return h;
684 }
685 
686 static char *
get_log_file_name(const char * fname)687 get_log_file_name (const char *fname)
688 {
689   const char *tmp_dir = concat (dump_dir_name, NULL);
690   char *full_name;
691   int dir_len;
692   int fname_len;
693 
694   dir_len = strlen (tmp_dir);
695   fname_len = strlen (fname);
696 
697   full_name = XNEWVEC (char, dir_len + fname_len + 1);
698   strcpy (full_name, tmp_dir);
699   strcpy (full_name + dir_len, fname);
700 
701   return full_name;
702 }
703 
704 static void
write_out_current_set_data(tree base_class,int set_size)705 write_out_current_set_data (tree base_class, int set_size)
706 {
707   static int class_data_log_fd = -1;
708   char buffer[1024];
709   int bytes_written __attribute__ ((unused));
710   char *file_name = get_log_file_name ("vtv_class_set_sizes.log");
711 
712   if (class_data_log_fd == -1)
713     class_data_log_fd = open (file_name,
714                               O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
715 
716   if (class_data_log_fd == -1)
717     {
718       warning_at (UNKNOWN_LOCATION, 0,
719 		  "unable to open log file %<vtv_class_set_sizes.log%>: %m");
720       return;
721     }
722 
723   snprintf (buffer, sizeof (buffer), "%s %d\n",
724             IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (base_class))),
725             set_size);
726   bytes_written = write (class_data_log_fd, buffer, strlen (buffer));
727 }
728 
729 static tree
build_key_buffer_arg(tree base_ptr_var_decl)730 build_key_buffer_arg (tree base_ptr_var_decl)
731 {
732   const int key_type_fixed_size = 8;
733   uint32_t len1 = IDENTIFIER_LENGTH (DECL_NAME (base_ptr_var_decl));
734   uint32_t hash_value = vtv_string_hash (IDENTIFIER_POINTER
735                                               (DECL_NAME (base_ptr_var_decl)));
736   void *key_buffer = xmalloc (len1 + key_type_fixed_size);
737   uint32_t *value_ptr = (uint32_t *) key_buffer;
738   tree ret_value;
739 
740   /* Set the len and hash for the string.  */
741   *value_ptr = len1;
742   value_ptr++;
743   *value_ptr = hash_value;
744 
745   /* Now copy the string representation of the vtbl map name...  */
746   memcpy ((char *) key_buffer + key_type_fixed_size,
747           IDENTIFIER_POINTER (DECL_NAME (base_ptr_var_decl)),
748           len1);
749 
750   /* ... and build a string literal from it. This will make a copy
751      so the key_bufffer is not needed anymore after this.  */
752   ret_value = build_string_literal (len1 + key_type_fixed_size,
753                                     (char *) key_buffer);
754   free (key_buffer);
755   return ret_value;
756 }
757 
758 static void
insert_call_to_register_set(tree class_name,vec<tree> * vtbl_ptr_array,tree body,tree arg1,tree arg2,tree size_hint_arg)759 insert_call_to_register_set (tree class_name,
760                              vec<tree> *vtbl_ptr_array, tree body, tree arg1,
761                              tree arg2, tree size_hint_arg)
762 {
763   tree call_expr;
764   int num_args = vtbl_ptr_array->length();
765   char *array_arg_name = ACONCAT (("__vptr_array_",
766                                    IDENTIFIER_POINTER (class_name), NULL));
767   tree array_arg_type = build_array_type_nelts (build_pointer_type
768                                                   (build_pointer_type
769                                                      (void_type_node)),
770                                                 num_args);
771   tree array_arg = build_decl (UNKNOWN_LOCATION, VAR_DECL,
772                                get_identifier (array_arg_name),
773                                array_arg_type);
774   int k;
775 
776   vec<constructor_elt, va_gc> *array_elements;
777   vec_alloc (array_elements, num_args);
778 
779   tree initial = NULL_TREE;
780   tree arg3 = NULL_TREE;
781 
782   TREE_PUBLIC (array_arg) = 0;
783   DECL_EXTERNAL (array_arg) = 0;
784   TREE_STATIC (array_arg) = 1;
785   DECL_ARTIFICIAL (array_arg) = 0;
786   TREE_READONLY (array_arg) = 1;
787   DECL_IGNORED_P (array_arg) = 0;
788   DECL_PRESERVE_P (array_arg) = 0;
789   DECL_VISIBILITY (array_arg) = VISIBILITY_HIDDEN;
790 
791   for (k = 0; k < num_args; ++k)
792     {
793       CONSTRUCTOR_APPEND_ELT (array_elements, NULL_TREE, (*vtbl_ptr_array)[k]);
794     }
795 
796   initial = build_constructor (TREE_TYPE (array_arg), array_elements);
797 
798   TREE_CONSTANT (initial) = 1;
799   TREE_STATIC (initial) = 1;
800   DECL_INITIAL (array_arg) = initial;
801   relayout_decl (array_arg);
802   varpool_node::finalize_decl (array_arg);
803 
804   arg3 = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (array_arg)), array_arg);
805 
806   TREE_TYPE (arg3) = build_pointer_type (TREE_TYPE (array_arg));
807 
808   call_expr = build_call_expr (vlt_register_set_fndecl, 5, arg1,
809                                arg2, /* set_symbol_key */
810                                size_hint_arg, build_int_cst (size_type_node,
811                                                              num_args),
812                                arg3);
813   append_to_statement_list (call_expr, &body);
814   num_calls_to_regset++;
815 }
816 
817 static void
insert_call_to_register_pair(vec<tree> * vtbl_ptr_array,tree arg1,tree arg2,tree size_hint_arg,tree str1,tree str2,tree body)818 insert_call_to_register_pair (vec<tree> *vtbl_ptr_array, tree arg1,
819                               tree arg2, tree size_hint_arg, tree str1,
820                               tree str2, tree body)
821 {
822   tree call_expr;
823   int num_args = vtbl_ptr_array->length();
824   tree vtable_address = NULL_TREE;
825 
826   if (num_args == 0)
827     vtable_address = build_int_cst (build_pointer_type (void_type_node), 0);
828   else
829     vtable_address = (*vtbl_ptr_array)[0];
830 
831   if (flag_vtv_debug)
832     call_expr = build_call_expr (vlt_register_pairs_fndecl, 6, arg1, arg2,
833                                  size_hint_arg, vtable_address, str1, str2);
834   else
835     call_expr = build_call_expr (vlt_register_pairs_fndecl, 4, arg1, arg2,
836                                  size_hint_arg, vtable_address);
837 
838   append_to_statement_list (call_expr, &body);
839   num_calls_to_regpair++;
840 }
841 
842 static void
output_set_info(tree record_type,vec<tree> vtbl_ptr_array)843 output_set_info (tree record_type, vec<tree> vtbl_ptr_array)
844 {
845   static int vtv_debug_log_fd = -1;
846   char buffer[1024];
847   int bytes_written __attribute__ ((unused));
848   int array_len = vtbl_ptr_array.length();
849   const char *class_name =
850               IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (record_type)));
851   char *file_name = get_log_file_name ("vtv_set_ptr_data.log");
852 
853   if (vtv_debug_log_fd == -1)
854     vtv_debug_log_fd = open (file_name,
855                              O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
856   if (vtv_debug_log_fd == -1)
857     {
858       warning_at (UNKNOWN_LOCATION, 0,
859 		  "unable to open log file %<vtv_set_ptr_data.log%>: %m");
860       return;
861     }
862 
863   for (int i = 0; i < array_len; ++i)
864     {
865       const char *vptr_name = "unknown";
866       int vptr_offset = 0;
867 
868       if (TREE_CODE (vtbl_ptr_array[i]) == POINTER_PLUS_EXPR)
869         {
870           tree arg0 = TREE_OPERAND (vtbl_ptr_array[i], 0);
871           tree arg1 = TREE_OPERAND (vtbl_ptr_array[i], 1);
872 
873           if (TREE_CODE (arg0) == ADDR_EXPR)
874             arg0 = TREE_OPERAND (arg0, 0);
875 
876 	  if (VAR_P (arg0))
877             vptr_name = IDENTIFIER_POINTER (DECL_NAME (arg0));
878 
879           if (TREE_CODE (arg1) == INTEGER_CST)
880             vptr_offset = TREE_INT_CST_LOW (arg1);
881         }
882 
883       snprintf (buffer, sizeof (buffer), "%s %s %s + %d\n",
884                 main_input_filename, class_name, vptr_name, vptr_offset);
885       bytes_written = write (vtv_debug_log_fd, buffer, strlen(buffer));
886     }
887 
888 }
889 
890 /* This function goes through our internal class hierarchy & vtable
891    pointer data structure and outputs calls to __VLTRegisterPair for
892    every class-vptr pair (for those classes whose vtable would be
893    output in the current compilation unit).  These calls get put into
894    our constructor initialization function.  BODY is the function
895    body, so far, of our constructor initialization function, to which we
896    add the calls.  */
897 
898 static bool
register_all_pairs(tree body)899 register_all_pairs (tree body)
900 {
901   bool registered_at_least_one = false;
902   vec<tree> *vtbl_ptr_array = NULL;
903   unsigned j;
904 
905   for (j = 0; j < num_vtable_map_nodes; ++j)
906     {
907       struct vtbl_map_node *current = vtbl_map_nodes_vec[j];
908       unsigned i = 0;
909       tree base_class = current->class_info->class_type;
910       tree base_ptr_var_decl = current->vtbl_map_decl;
911       tree arg1;
912       tree arg2;
913       tree new_type;
914       tree str1 = NULL_TREE;
915       tree str2 = NULL_TREE;
916       size_t size_hint;
917       tree size_hint_arg;
918 
919       gcc_assert (current->class_info != NULL);
920 
921 
922       if (flag_vtv_debug)
923         str1 = build_string_from_id (DECL_NAME (base_ptr_var_decl));
924 
925       new_type = build_pointer_type (TREE_TYPE (base_ptr_var_decl));
926       arg1 = build1 (ADDR_EXPR, new_type, base_ptr_var_decl);
927 
928       /* We need a fresh vector for each iteration.  */
929       if (vtbl_ptr_array)
930 	vec_free (vtbl_ptr_array);
931 
932       vec_alloc (vtbl_ptr_array, 10);
933 
934       for (i = 0; i < num_vtable_map_nodes; ++i)
935         if (bitmap_bit_p (current->class_info->descendants, i))
936           {
937             struct vtbl_map_node *vtbl_class_node = vtbl_map_nodes_vec[i];
938             tree class_type = vtbl_class_node->class_info->class_type;
939 
940             if (class_type
941                 && (TREE_CODE (class_type) == RECORD_TYPE))
942               {
943                 bool already_registered;
944 
945                 tree binfo = TYPE_BINFO (class_type);
946                 tree vtable_decl;
947                 bool vtable_should_be_output = false;
948 
949                 vtable_decl = CLASSTYPE_VTABLES (class_type);
950 
951                 /* Handle main vtable for this class.  */
952 
953                 if (vtable_decl)
954                   {
955                     vtable_should_be_output = TREE_ASM_WRITTEN (vtable_decl);
956                     str2 = build_string_from_id (DECL_NAME (vtable_decl));
957                   }
958 
959                 if (vtable_decl && vtable_should_be_output)
960                   {
961                     tree vtable_address = build_vtbl_address (binfo);
962 
963                     already_registered = check_and_record_registered_pairs
964                                                               (vtable_decl,
965                                                                vtable_address,
966                                                                base_class);
967 
968 
969                     if (!already_registered)
970                       {
971                         vtbl_ptr_array->safe_push (vtable_address);
972 
973                         /* Find and handle any 'extra' vtables associated
974                            with this class, via virtual inheritance.   */
975                         register_construction_vtables (base_class, class_type,
976                                                        vtbl_ptr_array);
977 
978                         /* Find and handle any 'extra' vtables associated
979                            with this class, via multiple inheritance.   */
980                         register_other_binfo_vtables (binfo, base_class,
981                                                       vtbl_ptr_array);
982                       }
983                   }
984               }
985           }
986       current_set_size = vtbl_ptr_array->length();
987 
988       /* Sometimes we need to initialize the set symbol even if we are
989          not adding any vtable pointers to the set in the current
990          compilation unit.  In that case, we need to initialize the
991          set to our best guess as to what the eventual size of the set
992          hash table will be (to prevent having to re-size the hash
993          table later).  */
994 
995       size_hint = guess_num_vtable_pointers (current->class_info);
996 
997       /* If we have added vtable pointers to the set in this
998          compilation unit, adjust the size hint for the set's hash
999          table appropriately.  */
1000       if (vtbl_ptr_array->length() > 0)
1001 	{
1002 	  unsigned len = vtbl_ptr_array->length();
1003 	  while ((size_t) len > size_hint)
1004 	    size_hint <<= 1;
1005 	}
1006       size_hint_arg = build_int_cst (size_type_node, size_hint);
1007 
1008       /* Get the key-buffer argument.  */
1009       arg2 = build_key_buffer_arg (base_ptr_var_decl);
1010 
1011       if (str2 == NULL_TREE)
1012         str2 = build_string_literal (strlen ("unknown") + 1,
1013                                      "unknown");
1014 
1015       if (flag_vtv_debug)
1016         output_set_info (current->class_info->class_type,
1017                          *vtbl_ptr_array);
1018 
1019       if (vtbl_ptr_array->length() > 1)
1020         {
1021           insert_call_to_register_set (current->class_name,
1022                                        vtbl_ptr_array, body, arg1, arg2,
1023                                        size_hint_arg);
1024           registered_at_least_one = true;
1025         }
1026       else
1027         {
1028 
1029           if (vtbl_ptr_array->length() > 0
1030               || (current->is_used
1031                   || (current->registered->size() > 0)))
1032             {
1033               insert_call_to_register_pair (vtbl_ptr_array,
1034                                             arg1, arg2, size_hint_arg, str1,
1035                                             str2, body);
1036               registered_at_least_one = true;
1037             }
1038         }
1039 
1040       if (flag_vtv_counts && current_set_size > 0)
1041         write_out_current_set_data (base_class, current_set_size);
1042 
1043     }
1044 
1045   return registered_at_least_one;
1046 }
1047 
1048 /* Given a tree containing a class type (CLASS_TYPE), this function
1049    finds and returns the class hierarchy node for that class in our
1050    data structure.  */
1051 
1052 static struct vtv_graph_node *
find_graph_node(tree class_type)1053 find_graph_node (tree class_type)
1054 {
1055   struct vtbl_map_node *vtbl_node;
1056 
1057   vtbl_node = vtbl_map_get_node (TYPE_MAIN_VARIANT (class_type));
1058   if (vtbl_node)
1059     return vtbl_node->class_info;
1060 
1061   return NULL;
1062 }
1063 
1064 /* Add base class/derived class pair to our internal class hierarchy
1065    data structure.  BASE_NODE is our vtv_graph_node that corresponds
1066    to a base class.  DERIVED_NODE is our vtv_graph_node that
1067    corresponds to a class that is a descendant of the base class
1068    (possibly the base class itself).  */
1069 
1070 static void
add_hierarchy_pair(struct vtv_graph_node * base_node,struct vtv_graph_node * derived_node)1071 add_hierarchy_pair (struct vtv_graph_node *base_node,
1072                     struct vtv_graph_node *derived_node)
1073 {
1074   (base_node->children).safe_push (derived_node);
1075   (derived_node->parents).safe_push (base_node);
1076 }
1077 
1078 /* This functions adds a new base class/derived class relationship to
1079    our class hierarchy data structure.  Both parameters are trees
1080    representing the class types, i.e. RECORD_TYPE trees.
1081    DERIVED_CLASS can be the same as BASE_CLASS.  */
1082 
1083 static void
update_class_hierarchy_information(tree base_class,tree derived_class)1084 update_class_hierarchy_information (tree base_class,
1085                                     tree derived_class)
1086 {
1087   struct vtv_graph_node *base_node = find_graph_node (base_class);
1088   struct vtv_graph_node *derived_node = find_graph_node (derived_class);
1089 
1090   add_hierarchy_pair (base_node, derived_node);
1091 }
1092 
1093 
1094 static void
write_out_vtv_count_data(void)1095 write_out_vtv_count_data (void)
1096 {
1097   static int vtv_count_log_fd = -1;
1098   char buffer[1024];
1099   int unused_vtbl_map_vars = 0;
1100   int bytes_written __attribute__ ((unused));
1101   char *file_name = get_log_file_name ("vtv_count_data.log");
1102 
1103   if (vtv_count_log_fd == -1)
1104     vtv_count_log_fd = open (file_name,
1105                              O_WRONLY | O_APPEND | O_CREAT, S_IRWXU);
1106   if (vtv_count_log_fd == -1)
1107     {
1108       warning_at (UNKNOWN_LOCATION, 0,
1109 		  "unable to open log file %<vtv_count_data.log%>: %m");
1110       return;
1111     }
1112 
1113   for (unsigned i = 0; i < num_vtable_map_nodes; ++i)
1114     {
1115       struct vtbl_map_node *current = vtbl_map_nodes_vec[i];
1116       if (!current->is_used
1117           && current->registered->size() == 0)
1118         unused_vtbl_map_vars++;
1119     }
1120 
1121   snprintf (buffer, sizeof (buffer), "%s %d %d %d %d %d\n",
1122             main_input_filename, total_num_virtual_calls,
1123             total_num_verified_vcalls, num_calls_to_regset,
1124             num_calls_to_regpair, unused_vtbl_map_vars);
1125 
1126   bytes_written = write (vtv_count_log_fd, buffer, strlen (buffer));
1127 }
1128 
1129 /* This function calls register_all_pairs, which actually generates
1130    all the calls to __VLTRegisterPair (in the verification constructor
1131    init function).  It also generates the calls to
1132    __VLTChangePermission, if the verification constructor init
1133    function is going into the preinit array.  INIT_ROUTINE_BODY is
1134    the body of our constructior initialization function, to which we
1135    add our function calls.*/
1136 
1137 bool
vtv_register_class_hierarchy_information(tree init_routine_body)1138 vtv_register_class_hierarchy_information (tree init_routine_body)
1139 {
1140   bool registered_something = false;
1141 
1142   init_functions ();
1143 
1144   if (num_vtable_map_nodes == 0)
1145     return false;
1146 
1147   /* Add class hierarchy pairs to the vtable map data structure.  */
1148   registered_something = register_all_pairs (init_routine_body);
1149 
1150   if (flag_vtv_counts)
1151     write_out_vtv_count_data ();
1152 
1153   return registered_something;
1154 }
1155 
1156 
1157 /* Generate the special constructor function that calls
1158    __VLTChangePermission and __VLTRegisterPairs, and give it a very
1159    high initialization priority.  */
1160 
1161 void
vtv_generate_init_routine(void)1162 vtv_generate_init_routine (void)
1163 {
1164   tree init_routine_body;
1165   bool vtable_classes_found = false;
1166 
1167   push_lang_context (lang_name_c);
1168 
1169   /* The priority for this init function (constructor) is carefully
1170      chosen so that it will happen after the calls to unprotect the
1171      memory used for vtable verification and before the memory is
1172      protected again.  */
1173   init_routine_body = vtv_start_verification_constructor_init_function ();
1174 
1175   vtable_classes_found =
1176                  vtv_register_class_hierarchy_information (init_routine_body);
1177 
1178   if (vtable_classes_found)
1179     {
1180       tree vtv_fndecl =
1181         vtv_finish_verification_constructor_init_function (init_routine_body);
1182       TREE_STATIC (vtv_fndecl) = 1;
1183       TREE_USED (vtv_fndecl) = 1;
1184       DECL_PRESERVE_P (vtv_fndecl) = 1;
1185       /* We are running too late to generate any meaningful debug information
1186          for this routine.  */
1187       DECL_IGNORED_P (vtv_fndecl) = 1;
1188       if (flag_vtable_verify == VTV_PREINIT_PRIORITY && !TARGET_PECOFF)
1189         DECL_STATIC_CONSTRUCTOR (vtv_fndecl) = 0;
1190 
1191       gimplify_function_tree (vtv_fndecl);
1192       cgraph_node::add_new_function (vtv_fndecl, false);
1193 
1194       if (flag_vtable_verify == VTV_PREINIT_PRIORITY && !TARGET_PECOFF)
1195         assemble_vtv_preinit_initializer (vtv_fndecl);
1196 
1197     }
1198   pop_lang_context ();
1199 }
1200 
1201 /* This funtion takes a tree containing a class type (BASE_TYPE), and
1202    it either finds the existing vtbl_map_node for that class in our
1203    data structure, or it creates a new node and adds it to the data
1204    structure if there is not one for the class already.  As part of
1205    this process it also creates the global vtable map variable for the
1206    class.  */
1207 
1208 struct vtbl_map_node *
vtable_find_or_create_map_decl(tree base_type)1209 vtable_find_or_create_map_decl (tree base_type)
1210 {
1211   char *var_name = NULL;
1212   struct vtbl_map_node *vtable_map_node = NULL;
1213 
1214   /* Verify the type has an associated vtable.  */
1215   if (!TYPE_BINFO (base_type) || !BINFO_VTABLE (TYPE_BINFO (base_type)))
1216     return NULL;
1217 
1218   /* Create map lookup symbol for base class */
1219   var_name = get_mangled_vtable_map_var_name (base_type);
1220 
1221   /* We've already created the variable; just look it.  */
1222   vtable_map_node = vtbl_map_get_node (TYPE_MAIN_VARIANT (base_type));
1223 
1224   if (!vtable_map_node || (vtable_map_node->vtbl_map_decl == NULL_TREE))
1225     {
1226       /* If we haven't already created the *__vtable_map global
1227          variable for this class, do so now, and add it to the
1228          varpool, to make sure it gets saved and written out.  */
1229 
1230       tree var_decl = NULL;
1231       tree var_type = build_pointer_type (void_type_node);
1232       tree initial_value = integer_zero_node;
1233 
1234       var_decl  = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1235                               get_identifier (var_name), var_type);
1236 
1237       DECL_EXTERNAL (var_decl) = 0;
1238       TREE_STATIC (var_decl) = 1;
1239       DECL_VISIBILITY (var_decl) = VISIBILITY_HIDDEN;
1240       SET_DECL_ASSEMBLER_NAME (var_decl, get_identifier (var_name));
1241       DECL_ARTIFICIAL (var_decl) = 1;
1242       /* We cannot mark this variable as read-only because we want to be
1243          able to write to it at runtime.  */
1244       TREE_READONLY (var_decl) = 0;
1245       DECL_IGNORED_P (var_decl) = 1;
1246       DECL_PRESERVE_P (var_decl) = 1;
1247 
1248       /* Put these mmap variables in thr .vtable_map_vars section, so
1249          we can find and protect them.  */
1250 
1251       set_decl_section_name (var_decl, ".vtable_map_vars");
1252       symtab_node::get (var_decl)->implicit_section = true;
1253       DECL_INITIAL (var_decl) = initial_value;
1254 
1255       comdat_linkage (var_decl);
1256 
1257       varpool_node::finalize_decl (var_decl);
1258       if (!vtable_map_node)
1259         vtable_map_node =
1260                    find_or_create_vtbl_map_node (TYPE_MAIN_VARIANT (base_type));
1261       if (vtable_map_node->vtbl_map_decl == NULL_TREE)
1262         vtable_map_node->vtbl_map_decl = var_decl;
1263     }
1264 
1265   gcc_assert (vtable_map_node);
1266   return vtable_map_node;
1267 }
1268 
1269 /* This function is used to build up our class hierarchy data for a
1270    particular class.  TYPE is the record_type tree node for the
1271    class.  */
1272 
1273 static void
vtv_insert_single_class_info(tree type)1274 vtv_insert_single_class_info (tree type)
1275 {
1276   if (flag_vtable_verify)
1277     {
1278       tree binfo =  TYPE_BINFO (type);
1279       tree base_binfo;
1280       struct vtbl_map_node *own_map;
1281       int i;
1282 
1283       /* First make sure to create the map for this record type.  */
1284       own_map = vtable_find_or_create_map_decl (type);
1285       if (own_map == NULL)
1286         return;
1287 
1288       /* Go through the list of all base classes for the current
1289          (derived) type, make sure the *__vtable_map global variable
1290          for the base class exists, and add the base class/derived
1291          class pair to the class hierarchy information we are
1292          accumulating (for vtable pointer verification).  */
1293       for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
1294         {
1295           tree tree_val = BINFO_TYPE (base_binfo);
1296           struct vtbl_map_node *vtable_map_node = NULL;
1297 
1298           vtable_map_node = vtable_find_or_create_map_decl (tree_val);
1299 
1300           if (vtable_map_node != NULL)
1301             update_class_hierarchy_information (tree_val, type);
1302         }
1303     }
1304 }
1305 
1306 /* This function adds classes we are interested in to a list of
1307    classes.  RECORD is the record_type node for the class we are
1308    adding to the list.  */
1309 
1310 void
vtv_save_class_info(tree record)1311 vtv_save_class_info (tree record)
1312 {
1313   if (!flag_vtable_verify || TREE_CODE (record) == UNION_TYPE)
1314     return;
1315 
1316   if (!vlt_saved_class_info)
1317     vec_alloc (vlt_saved_class_info, 10);
1318 
1319   gcc_assert (TREE_CODE (record) == RECORD_TYPE);
1320 
1321   vec_safe_push (vlt_saved_class_info, record);
1322 }
1323 
1324 
1325 /* This function goes through the list of classes we saved and calls
1326    vtv_insert_single_class_info on each one, to build up our class
1327    hierarchy data structure.  */
1328 
1329 void
vtv_recover_class_info(void)1330 vtv_recover_class_info (void)
1331 {
1332   tree current_class;
1333   unsigned i;
1334 
1335   if (vlt_saved_class_info)
1336     {
1337       for (i = 0; i < vlt_saved_class_info->length(); ++i)
1338         {
1339           current_class = (*vlt_saved_class_info)[i];
1340           gcc_assert (TREE_CODE (current_class) == RECORD_TYPE);
1341           vtv_insert_single_class_info (current_class);
1342         }
1343     }
1344 }
1345 
1346 #include "gt-cp-vtable-class-hierarchy.h"
1347