From a43db08f773bef2ca72353af411d16449c94d16c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 6 Nov 2014 16:04:43 +0300 Subject: [PATCH] capable: track which functions are only called under capable() I don't use this at all currently but it seemed like a useful thing. Signed-off-by: Dan Carpenter --- check_capable.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ check_list.h | 2 + smatch.h | 2 + smatch_data/db/smdb.py | 2 + 4 files changed, 130 insertions(+) create mode 100644 check_capable.c diff --git a/check_capable.c b/check_capable.c new file mode 100644 index 00000000..7366fa9c --- /dev/null +++ b/check_capable.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2014 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 + */ + +#include "smatch.h" +#include "smatch_slist.h" + +STATE(capable); + +static int capable_id; +static int ns_capable_id; + +static void match_capable(const char *fn, struct expression *expr, void *_param) +{ + struct expression *arg; + sval_t sval; + char buf[32]; + + arg = get_argument_from_call_expr(expr->args, 0); + if (!get_implied_value(arg, &sval)) + return; + snprintf(buf, sizeof(buf), "%s", sval_to_str(sval)); + set_state(capable_id, buf, NULL, &capable); +} + +static void match_ns_capable(const char *fn, struct expression *expr, void *_param) +{ + struct expression *arg; + sval_t sval; + char buf[32]; + + if (get_function() && strcmp(get_function(), "capable") == 0) + return; + + arg = get_argument_from_call_expr(expr->args, 1); + if (!get_implied_value(arg, &sval)) + return; + snprintf(buf, sizeof(buf), "%s", sval_to_str(sval)); + set_state(ns_capable_id, buf, NULL, &capable); +} + +static void save_call_info(struct expression *call) +{ + struct sm_state *sm; + + FOR_EACH_MY_SM(capable_id, __get_cur_stree(), sm) { + if (sm->state == &capable) + sql_insert_caller_info(call, CAPABLE, 0, sm->name, ""); + } END_FOR_EACH_SM(sm); + + FOR_EACH_MY_SM(ns_capable_id, __get_cur_stree(), sm) { + if (sm->state == &capable) + sql_insert_caller_info(call, NS_CAPABLE, 0, sm->name, ""); + } END_FOR_EACH_SM(sm); +} + +static void save_return_info(int return_id, char *return_ranges, struct expression *expr) +{ + struct sm_state *sm; + + FOR_EACH_MY_SM(capable_id, __get_cur_stree(), sm) { + if (sm->state == &capable) + sql_insert_return_states(return_id, return_ranges, + CAPABLE, 0, sm->name, ""); + } END_FOR_EACH_SM(sm); + + FOR_EACH_MY_SM(ns_capable_id, __get_cur_stree(), sm) { + if (sm->state == &capable) + sql_insert_return_states(return_id, return_ranges, + CAPABLE, 0, sm->name, ""); + } END_FOR_EACH_SM(sm); +} + +static void set_db_capable(const char *name, struct symbol *sym, char *key, char *value) +{ + char buf[32]; + + snprintf(buf, sizeof(buf), "%s", key); + set_state(capable_id, buf, NULL, &capable); +} + +static void set_db_ns_capable(const char *name, struct symbol *sym, char *key, char *value) +{ + char buf[32]; + + snprintf(buf, sizeof(buf), "%s", key); + set_state(ns_capable_id, buf, NULL, &capable); +} + +void check_capable(int id) +{ + if (option_project != PROJ_KERNEL) + return; + + capable_id = id; + add_function_hook("capable", &match_capable, INT_PTR(0)); + + add_hook(&save_call_info, FUNCTION_CALL_HOOK); + add_split_return_callback(save_return_info); + select_caller_info_hook(set_db_capable, CAPABLE); +} + +void check_ns_capable(int id) +{ + if (option_project != PROJ_KERNEL) + return; + + ns_capable_id = id; + add_function_hook("ns_capable", &match_ns_capable, INT_PTR(0)); + select_caller_info_hook(set_db_ns_capable, NS_CAPABLE); +} diff --git a/check_list.h b/check_list.h index dcd744bc..9789ab2c 100644 --- a/check_list.h +++ b/check_list.h @@ -123,6 +123,8 @@ CK(check_wait_for_common) CK(check_bogus_irqrestore) CK(check_buf_comparison) CK(check_buf_comparison_links) +CK(check_capable) +CK(check_ns_capable) /* wine specific stuff */ CK(check_wine_filehandles) diff --git a/smatch.h b/smatch.h index 4e0fe4b5..f5ec1d94 100644 --- a/smatch.h +++ b/smatch.h @@ -585,6 +585,8 @@ enum info_type { FUZZY_MAX = 1015, STR_LEN = 1016, ARRAY_LEN = 1017, + CAPABLE = 1018, + NS_CAPABLE = 1019, /* put random temporary stuff in the 7000-7999 range for testing */ USER_DATA2 = 9017, diff --git a/smatch_data/db/smdb.py b/smatch_data/db/smdb.py index 426fc39d..765b0180 100755 --- a/smatch_data/db/smdb.py +++ b/smatch_data/db/smdb.py @@ -65,6 +65,8 @@ db_types = { 0: "INTERNAL", 1014: "DATA_SOURCE", 1015: "FUZZY_MAX", 1016: "STR_LEN", + 1018: "CAPABLE", + 1019: "NS_CAPABLE", }; def type_to_str(type_int): -- 2.11.4.GIT