[PATCH smatch-devel 3/5] smatch: track functions variables are passed to
Harshit Mogalapalli <[email protected]>
| Newsgroups | org.kernel.vger.smatch |
|---|---|
| Message-ID | <[email protected]> |
Record every direct variable argument handled by FUNCTION_CALL_HOOK. Keep the call expression, zero-based parameter index, and previous sm_state in a linked smatch_state data payload. Expose print_passed_to() to walk linear and merged histories. Deduplicate shared states and print each function with its $N index. Assisted-by: Codex:5.6 Signed-off-by: Harshit Mogalapalli <[email protected]> --- Makefile | 1 + smatch.h | 1 + smatch_modules.h | 1 + smatch_passed_to.c | 111 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 smatch_passed_to.c diff --git a/Makefile b/Makefile index eabaef4c8e01..85517e4660e6 100644 --- a/Makefile +++ b/Makefile @@ -353,6 +353,7 @@ SMATCH_OBJS += smatch_parents.o SMATCH_OBJS += smatch_parse_call_math.o SMATCH_OBJS += smatch_parsed_conditions.o SMATCH_OBJS += smatch_passes_array_size.o +SMATCH_OBJS += smatch_passed_to.o SMATCH_OBJS += smatch_points_to_container.o SMATCH_OBJS += smatch_points_to_user_data.o SMATCH_OBJS += smatch_points_to_host_data.o diff --git a/smatch.h b/smatch.h index 681be3354bc1..58edc256965a 100644 --- a/smatch.h +++ b/smatch.h @@ -1050,6 +1050,7 @@ void __call_array_initialized_hooks(struct expression *array, int nr); /* smatch_function_hooks.c */ const char *get_fn_name(struct expression *fn); struct expression *get_current_fn_call(void); +void print_passed_to(struct expression *expr); void add_fake_call_after_return(struct expression *call); struct expression *get_real_call(void); struct expression *get_this_fn_call(void); diff --git a/smatch_modules.h b/smatch_modules.h index c8fd14f5dca0..dbc8fa4dd0dc 100644 --- a/smatch_modules.h +++ b/smatch_modules.h @@ -107,6 +107,7 @@ CK(smatch_parameter_names) CK(smatch_param_filter) CK(smatch_param_to_mtag_data) CK(smatch_parse_call_math) +CK(smatch_passed_to) CK(smatch_points_to_container) CK(smatch_points_to_host_data) CK(smatch_points_to_user_data) diff --git a/smatch_passed_to.c b/smatch_passed_to.c new file mode 100644 index 000000000000..06b1e2a77fec --- /dev/null +++ b/smatch_passed_to.c @@ -0,0 +1,111 @@ +#include "smatch.h" + +static int my_id; + +struct smatch_state_data { + struct sm_state *previous; + struct expression *expr; + int param; +}; + +static struct smatch_state *alloc_passed_to_state(const char *fn_name, + struct expression *expr, + int param, + struct sm_state *previous) +{ + struct smatch_state_data *data; + struct smatch_state *state; + + state = __alloc_smatch_state(sizeof(*data)); + data = (struct smatch_state_data *)(state + 1); + + state->name = alloc_sname(fn_name); + state->data = data; + data->previous = previous; + data->expr = expr; + data->param = param; + + return state; +} + +static void save_passed_to(const char *fn_name, struct expression *expr, int param, + struct expression *arg) +{ + struct smatch_state *state; + struct sm_state *previous; + struct symbol *sym; + char *name; + + name = expr_to_var_sym(arg, &sym); + if (!name || !sym) + goto free; + + previous = get_sm_state(my_id, name, sym); + state = alloc_passed_to_state(fn_name, expr, param, previous); + set_state(my_id, name, sym, state); +free: + free_string(name); +} + +static void match_call(struct expression *expr) +{ + struct expression *arg; + char *fn_name; + int param = -1; + + if (sym_name_is(expr->fn, "__smatch_passed_to")) + return; + + fn_name = expr_to_str(expr->fn); + if (!fn_name) + return; + + FOR_EACH_PTR(expr->args, arg) { + save_passed_to(fn_name, expr, ++param, arg); + } END_FOR_EACH_PTR(arg); + + free_string(fn_name); +} + +static void print_passed_to_sm(struct sm_state *sm, struct state_list **printed) +{ + struct smatch_state_data *data; + char *fn_name; + + if (!sm) + return; + if (lookup_ptr_list_entry((struct ptr_list *)*printed, sm)) + return; + add_ptr_list(printed, sm); + + data = sm->state->data; + if (!data) { + print_passed_to_sm(sm->left, printed); + print_passed_to_sm(sm->right, printed); + return; + } + + print_passed_to_sm(data->previous, printed); + + fn_name = expr_to_str(data->expr->fn); + if (!fn_name) + return; + sm_msg("passed to %s $%d", fn_name, data->param); + free_string(fn_name); +} + +void print_passed_to(struct expression *expr) +{ + struct state_list *printed = NULL; + + print_passed_to_sm(get_sm_state_expr(my_id, expr), &printed); + free_slist(&printed); +} + +void smatch_passed_to(int id) +{ + my_id = id; + + set_dynamic_states(my_id); + add_hook(&match_call, FUNCTION_CALL_HOOK); +} -- 2.52.0