1/* Copyright (C) 2012-2022 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
15You should have received a copy of the GNU General Public License
16along 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.cc.  */
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
125static int num_calls_to_regset = 0;
126static int num_calls_to_regpair = 0;
127static int current_set_size;
128
129/* Mark these specially since they need to be stored in precompiled
130   header IR.  */
131static GTY (()) vec<tree, va_gc> *vlt_saved_class_info;
132static GTY (()) tree vlt_register_pairs_fndecl = NULL_TREE;
133static GTY (()) tree vlt_register_set_fndecl = NULL_TREE;
134
135struct work_node {
136  struct vtv_graph_node *node;
137  struct work_node *next;
138};
139
140struct 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
160void
161vtv_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
222static void
223init_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
322static void
323add_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
346static struct vtv_graph_node *
347find_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
379void
380vtv_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
443static bool
444check_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
472static tree
473build_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
496static void
497register_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
602static void
603register_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
646static int
647guess_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
674static uint32_t
675vtv_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
686static char *
687get_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
704static void
705write_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
729static tree
730build_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
758static void
759insert_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
817static void
818insert_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
842static void
843output_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
898static bool
899register_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
1052static struct vtv_graph_node *
1053find_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
1070static void
1071add_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
1083static void
1084update_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
1094static void
1095write_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
1137bool
1138vtv_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
1161void
1162vtv_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
1208struct vtbl_map_node *
1209vtable_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
1273static void
1274vtv_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
1310void
1311vtv_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
1329void
1330vtv_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