public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/arsenic/heads/analyzer_extension)] analyzer: refactor analyzer to detect calls via function pointer
@ 2021-07-04 12:54 Ankur saini
  0 siblings, 0 replies; only message in thread
From: Ankur saini @ 2021-07-04 12:54 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:8091a33c6d4ca99f9c46204d9d3743ce6ee6ea4a

commit 8091a33c6d4ca99f9c46204d9d3743ce6ee6ea4a
Author: Ankur Saini <arsenic@sourceware.org>
Date:   Sun Jul 4 18:01:10 2021 +0530

    analyzer: refactor analyzer to detect calls via function pointer
    
        2021-07-4  Ankur Saini  <arsenic@sourceware.org>
    
            gcc/analyzer/
    
                            * engine.cc (exploded_graph::process_node): handle calls via function pointers.
                            * program-point.cc (program_point::push_to_call_stack): New function.
                            * program-point.h (program_point::push_to_call_stack): New decl.
                            * program-state.cc (program_state::push_call): New function.
                            * program-state.h (program_state::push_call): New decl.
                            * region-model.cc (region_model::update_for_gcall): New function.
                            * region-model.h (region_model::update_for_gcall): New decl.
                            * supergraph.cc (supergraph::supergraph): split nodes even for function that doesn't have a cgraph_edge
                            * call-string.cc (call_string::validate): fix validation process

Diff:
---
 gcc/analyzer/call-string.cc   |  2 +-
 gcc/analyzer/engine.cc        | 41 +++++++++++++++++++++++++++++++++++++++++
 gcc/analyzer/program-point.cc | 10 ++++++++++
 gcc/analyzer/program-point.h  |  3 ++-
 gcc/analyzer/program-state.cc | 22 ++++++++++++++++++++++
 gcc/analyzer/program-state.h  |  4 ++++
 gcc/analyzer/region-model.cc  | 24 ++++++++++++++++++++++++
 gcc/analyzer/region-model.h   |  3 +++
 gcc/analyzer/supergraph.cc    | 31 ++++++++++++++++++++++++++-----
 9 files changed, 133 insertions(+), 7 deletions(-)

diff --git a/gcc/analyzer/call-string.cc b/gcc/analyzer/call-string.cc
index 50dfb9e8c7c..a7cde397a8f 100644
--- a/gcc/analyzer/call-string.cc
+++ b/gcc/analyzer/call-string.cc
@@ -249,7 +249,7 @@ call_string::validate () const
   FOR_EACH_VEC_ELT (m_supernodes, i, e)
     if (i > 0)
     {
-      gcc_assert (e->second->get_function () == m_supernodes[i - 1]->second->get_function());
+      gcc_assert (e->second->get_function () == m_supernodes[i - 1]->first->get_function());
     }
 }
 
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 4456d9b828b..5d981963b7e 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -3194,6 +3194,47 @@ exploded_graph::process_node (exploded_node *node)
 						 point.get_call_string ());
 	    program_state next_state (state);
 	    uncertainty_t uncertainty;
+
+      // check if now the analyzer know about the call via function pointer or not
+      if (succ->m_kind == SUPEREDGE_INTRAPROCEDURAL_CALL && !(succ->get_any_callgraph_edge()))
+      {    
+        const program_point *this_point = &node->get_point();
+        const program_state *this_state = &node->get_state ();
+        const gcall *call = this_point->get_supernode ()->get_final_call ();  
+
+        impl_region_model_context ctxt (*this,
+          node, 
+          this_state, 
+          &next_state, 
+          &uncertainty,
+          this_point->get_stmt());
+
+        region_model *model = this_state->m_region_model;
+        tree fn_decl = model->get_fndecl_for_call(call,&ctxt);
+        function *fun = DECL_STRUCT_FUNCTION(fn_decl);
+        if(fun)
+        {
+          const supergraph *sg = &(this->get_supergraph());
+          supernode * sn_entry =  sg->get_node_for_function_entry (fun);
+          supernode * sn_exit =  sg->get_node_for_function_exit (fun);
+          //logger->log("found supernode = SN: %i",sn->m_index);
+
+          program_point new_point = program_point::before_supernode (sn_entry, NULL,
+             point.get_call_string ());
+
+          // update callstring for returing back
+          new_point.push_to_call_stack (sn_exit,this_point->get_supernode());
+
+          next_state.push_call(*this, node, call, &uncertainty);
+
+          if (next_state.m_valid)
+          {
+            exploded_node *enode = get_or_create_node (new_point, next_state, node);
+            if (enode)
+              add_edge (node,enode, NULL);
+          }
+        }
+      }
 	    if (!node->on_edge (*this, succ, &next_point, &next_state,
 				&uncertainty))
 	      {
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
index 40afafc7ad0..f2ba7463c79 100644
--- a/gcc/analyzer/program-point.cc
+++ b/gcc/analyzer/program-point.cc
@@ -323,6 +323,16 @@ program_point::to_json () const
   return point_obj;
 }
 
+/* update the callstack to represent a call from caller to callee 
+   genrally used to push a custom call to a perticular program point 
+   where we don't have a superedge representing the call.  */
+void 
+program_point::push_to_call_stack(const supernode *caller,
+      const supernode *callee)
+{
+  m_call_string.push_call(callee,caller);
+}
+
 /* Generate a hash value for this program_point.  */
 
 hashval_t
diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h
index 5f86745cd1e..e08cebd750d 100644
--- a/gcc/analyzer/program-point.h
+++ b/gcc/analyzer/program-point.h
@@ -293,7 +293,8 @@ public:
   }
 
   bool on_edge (exploded_graph &eg, const superedge *succ);
-
+  void push_to_call_stack(const supernode *caller,
+      const supernode *callee);
   void validate () const;
 
   /* For before_stmt, go to next stmt.  */
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 6d60c0449ce..1d25bc15212 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -1000,6 +1000,28 @@ program_state::on_edge (exploded_graph &eg,
   return true;
 }
 
+/* Update this program_state to reflect a call to function
+   represented by CALL_STMT.
+   currently used only when the call doesn't have a superedge representing 
+   the call ( like call via a function pointer )  */
+void
+program_state::push_call(exploded_graph &eg,
+      exploded_node *enode,
+      const gcall *call_stmt,
+      uncertainty_t *uncertainty)
+{
+  /* Update state.  */
+  const program_point &point = enode->get_point ();
+  const gimple *last_stmt = point.get_supernode ()->get_last_stmt ();
+
+  impl_region_model_context ctxt (eg, enode,
+          &enode->get_state (),
+          this,
+          uncertainty,
+          last_stmt);
+  m_region_model->update_for_gcall(call_stmt, &ctxt);
+}
+
 /* Generate a simpler version of THIS, discarding state that's no longer
    relevant at POINT.
    The idea is that we're more likely to be able to consolidate
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index f16fe6ba984..ef52de4f63f 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -215,6 +215,10 @@ public:
 
   void push_frame (const extrinsic_state &ext_state, function *fun);
   function * get_current_function () const;
+  void push_call(exploded_graph &eg,
+      exploded_node *enode,
+      const gcall *call_stmt,
+      uncertainty_t *uncertainty);
 
   bool on_edge (exploded_graph &eg,
 		exploded_node *enode,
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 4fb6bc9f747..dbaab3b770a 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -2875,6 +2875,30 @@ region_model::update_for_call_superedge (const call_superedge &call_edge,
   push_frame (call_edge.get_callee_function (), &arg_svals, ctxt);
 }
 
+/* Push a new frame_region on to the stack region.
+   works in similar manner of that of region_model::update_for_call_superedge()
+   but it get the call info from CALL_STMT instead from a suerpedge and 
+   is availabe publicically   */
+void
+region_model::update_for_gcall (const gcall *call_stmt,
+           region_model_context *ctxt)
+{
+  /* Build a vec of argument svalues, using the current top
+     frame for resolving tree expressions.  */
+  auto_vec<const svalue *> arg_svals (gimple_call_num_args (call_stmt));
+
+  for (unsigned i = 0; i < gimple_call_num_args (call_stmt); i++)
+    {
+      tree arg = gimple_call_arg (call_stmt, i);
+      arg_svals.quick_push (get_rvalue (arg, ctxt));
+    }
+
+  /* get the function * from the call */
+  tree fn_decl = get_fndecl_for_call(call_stmt,ctxt);
+  function *fun = DECL_STRUCT_FUNCTION(fn_decl);
+  push_frame (fun, &arg_svals, ctxt);
+}
+
 /* Pop the top-most frame_region from the stack, and copy the return
    region's values (if any) into the region for the lvalue of the LHS of
    the call (if any).  */
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index b42852b3db9..fd1ab6efc6d 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -574,6 +574,9 @@ class region_model
 			      region_model_context *ctxt,
 			      rejected_constraint **out);
 
+  void update_for_gcall (const gcall *call_stmt,
+           region_model_context *ctxt);
+
   const region *push_frame (function *fun, const vec<const svalue *> *arg_sids,
 			    region_model_context *ctxt);
   const frame_region *get_current_frame () const { return m_current_frame; }
diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index 8611d0f8689..4792592cf86 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -183,11 +183,32 @@ supergraph::supergraph (logger *logger)
 	      m_stmt_to_node_t.put (stmt, node_for_stmts);
 	      m_stmt_uids.make_uid_unique (stmt);
 	      if (cgraph_edge *edge = supergraph_call_edge (fun, stmt))
-		{
-		  m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts);
-		  node_for_stmts = add_node (fun, bb, as_a <gcall *> (stmt), NULL);
-		  m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts);
-		}
+    		{
+    		  m_cgraph_edge_to_caller_prev_node.put(edge, node_for_stmts);
+    		  node_for_stmts = add_node (fun, bb, as_a <gcall *> (stmt), NULL);
+    		  m_cgraph_edge_to_caller_next_node.put (edge, node_for_stmts);
+    		}
+        else
+        {
+          // maybe call is via a function pointer
+          gcall *call = dyn_cast<gcall *> (stmt);
+          if (call)
+          {
+            cgraph_edge *edge = cgraph_node::get (fun->decl)->get_edge (stmt);
+            if (!edge || !edge->callee)
+            {
+              supernode *old_node_for_stmts = node_for_stmts;
+              node_for_stmts = add_node (fun, bb, call, NULL);
+
+              // add edge for such calls right away as it would not be added later
+              superedge *sedge = new callgraph_superedge (old_node_for_stmts,
+                  node_for_stmts,
+                  SUPEREDGE_INTRAPROCEDURAL_CALL,
+                  NULL);
+              add_edge (sedge);
+            }
+          }
+        }
 	    }
 
 	  m_bb_to_final_node.put (bb, node_for_stmts);


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-04 12:54 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-04 12:54 [gcc(refs/users/arsenic/heads/analyzer_extension)] analyzer: refactor analyzer to detect calls via function pointer Ankur saini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).