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