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).