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