/* * Copyright (C) 2021 Oracle. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt */ /* * This module answers the question: * is_probe_function() * called_from_probe() which returns 1 for yes, -1 for maybe and 0 for no. * */ #include "smatch.h" static int my_id; STATE(from_probe); STATE(maybe); static unsigned long is_probe_fn; bool is_probe_function(void) { return is_probe_fn; } int called_from_probe(void) { struct smatch_state *state; if (is_probe_function()) return 1; state = get_state(my_id, "from_probe", NULL); if (state == &from_probe) return 1; if (state == &maybe) return -1; return 0; } static struct smatch_state *merge_func(struct smatch_state *s1, struct smatch_state *s2) { return &maybe; } static void match_probe_call(struct expression *expr) { char *name; name = get_member_name(expr); if (!name) return; if (strstr(name, "->probe")) sql_insert_caller_info(expr, PROBE_FN, -1, "", ""); free_string(name); } static void select_probe_fn(const char *name, struct symbol *sym, char *key, char *value) { is_probe_fn = 1; } static void match_call_info(struct expression *expr) { int call; call = called_from_probe(); if (!call) return; sql_insert_caller_info(expr, CALLED_FROM_PROBE, -1, "", (call == 1) ? "y" : "m"); } static void select_from_probe(const char *name, struct symbol *sym, char *key, char *value) { if (strcmp(value, "y") == 0) set_state(my_id, "from_probe", NULL, &from_probe); else set_state(my_id, "from_probe", NULL, &maybe); } void register_kernel_probe(int id) { my_id = id; if (option_project != PROJ_KERNEL) return; add_merge_hook(my_id, &merge_func); add_function_data(&is_probe_fn); add_hook(&match_probe_call, FUNCTION_CALL_HOOK); select_caller_info_hook(&select_probe_fn, PROBE_FN); add_hook(&match_call_info, FUNCTION_CALL_HOOK); select_caller_info_hook(&select_from_probe, CALLED_FROM_PROBE); }