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