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