gcc80: Handle TZ specific "%+" format in strftime.
[dragonfly.git] / contrib / gcc-8.0 / gcc / vtable-verify.c
1 /* Copyright (C) 2013-2018 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 under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 3, or (at your option) any later
8 version.
9
10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 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 variable 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 for the tree pass that goes through all the
104   statements in each basic block, looking for virtual calls, and
105   inserting a call to __VLTVerifyVtablePointer (with appropriate
106   arguments) before each one.  It also contains the hash table
107   functions for the data structures used for collecting the class
108   hierarchy data and building/maintaining the vtable map variable data
109   are defined in gcc/vtable-verify.h.  These data structures are
110   shared with the code in the C++ front end that collects the class
111   hierarchy & vtable information and generates the vtable map
112   variables (see cp/vtable-class-hierarchy.c).  This tree pass should
113   run just before the gimple is converted to RTL.
114
115   Some implementation details for this pass:
116
117   To find all of the virtual calls, we iterate through all the
118   gimple statements in each basic block, looking for any call
119   statement with the code "OBJ_TYPE_REF".  Once we have found the
120   virtual call, we need to find the vtable pointer through which the
121   call is being made, and the type of the object containing the
122   pointer (to find the appropriate vtable map variable).  We then use
123   these to build a call to __VLTVerifyVtablePointer, passing the
124   vtable map variable, and the vtable pointer.  We insert the
125   verification call just after the gimple statement that gets the
126   vtable pointer out of the object, and we update the next
127   statement to depend on the result returned from
128   __VLTVerifyVtablePointer (the vtable pointer value), to ensure
129   subsequent compiler phases don't remove or reorder the call (it's no
130   good to have the verification occur after the virtual call, for
131   example).  To find the vtable pointer being used (and the type of
132   the object) we search backwards through the def_stmts chain from the
133   virtual call (see verify_bb_vtables for more details).  */
134
135 #include "config.h"
136 #include "system.h"
137 #include "coretypes.h"
138 #include "backend.h"
139 #include "tree.h"
140 #include "gimple.h"
141 #include "tree-pass.h"
142 #include "ssa.h"
143 #include "gimple-iterator.h"
144
145 #include "vtable-verify.h"
146
147 unsigned num_vtable_map_nodes = 0;
148 int total_num_virtual_calls = 0;
149 int total_num_verified_vcalls = 0;
150
151 extern GTY(()) tree verify_vtbl_ptr_fndecl;
152 tree verify_vtbl_ptr_fndecl = NULL_TREE;
153
154 /* Keep track of whether or not any virtual call were verified.  */
155 static bool any_verification_calls_generated = false;
156
157 unsigned int vtable_verify_main (void);
158
159
160 /* The following few functions are for the vtbl pointer hash table
161    in the 'registered' field of the struct vtable_map_node.  The hash
162    table keeps track of which vtable pointers have been used in
163    calls to __VLTRegisterPair with that particular vtable map variable.  */
164
165 /* This function checks to see if a particular VTABLE_DECL and OFFSET are
166    already in the 'registered' hash table for NODE.  */
167
168 bool
169 vtbl_map_node_registration_find (struct vtbl_map_node *node,
170                                  tree vtable_decl,
171                                  unsigned offset)
172 {
173   struct vtable_registration key;
174   struct vtable_registration **slot;
175
176   gcc_assert (node && node->registered);
177
178   key.vtable_decl = vtable_decl;
179   slot = node->registered->find_slot (&key, NO_INSERT);
180
181   if (slot && (*slot))
182     {
183       unsigned i;
184       for (i = 0; i < ((*slot)->offsets).length (); ++i)
185         if ((*slot)->offsets[i] == offset)
186           return true;
187     }
188
189   return false;
190 }
191
192 /* This function inserts VTABLE_DECL and OFFSET into the 'registered'
193    hash table for NODE.  It returns a boolean indicating whether or not
194    it actually inserted anything.  */
195
196 bool
197 vtbl_map_node_registration_insert (struct vtbl_map_node *node,
198                                    tree vtable_decl,
199                                    unsigned offset)
200 {
201   struct vtable_registration key;
202   struct vtable_registration **slot;
203   bool inserted_something = false;
204
205   if (!node || !node->registered)
206     return false;
207
208   key.vtable_decl = vtable_decl;
209   slot = node->registered->find_slot (&key, INSERT);
210
211   if (! *slot)
212     {
213       struct vtable_registration *node;
214       node = XNEW (struct vtable_registration);
215       node->vtable_decl = vtable_decl;
216
217       (node->offsets).create (10);
218       (node->offsets).safe_push (offset);
219       *slot = node;
220       inserted_something = true;
221     }
222   else
223     {
224       /* We found the vtable_decl slot; we need to see if it already
225          contains the offset.  If not, we need to add the offset.  */
226       unsigned i;
227       bool found = false;
228       for (i = 0; i < ((*slot)->offsets).length () && !found; ++i)
229         if ((*slot)->offsets[i] == offset)
230           found = true;
231
232       if (!found)
233         {
234           ((*slot)->offsets).safe_push (offset);
235           inserted_something = true;
236         }
237      }
238   return inserted_something;
239 }
240
241 /* Hashtable functions for vtable_registration hashtables.  */
242
243 inline hashval_t
244 registration_hasher::hash (const vtable_registration *p)
245 {
246   const struct vtable_registration *n = (const struct vtable_registration *) p;
247   return (hashval_t) (DECL_UID (n->vtable_decl));
248 }
249
250 inline bool
251 registration_hasher::equal (const vtable_registration *p1,
252                             const vtable_registration *p2)
253 {
254   const struct vtable_registration *n1 =
255                                     (const struct vtable_registration *) p1;
256   const struct vtable_registration *n2 =
257                                     (const struct vtable_registration *) p2;
258   return (DECL_UID (n1->vtable_decl) == DECL_UID (n2->vtable_decl));
259 }
260
261 /* End of hashtable functions for "registered" hashtables.  */
262
263
264
265 /* Hashtable definition and functions for vtbl_map_hash.  */
266
267 struct vtbl_map_hasher : nofree_ptr_hash <struct vtbl_map_node>
268 {
269   static inline hashval_t hash (const vtbl_map_node *);
270   static inline bool equal (const vtbl_map_node *, const vtbl_map_node *);
271 };
272
273 /* Returns a hash code for P.  */
274
275 inline hashval_t
276 vtbl_map_hasher::hash (const vtbl_map_node *p)
277 {
278   const struct vtbl_map_node n = *((const struct vtbl_map_node *) p);
279   return (hashval_t) IDENTIFIER_HASH_VALUE (n.class_name);
280 }
281
282 /* Returns nonzero if P1 and P2 are equal.  */
283
284 inline bool
285 vtbl_map_hasher::equal (const vtbl_map_node *p1, const vtbl_map_node *p2)
286 {
287   const struct vtbl_map_node n1 = *((const struct vtbl_map_node *) p1);
288   const struct vtbl_map_node n2 = *((const struct vtbl_map_node *) p2);
289   return (IDENTIFIER_HASH_VALUE (n1.class_name) ==
290           IDENTIFIER_HASH_VALUE (n2.class_name));
291 }
292
293 /* Here are the two structures into which we insert vtable map nodes.
294    We use two data structures because of the vastly different ways we need
295    to find the nodes for various tasks (see comments in vtable-verify.h
296    for more details.  */
297
298 typedef hash_table<vtbl_map_hasher> vtbl_map_table_type;
299 typedef vtbl_map_table_type::iterator vtbl_map_iterator_type;
300
301 /* Vtable map variable nodes stored in a hash table.  */
302 static vtbl_map_table_type *vtbl_map_hash;
303
304 /* Vtable map variable nodes stored in a vector.  */
305 vec<struct vtbl_map_node *> vtbl_map_nodes_vec;
306
307 /* Vector of mangled names for anonymous classes.  */
308 extern GTY(()) vec<tree, va_gc> *vtbl_mangled_name_types;
309 extern GTY(()) vec<tree, va_gc> *vtbl_mangled_name_ids;
310 vec<tree, va_gc> *vtbl_mangled_name_types;
311 vec<tree, va_gc> *vtbl_mangled_name_ids;
312
313 /* Look up class_type (a type decl for record types) in the vtbl_mangled_names_*
314    vectors.  This is a linear lookup.  Return the associated mangled name for
315    the class type.  This is for handling types from anonymous namespaces, whose
316    DECL_ASSEMBLER_NAME ends up being "<anon>", which is useless for our
317    purposes.
318
319    We use two vectors of trees to keep track of the mangled names:  One is a
320    vector of class types and the other is a vector of the mangled names.  The
321    assumption is that these two vectors are kept in perfect lock-step so that
322    vtbl_mangled_name_ids[i] is the mangled name for
323    vtbl_mangled_name_types[i].  */
324
325 static tree
326 vtbl_find_mangled_name (tree class_type)
327 {
328   tree result = NULL_TREE;
329   unsigned i;
330
331   if (!vtbl_mangled_name_types or !vtbl_mangled_name_ids)
332     return result;
333
334   if (vtbl_mangled_name_types->length() != vtbl_mangled_name_ids->length())
335     return result;
336
337   for (i = 0; i < vtbl_mangled_name_types->length(); ++i)
338     if ((*vtbl_mangled_name_types)[i] == class_type)
339       {
340         result = (*vtbl_mangled_name_ids)[i];
341         break;
342       }
343
344   return result;
345 }
346
347 /* Store a class type decl and its mangled name, for an anonymous RECORD_TYPE,
348    in the vtbl_mangled_names vector.  Make sure there is not already an
349    entry for the class type before adding it.  */
350
351 void
352 vtbl_register_mangled_name (tree class_type, tree mangled_name)
353 {
354   if (!vtbl_mangled_name_types)
355     vec_alloc (vtbl_mangled_name_types, 10);
356
357   if (!vtbl_mangled_name_ids)
358     vec_alloc (vtbl_mangled_name_ids, 10);
359
360   gcc_assert (vtbl_mangled_name_types->length() ==
361               vtbl_mangled_name_ids->length());
362     
363
364   if (vtbl_find_mangled_name (class_type) == NULL_TREE)
365     {
366       vec_safe_push (vtbl_mangled_name_types, class_type);
367       vec_safe_push (vtbl_mangled_name_ids, mangled_name);
368     }
369 }
370
371 /* Return vtbl_map node for CLASS_NAME  without creating a new one.  */
372
373 struct vtbl_map_node *
374 vtbl_map_get_node (tree class_type)
375 {
376   struct vtbl_map_node key;
377   struct vtbl_map_node **slot;
378
379   tree class_type_decl;
380   tree class_name;
381   unsigned int type_quals;
382
383   if (!vtbl_map_hash)
384     return NULL;
385
386   gcc_assert (TREE_CODE (class_type) == RECORD_TYPE);
387
388
389   /* Find the TYPE_DECL for the class.  */
390   class_type_decl = TYPE_NAME (class_type);
391
392   /* Verify that there aren't any qualifiers on the type.  */
393   type_quals = TYPE_QUALS (TREE_TYPE (class_type_decl));
394   gcc_assert (type_quals == TYPE_UNQUALIFIED);
395
396   /* Get the mangled name for the unqualified type.  */
397   gcc_assert (HAS_DECL_ASSEMBLER_NAME_P (class_type_decl));
398   class_name = DECL_ASSEMBLER_NAME (class_type_decl);
399
400   if (strstr (IDENTIFIER_POINTER (class_name), "<anon>") != NULL)
401     class_name = vtbl_find_mangled_name (class_type_decl);
402
403   key.class_name = class_name;
404   slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, NO_INSERT);
405   if (!slot)
406     return NULL;
407   return *slot;
408 }
409
410 /* Return vtbl_map node assigned to BASE_CLASS_TYPE.  Create new one
411    when needed.  */
412
413 struct vtbl_map_node *
414 find_or_create_vtbl_map_node (tree base_class_type)
415 {
416   struct vtbl_map_node key;
417   struct vtbl_map_node *node;
418   struct vtbl_map_node **slot;
419   tree class_type_decl;
420   unsigned int type_quals;
421
422   if (!vtbl_map_hash)
423     vtbl_map_hash = new vtbl_map_table_type (10);
424
425   /* Find the TYPE_DECL for the class.  */
426   class_type_decl = TYPE_NAME (base_class_type);
427
428   /* Verify that there aren't any type qualifiers on type.  */
429   type_quals = TYPE_QUALS (TREE_TYPE (class_type_decl));
430   gcc_assert (type_quals == TYPE_UNQUALIFIED);
431
432   gcc_assert (HAS_DECL_ASSEMBLER_NAME_P (class_type_decl));
433   key.class_name = DECL_ASSEMBLER_NAME (class_type_decl);
434
435   if (strstr (IDENTIFIER_POINTER (key.class_name), "<anon>") != NULL)
436     key.class_name = vtbl_find_mangled_name (class_type_decl);
437
438   slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, INSERT);
439
440   if (*slot)
441     return *slot;
442
443   node = XNEW (struct vtbl_map_node);
444   node->vtbl_map_decl = NULL_TREE;
445   node->class_name = key.class_name;
446   node->uid = num_vtable_map_nodes++;
447
448   node->class_info = XNEW (struct vtv_graph_node);
449   node->class_info->class_type = base_class_type;
450   node->class_info->class_uid = node->uid;
451   node->class_info->num_processed_children = 0;
452
453   (node->class_info->parents).create (4);
454   (node->class_info->children).create (4);
455
456   node->registered = new register_table_type (16);
457
458   node->is_used = false;
459
460   vtbl_map_nodes_vec.safe_push (node);
461   gcc_assert (vtbl_map_nodes_vec[node->uid] == node);
462
463   *slot = node;
464   return node;
465 }
466
467 /* End of hashtable functions for vtable_map variables hash table.   */
468
469 /* Given a gimple STMT, this function checks to see if the statement
470    is an assignment, the rhs of which is getting the vtable pointer
471    value out of an object.  (i.e. it's the value we need to verify
472    because its the vtable pointer that will be used for a virtual
473    call).  */
474
475 static bool
476 is_vtable_assignment_stmt (gimple *stmt)
477 {
478
479   if (gimple_code (stmt) != GIMPLE_ASSIGN)
480     return false;
481   else
482     {
483       tree lhs = gimple_assign_lhs (stmt);
484       tree rhs = gimple_assign_rhs1 (stmt);
485
486       if (TREE_CODE (lhs) != SSA_NAME)
487         return false;
488
489       if (TREE_CODE (rhs) != COMPONENT_REF)
490         return false;
491
492       if (! (TREE_OPERAND (rhs, 1))
493           || (TREE_CODE (TREE_OPERAND (rhs, 1)) != FIELD_DECL))
494         return false;
495
496       if (! DECL_VIRTUAL_P (TREE_OPERAND (rhs, 1)))
497         return false;
498     }
499
500     return true;
501 }
502
503 /* This function attempts to recover the declared class of an object
504    that is used in making a virtual call.  We try to get the type from
505    the type cast in the gimple assignment statement that extracts the
506    vtable pointer from the object (DEF_STMT).  The gimple statement
507    usually looks something like this:
508
509    D.2201_4 = MEM[(struct Event *)this_1(D)]._vptr.Event    */
510
511 static tree
512 extract_object_class_type (tree rhs)
513 {
514   tree result = NULL_TREE;
515
516   /* Try to find and extract the type cast from that stmt.  */
517   if (TREE_CODE (rhs) == COMPONENT_REF)
518     {
519       tree op0 = TREE_OPERAND (rhs, 0);
520       tree op1 = TREE_OPERAND (rhs, 1);
521
522       if (TREE_CODE (op1) == FIELD_DECL
523           && DECL_VIRTUAL_P (op1))
524         {
525           if (TREE_CODE (op0) == COMPONENT_REF
526               && TREE_CODE (TREE_OPERAND (op0, 0)) == MEM_REF
527               && TREE_CODE (TREE_TYPE (TREE_OPERAND (op0, 0)))== RECORD_TYPE)
528             result = TREE_TYPE (TREE_OPERAND (op0, 0));
529           else
530             result = TREE_TYPE (op0);
531         }
532       else if (TREE_CODE (op0) == COMPONENT_REF)
533         {
534           result = extract_object_class_type (op0);
535           if (result == NULL_TREE
536               && TREE_CODE (op1) == COMPONENT_REF)
537             result = extract_object_class_type (op1);
538         }
539     }
540
541   return result;
542 }
543
544 /* This function traces forward through the def-use chain of an SSA
545    variable to see if it ever gets used in a virtual function call.  It
546    returns a boolean indicating whether or not it found a virtual call in
547    the use chain.  */
548
549 static bool
550 var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth,
551                                 int *recursion_depth)
552 {
553   imm_use_iterator imm_iter;
554   bool found_vcall = false;
555   use_operand_p use_p;
556
557   if (TREE_CODE (lhs) != SSA_NAME)
558     return false;
559
560   if (*mem_ref_depth > 2)
561     return false;
562
563   if (*recursion_depth > 25)
564     /* If we've recursed this far the chances are pretty good that
565        we're not going to find what we're looking for, and that we've
566        gone down a recursion black hole. Time to stop.  */
567     return false;
568
569   *recursion_depth = *recursion_depth + 1;
570
571   /* Iterate through the immediate uses of the current variable.  If
572      it's a virtual function call, we're done.  Otherwise, if there's
573      an LHS for the use stmt, add the ssa var to the work list
574      (assuming it's not already in the list and is not a variable
575      we've already examined.  */
576
577   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
578     {
579       gimple *stmt2 = USE_STMT (use_p);
580
581       if (is_gimple_call (stmt2))
582         {
583           tree fncall = gimple_call_fn (stmt2);
584           if (fncall && TREE_CODE (fncall) == OBJ_TYPE_REF)
585             found_vcall = true;
586           else
587             return false;
588         }
589       else if (gimple_code (stmt2) == GIMPLE_PHI)
590         {
591           found_vcall = var_is_used_for_virtual_call_p
592                                                     (gimple_phi_result (stmt2),
593                                                      mem_ref_depth,
594                                                      recursion_depth);
595         }
596       else if (is_gimple_assign (stmt2))
597         {
598           tree rhs = gimple_assign_rhs1 (stmt2);
599           if (TREE_CODE (rhs) == ADDR_EXPR
600               || TREE_CODE (rhs) == MEM_REF)
601             *mem_ref_depth = *mem_ref_depth + 1;
602           
603           if (TREE_CODE (rhs) == COMPONENT_REF)
604             {
605               while (TREE_CODE (TREE_OPERAND (rhs, 0)) == COMPONENT_REF)
606                 rhs = TREE_OPERAND (rhs, 0);
607
608               if (TREE_CODE (TREE_OPERAND (rhs, 0)) == ADDR_EXPR
609                   || TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF)
610                 *mem_ref_depth = *mem_ref_depth + 1;
611             }
612
613           if (*mem_ref_depth < 3)
614             found_vcall = var_is_used_for_virtual_call_p
615                                                     (gimple_assign_lhs (stmt2),
616                                                      mem_ref_depth,
617                                                      recursion_depth);
618         }
619
620       else
621         break;
622
623       if (found_vcall)
624         return true;
625     }
626
627   return false;
628 }
629
630 /* Search through all the statements in a basic block (BB), searching
631    for virtual method calls.  For each virtual method dispatch, find
632    the vptr value used, and the statically declared type of the
633    object; retrieve the vtable map variable for the type of the
634    object; generate a call to __VLTVerifyVtablePointer; and insert the
635    generated call into the basic block, after the point where the vptr
636    value is gotten out of the object and before the virtual method
637    dispatch. Make the virtual method dispatch depend on the return
638    value from the verification call, so that subsequent optimizations
639    cannot reorder the two calls.  */
640
641 static void
642 verify_bb_vtables (basic_block bb)
643 {
644   gimple_seq stmts;
645   gimple *stmt = NULL;
646   gimple_stmt_iterator gsi_vtbl_assign;
647   gimple_stmt_iterator gsi_virtual_call;
648
649   stmts = bb_seq (bb);
650   gsi_virtual_call = gsi_start (stmts);
651   for (; !gsi_end_p (gsi_virtual_call); gsi_next (&gsi_virtual_call))
652     {
653       stmt = gsi_stmt (gsi_virtual_call);
654
655       /* Count virtual calls.  */
656       if (is_gimple_call (stmt))
657         {
658           tree fncall = gimple_call_fn (stmt);
659           if (fncall && TREE_CODE (fncall) == OBJ_TYPE_REF)
660             total_num_virtual_calls++;
661         }
662
663       if (is_vtable_assignment_stmt (stmt))
664         {
665           tree lhs = gimple_assign_lhs (stmt);
666           tree vtbl_var_decl = NULL_TREE;
667           struct vtbl_map_node *vtable_map_node;
668           tree vtbl_decl = NULL_TREE;
669           gcall *call_stmt;
670           const char *vtable_name = "<unknown>";
671           tree tmp0;
672           bool found;
673           int mem_ref_depth = 0;
674           int recursion_depth = 0;
675
676           /* Make sure this vptr field access is for a virtual call.  */
677           if (!var_is_used_for_virtual_call_p (lhs, &mem_ref_depth,
678                                                &recursion_depth))
679             continue;
680
681           /* Now we have found the virtual method dispatch and
682              the preceding access of the _vptr.* field... Next
683              we need to find the statically declared type of
684              the object, so we can find and use the right
685              vtable map variable in the verification call.  */
686           tree class_type = extract_object_class_type
687                                                    (gimple_assign_rhs1 (stmt));
688
689           gsi_vtbl_assign = gsi_for_stmt (stmt);
690
691           if (class_type
692               && (TREE_CODE (class_type) == RECORD_TYPE)
693               && TYPE_BINFO (class_type))
694             {
695               /* Get the vtable VAR_DECL for the type.  */
696               vtbl_var_decl = BINFO_VTABLE (TYPE_BINFO (class_type));
697
698               if (TREE_CODE (vtbl_var_decl) == POINTER_PLUS_EXPR)
699                 vtbl_var_decl = TREE_OPERAND (TREE_OPERAND (vtbl_var_decl, 0),
700                                               0);
701
702               gcc_assert (vtbl_var_decl);
703
704               vtbl_decl = vtbl_var_decl;
705               vtable_map_node = vtbl_map_get_node
706                                                (TYPE_MAIN_VARIANT (class_type));
707
708               gcc_assert (verify_vtbl_ptr_fndecl);
709
710               /* Given the vtable pointer for the base class of the
711                  object, build the call to __VLTVerifyVtablePointer to
712                  verify that the object's vtable pointer (contained in
713                  lhs) is in the set of valid vtable pointers for the
714                  base class.  */
715
716               if (vtable_map_node && vtable_map_node->vtbl_map_decl)
717                 {
718                   vtable_map_node->is_used = true;
719                   vtbl_var_decl = vtable_map_node->vtbl_map_decl;
720
721                   if (VAR_P (vtbl_decl))
722                     vtable_name = IDENTIFIER_POINTER (DECL_NAME (vtbl_decl));
723
724                   /* Call different routines if we are interested in
725                      trace information to debug problems.  */
726                   if (flag_vtv_debug)
727                     {
728                       int len1 = IDENTIFIER_LENGTH
729                                                  (DECL_NAME (vtbl_var_decl));
730                       int len2 = strlen (vtable_name);
731
732                       call_stmt = gimple_build_call
733                                      (verify_vtbl_ptr_fndecl, 4,
734                                       build1 (ADDR_EXPR,
735                                                 TYPE_POINTER_TO
736                                                   (TREE_TYPE (vtbl_var_decl)),
737                                               vtbl_var_decl),
738                                       lhs,
739                                       build_string_literal
740                                                   (len1 + 1,
741                                                    IDENTIFIER_POINTER
742                                                        (DECL_NAME
743                                                             (vtbl_var_decl))),
744                                       build_string_literal (len2 + 1,
745                                                             vtable_name));
746                     }
747                   else
748                     call_stmt = gimple_build_call
749                                      (verify_vtbl_ptr_fndecl, 2,
750                                       build1 (ADDR_EXPR,
751                                                 TYPE_POINTER_TO
752                                                   (TREE_TYPE (vtbl_var_decl)),
753                                                  vtbl_var_decl),
754                                       lhs);
755
756
757                   /* Create a new SSA_NAME var to hold the call's
758                      return value, and make the call_stmt use the
759                      variable for that purpose.  */
760                   tmp0 = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "VTV");
761                   gimple_call_set_lhs (call_stmt, tmp0);
762                   update_stmt (call_stmt);
763
764                   /* Replace all uses of lhs with tmp0. */
765                   found = false;
766                   imm_use_iterator iterator;
767                   gimple *use_stmt;
768                   FOR_EACH_IMM_USE_STMT (use_stmt, iterator, lhs)
769                     {
770                       use_operand_p use_p;
771                       if (use_stmt == call_stmt)
772                         continue;
773                       FOR_EACH_IMM_USE_ON_STMT (use_p, iterator)
774                         SET_USE (use_p, tmp0);
775                       update_stmt (use_stmt);
776                       found = true;
777                     }
778
779                   gcc_assert (found);
780
781                   /* Insert the new verification call just after the
782                      statement that gets the vtable pointer out of the
783                      object.  */
784                   gcc_assert (gsi_stmt (gsi_vtbl_assign) == stmt);
785                   gsi_insert_after (&gsi_vtbl_assign, call_stmt,
786                                     GSI_NEW_STMT);
787
788                   any_verification_calls_generated = true;
789                   total_num_verified_vcalls++;
790                 }
791             }
792         }
793     }
794 }
795
796 /* Definition of this optimization pass.  */
797
798 namespace {
799
800 const pass_data pass_data_vtable_verify =
801 {
802   GIMPLE_PASS, /* type */
803   "vtable-verify", /* name */
804   OPTGROUP_NONE, /* optinfo_flags */
805   TV_VTABLE_VERIFICATION, /* tv_id */
806   ( PROP_cfg | PROP_ssa ), /* properties_required */
807   0, /* properties_provided */
808   0, /* properties_destroyed */
809   0, /* todo_flags_start */
810   TODO_update_ssa, /* todo_flags_finish */
811 };
812
813 class pass_vtable_verify : public gimple_opt_pass
814 {
815 public:
816   pass_vtable_verify (gcc::context *ctxt)
817     : gimple_opt_pass (pass_data_vtable_verify, ctxt)
818   {}
819
820   /* opt_pass methods: */
821   virtual bool gate (function *) { return (flag_vtable_verify); }
822   virtual unsigned int execute (function *);
823
824 }; // class pass_vtable_verify
825
826 /* Loop through all the basic blocks in the current function, passing them to
827    verify_bb_vtables, which searches for virtual calls, and inserts
828    calls to __VLTVerifyVtablePointer.  */
829
830 unsigned int
831 pass_vtable_verify::execute (function *fun)
832 {
833   unsigned int ret = 1;
834   basic_block bb;
835
836   FOR_ALL_BB_FN (bb, fun)
837       verify_bb_vtables (bb);
838
839   return ret;
840 }
841
842 } // anon namespace
843
844 gimple_opt_pass *
845 make_pass_vtable_verify (gcc::context *ctxt)
846 {
847   return new pass_vtable_verify (ctxt);
848 }
849
850 #include "gt-vtable-verify.h"