diff options
Diffstat (limited to 'usr/src')
62 files changed, 1153 insertions, 382 deletions
diff --git a/usr/src/tools/smatch/Makefile b/usr/src/tools/smatch/Makefile index bc92591526..4b2c909785 100644 --- a/usr/src/tools/smatch/Makefile +++ b/usr/src/tools/smatch/Makefile @@ -20,7 +20,7 @@ # PROG = smatch -SPARSE_VERSION = 0.6.1-rc1-il-4 +SPARSE_VERSION = 0.6.1-rc1-il-5 include ../Makefile.tools @@ -230,6 +230,7 @@ SMATCH_DB_DATA += mtag_alias.schema SMATCH_DB_DATA += type_size.schema SMATCH_DB_DATA += fn_ptr_data_link.schema SMATCH_DB_DATA += mtag_data.schema +SMATCH_DB_DATA += mtag_info.schema SMATCH_DB_DATA += type_value.schema ROOTONBLDDATAFILES = $(SMATCH_DATA:%=$(SMATCHDATADIR)/smatch_data/%) diff --git a/usr/src/tools/smatch/src/Makefile b/usr/src/tools/smatch/src/Makefile index bc8b3071a1..7cd1db3039 100644 --- a/usr/src/tools/smatch/src/Makefile +++ b/usr/src/tools/smatch/src/Makefile @@ -1,4 +1,4 @@ -VERSION=0.6.1-rc1-il-4 +VERSION=0.6.1-rc1-il-5 ######################################################################## # The following variables can be overwritten from the command line diff --git a/usr/src/tools/smatch/src/check_all_func_returns.c b/usr/src/tools/smatch/src/check_all_func_returns.c index f9d774499c..1ff50433d5 100644 --- a/usr/src/tools/smatch/src/check_all_func_returns.c +++ b/usr/src/tools/smatch/src/check_all_func_returns.c @@ -74,7 +74,7 @@ static void check_func_return(struct expression *expr) stmt = last_ptr_list((struct ptr_list *)big_statement_stack); - if (stmt->type == STMT_EXPRESSION && stmt->expression == expr) + if (stmt && stmt->type == STMT_EXPRESSION && stmt->expression == expr) sm_error("unchecked function return '%s'", expr_to_str(expr->fn)); } diff --git a/usr/src/tools/smatch/src/check_allocating_enough_data.c b/usr/src/tools/smatch/src/check_allocating_enough_data.c index 12cb72bf23..79b3295195 100644 --- a/usr/src/tools/smatch/src/check_allocating_enough_data.c +++ b/usr/src/tools/smatch/src/check_allocating_enough_data.c @@ -23,6 +23,7 @@ static void db_returns_buf_size(struct expression *expr, int param, char *unused struct symbol *left_type, *right_type; int bytes; sval_t sval; + char *str; if (expr->type != EXPR_ASSIGNMENT) return; @@ -42,7 +43,10 @@ static void db_returns_buf_size(struct expression *expr, int param, char *unused return; if (sval.uvalue >= bytes) return; - sm_error("not allocating enough data %d vs %s", bytes, sval_to_str(sval)); + + str = expr_to_str(expr->left); + sm_error("not allocating enough for = '%s' %d vs %s", str, bytes, sval_to_str(sval)); + free_string(str); } void check_allocating_enough_data(int id) diff --git a/usr/src/tools/smatch/src/check_atomic_inc_dec.c b/usr/src/tools/smatch/src/check_atomic_inc_dec.c index 6474323eac..c83dc893b2 100644 --- a/usr/src/tools/smatch/src/check_atomic_inc_dec.c +++ b/usr/src/tools/smatch/src/check_atomic_inc_dec.c @@ -15,6 +15,8 @@ * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt */ +#include <ctype.h> + #include "smatch.h" #include "smatch_extra.h" #include "smatch_slist.h" @@ -25,12 +27,72 @@ STATE(inc); STATE(orig); STATE(dec); +static struct smatch_state *unmatched_state(struct sm_state *sm) +{ + if (parent_is_gone_var_sym(sm->name, sm->sym)) + return sm->state; + return &undefined; +} + +static struct stree *start_states; +static struct stree_stack *saved_stack; +static void set_start_state(const char *name, struct symbol *sym, struct smatch_state *start) +{ + struct smatch_state *orig; + + orig = get_state_stree(start_states, my_id, name, sym); + if (!orig) + set_state_stree(&start_states, my_id, name, sym, start); + else if (orig != start) + set_state_stree(&start_states, my_id, name, sym, &undefined); +} + +static struct sm_state *get_best_match(const char *key) +{ + struct sm_state *sm; + struct sm_state *match; + int cnt = 0; + int start_pos, state_len, key_len, chunks, i; + + if (strncmp(key, "$->", 3) == 0) + key += 3; + + key_len = strlen(key); + chunks = 0; + for (i = key_len - 1; i > 0; i--) { + if (key[i] == '>' || key[i] == '.') + chunks++; + if (chunks == 2) { + key += (i + 1); + key_len = strlen(key); + break; + } + } + + FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) { + state_len = strlen(sm->name); + if (state_len < key_len) + continue; + start_pos = state_len - key_len; + if ((start_pos == 0 || !isalnum(sm->name[start_pos - 1])) && + strcmp(sm->name + start_pos, key) == 0) { + cnt++; + match = sm; + } + } END_FOR_EACH_SM(sm); + + if (cnt == 1) + return match; + return NULL; +} + static void db_inc_dec(struct expression *expr, int param, const char *key, const char *value, int inc_dec) { - struct smatch_state *start_state; + struct sm_state *start_sm; struct expression *arg; char *name; struct symbol *sym; + bool free_at_end = true; while (expr->type == EXPR_ASSIGNMENT) expr = strip_expr(expr->right); @@ -45,23 +107,36 @@ static void db_inc_dec(struct expression *expr, int param, const char *key, cons if (!name || !sym) goto free; - start_state = get_state(my_id, name, sym); + start_sm = get_sm_state(my_id, name, sym); + if (!start_sm && inc_dec == ATOMIC_DEC) { + start_sm = get_best_match(key); + if (start_sm) { + free_string(name); + free_at_end = false; + name = (char *)start_sm->name; + sym = start_sm->sym; + } + } if (inc_dec == ATOMIC_INC) { -// if (start_state == &inc) -// sm_error("XXX double increment '%s'", name); + if (!start_sm) + set_start_state(name, sym, &dec); +// set_refcount_inc(name, sym); set_state(my_id, name, sym, &inc); } else { -// if (start_state == &dec) -// sm_error("XXX double decrement '%s'", name); - if (start_state == &inc) +// set_refcount_dec(name, sym); + if (!start_sm) + set_start_state(name, sym, &inc); + + if (start_sm && start_sm->state == &inc) set_state(my_id, name, sym, &orig); else set_state(my_id, name, sym, &dec); } free: - free_string(name); + if (free_at_end) + free_string(name); } static void db_inc(struct expression *expr, int param, char *key, char *value) @@ -123,6 +198,8 @@ static void match_return_info(int return_id, char *return_ranges, struct express if (sm->state != &inc && sm->state != &dec) continue; + if (parent_is_gone_var_sym(sm->name, sm->sym)) + continue; param = get_param_num_from_sym(sm->sym); if (param < 0) continue; @@ -136,13 +213,13 @@ static void match_return_info(int return_id, char *return_ranges, struct express } enum { - NEGATIVE, ZERO, POSITIVE, + EMPTY, NEGATIVE, ZERO, POSITIVE, NUM_BUCKETS }; static int success_fail_positive(struct range_list *rl) { if (!rl) - return ZERO; + return EMPTY; if (sval_is_negative(rl_min(rl))) return NEGATIVE; @@ -157,31 +234,49 @@ static void check_counter(const char *name, struct symbol *sym) { struct range_list *inc_lines = NULL; struct range_list *dec_lines = NULL; - int inc_buckets[3] = {}; - struct stree *stree; + int inc_buckets[NUM_BUCKETS] = {}; + int dec_buckets[NUM_BUCKETS] = {}; + struct stree *stree, *orig_stree; struct sm_state *return_sm; struct sm_state *sm; sval_t line = sval_type_val(&int_ctype, 0); + int bucket; FOR_EACH_PTR(get_all_return_strees(), stree) { - return_sm = get_sm_state_stree(stree, RETURN_ID, "return_ranges", NULL); + orig_stree = __swap_cur_stree(stree); + + return_sm = get_sm_state(RETURN_ID, "return_ranges", NULL); if (!return_sm) - continue; + goto swap_stree; line.value = return_sm->line; - sm = get_sm_state_stree(stree, my_id, name, sym); + if (get_state_stree(start_states, my_id, name, sym) == &inc) + goto swap_stree; + + if (parent_is_gone_var_sym(name, sym)) + goto swap_stree; + + sm = get_sm_state(my_id, name, sym); if (!sm) - continue; + goto swap_stree; - if (sm->state != &inc && sm->state != &dec) - continue; + if (sm->state != &inc && + sm->state != &dec && + sm->state != &orig) + goto swap_stree; + + bucket = success_fail_positive(estate_rl(return_sm->state)); if (sm->state == &inc) { add_range(&inc_lines, line, line); - inc_buckets[success_fail_positive(estate_rl(return_sm->state))] = 1; + inc_buckets[bucket] = true; } - if (sm->state == &dec) + if (sm->state == &dec || sm->state == &orig) { add_range(&dec_lines, line, line); + dec_buckets[bucket] = true; + } +swap_stree: + __swap_cur_stree(orig_stree); } END_FOR_EACH_PTR(stree); if (inc_buckets[NEGATIVE] && @@ -217,6 +312,22 @@ int was_inced(const char *name, struct symbol *sym) return get_state(my_id, name, sym) == &inc; } +static void match_save_states(struct expression *expr) +{ + push_stree(&saved_stack, start_states); + start_states = NULL; +} + +static void match_restore_states(struct expression *expr) +{ + start_states = pop_stree(&saved_stack); +} + +static void match_after_func(struct symbol *sym) +{ + free_stree(&start_states); +} + void check_atomic_inc_dec(int id) { my_id = id; @@ -224,8 +335,12 @@ void check_atomic_inc_dec(int id) if (option_project != PROJ_KERNEL) return; + add_unmatched_state_hook(my_id, &unmatched_state); + + add_split_return_callback(match_return_info); select_return_states_hook(ATOMIC_INC, &db_inc); select_return_states_hook(ATOMIC_DEC, &db_dec); + add_function_hook("atomic_inc_return", &match_atomic_inc, NULL); add_function_hook("atomic_add_return", &match_atomic_add, NULL); add_function_hook("atomic_sub_return", &match_atomic_sub, NULL); @@ -237,12 +352,18 @@ void check_atomic_inc_dec(int id) add_function_hook("atomic_long_dec", &match_atomic_dec, NULL); add_function_hook("atomic_inc", &match_atomic_inc, NULL); add_function_hook("atomic_sub", &match_atomic_sub, NULL); - add_split_return_callback(match_return_info); + add_function_hook("refcount_inc", &refcount_inc, INT_PTR(0)); + add_function_hook("refcount_dec", &refcount_dec, INT_PTR(0)); + add_function_hook("refcount_add", &refcount_inc, INT_PTR(1)); add_function_hook("refcount_add_not_zero", &refcount_inc, INT_PTR(1)); add_function_hook("refcount_inc_not_zero", &refcount_inc, INT_PTR(0)); add_function_hook("refcount_sub_and_test", &refcount_dec, INT_PTR(1)); - add_function_hook("refcount_dec_and_test", &refcount_dec, INT_PTR(1)); + add_function_hook("refcount_dec_and_test", &refcount_dec, INT_PTR(0)); add_hook(&match_check_missed, END_FUNC_HOOK); + + add_hook(&match_after_func, AFTER_FUNC_HOOK); + add_hook(&match_save_states, INLINE_FN_START); + add_hook(&match_restore_states, INLINE_FN_END); } diff --git a/usr/src/tools/smatch/src/check_debug.c b/usr/src/tools/smatch/src/check_debug.c index abe98b72db..8f283dbac9 100644 --- a/usr/src/tools/smatch/src/check_debug.c +++ b/usr/src/tools/smatch/src/check_debug.c @@ -78,8 +78,6 @@ static void match_state(const char *fn, struct expression *expr, void *info) static void match_states(const char *fn, struct expression *expr, void *info) { struct expression *check_arg; - struct sm_state *sm; - int found = 0; check_arg = get_argument_from_call_expr(expr->args, 0); if (check_arg->type != EXPR_STRING) { @@ -87,14 +85,7 @@ static void match_states(const char *fn, struct expression *expr, void *info) return; } - FOR_EACH_SM(__get_cur_stree(), sm) { - if (!strstr(check_name(sm->owner), check_arg->string->data)) - continue; - sm_msg("%s", show_sm(sm)); - found = 1; - } END_FOR_EACH_SM(sm); - - if (found) + if (__print_states(check_arg->string->data)) return; if (!id_from_name(check_arg->string->data)) @@ -210,6 +201,9 @@ static void match_user_rl(const char *fn, struct expression *expr, void *info) bool capped = false; char *name; + if (option_project != PROJ_KERNEL) + sm_msg("no user data for project = '%s'", option_project_str); + arg = get_argument_from_call_expr(expr->args, 0); name = expr_to_str(arg); @@ -526,6 +520,17 @@ static void match_debug_db_off(const char *fn, struct expression *expr, void *in debug_db = 0; } +static void mtag_info(struct expression *expr) +{ + mtag_t tag = 0; + int offset = 0; + struct range_list *rl = NULL; + + expr_to_mtag_offset(expr, &tag, &offset); + get_mtag_rl(expr, &rl); + sm_msg("mtag = %llu offset = %d rl = '%s'", tag, offset, show_rl(rl)); +} + static void match_about(const char *fn, struct expression *expr, void *info) { struct expression *arg; @@ -537,6 +542,7 @@ static void match_about(const char *fn, struct expression *expr, void *info) match_buf_size(fn, expr, NULL); match_strlen(fn, expr, NULL); match_real_absolute(fn, expr, NULL); + mtag_info(expr); arg = get_argument_from_call_expr(expr->args, 0); name = expr_to_str(arg); @@ -651,6 +657,21 @@ static void match_print_stree_id(const char *fn, struct expression *expr, void * sm_msg("stree_id %d", __stree_id); } +static void match_bits(const char *fn, struct expression *expr, void *_unused) +{ + struct expression *arg; + struct bit_info *info; + char *name; + + arg = get_argument_from_call_expr(expr->args, 0); + name = expr_to_str(arg); + + info = get_bit_info(arg); + + sm_msg("bit info '%s': definitely set 0x%llx. possibly set 0x%llx.", + name, info->set, info->possible); +} + static void match_mtag(const char *fn, struct expression *expr, void *info) { struct expression *arg; @@ -695,6 +716,28 @@ static void match_container(const char *fn, struct expression *expr, void *info) free_string(name); } +static void match_expr(const char *fn, struct expression *expr, void *info) +{ + struct expression *arg, *str, *new; + char *name, *new_name; + + str = get_argument_from_call_expr(expr->args, 0); + arg = get_argument_from_call_expr(expr->args, 1); + if (!arg || !str) + return; + + if (str->type != EXPR_STRING) + return; + + new = gen_expression_from_key(arg, str->string->data); + name = expr_to_str(arg); + new_name = expr_to_str(new); + + sm_msg("str = '%s', arg = '%s' expr = '%s'", str->string->data, name, new_name); + + free_string(new_name); + free_string(name); +} static void match_state_count(const char *fn, struct expression *expr, void *info) { sm_msg("state_count = %d\n", sm_state_counter); @@ -792,8 +835,10 @@ void check_debug(int id) add_implied_return_hook("__smatch_type_rl_helper", &match_type_rl_return, NULL); add_function_hook("__smatch_merge_tree", &match_print_merge_tree, NULL); add_function_hook("__smatch_stree_id", &match_print_stree_id, NULL); + add_function_hook("__smatch_bits", &match_bits, NULL); add_function_hook("__smatch_mtag", &match_mtag, NULL); add_function_hook("__smatch_mtag_data", &match_mtag_data_offset, NULL); + add_function_hook("__smatch_expr", &match_expr, NULL); add_function_hook("__smatch_state_count", &match_state_count, NULL); add_function_hook("__smatch_mem", &match_mem, NULL); add_function_hook("__smatch_exit", &match_exit, NULL); diff --git a/usr/src/tools/smatch/src/check_debug.h b/usr/src/tools/smatch/src/check_debug.h index 823fca2003..f89b52dfef 100644 --- a/usr/src/tools/smatch/src/check_debug.h +++ b/usr/src/tools/smatch/src/check_debug.h @@ -63,7 +63,7 @@ static inline long long __smatch_type_rl_helper(long long type, const char *str, #define __smatch_type_rl(type, fmt...) __smatch_type_rl_helper((type)0, fmt) #define __smatch_rl(fmt...) __smatch_type_rl(long long, fmt) -static inline void __smatch_bit_info(long long expr){} +static inline void __smatch_bits(long long expr){} static inline void __smatch_oops(unsigned long null_val){} @@ -75,8 +75,11 @@ static inline void __smatch_mtag(void *p){} static inline void __smatch_mtag_data(long long arg){} static inline void __smatch_exit(void){} +static inline void __smatch_expr(const char *str, void *p){} + static inline void __smatch_state_count(void){} static inline void __smatch_mem(void){} static inline void __smatch_container(long long container, long long x){} + #endif diff --git a/usr/src/tools/smatch/src/check_err_ptr.c b/usr/src/tools/smatch/src/check_err_ptr.c index c3d0f7e9ae..60b8ff2c58 100644 --- a/usr/src/tools/smatch/src/check_err_ptr.c +++ b/usr/src/tools/smatch/src/check_err_ptr.c @@ -37,7 +37,6 @@ static void match_err_ptr(struct expression *expr) err_ptr = 1; } -extern int check_assigned_expr_id; static void match_return(struct expression *ret_value) { struct state_list *slist; diff --git a/usr/src/tools/smatch/src/check_kernel.c b/usr/src/tools/smatch/src/check_kernel.c index a67511ef43..50c884b1a6 100644 --- a/usr/src/tools/smatch/src/check_kernel.c +++ b/usr/src/tools/smatch/src/check_kernel.c @@ -32,10 +32,10 @@ static int implied_err_cast_return(struct expression *call, void *unused, struct struct expression *arg; arg = get_argument_from_call_expr(call->args, 0); - if (!get_implied_rl(arg, rl)) { + if (!get_implied_rl(arg, rl)) *rl = alloc_rl(err_ptr_min, err_ptr_max); - *rl = cast_rl(get_type(arg), *rl); - } + + *rl = cast_rl(get_type(call), *rl); return 1; } @@ -130,12 +130,9 @@ static void match_not_err(const char *fn, struct expression *call_expr, arg = get_argument_from_call_expr(call_expr->args, 0); pre_state = get_state_expr(SMATCH_EXTRA, arg); - if (estate_rl(pre_state)) { - rl = estate_rl(pre_state); - rl = remove_range(rl, err_ptr_min, err_ptr_max); - } else { - rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval); - } + if (pre_state) + return; + rl = alloc_rl(valid_ptr_min_sval, valid_ptr_max_sval); rl = cast_rl(get_type(arg), rl); set_extra_expr_nomod(arg, alloc_estate_rl(rl)); } @@ -154,6 +151,14 @@ static void match_err(const char *fn, struct expression *call_expr, rl = alloc_rl(err_ptr_min, err_ptr_max); rl = rl_intersection(rl, alloc_rl(err_ptr_min, err_ptr_max)); rl = cast_rl(get_type(arg), rl); + if (pre_state && rl) { + /* + * Ideally this would all be handled by smatch_implied.c + * but it doesn't work very well for impossible paths. + * + */ + return; + } set_extra_expr_nomod(arg, alloc_estate_rl(rl)); } @@ -257,8 +262,6 @@ static int match_fls(struct expression *call, void *unused, struct range_list ** return 1; } - - static void find_module_init_exit(struct symbol_list *sym_list) { struct symbol *sym; @@ -406,6 +409,22 @@ static void match__read_once_size(const char *fn, struct expression *call, __in_fake_assign--; } +static void match_closure_call(const char *name, struct expression *call, + void *unused) +{ + struct expression *cl, *fn, *fake_call; + struct expression_list *args = NULL; + + cl = get_argument_from_call_expr(call->args, 0); + fn = get_argument_from_call_expr(call->args, 1); + if (!fn || !cl) + return; + + add_ptr_list(&args, cl); + fake_call = call_expression(fn, args); + __split_expr(fake_call); +} + bool is_ignored_kernel_data(const char *name) { if (option_project != PROJ_KERNEL) @@ -463,6 +482,8 @@ void check_kernel(int id) add_function_hook("__read_once_size", &match__read_once_size, NULL); add_function_hook("__read_once_size_nocheck", &match__read_once_size, NULL); + add_function_hook("closure_call", &match_closure_call, NULL); + if (option_info) add_hook(match_end_file, END_FILE_HOOK); } diff --git a/usr/src/tools/smatch/src/check_shift_to_zero.c b/usr/src/tools/smatch/src/check_shift_to_zero.c index 019b06fb75..a6f227d974 100644 --- a/usr/src/tools/smatch/src/check_shift_to_zero.c +++ b/usr/src/tools/smatch/src/check_shift_to_zero.c @@ -56,9 +56,9 @@ static void match_binop2(struct expression *expr) if (left->type != EXPR_BINOP || left->op != '&') return; - if (!get_implied_value(expr->right, &shift)) + if (!get_value(expr->right, &shift)) return; - if (!get_implied_value(left->right, &mask)) + if (!get_value(left->right, &mask)) return; if (mask.uvalue >> shift.uvalue) diff --git a/usr/src/tools/smatch/src/expression.h b/usr/src/tools/smatch/src/expression.h index f90f8d65ef..59c781bb30 100644 --- a/usr/src/tools/smatch/src/expression.h +++ b/usr/src/tools/smatch/src/expression.h @@ -134,8 +134,9 @@ enum constexpr_flag { enum { Handled = 1 << 0, - Fake = 1 << 1, -}; /* for expr->flags */ + Tmp = 1 << 1, + Fake = 1 << 2, +}; /* for expr->smatch_flags */ enum { Taint_comma = 1, diff --git a/usr/src/tools/smatch/src/smatch.c b/usr/src/tools/smatch/src/smatch.c index b6963a0016..c18c2f6e54 100644 --- a/usr/src/tools/smatch/src/smatch.c +++ b/usr/src/tools/smatch/src/smatch.c @@ -340,6 +340,7 @@ int main(int argc, char **argv) allocate_hook_memory(); allocate_dynamic_states_array(num_checks); + allocate_tracker_array(num_checks); create_function_hook_hash(); open_smatch_db(option_db_file); sparse_initialize(argc, argv, &filelist); diff --git a/usr/src/tools/smatch/src/smatch.h b/usr/src/tools/smatch/src/smatch.h index 6e0698085e..6df9c529e4 100644 --- a/usr/src/tools/smatch/src/smatch.h +++ b/usr/src/tools/smatch/src/smatch.h @@ -196,6 +196,7 @@ void select_return_states_before(void (*fn)(void)); void select_return_states_after(void (*fn)(void)); int get_implied_return(struct expression *expr, struct range_list **rl); void allocate_hook_memory(void); +void allocate_tracker_array(int num_checks); struct modification_data { struct smatch_state *prev; @@ -388,6 +389,7 @@ struct smatch_state *merge_str_state(struct smatch_state *s1, struct smatch_stat struct smatch_state *alloc_state_expr(struct expression *expr); struct expression *get_argument_from_call_expr(struct expression_list *args, int num); +struct expression *get_array_expr(struct expression *expr); char *expr_to_var(struct expression *expr); struct symbol *expr_to_sym(struct expression *expr); @@ -446,9 +448,16 @@ int positions_eq(struct position pos1, struct position pos2); struct statement *get_current_statement(void); struct statement *get_prev_statement(void); struct expression *get_last_expr_from_expression_stmt(struct expression *expr); + +#define RETURN_VAR -1 +#define LOCAL_SCOPE -2 +#define FILE_SCOPE -3 +#define GLOBAL_SCOPE -4 +#define UNKNOWN_SCOPE -5 int get_param_num_from_sym(struct symbol *sym); int get_param_num(struct expression *expr); struct symbol *get_param_sym_from_num(int num); + int ms_since(struct timeval *start); int parent_is_gone_var_sym(const char *name, struct symbol *sym); int parent_is_gone(struct expression *expr); @@ -478,9 +487,11 @@ int nr_bits(struct expression *expr); int is_void_pointer(struct expression *expr); int is_char_pointer(struct expression *expr); int is_string(struct expression *expr); +bool is_struct_ptr(struct symbol *type); int is_static(struct expression *expr); bool is_local_variable(struct expression *expr); int types_equiv(struct symbol *one, struct symbol *two); +bool type_fits(struct symbol *type, struct symbol *test); int fn_static(void); const char *global_static(); struct symbol *cur_func_return_type(void); @@ -581,7 +592,7 @@ int __handle_expr_statement_assigns(struct expression *expr); /* smatch_implied.c */ struct range_list_stack; -void param_limit_implications(struct expression *expr, int param, char *key, char *value); +void param_limit_implications(struct expression *expr, int param, char *key, char *value, struct stree **implied); struct stree *__implied_case_stree(struct expression *switch_expr, struct range_list *case_rl, struct range_list_stack **remaining_cases, @@ -780,6 +791,9 @@ void __save_gotos(const char *name, struct symbol *sym); void __merge_gotos(const char *name, struct symbol *sym); void __print_cur_stree(void); +bool __print_states(const char *owner); +typedef void (check_tracker_hook)(int owner, const char *name, struct symbol *sym, struct smatch_state *state); +void add_check_tracker(const char *check_name, check_tracker_hook *fn); /* smatch_hooks.c */ void __pass_to_client(void *data, enum hook_type type); @@ -847,6 +861,7 @@ enum info_type { STMT_CNT = 1037, TERMINATED = 1038, FRESH_ALLOC = 1044, + ALLOCATOR = 1045, /* put random temporary stuff in the 7000-7999 range for testing */ USER_DATA = 8017, @@ -862,6 +877,7 @@ enum info_type { SET_FS = 8022, ATOMIC_INC = 8023, ATOMIC_DEC = 8024, + REFCOUNT = 9025, NO_SIDE_EFFECT = 8025, FN_ARG_LINK = 8028, DATA_VALUE = 8029, @@ -885,6 +901,7 @@ extern struct sqlite3 *cache_db; void db_ignore_states(int id); void select_caller_info_hook(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type); void add_member_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm)); +void add_caller_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm)); void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr)); void add_returned_member_callback(int owner, void (*callback)(int return_id, char *return_ranges, struct expression *expr, char *printed_name, struct smatch_state *state)); void select_call_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value)); @@ -996,11 +1013,12 @@ void sql_copy_constraint_required(const char *new_limit, const char *old_limit); void sql_insert_fn_ptr_data_link(const char *ptr, const char *data); void sql_insert_fn_data_link(struct expression *fn, int type, int param, const char *key, const char *value); void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name); -void sql_insert_mtag_map(mtag_t tag, int offset, mtag_t container); +void sql_insert_mtag_info(mtag_t tag, int type, const char *value); +void sql_insert_mtag_map(mtag_t container, int container_offset, mtag_t tag, int tag_offset); void sql_insert_mtag_alias(mtag_t orig, mtag_t alias); -int mtag_map_select_container(mtag_t tag, int offset, mtag_t *container); +int mtag_map_select_container(mtag_t tag, int container_offset, mtag_t *container); int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag); -struct smatch_state *swap_mtag_return(struct expression *expr, struct smatch_state *state); +struct smatch_state *get_mtag_return(struct expression *expr, struct smatch_state *state); struct range_list *swap_mtag_seed(struct expression *expr, struct range_list *rl); void sql_select_return_states(const char *cols, struct expression *call, @@ -1069,6 +1087,7 @@ struct range_list *var_user_rl(struct expression *expr); void print_held_locks(); /* check_assigned_expr.c */ +extern int check_assigned_expr_id; struct expression *get_assigned_expr(struct expression *expr); struct expression *get_assigned_expr_name_sym(const char *name, struct symbol *sym); /* smatch_return_to_param.c */ @@ -1119,9 +1138,6 @@ int negate_comparison(int op); int remove_unsigned_from_comparison(int op); int param_compare_limit_is_impossible(struct expression *expr, int left_param, char *left_key, char *value); void filter_by_comparison(struct range_list **rl, int comparison, struct range_list *right); -struct sm_state *comparison_implication_hook(struct expression *expr, - struct state_list **true_stack, - struct state_list **false_stack); void __compare_param_limit_hook(struct expression *left_expr, struct expression *right_expr, const char *state_name, struct smatch_state *true_state, struct smatch_state *false_state); @@ -1193,6 +1209,10 @@ struct sm_state *stored_condition_implication_hook(struct expression *expr, struct sm_state *parsed_condition_implication_hook(struct expression *expr, struct state_list **true_stack, struct state_list **false_stack); +/* smatch_comparison.c */ +struct sm_state *comparison_implication_hook(struct expression *expr, + struct state_list **true_stack, + struct state_list **false_stack); /* check_string_len.c */ int get_formatted_string_size(struct expression *call, int arg); @@ -1240,10 +1260,14 @@ void __get_state_hook(int owner, const char *name, struct symbol *sym); /* smatch_buf_comparison.c */ int db_var_is_array_limit(struct expression *array, const char *name, struct var_sym_list *vsl); +struct range_list *get_fs(void); + struct stree *get_all_return_states(void); struct stree_stack *get_all_return_strees(void); int on_atomic_dec_path(void); int was_inced(const char *name, struct symbol *sym); +void set_refcount_inc(char *name, struct symbol *sym); +void set_refcount_dec(char *name, struct symbol *sym); /* smatch_constraints.c */ char *get_constraint_str(struct expression *expr); diff --git a/usr/src/tools/smatch/src/smatch_bits.c b/usr/src/tools/smatch/src/smatch_bits.c index 2fcd5e8f60..5e310a13f7 100644 --- a/usr/src/tools/smatch/src/smatch_bits.c +++ b/usr/src/tools/smatch/src/smatch_bits.c @@ -111,10 +111,46 @@ static struct smatch_state *unmatched_state(struct sm_state *sm) return alloc_bstate(0, possible); } +static bool is_loop_iterator(struct expression *expr) +{ + struct statement *pre_stmt, *loop_stmt; + + pre_stmt = expr_get_parent_stmt(expr); + if (!pre_stmt || pre_stmt->type != STMT_EXPRESSION) + return false; + + loop_stmt = stmt_get_parent_stmt(pre_stmt); + if (!loop_stmt || loop_stmt->type != STMT_ITERATOR) + return false; + if (loop_stmt->iterator_pre_statement != pre_stmt) + return false; + + return true; +} + +static bool handled_by_assign_hook(struct expression *expr) +{ + if (!expr || expr->type != EXPR_ASSIGNMENT) + return false; + if (__in_fake_assign) + return false; + if (is_loop_iterator(expr)) + return false; + + if (expr->op == '=' || + expr->op == SPECIAL_OR_ASSIGN || + expr->op == SPECIAL_AND_ASSIGN) + return true; + + return false; +} + static void match_modify(struct sm_state *sm, struct expression *mod_expr) { // FIXME: we really need to store the type + if (handled_by_assign_hook(mod_expr)) + return; set_state(my_id, sm->name, sm->sym, alloc_bstate(0, -1ULL)); } @@ -283,40 +319,31 @@ static void match_compare(struct expression *expr) (expr->op == SPECIAL_EQUAL) ? NULL : alloc_bstate(val.uvalue, val.uvalue)); } -static bool is_loop_iterator(struct expression *expr) -{ - struct statement *pre_stmt, *loop_stmt; - - pre_stmt = expr_get_parent_stmt(expr); - if (!pre_stmt || pre_stmt->type != STMT_EXPRESSION) - return false; - - loop_stmt = stmt_get_parent_stmt(pre_stmt); - if (!loop_stmt || loop_stmt->type != STMT_ITERATOR) - return false; - if (loop_stmt->iterator_pre_statement != pre_stmt) - return false; - - return true; -} - static void match_assign(struct expression *expr) { - struct bit_info *binfo; + struct bit_info *start, *binfo; + struct smatch_state *new; - if (expr->op != '=') - return; - if (__in_fake_assign) - return; - if (is_loop_iterator(expr)) + if (!handled_by_assign_hook(expr)) return; binfo = get_bit_info(expr->right); if (!binfo) return; - if (is_unknown_binfo(get_type(expr->left), binfo)) - return; - set_state_expr(my_id, expr->left, alloc_bstate(binfo->set, binfo->possible)); + if (expr->op == '=') { + if (is_unknown_binfo(get_type(expr->left), binfo)) + return; + + set_state_expr(my_id, expr->left, alloc_bstate(binfo->set, binfo->possible)); + } else if (expr->op == SPECIAL_OR_ASSIGN) { + start = get_bit_info(expr->left); + new = alloc_bstate(start->set | binfo->set, start->possible | binfo->possible); + set_state_expr(my_id, expr->left, new); + } else if (expr->op == SPECIAL_AND_ASSIGN) { + start = get_bit_info(expr->left); + new = alloc_bstate(start->set & binfo->set, start->possible & binfo->possible); + set_state_expr(my_id, expr->left, new); + } } static void match_condition(struct expression *expr) diff --git a/usr/src/tools/smatch/src/smatch_buf_size.c b/usr/src/tools/smatch/src/smatch_buf_size.c index 1a2dd87d01..b98d97f193 100644 --- a/usr/src/tools/smatch/src/smatch_buf_size.c +++ b/usr/src/tools/smatch/src/smatch_buf_size.c @@ -269,6 +269,7 @@ static void db_returns_buf_size(struct expression *expr, int param, char *unused { struct expression *call; struct range_list *rl; + sval_t sval; if (expr->type != EXPR_ASSIGNMENT) return; @@ -276,6 +277,8 @@ static void db_returns_buf_size(struct expression *expr, int param, char *unused call_results_to_rl(call, &int_ctype, math, &rl); rl = cast_rl(&int_ctype, rl); + if (rl_to_sval(rl, &sval) && sval.value == 0) + return; set_state_expr(my_size_id, expr->left, alloc_estate_rl(rl)); } @@ -451,7 +454,7 @@ static int get_stored_size_end_struct_bytes(struct expression *expr) return 0; state = get_state(my_size_id, sym->ident->name, sym); - if (!estate_to_size(state)) + if (!estate_to_size(state) || estate_to_size(state) == -1) return 0; return estate_to_size(state) - type_bytes(base_sym) + type_bytes(get_type(expr)); @@ -504,6 +507,11 @@ struct range_list *get_array_size_bytes_rl(struct expression *expr) return alloc_int_rl(size - offset.value); } + /* buf = malloc(1024); */ + ret = get_stored_size_bytes(expr); + if (ret) + return ret; + size = get_stored_size_end_struct_bytes(expr); if (size) return alloc_int_rl(size); @@ -513,11 +521,6 @@ struct range_list *get_array_size_bytes_rl(struct expression *expr) if (size) return alloc_int_rl(elements_to_bytes(expr, size)); - /* buf = malloc(1024); */ - ret = get_stored_size_bytes(expr); - if (ret) - return ret; - /* char *foo = "BAR" */ size = get_size_from_initializer(expr); if (size) @@ -636,7 +639,11 @@ static void store_alloc(struct expression *expr, struct range_list *rl) rl = clone_rl(rl); // FIXME!!! if (!rl) rl = size_to_rl(UNKNOWN_SIZE); - set_state_expr(my_size_id, expr, alloc_estate_rl(rl)); + + if (rl_min(rl).value != UNKNOWN_SIZE || + rl_max(rl).value != UNKNOWN_SIZE || + get_state_expr(my_size_id, expr)) + set_state_expr(my_size_id, expr, alloc_estate_rl(rl)); type = get_type(expr); if (!type) @@ -654,6 +661,16 @@ static void store_alloc(struct expression *expr, struct range_list *rl) info_record_alloction(expr, rl); } +static bool is_array_base(struct expression *expr) +{ + struct symbol *type; + + type = get_type(expr); + if (type && type->type == SYM_ARRAY) + return true; + return false; +} + static void match_array_assignment(struct expression *expr) { struct expression *left; @@ -664,12 +681,16 @@ static void match_array_assignment(struct expression *expr) if (expr->op != '=') return; + left = strip_expr(expr->left); right = strip_expr(expr->right); right = strip_ampersands(right); if (!is_pointer(left)) return; + /* char buf[24] = "str"; */ + if (is_array_base(left)) + return; if (is_allocation_function(right)) return; @@ -710,15 +731,16 @@ static void match_alloc(const char *fn, struct expression *expr, void *_size_arg store_alloc(expr->left, rl); } -static void match_calloc(const char *fn, struct expression *expr, void *unused) +static void match_calloc(const char *fn, struct expression *expr, void *_param) { struct expression *right; struct expression *size, *nr, *mult; struct range_list *rl; + int param = PTR_INT(_param); right = strip_expr(expr->right); - nr = get_argument_from_call_expr(right->args, 0); - size = get_argument_from_call_expr(right->args, 1); + nr = get_argument_from_call_expr(right->args, param); + size = get_argument_from_call_expr(right->args, param + 1); mult = binop_expression(nr, '*', size); if (get_implied_rl(mult, &rl)) store_alloc(expr->left, rl); @@ -812,6 +834,9 @@ static void match_call(struct expression *expr) rl = get_array_size_bytes_rl(arg); if (!rl) continue; + if (rl_min(rl).value == UNKNOWN_SIZE && + rl_max(rl).value == UNKNOWN_SIZE) + continue; if (is_whole_rl(rl)) continue; if (is_type_bytes(rl, arg)) @@ -909,12 +934,12 @@ void register_buf_size(int id) add_allocation_function("kzalloc", &match_alloc, 0); add_allocation_function("kzalloc_node", &match_alloc, 0); add_allocation_function("vmalloc", &match_alloc, 0); + add_allocation_function("vzalloc", &match_alloc, 0); add_allocation_function("__vmalloc", &match_alloc, 0); add_allocation_function("kvmalloc", &match_alloc, 0); add_allocation_function("kcalloc", &match_calloc, 0); add_allocation_function("kmalloc_array", &match_calloc, 0); - add_allocation_function("drm_malloc_ab", &match_calloc, 0); - add_allocation_function("drm_calloc_large", &match_calloc, 0); + add_allocation_function("devm_kmalloc_array", &match_calloc, 1); add_allocation_function("sock_kmalloc", &match_alloc, 1); add_allocation_function("kmemdup", &match_alloc, 1); add_allocation_function("kmemdup_user", &match_alloc, 1); diff --git a/usr/src/tools/smatch/src/smatch_capped.c b/usr/src/tools/smatch/src/smatch_capped.c index 1b25c4795e..ce290b9630 100644 --- a/usr/src/tools/smatch/src/smatch_capped.c +++ b/usr/src/tools/smatch/src/smatch_capped.c @@ -94,12 +94,14 @@ int is_capped(struct expression *expr) if (expr->type == EXPR_BINOP) { struct range_list *left_rl, *right_rl; + sval_t sval; - if (expr->op == '&') + if (expr->op == '&' && !get_value(expr->right, &sval)) return 1; if (expr->op == SPECIAL_RIGHTSHIFT) - return 1; - if (expr->op == '%' && is_capped(expr->right)) + return 0; + if (expr->op == '%' && + !get_value(expr->right, &sval) && is_capped(expr->right)) return 1; if (!is_capped(expr->left)) return 0; diff --git a/usr/src/tools/smatch/src/smatch_comparison.c b/usr/src/tools/smatch/src/smatch_comparison.c index 78724c2339..8267555e14 100644 --- a/usr/src/tools/smatch/src/smatch_comparison.c +++ b/usr/src/tools/smatch/src/smatch_comparison.c @@ -2748,8 +2748,8 @@ split: } struct sm_state *comparison_implication_hook(struct expression *expr, - struct state_list **true_stack, - struct state_list **false_stack) + struct state_list **true_stack, + struct state_list **false_stack) { struct sm_state *sm; char *left, *right; diff --git a/usr/src/tools/smatch/src/smatch_container_of.c b/usr/src/tools/smatch/src/smatch_container_of.c index 65d4a8d8ac..098885be7d 100644 --- a/usr/src/tools/smatch/src/smatch_container_of.c +++ b/usr/src/tools/smatch/src/smatch_container_of.c @@ -528,7 +528,7 @@ static struct stree *load_tag_info_sym(mtag_t tag, struct symbol *arg, int arg_o tag, arg_offset, DATA_VALUE); } else { /* presumably the parameter is a struct pointer */ run_sql(save_vals, &db_info, - "select offset, value from mtag_data where tag = %lld and type = %d;", + "select offset, value from mtag_data where tag = %lld and type = %d order by offset;", tag, DATA_VALUE); } @@ -579,7 +579,7 @@ static void load_container_data(struct symbol *arg, const char *info) if (local_debug) sm_msg("%s: cur_tag = %llu container_offset = %d", __func__, cur_tag, container_offset); - if (!mtag_map_select_container(cur_tag, container_offset, &container_tag)) + if (!mtag_map_select_container(cur_tag, -container_offset, &container_tag)) return; cur_tag = container_tag; if (local_debug) @@ -603,7 +603,7 @@ static void load_container_data(struct symbol *arg, const char *info) if (!arg_offset || star) { arg_tag = container_tag; } else { - if (!mtag_map_select_tag(container_tag, -arg_offset, &arg_tag)) + if (!mtag_map_select_tag(container_tag, arg_offset, &arg_tag)) return; } diff --git a/usr/src/tools/smatch/src/smatch_data/db/create_db.sh b/usr/src/tools/smatch/src/smatch_data/db/create_db.sh index 313ba59133..4d80242727 100755 --- a/usr/src/tools/smatch/src/smatch_data/db/create_db.sh +++ b/usr/src/tools/smatch/src/smatch_data/db/create_db.sh @@ -52,6 +52,8 @@ ${bin_dir}/mark_function_ptrs_searchable.pl $db_file echo "delete from function_ptr where rowid not in (select min(rowid) from function_ptr group by file, function, ptr, searchable);" | sqlite3 $db_file ${bin_dir}/apply_return_fixes.sh -p=${PROJ} $db_file -${bin_dir}/insert_manual_states.pl ${PROJ} $db_file +if [ "$PROJ" != "" ] ; then + ${bin_dir}/insert_manual_states.pl ${PROJ} $db_file +fi mv $db_file smatch_db.sqlite diff --git a/usr/src/tools/smatch/src/smatch_data/db/kernel.return_fixes b/usr/src/tools/smatch/src/smatch_data/db/kernel.return_fixes index d6b8f8e5d1..d75b3f3a06 100644 --- a/usr/src/tools/smatch/src/smatch_data/db/kernel.return_fixes +++ b/usr/src/tools/smatch/src/smatch_data/db/kernel.return_fixes @@ -20,6 +20,7 @@ nilfs_mdt_insert_new_block s32min-(-23),(-21)-(-1),1-s32max (-4095)-(-23),(-21)- simple_write_to_buffer s64min-s64max 0-s32max[<=$1] atomic_read s32min-s32max s32min-s32max[==$0->counter] notifier_to_errno (-2147483646)-(-1) (-4095)-(-1) +notifier_to_errno (-2147450878)-(-1) (-4095)-(-1) mc_status_to_error s32min-s32max (-4095)-0 fls s32min-s32max 0-32 fls64 s64min-s64max 0-64 @@ -57,3 +58,13 @@ __rounddown_pow_of_two 0-u64max 0-u64max[<=$0] __roundup_pow_of_two 0-u64max 0-u64max[>=$0] kthread_probe_data 0 0-u64max bus_for_each_dev (-4095)-1 (-4095)-1[r\ $3] +ahd_probe_stack_size 0 0-s32max +mutex_lock_interruptible_nested (-35),(-4) (-4) +dlfb_get_urb 0-u64max 4096-ptr_max +bitmap_find_free_region 0 0-s32max +mutex_lock_interruptible (-35),(-4) (-4) +mutex_lock_interruptible_nested (-35),(-4) (-4) +mutex_lock_killable (-35),(-4) (-4) +mutex_lock_killable_nested (-35),(-4) (-4) +ww_mutex_lock_interruptible (-35),(-4) (-4) +ww_mutex_lock (-35),(-4) (-35) diff --git a/usr/src/tools/smatch/src/smatch_data/db/mark_function_ptrs_searchable.pl b/usr/src/tools/smatch/src/smatch_data/db/mark_function_ptrs_searchable.pl index a35148febc..017d21149f 100755 --- a/usr/src/tools/smatch/src/smatch_data/db/mark_function_ptrs_searchable.pl +++ b/usr/src/tools/smatch/src/smatch_data/db/mark_function_ptrs_searchable.pl @@ -22,17 +22,6 @@ $sth = $db->prepare('select distinct(ptr) from function_ptr;'); $sth->execute(); while ($fn_ptr = $sth->fetchrow_array()) { - - # following a pointer to pointer chain is too complicated for now - $ptr_to_ptr = $db->selectrow_array("select function from function_ptr where ptr = '$fn_ptr' and function like '% %';"); - if ($ptr_to_ptr) { - next; - } - $ptr_to_ptr = $db->selectrow_array("select function from function_ptr where ptr = '$fn_ptr' and function like '%[]';"); - if ($ptr_to_ptr) { - next; - } - $count = $db->selectrow_array("select count(*) from return_states join function_ptr where return_states.function == function_ptr.function and ptr = '$fn_ptr';"); # if there are too many states then bail if ($count > 1000) { diff --git a/usr/src/tools/smatch/src/smatch_data/db/mtag_about.schema b/usr/src/tools/smatch/src/smatch_data/db/mtag_about.schema index 775764fedf..74939582ef 100644 --- a/usr/src/tools/smatch/src/smatch_data/db/mtag_about.schema +++ b/usr/src/tools/smatch/src/smatch_data/db/mtag_about.schema @@ -1 +1,10 @@ -CREATE TABLE mtag_about (tag big int, file varchar(80), function varchar(80), line integer, left_name varchar(80), right_name varchar(80)); +CREATE TABLE mtag_about ( + tag big int, + file varchar(80), + function varchar(80), + line integer, + left_name varchar(80), + right_name varchar(80), + + CONSTRAINT mtag_about_row UNIQUE (tag, file, function, line, left_name, right_name) +); diff --git a/usr/src/tools/smatch/src/smatch_data/db/mtag_info.schema b/usr/src/tools/smatch/src/smatch_data/db/mtag_info.schema new file mode 100644 index 0000000000..85e437b027 --- /dev/null +++ b/usr/src/tools/smatch/src/smatch_data/db/mtag_info.schema @@ -0,0 +1 @@ +CREATE TABLE mtag_info (file varchar(80), tag big int, type integer, value varchar(80)); diff --git a/usr/src/tools/smatch/src/smatch_data/db/mtag_map.schema b/usr/src/tools/smatch/src/smatch_data/db/mtag_map.schema index 3eb892d3ac..5e254e2eb6 100644 --- a/usr/src/tools/smatch/src/smatch_data/db/mtag_map.schema +++ b/usr/src/tools/smatch/src/smatch_data/db/mtag_map.schema @@ -1 +1 @@ -CREATE TABLE mtag_map (tag big int, offset integer, container big int); +CREATE TABLE mtag_map (container big int, container_offset int, tag big int, tag_offset int); diff --git a/usr/src/tools/smatch/src/smatch_data/db/return_states.schema b/usr/src/tools/smatch/src/smatch_data/db/return_states.schema index a222eac9b7..d6f0bbe36c 100644 --- a/usr/src/tools/smatch/src/smatch_data/db/return_states.schema +++ b/usr/src/tools/smatch/src/smatch_data/db/return_states.schema @@ -1 +1 @@ -CREATE TABLE return_states (file varchar(128), function varchar(64), call_id integer, return_id integer, return varchar(256), static boolean, type integer, parameter integer, key varchar(256), value varchar(256)); +CREATE TABLE return_states (file varchar(128), function varchar(64), call_id big int, return_id integer, return varchar(256), static boolean, type integer, parameter integer, key varchar(256), value varchar(256)); diff --git a/usr/src/tools/smatch/src/smatch_data/db/smdb.py b/usr/src/tools/smatch/src/smatch_data/db/smdb.py index 04bff00be4..2d8256373b 100755 --- a/usr/src/tools/smatch/src/smatch_data/db/smdb.py +++ b/usr/src/tools/smatch/src/smatch_data/db/smdb.py @@ -74,6 +74,7 @@ db_types = { 0: "INTERNAL", 1017: "ARRAY_LEN", 1018: "CAPABLE", 1019: "NS_CAPABLE", + 1020: "CONTAINER", 1022: "TYPE_LINK", 1023: "UNTRACKED_PARAM", 1024: "CULL_PATH", @@ -92,7 +93,7 @@ db_types = { 0: "INTERNAL", 1037: "STMT_CNT", 1038: "TERMINATED", 1039: "SLEEP", - 1040: "NO_SLEEP_CNT", + 1040: "PREEMPT_CNT", 1041: "SMALLISH", 1042: "FRESH_MTAG", @@ -102,6 +103,10 @@ db_types = { 0: "INTERNAL", 8019: "NO_OVERFLOW_SIMPLE", 8020: "LOCKED", 8021: "UNLOCKED", + 9022: "HALF_LOCKED", + 9023: "LOCK_RESTORED", + 9024: "KNOWN_LOCKED", + 9025: "KNOWN_UNLOCKED", 8023: "ATOMIC_INC", 8024: "ATOMIC_DEC", }; diff --git a/usr/src/tools/smatch/src/smatch_db.c b/usr/src/tools/smatch/src/smatch_db.c index 70be64093d..d31c3a17cf 100644 --- a/usr/src/tools/smatch/src/smatch_db.c +++ b/usr/src/tools/smatch/src/smatch_db.c @@ -50,6 +50,7 @@ struct member_info_callback { ALLOCATOR(member_info_callback, "caller_info callbacks"); DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback); static struct member_info_cb_list *member_callbacks; +static struct member_info_cb_list *member_callbacks_new; struct returned_state_callback { void (*callback)(int return_id, char *return_ranges, struct expression *return_expr); @@ -178,15 +179,36 @@ void db_ignore_states(int id) use_states[id] = 0; } +unsigned long long __fn_mtag; +static void set_fn_mtag(struct symbol *sym) +{ + char buf[128]; + + if (cur_func_sym->ctype.modifiers & MOD_STATIC) + snprintf(buf, sizeof(buf), "%s %s", get_base_file(), get_function()); + else + snprintf(buf, sizeof(buf), "extern %s", get_function()); + + __fn_mtag = str_to_mtag(buf); +} + void sql_insert_return_states(int return_id, const char *return_ranges, int type, int param, const char *key, const char *value) { + unsigned long long id; + + if (key && strlen(key) >= 80) return; + if (__inline_fn) + id = (unsigned long)__inline_fn; + else + id = __fn_mtag; + return_ranges = replace_return_ranges(return_ranges); - sql_insert(return_states, "'%s', '%s', %lu, %d, '%s', %d, %d, %d, '%s', '%s'", - get_base_file(), get_function(), (unsigned long)__inline_fn, - return_id, return_ranges, fn_static(), type, param, key, value); + sql_insert(return_states, "'%s', '%s', %llu, %d, '%s', %d, %d, %d, '%s', '%s'", + get_base_file(), get_function(), id, return_id, + return_ranges, fn_static(), type, param, key, value); } static struct string_list *common_funcs; @@ -372,13 +394,19 @@ void sql_insert_fn_data_link(struct expression *fn, int type, int param, const c void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name) { - sql_insert(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'", - tag, get_filename(), get_function(), get_lineno(), left_name, right_name); + sql_insert_cache(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'", + tag, get_filename(), get_function(), get_lineno(), + left_name, right_name); } -void sql_insert_mtag_map(mtag_t tag, int offset, mtag_t container) +void sql_insert_mtag_info(mtag_t tag, int type, const char *value) { - sql_insert(mtag_map, "%lld, %d, %lld", tag, offset, container); + sql_insert_cache(mtag_info, "'%s', %lld, %d, '%s'", get_filename(), tag, type, value); +} + +void sql_insert_mtag_map(mtag_t container, int container_offset, mtag_t tag, int tag_offset) +{ + sql_insert(mtag_map, "%lld, %d, %lld, %d", container, container_offset, tag, tag_offset); } void sql_insert_mtag_alias(mtag_t orig, mtag_t alias) @@ -401,13 +429,13 @@ static int save_mtag(void *_tag, int argc, char **argv, char **azColName) return 0; } -int mtag_map_select_container(mtag_t tag, int offset, mtag_t *container) +int mtag_map_select_container(mtag_t tag, int container_offset, mtag_t *container) { mtag_t tmp = 0; run_sql(save_mtag, &tmp, - "select container from mtag_map where tag = %lld and offset = %d;", - tag, offset); + "select container from mtag_map where tag = %lld and container_offset = %d and tag_offset = 0;", + tag, container_offset); if (tmp == 0 || tmp == -1ULL) return 0; @@ -420,7 +448,7 @@ int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag) mtag_t tmp = 0; run_sql(save_mtag, &tmp, - "select tag from mtag_map where container = %lld and offset = %d;", + "select tag from mtag_map where container = %lld and container_offset = %d;", container, offset); if (tmp == 0 || tmp == -1ULL) @@ -622,6 +650,15 @@ void add_member_info_callback(int owner, void (*callback)(struct expression *cal add_ptr_list(&member_callbacks, member_callback); } +void add_caller_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm)) +{ + struct member_info_callback *member_callback = __alloc_member_info_callback(0); + + member_callback->owner = owner; + member_callback->callback = callback; + add_ptr_list(&member_callbacks_new, member_callback); +} + void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr)) { struct returned_state_callback *callback = __alloc_returned_state_callback(0); @@ -851,7 +888,8 @@ free: } static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree, - void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm)) + void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm), + bool new) { struct sm_state *sm; const char *sm_name; @@ -891,24 +929,33 @@ static void print_struct_members(struct expression *call, struct expression *exp } // FIXME: simplify? if (!add_star && strcmp(name, sm_name) == 0) { - if (is_address) + if (is_address) { snprintf(printed_name, sizeof(printed_name), "*$"); - else /* these are already handled. fixme: handle them here */ - continue; + } else { + if (new) + snprintf(printed_name, sizeof(printed_name), "$"); + else + continue; + } } else if (add_star && strcmp(name, sm_name) == 0) { snprintf(printed_name, sizeof(printed_name), "%s*$", is_address ? "*" : ""); } else if (strncmp(name, sm_name, len) == 0) { if (sm_name[len] != '.' && sm_name[len] != '-') continue; - if (is_address) + if (is_address && sm_name[len] == '.') { snprintf(printed_name, sizeof(printed_name), "%s$->%s", add_star ? "*" : "", sm_name + len + 1); - else + } else if (is_address && sm_name[len] == '-') { + snprintf(printed_name, sizeof(printed_name), + "%s(*$)%s", add_star ? "*" : "", + sm_name + len); + } else { snprintf(printed_name, sizeof(printed_name), "%s$%s", add_star ? "*" : "", sm_name + len); + } } else { continue; } @@ -936,7 +983,32 @@ static void match_call_info(struct expression *call) stree = get_all_states_stree(cb->owner); i = 0; FOR_EACH_PTR(call->args, arg) { - print_struct_members(call, arg, i, stree, cb->callback); + print_struct_members(call, arg, i, stree, cb->callback, 0); + i++; + } END_FOR_EACH_PTR(arg); + free_stree(&stree); + } END_FOR_EACH_PTR(cb); + + free_string(name); +} + +static void match_call_info_new(struct expression *call) +{ + struct member_info_callback *cb; + struct expression *arg; + struct stree *stree; + char *name; + int i; + + name = get_fnptr_name(call->fn); + if (!name) + return; + + FOR_EACH_PTR(member_callbacks_new, cb) { + stree = get_all_states_stree(cb->owner); + i = 0; + FOR_EACH_PTR(call->args, arg) { + print_struct_members(call, arg, i, stree, cb->callback, 1); i++; } END_FOR_EACH_PTR(arg); free_stree(&stree); @@ -1106,6 +1178,7 @@ static void match_data_from_db(struct symbol *sym) if (!sym || !sym->ident) return; + set_fn_mtag(sym); gettimeofday(&data.start_time, NULL); __push_fake_cur_stree(); @@ -1569,7 +1642,7 @@ static int call_return_state_hooks_split_possible(struct expression *expr) { struct sm_state *sm; - if (!expr || expr_equal_to_param(expr, -1)) + if (!expr) return 0; sm = get_sm_state_expr(SMATCH_EXTRA, expr); @@ -1707,6 +1780,8 @@ static int call_return_state_hooks_split_null_non_null_zero(struct expression *e return 0; if (estate_min(state).value == 0 && estate_max(state).value == 0) return 0; + if (has_possible_negative(sm)) + return 0; if (!has_separate_zero_null(sm)) return 0; @@ -2020,6 +2095,24 @@ struct expression *strip_expr_statement(struct expression *expr) return strip_expr(last_stmt->expression); } +static bool is_kernel_error_path(struct expression *expr) +{ + struct range_list *rl; + + /* + * Splitting up returns requires resources. It also requires resources + * for the caller. It doesn't seem worth it to split anything up. + */ + if (!get_implied_rl(expr, &rl)) + return false; + if (rl_type(rl) != &int_ctype) + return false; + if (rl_min(rl).value >= -4095 && + rl_max(rl).value < 0) + return true; + return false; +} + static void call_return_state_hooks(struct expression *expr) { struct returned_state_callback *cb; @@ -2044,6 +2137,8 @@ static void call_return_state_hooks(struct expression *expr) return; } else if (call_return_state_hooks_conditional(expr)) { return; + } else if (is_kernel_error_path(expr)) { + goto vanilla; } else if (call_return_state_hooks_split_possible(expr)) { return; } else if (split_positive_from_negative(expr)) { @@ -2165,6 +2260,7 @@ static void init_memdb(void) "db/fn_ptr_data_link.schema", "db/fn_data_link.schema", "db/mtag_about.schema", + "db/mtag_info.schema", "db/mtag_map.schema", "db/mtag_data.schema", "db/mtag_alias.schema", @@ -2212,7 +2308,9 @@ static void init_cachedb(void) "db/call_implies.schema", "db/return_implies.schema", "db/type_info.schema", + "db/mtag_about.schema", "db/mtag_data.schema", + "db/mtag_info.schema", "db/sink_info.schema", }; static char buf[4096]; @@ -2277,13 +2375,20 @@ static int save_cache_data(void *_table, int argc, char **argv, char **azColName static void dump_cache(struct symbol_list *sym_list) { + const char *cache_tables[] = { + "type_info", "return_implies", "call_implies", "mtag_data", + "mtag_info", "mtag_about", "sink_info", + }; + char buf[64]; + int i; + if (!option_info) return; - cache_sql(&save_cache_data, (char *)"type_info", "select * from type_info;"); - cache_sql(&save_cache_data, (char *)"return_implies", "select * from return_implies;"); - cache_sql(&save_cache_data, (char *)"call_implies", "select * from call_implies;"); - cache_sql(&save_cache_data, (char *)"mtag_data", "select * from mtag_data;"); - cache_sql(&save_cache_data, (char *)"sink_info", "select * from sink_info;"); + + for (i = 0; i < ARRAY_SIZE(cache_tables); i++) { + snprintf(buf, sizeof(buf), "select * from %s;", cache_tables[i]); + cache_sql(&save_cache_data, (char *)cache_tables[i], buf); + } } void open_smatch_db(char *db_file) @@ -2429,6 +2534,7 @@ static void register_return_replacements(void) void register_definition_db_callbacks(int id) { add_hook(&match_call_info, FUNCTION_CALL_HOOK); + add_hook(&match_call_info_new, FUNCTION_CALL_HOOK); add_split_return_callback(match_return_info); add_split_return_callback(print_returned_struct_members); add_hook(&call_return_state_hooks, RETURN_HOOK); @@ -2493,9 +2599,11 @@ char *return_state_to_var_sym(struct expression *expr, int param, const char *ke char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym) { + struct symbol *type; char buf[256]; char *tmp; int star_cnt = 0; + bool add_dot = false; if (!arg) return NULL; @@ -2519,12 +2627,37 @@ char *get_variable_from_key(struct expression *arg, const char *key, struct symb } } + if (strncmp(key, "(*$)", 4) == 0) { + char buf[64]; + + if (arg->type == EXPR_PREOP && arg->op == '&') { + arg = strip_expr(arg->unop); + snprintf(buf, sizeof(buf), "$%s", key + 4); + return get_variable_from_key(arg, buf, sym); + } else { + tmp = expr_to_var_sym(arg, sym); + if (!tmp) + return NULL; + snprintf(buf, sizeof(buf), "(*%s)%s", tmp, key + 4); + free_string(tmp); + return alloc_string(buf); + } + } + while (key[0] == '*') { star_cnt++; key++; } - if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt) { + /* + * FIXME: This is a hack. + * We should be able to parse expressions like (*$)->foo and *$->foo. + */ + type = get_type(arg); + if (is_struct_ptr(type)) + add_dot = true; + + if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt && !add_dot) { arg = strip_expr(arg->unop); star_cnt--; } @@ -2573,6 +2706,14 @@ const char *state_name_to_param_name(const char *state_name, const char *param_n if (star_cnt > 10) return NULL; + if (strncmp(state_name, "(*", 2) == 0 && + strncmp(state_name + 2, param_name, name_len) == 0 && + state_name[name_len + 2] == ')') { + snprintf(buf, sizeof(buf), "%.*s(*$)%s", star_cnt, "**********", + state_name + name_len + 3); + return alloc_sname(buf); + } + if (strcmp(state_name, param_name) == 0) { snprintf(buf, sizeof(buf), "%.*s$", star_cnt, "**********"); return alloc_sname(buf); diff --git a/usr/src/tools/smatch/src/smatch_estate.c b/usr/src/tools/smatch/src/smatch_estate.c index 4882347776..c8cc4b76b0 100644 --- a/usr/src/tools/smatch/src/smatch_estate.c +++ b/usr/src/tools/smatch/src/smatch_estate.c @@ -56,6 +56,9 @@ struct smatch_state *merge_estates(struct smatch_state *s1, struct smatch_state if (estate_treat_untagged(s1) && estate_treat_untagged(s2)) estate_set_treat_untagged(tmp); + if (estate_new(s1) || estate_new(s2)) + estate_set_new(tmp); + return tmp; } @@ -126,6 +129,9 @@ int estate_has_hard_max(struct smatch_state *state) void estate_set_hard_max(struct smatch_state *state) { + /* pointers don't have a hard max */ + if (is_ptr_type(estate_type(state))) + return; get_dinfo(state)->hard_max = 1; } @@ -174,6 +180,18 @@ void estate_set_treat_untagged(struct smatch_state *state) get_dinfo(state)->treat_untagged = true; } +bool estate_new(struct smatch_state *state) +{ + if (!estate_rl(state)) + return false; + return get_dinfo(state)->set; +} + +void estate_set_new(struct smatch_state *state) +{ + get_dinfo(state)->set = true; +} + sval_t estate_min(struct smatch_state *state) { return rl_min(estate_rl(state)); @@ -226,6 +244,10 @@ int estates_equiv(struct smatch_state *one, struct smatch_state *two) return 0; if (estate_treat_untagged(one) != estate_treat_untagged(two)) return 0; + if (estate_has_hard_max(one) != estate_has_hard_max(two)) + return 0; + if (estate_new(one) != estate_new(two)) + return 0; if (strcmp(one->name, two->name) == 0) return 1; return 0; diff --git a/usr/src/tools/smatch/src/smatch_expressions.c b/usr/src/tools/smatch/src/smatch_expressions.c index 97f3c98ff6..c185b89b4f 100644 --- a/usr/src/tools/smatch/src/smatch_expressions.c +++ b/usr/src/tools/smatch/src/smatch_expressions.c @@ -27,7 +27,7 @@ struct expression *alloc_tmp_expression(struct position pos, int type) struct expression *expr; expr = __alloc_tmp_expression(0); - expr->smatch_flags |= Fake; + expr->smatch_flags |= Tmp; expr->type = type; expr->pos = pos; return expr; @@ -300,7 +300,7 @@ void expr_set_parent_expr(struct expression *expr, struct expression *parent) { if (!expr) return; - if (parent->smatch_flags & Fake) + if (parent && parent->smatch_flags & Tmp) return; expr->parent = (unsigned long)parent | 0x1UL; diff --git a/usr/src/tools/smatch/src/smatch_extra.c b/usr/src/tools/smatch/src/smatch_extra.c index 9d7744d97c..5d34a5d7ee 100644 --- a/usr/src/tools/smatch/src/smatch_extra.c +++ b/usr/src/tools/smatch/src/smatch_extra.c @@ -36,7 +36,6 @@ static int my_id; static int link_id; -extern int check_assigned_expr_id; static void match_link_modify(struct sm_state *sm, struct expression *mod_expr); @@ -172,12 +171,17 @@ done: static bool in_param_set; void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state) { + struct expression *faked; + if (!expr) expr = gen_expression_from_name_sym(name, sym); remove_from_equiv(name, sym); set_union_info(name, sym, expr, state); call_extra_mod_hooks(name, sym, expr, state); - update_mtag_data(expr, state); + faked = get_faked_expression(); + if (!faked || + (faked->type == EXPR_ASSIGNMENT && is_fresh_alloc(faked->right))) + update_mtag_data(expr, state); if (in_param_set && estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym)) return; @@ -2800,19 +2804,15 @@ static void set_param_value(const char *name, struct symbol *sym, char *key, cha struct range_list *rl = NULL; struct smatch_state *state; struct symbol *type; - char fullname[256]; char *key_orig = key; - bool add_star = false; + char *fullname; sval_t dummy; - if (key[0] == '*') { - add_star = true; - key++; - } - - snprintf(fullname, 256, "%s%s%s", add_star ? "*" : "", name, key + 1); - expr = symbol_expression(sym); + fullname = get_variable_from_key(expr, key, NULL); + if (!fullname) + return; + type = get_member_type_from_key(expr, key_orig); str_to_rl(type, value, &rl); state = alloc_estate_rl(rl); @@ -2823,17 +2823,16 @@ static void set_param_value(const char *name, struct symbol *sym, char *key, cha static void set_param_fuzzy_max(const char *name, struct symbol *sym, char *key, char *value) { + struct expression *expr; struct range_list *rl = NULL; struct smatch_state *state; struct symbol *type; - char fullname[256]; + char *fullname; sval_t max; - if (strcmp(key, "*$") == 0) - snprintf(fullname, sizeof(fullname), "*%s", name); - else if (strncmp(key, "$", 1) == 0) - snprintf(fullname, 256, "%s%s", name, key + 1); - else + expr = symbol_expression(sym); + fullname = get_variable_from_key(expr, key, NULL); + if (!fullname) return; state = get_state(SMATCH_EXTRA, fullname, sym); @@ -2849,13 +2848,12 @@ static void set_param_fuzzy_max(const char *name, struct symbol *sym, char *key, static void set_param_hard_max(const char *name, struct symbol *sym, char *key, char *value) { struct smatch_state *state; - char fullname[256]; + struct expression *expr; + char *fullname; - if (strcmp(key, "*$") == 0) - snprintf(fullname, sizeof(fullname), "*%s", name); - else if (strncmp(key, "$", 1) == 0) - snprintf(fullname, 256, "%s%s", name, key + 1); - else + expr = symbol_expression(sym); + fullname = get_variable_from_key(expr, key, NULL); + if (!fullname) return; state = get_state(SMATCH_EXTRA, fullname, sym); diff --git a/usr/src/tools/smatch/src/smatch_extra.h b/usr/src/tools/smatch/src/smatch_extra.h index 3fb917a5ea..222be0f29c 100644 --- a/usr/src/tools/smatch/src/smatch_extra.h +++ b/usr/src/tools/smatch/src/smatch_extra.h @@ -32,6 +32,7 @@ struct data_info { unsigned int hard_max:1; unsigned int capped:1; unsigned int treat_untagged:1; + unsigned int set:1; }; DECLARE_ALLOCATOR(data_info); @@ -101,6 +102,7 @@ struct range_list *rl_truncate_cast(struct symbol *type, struct range_list *rl); struct range_list *cast_rl(struct symbol *type, struct range_list *rl); int get_implied_rl(struct expression *expr, struct range_list **rl); int get_absolute_rl(struct expression *expr, struct range_list **rl); +void set_real_absolute(struct expression *expr, struct smatch_state *state); int get_real_absolute_rl(struct expression *expr, struct range_list **rl); struct range_list *var_to_absolute_rl(struct expression *expr); int custom_get_absolute_rl(struct expression *expr, @@ -151,6 +153,8 @@ bool estate_capped(struct smatch_state *state); void estate_set_capped(struct smatch_state *state); bool estate_treat_untagged(struct smatch_state *state); void estate_set_treat_untagged(struct smatch_state *state); +bool estate_new(struct smatch_state *state); +void estate_set_new(struct smatch_state *state); int estate_get_single_value(struct smatch_state *state, sval_t *sval); struct smatch_state *get_implied_estate(struct expression *expr); diff --git a/usr/src/tools/smatch/src/smatch_flow.c b/usr/src/tools/smatch/src/smatch_flow.c index 4a842027e3..1971599bbb 100644 --- a/usr/src/tools/smatch/src/smatch_flow.c +++ b/usr/src/tools/smatch/src/smatch_flow.c @@ -438,20 +438,20 @@ void __split_expr(struct expression *expr) /* foo = !bar() */ if (__handle_condition_assigns(expr)) - break; + goto after_assign; /* foo = (x < 5 ? foo : 5); */ if (__handle_select_assigns(expr)) - break; + goto after_assign; /* foo = ({frob(); frob(); frob(); 1;}) */ if (__handle_expr_statement_assigns(expr)) - break; + break; // FIXME: got after /* foo = (3, 4); */ if (handle_comma_assigns(expr)) - break; - if (handle_postop_assigns(expr)) - break; + goto after_assign; if (handle__builtin_choose_expr_assigns(expr)) - break; + goto after_assign; + if (handle_postop_assigns(expr)) + break; /* no need to goto after_assign */ __split_expr(expr->right); if (outside_of_function()) @@ -470,8 +470,8 @@ void __split_expr(struct expression *expr) get_macro_name(expr->pos) != get_macro_name(right->pos)) __pass_to_client(expr, MACRO_ASSIGNMENT_HOOK); +after_assign: __pass_to_client(expr, ASSIGNMENT_HOOK_AFTER); - __split_expr(expr->left); break; } diff --git a/usr/src/tools/smatch/src/smatch_fresh_alloc.c b/usr/src/tools/smatch/src/smatch_fresh_alloc.c index d7104f6b53..cec6b62c9e 100644 --- a/usr/src/tools/smatch/src/smatch_fresh_alloc.c +++ b/usr/src/tools/smatch/src/smatch_fresh_alloc.c @@ -23,6 +23,7 @@ */ #include "smatch.h" +#include "smatch_extra.h" #include "smatch_slist.h" static int my_id; @@ -65,6 +66,16 @@ struct alloc_info general_allocation_funcs[] = { {}, }; +static void pre_merge_hook(struct sm_state *cur, struct sm_state *other) +{ + struct smatch_state *state; + sval_t sval; + + state = get_state(SMATCH_EXTRA, cur->name, cur->sym); + if (estate_get_single_value(state, &sval) && sval.value == 0) + set_state(my_id, cur->name, cur->sym, &undefined); +} + static int fresh_callback(void *fresh, int argc, char **argv, char **azColName) { *(int *)fresh = 1; @@ -150,12 +161,23 @@ static void match_call(struct expression *expr) } END_FOR_EACH_PTR(arg); } +static struct expression *handled; static void set_fresh(struct expression *expr) { + struct range_list *rl; + expr = strip_expr(expr); if (expr->type != EXPR_SYMBOL) return; + if (expr == handled) + return; + + get_absolute_rl(expr, &rl); + rl = rl_intersection(rl, valid_ptr_rl); + if (!rl) + return; set_state_expr(my_id, expr, &fresh); + handled = expr; } static void returns_fresh_alloc(struct expression *expr, int param, char *key, char *value) @@ -192,4 +214,6 @@ void register_fresh_alloc(int id) select_return_states_hook(FRESH_ALLOC, &returns_fresh_alloc); add_hook(&match_assign, ASSIGNMENT_HOOK); add_hook(&match_call, FUNCTION_CALL_HOOK); + + add_pre_merge_hook(my_id, &pre_merge_hook); } diff --git a/usr/src/tools/smatch/src/smatch_function_hooks.c b/usr/src/tools/smatch/src/smatch_function_hooks.c index d38cff1936..f821d62189 100644 --- a/usr/src/tools/smatch/src/smatch_function_hooks.c +++ b/usr/src/tools/smatch/src/smatch_function_hooks.c @@ -357,6 +357,7 @@ struct db_callback_info { struct range_list *rl; int left; struct stree *stree; + struct stree *implied; struct db_implies_list *callbacks; int prev_return_id; int cull; @@ -367,6 +368,17 @@ struct db_callback_info { int handled; }; +static void set_implied_states(struct db_callback_info *db_info) +{ + struct sm_state *sm; + + FOR_EACH_SM(db_info->implied, sm) { + __set_sm(sm); + } END_FOR_EACH_SM(sm); + + free_stree(&db_info->implied); +} + static void store_return_state(struct db_callback_info *db_info, const char *ret_str, struct smatch_state *state) { db_info->ret_str = alloc_sname(ret_str), @@ -460,6 +472,26 @@ static bool fake_a_param_assignment(struct expression *expr, const char *return_ return true; } +static void set_fresh_mtag_returns(struct db_callback_info *db_info) +{ + struct expression *expr = db_info->expr->left; + struct smatch_state *state; + + if (!db_info->ret_state) + return; + + state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state)))); + state = get_mtag_return(db_info->expr, state); + if (!state) + return; + + set_real_absolute(expr, state); + set_extra_expr_mod(expr, state); + + db_info->ret_state = NULL; + db_info->ret_str = NULL; +} + static void set_return_assign_state(struct db_callback_info *db_info) { struct expression *expr = db_info->expr->left; @@ -635,8 +667,8 @@ static int db_compare_callback(void *_info, int argc, char **argv, char **azColN db_info->has_states = 1; if (db_info->prev_return_id != -1 && type == INTERNAL) { set_other_side_state(db_info); + set_implied_states(db_info); stree = __pop_fake_cur_stree(); - if (!db_info->cull) merge_fake_stree(&db_info->stree, stree); free_stree(&stree); @@ -672,14 +704,14 @@ static int db_compare_callback(void *_info, int argc, char **argv, char **azColN if (!possibly_true_rl(var_rl, comparison, ret_range)) return 0; if (type == PARAM_LIMIT) - param_limit_implications(db_info->expr, param, key, value); + param_limit_implications(db_info->expr, param, key, value, &db_info->implied); filter_by_comparison(&var_rl, comparison, ret_range); filter_by_comparison(&ret_range, flip_comparison(comparison), var_rl); } else { if (!possibly_false_rl(var_rl, comparison, ret_range)) return 0; if (type == PARAM_LIMIT) - param_limit_implications(db_info->expr, param, key, value); + param_limit_implications(db_info->expr, param, key, value, &db_info->implied); filter_by_comparison(&var_rl, negate_comparison(comparison), ret_range); filter_by_comparison(&ret_range, flip_comparison(negate_comparison(comparison)), var_rl); } @@ -744,6 +776,7 @@ static void compare_db_return_states_callbacks(struct expression *left, int comp sql_select_return_states("return_id, return, type, parameter, key, value", call_expr, db_compare_callback, &db_info); set_other_side_state(&db_info); + set_implied_states(&db_info); stree = __pop_fake_cur_stree(); if (!db_info.cull) merge_fake_stree(&db_info.stree, stree); @@ -769,6 +802,7 @@ static void compare_db_return_states_callbacks(struct expression *left, int comp sql_select_return_states("return_id, return, type, parameter, key, value", call_expr, db_compare_callback, &db_info); set_other_side_state(&db_info); + set_implied_states(&db_info); stree = __pop_fake_cur_stree(); if (!db_info.cull) merge_fake_stree(&db_info.stree, stree); @@ -893,6 +927,7 @@ static int db_assign_return_states_callback(void *_info, int argc, char **argv, if (db_info->prev_return_id != -1 && type == INTERNAL) { call_ranged_return_hooks(db_info); set_return_assign_state(db_info); + set_implied_states(db_info); stree = __pop_fake_cur_stree(); if (!db_info->cull) merge_fake_stree(&db_info->stree, stree); @@ -916,7 +951,7 @@ static int db_assign_return_states_callback(void *_info, int argc, char **argv, } if (type == PARAM_LIMIT) - param_limit_implications(db_info->expr, param, key, value); + param_limit_implications(db_info->expr, param, key, value, &db_info->implied); db_info->handled = 1; call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), ret_str, &ret_range); @@ -930,6 +965,7 @@ static int db_assign_return_states_callback(void *_info, int argc, char **argv, __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), ret_str); __add_return_to_param_mapping(db_info->expr, ret_str); store_return_state(db_info, ret_str, alloc_estate_rl(ret_range)); + set_fresh_mtag_returns(db_info); } FOR_EACH_PTR(db_return_states_list, tmp) { @@ -968,6 +1004,7 @@ static int db_return_states_assign(struct expression *expr) if (db_info.handled) call_ranged_return_hooks(&db_info); set_return_assign_state(&db_info); + set_implied_states(&db_info); stree = __pop_fake_cur_stree(); if (!db_info.cull) merge_fake_stree(&db_info.stree, stree); @@ -1079,6 +1116,7 @@ static int db_return_states_callback(void *_info, int argc, char **argv, char ** if (db_info->prev_return_id != -1 && type == INTERNAL) { call_ranged_return_hooks(db_info); + set_implied_states(db_info); stree = __pop_fake_cur_stree(); if (!db_info->cull) merge_fake_stree(&db_info->stree, stree); @@ -1103,7 +1141,7 @@ static int db_return_states_callback(void *_info, int argc, char **argv, char ** } if (type == PARAM_LIMIT) - param_limit_implications(db_info->expr, param, key, value); + param_limit_implications(db_info->expr, param, key, value, &db_info->implied); call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range); ret_range = cast_rl(get_type(db_info->expr), ret_range); @@ -1154,6 +1192,7 @@ static void db_return_states(struct expression *expr) sql_select_return_states("return_id, return, type, parameter, key, value", expr, db_return_states_callback, &db_info); call_ranged_return_hooks(&db_info); + set_implied_states(&db_info); stree = __pop_fake_cur_stree(); if (!db_info.cull) merge_fake_stree(&db_info.stree, stree); diff --git a/usr/src/tools/smatch/src/smatch_function_ptrs.c b/usr/src/tools/smatch/src/smatch_function_ptrs.c index fc9c51b6a6..f728337e99 100644 --- a/usr/src/tools/smatch/src/smatch_function_ptrs.c +++ b/usr/src/tools/smatch/src/smatch_function_ptrs.c @@ -218,7 +218,7 @@ char *get_fnptr_name(struct expression *expr) return alloc_string(buf); } - name = expr_to_var_sym(expr, &sym); + name = expr_to_var_sym(expr, &sym); if (!name) return NULL; type = get_type(expr); diff --git a/usr/src/tools/smatch/src/smatch_helper.c b/usr/src/tools/smatch/src/smatch_helper.c index 485f041123..812b65e8fe 100644 --- a/usr/src/tools/smatch/src/smatch_helper.c +++ b/usr/src/tools/smatch/src/smatch_helper.c @@ -147,7 +147,7 @@ struct expression *get_argument_from_call_expr(struct expression_list *args, return NULL; } -static struct expression *get_array_expr(struct expression *expr) +struct expression *get_array_expr(struct expression *expr) { struct expression *parent; struct symbol *type; @@ -174,10 +174,8 @@ static struct expression *get_array_expr(struct expression *expr) static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, struct expression *expr, int len, - int *complicated, int no_parens) + int *complicated) { - - if (!expr) { /* can't happen on valid code */ *complicated = 1; @@ -204,7 +202,7 @@ static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, } } - __get_variable_from_expr(sym_ptr, buf, deref, len, complicated, no_parens); + __get_variable_from_expr(sym_ptr, buf, deref, len, complicated); if (op == '*') append(buf, "->", len); @@ -236,20 +234,20 @@ static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, } if (expr->op == '(') { - if (!no_parens && expr->unop->type != EXPR_SYMBOL) + if (expr->unop->type != EXPR_SYMBOL) append(buf, "(", len); } else if (expr->op != '*' || !get_array_expr(expr->unop)) { tmp = show_special(expr->op); append(buf, tmp, len); } __get_variable_from_expr(sym_ptr, buf, expr->unop, - len, complicated, no_parens); + len, complicated); - if (expr->op == '(' && !no_parens && expr->unop->type != EXPR_SYMBOL) + if (expr->op == '(' && expr->unop->type != EXPR_SYMBOL) append(buf, ")", len); if (expr->op == SPECIAL_DECREMENT || - expr->op == SPECIAL_INCREMENT) + expr->op == SPECIAL_INCREMENT) *complicated = 1; return; @@ -258,7 +256,7 @@ static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, const char *tmp; __get_variable_from_expr(sym_ptr, buf, expr->unop, - len, complicated, no_parens); + len, complicated); tmp = show_special(expr->op); append(buf, tmp, len); @@ -276,14 +274,14 @@ static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, *complicated = 1; array_expr = get_array_expr(expr); if (array_expr) { - __get_variable_from_expr(sym_ptr, buf, array_expr, len, complicated, no_parens); + __get_variable_from_expr(sym_ptr, buf, array_expr, len, complicated); append(buf, "[", len); } else { - __get_variable_from_expr(sym_ptr, buf, expr->left, len, complicated, no_parens); + __get_variable_from_expr(sym_ptr, buf, expr->left, len, complicated); snprintf(tmp, sizeof(tmp), " %s ", show_special(expr->op)); append(buf, tmp, len); } - __get_variable_from_expr(NULL, buf, expr->right, len, complicated, no_parens); + __get_variable_from_expr(NULL, buf, expr->right, len, complicated); if (array_expr) append(buf, "]", len); return; @@ -321,13 +319,13 @@ static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, int i; *complicated = 1; - __get_variable_from_expr(NULL, buf, expr->fn, len, complicated, no_parens); + __get_variable_from_expr(NULL, buf, expr->fn, len, complicated); append(buf, "(", len); i = 0; FOR_EACH_PTR(expr->args, tmp) { if (i++) append(buf, ", ", len); - __get_variable_from_expr(NULL, buf, tmp, len, complicated, no_parens); + __get_variable_from_expr(NULL, buf, tmp, len, complicated); } END_FOR_EACH_PTR(tmp); append(buf, ")", len); return; @@ -336,7 +334,7 @@ static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, case EXPR_FORCE_CAST: __get_variable_from_expr(sym_ptr, buf, expr->cast_expression, len, - complicated, no_parens); + complicated); return; case EXPR_SIZEOF: { sval_t sval; @@ -358,16 +356,30 @@ static void __get_variable_from_expr(struct symbol **sym_ptr, char *buf, if (expr->expr_ident) append(buf, expr->expr_ident->name, len); return; - default: + case EXPR_SELECT: + case EXPR_CONDITIONAL: *complicated = 1; - //printf("unknown type = %d\n", expr->type); + append(buf, "(", len); + __get_variable_from_expr(NULL, buf, expr->conditional, len, complicated); + append(buf, ") ?", len); + if (expr->cond_true) + __get_variable_from_expr(NULL, buf, expr->cond_true, len, complicated); + append(buf, ":", len); + __get_variable_from_expr(NULL, buf, expr->cond_false, len, complicated); + return; + default: { + char tmp[64]; + + snprintf(tmp, sizeof(tmp), "$expr_%p(%d)", expr, expr->type); + append(buf, tmp, len); + *complicated = 1; + } return; } } struct expr_str_cache_results { struct expression *expr; - int no_parens; char str[VAR_LEN]; struct symbol *sym; int complicated; @@ -375,7 +387,7 @@ struct expr_str_cache_results { static void get_variable_from_expr(struct symbol **sym_ptr, char *buf, struct expression *expr, int len, - int *complicated, int no_parens) + int *complicated) { static struct expr_str_cache_results cached[8]; struct symbol *tmp_sym = NULL; @@ -383,8 +395,7 @@ static void get_variable_from_expr(struct symbol **sym_ptr, char *buf, int i; for (i = 0; i < ARRAY_SIZE(cached); i++) { - if (expr == cached[i].expr && - no_parens == cached[i].no_parens) { + if (expr == cached[i].expr) { strncpy(buf, cached[i].str, len); if (sym_ptr) *sym_ptr = cached[i].sym; @@ -393,12 +404,14 @@ static void get_variable_from_expr(struct symbol **sym_ptr, char *buf, } } - __get_variable_from_expr(&tmp_sym, buf, expr, len, complicated, no_parens); + __get_variable_from_expr(&tmp_sym, buf, expr, len, complicated); if (sym_ptr) *sym_ptr = tmp_sym; + if (expr->smatch_flags & Tmp) + return; + cached[idx].expr = expr; - cached[idx].no_parens = no_parens; strncpy(cached[idx].str, buf, VAR_LEN); cached[idx].sym = tmp_sym; cached[idx].complicated = *complicated; @@ -427,7 +440,7 @@ char *expr_to_str_sym(struct expression *expr, struct symbol **sym_ptr) if (!expr) return NULL; get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name), - &complicated, 0); + &complicated); if (complicated < 2) return alloc_string(var_name); else @@ -458,7 +471,7 @@ char *expr_to_var_sym(struct expression *expr, return NULL; expr = strip_expr(expr); get_variable_from_expr(sym_ptr, var_name, expr, sizeof(var_name), - &complicated, 1); + &complicated); if (complicated) { if (sym_ptr) @@ -1051,8 +1064,23 @@ int get_param_num_from_sym(struct symbol *sym) struct symbol *tmp; int i; - if (!cur_func_sym) - return -1; + if (!sym) + return UNKNOWN_SCOPE; + + if (sym->ctype.modifiers & MOD_TOPLEVEL) { + if (sym->ctype.modifiers & MOD_STATIC) + return FILE_SCOPE; + return GLOBAL_SCOPE; + } + + if (!cur_func_sym) { + if (!parse_error) { + sm_msg("warn: internal. problem with scope: %s", + sym->ident ? sym->ident->name : "<anon var>"); + } + return GLOBAL_SCOPE; + } + i = 0; FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, tmp) { @@ -1060,7 +1088,7 @@ int get_param_num_from_sym(struct symbol *sym) return i; i++; } END_FOR_EACH_PTR(tmp); - return -1; + return LOCAL_SCOPE; } int get_param_num(struct expression *expr) @@ -1069,11 +1097,11 @@ int get_param_num(struct expression *expr) char *name; if (!cur_func_sym) - return -1; + return UNKNOWN_SCOPE; name = expr_to_var_sym(expr, &sym); free_string(name); if (!sym) - return -1; + return UNKNOWN_SCOPE; return get_param_num_from_sym(sym); } diff --git a/usr/src/tools/smatch/src/smatch_implied.c b/usr/src/tools/smatch/src/smatch_implied.c index b498c8e71f..477dab791d 100644 --- a/usr/src/tools/smatch/src/smatch_implied.c +++ b/usr/src/tools/smatch/src/smatch_implied.c @@ -72,6 +72,8 @@ bool implications_off; bool debug_implied(void) { + if (option_debug) + return true; return implied_debug; } @@ -91,6 +93,13 @@ static struct range_list *tmp_range_list(struct symbol *type, long long num) return my_list; } +static const char *show_comparison(int op) +{ + if (op == PARAM_LIMIT) + return "<lim>"; + return show_special(op); +} + static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse) { if (!implied_debug && !option_debug) @@ -115,6 +124,18 @@ static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse) } } +void split_comparison_helper(struct range_list *left_orig, int op, struct range_list *right_orig, + struct range_list **left_true_rl, struct range_list **left_false_rl) +{ + if (op == PARAM_LIMIT) { + *left_true_rl = rl_intersection(left_orig, right_orig); + *left_false_rl = rl_filter(left_orig, right_orig); + return; + } + + split_comparison_rl(left_orig, op, right_orig, left_true_rl, left_false_rl, NULL, NULL); +} + static int create_fake_history(struct sm_state *sm, int comparison, struct range_list *rl) { struct range_list *orig_rl; @@ -131,7 +152,7 @@ static int create_fake_history(struct sm_state *sm, int comparison, struct range return 0; orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state)); - split_comparison_rl(orig_rl, comparison, rl, &true_rl, &false_rl, NULL, NULL); + split_comparison_helper(orig_rl, comparison, rl, &true_rl, &false_rl); true_rl = rl_truncate_cast(estate_type(sm->state), true_rl); false_rl = rl_truncate_cast(estate_type(sm->state), false_rl); @@ -154,7 +175,7 @@ static int create_fake_history(struct sm_state *sm, int comparison, struct range if (implied_debug) sm_msg("fake_history: %s vs %s. %s %s %s. --> T: %s F: %s", - sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl), + sm->name, show_rl(rl), sm->state->name, show_comparison(comparison), show_rl(rl), show_rl(true_rl), show_rl(false_rl)); true_sm = clone_sm(sm); @@ -233,6 +254,32 @@ static int remove_pool(struct state_list **pools, struct stree *remove) return ret; } +static bool possibly_true_helper(struct range_list *var_rl, int comparison, struct range_list *rl) +{ + if (comparison == PARAM_LIMIT) { + struct range_list *intersect; + + intersect = rl_intersection(var_rl, rl); + if (intersect) + return true; + return false; + } + return possibly_true_rl(var_rl, comparison, rl); +} + +static bool possibly_false_helper(struct range_list *var_rl, int comparison, struct range_list *rl) +{ + if (comparison == PARAM_LIMIT) { + struct range_list *intersect; + + intersect = rl_intersection(var_rl, rl); + if (!rl_equiv(var_rl, intersect)) + return true; + return false; + } + return possibly_false_rl(var_rl, comparison, rl); +} + /* * If 'foo' == 99 add it that pool to the true pools. If it's false, add it to * the false pools. If we're not sure, then we don't add it to either. @@ -252,8 +299,8 @@ static void do_compare(struct sm_state *sm, int comparison, struct range_list *r var_rl = cast_rl(rl_type(rl), estate_rl(sm->state)); - istrue = !possibly_false_rl(var_rl, comparison, rl); - isfalse = !possibly_true_rl(var_rl, comparison, rl); + istrue = !possibly_false_helper(var_rl, comparison, rl); + isfalse = !possibly_true_helper(var_rl, comparison, rl); print_debug_tf(sm, istrue, isfalse); @@ -315,7 +362,7 @@ static void __separate_pools(struct sm_state *sm, int comparison, struct range_l if (diff.tv_sec >= 1) { if (implied_debug) { sm_msg("debug: %s: implications taking too long. (%s %s %s)", - __func__, sm->state->name, show_special(comparison), show_rl(rl)); + __func__, sm->state->name, show_comparison(comparison), show_rl(rl)); } if (mixed) *mixed = 1; @@ -538,9 +585,9 @@ struct sm_state *filter_pools(struct sm_state *sm, } static struct stree *filter_stack(struct sm_state *gate_sm, - struct stree *pre_stree, - const struct state_list *remove_stack, - const struct state_list *keep_stack) + struct stree *pre_stree, + const struct state_list *remove_stack, + const struct state_list *keep_stack) { struct stree *ret = NULL; struct sm_state *tmp; @@ -593,7 +640,7 @@ static void separate_and_filter(struct sm_state *sm, int comparison, struct rang gettimeofday(&time_before, NULL); DIMPLIED("checking implications: (%s (%s) %s %s)\n", - sm->name, sm->state->name, show_special(comparison), show_rl(rl)); + sm->name, sm->state->name, show_comparison(comparison), show_rl(rl)); if (!is_merged(sm)) { DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line); @@ -752,7 +799,7 @@ static int handle_zero_comparison(struct expression *expr, if (!name || !sym) goto free; sm = get_sm_state(SMATCH_EXTRA, name, sym); - if (!sm) + if (!sm || !sm->merged) goto free; separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed); @@ -770,13 +817,13 @@ free: } static int handled_by_comparison_hook(struct expression *expr, - struct stree **implied_true, - struct stree **implied_false) + struct stree **implied_true, + struct stree **implied_false) { + struct sm_state *sm, *true_sm, *false_sm; struct state_list *true_stack = NULL; struct state_list *false_stack = NULL; struct stree *pre_stree; - struct sm_state *sm; sm = comparison_implication_hook(expr, &true_stack, &false_stack); if (!sm) @@ -787,6 +834,13 @@ static int handled_by_comparison_hook(struct expression *expr, *implied_true = filter_stack(sm, pre_stree, false_stack, true_stack); *implied_false = filter_stack(sm, pre_stree, true_stack, false_stack); + true_sm = get_sm_state_stree(*implied_true, sm->owner, sm->name, sm->sym); + false_sm = get_sm_state_stree(*implied_false, sm->owner, sm->name, sm->sym); + if (true_sm && strcmp(true_sm->state->name, "unknown") == 0) + delete_state_stree(implied_true, sm->owner, sm->name, sm->sym); + if (false_sm && strcmp(false_sm->state->name, "unknown") == 0) + delete_state_stree(implied_false, sm->owner, sm->name, sm->sym); + free_stree(&pre_stree); free_slist(&true_stack); free_slist(&false_stack); @@ -953,9 +1007,9 @@ static void set_extra_implied_states(struct expression *expr) set_implied_states(NULL); } -void param_limit_implications(struct expression *expr, int param, char *key, char *value) +void param_limit_implications(struct expression *expr, int param, char *key, char *value, struct stree **implied) { - struct expression *arg; + struct expression *orig_expr, *arg; struct symbol *compare_type; char *name; struct symbol *sym; @@ -964,10 +1018,14 @@ void param_limit_implications(struct expression *expr, int param, char *key, cha struct stree *implied_true = NULL; struct stree *implied_false = NULL; struct range_list *orig, *limit; + char *left_name = NULL; + struct symbol *left_sym = NULL; + int mixed = 0; if (time_parsing_function() > 40) return; + orig_expr = expr; while (expr->type == EXPR_ASSIGNMENT) expr = strip_expr(expr->right); if (expr->type != EXPR_CALL) @@ -999,9 +1057,25 @@ void param_limit_implications(struct expression *expr, int param, char *key, cha call_results_to_rl(expr, compare_type, value, &limit); - separate_and_filter(sm, SPECIAL_EQUAL, limit, __get_cur_stree(), &implied_true, &implied_false, NULL); + separate_and_filter(sm, PARAM_LIMIT, limit, __get_cur_stree(), &implied_true, &implied_false, &mixed); + + if (orig_expr->type == EXPR_ASSIGNMENT) + left_name = expr_to_var_sym(orig_expr->left, &left_sym); FOR_EACH_SM(implied_true, tmp) { + /* + * What we're trying to do here is preserve the sm state so that + * smatch extra doesn't create a new sm state when it parses the + * PARAM_LIMIT. + */ + if (!mixed && tmp->sym == sym && + strcmp(tmp->name, name) == 0 && + (!left_name || strcmp(left_name, name) != 0)) { + overwrite_sm_state_stree(implied, tmp); + continue; + } + + // TODO why can't this just be __set_sm()? __set_sm_fake_stree(tmp); } END_FOR_EACH_SM(tmp); diff --git a/usr/src/tools/smatch/src/smatch_kernel_user_data.c b/usr/src/tools/smatch/src/smatch_kernel_user_data.c index cda3b58d9d..0ed3a84577 100644 --- a/usr/src/tools/smatch/src/smatch_kernel_user_data.c +++ b/usr/src/tools/smatch/src/smatch_kernel_user_data.c @@ -1067,21 +1067,6 @@ static void match_call_info(struct expression *expr) } END_FOR_EACH_PTR(arg); } -static int is_struct_ptr(struct symbol *sym) -{ - struct symbol *type; - - if (!sym) - return 0; - type = get_real_base_type(sym); - if (!type || type->type != SYM_PTR) - return 0; - type = get_real_base_type(type); - if (!type || type->type != SYM_STRUCT) - return 0; - return 1; -} - static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm) { struct smatch_state *state; diff --git a/usr/src/tools/smatch/src/smatch_math.c b/usr/src/tools/smatch/src/smatch_math.c index e6e033172f..bfb698e67c 100644 --- a/usr/src/tools/smatch/src/smatch_math.c +++ b/usr/src/tools/smatch/src/smatch_math.c @@ -335,6 +335,27 @@ static int handle_offset_subtraction(struct expression *expr) return left_offset - right_offset; } +static bool max_is_unknown_max(struct range_list *rl) +{ + /* + * The issue with this code is that we had: + * if (foo > 1) return 1 - foo; + * Ideally we would say that returns s32min-(-1) but what Smatch + * was saying was that the lowest possible value was "1 - INT_MAX" + * + * My solution is to ignore max values for int or larger. I keep + * the max for shorts etc, because those might be worthwhile. + * + * The problem with just returning 1 - INT_MAX is that that is + * treated as useful information but s32min is treated as basically + * unknown. + */ + + if (type_bits(rl_type(rl)) < 31) + return false; + return sval_is_max(rl_max(rl)); +} + static bool handle_subtract_rl(struct expression *expr, int implied, int *recurse_cnt, struct range_list **res) { struct symbol *type; @@ -409,7 +430,8 @@ static bool handle_subtract_rl(struct expression *expr, int implied, int *recurs return true; } - if (!sval_binop_overflows(rl_min(left_rl), '-', rl_max(right_rl))) { + if (!max_is_unknown_max(right_rl) && + !sval_binop_overflows(rl_min(left_rl), '-', rl_max(right_rl))) { tmp = sval_binop(rl_min(left_rl), '-', rl_max(right_rl)); if (sval_cmp(tmp, min) > 0) min = tmp; @@ -1215,7 +1237,7 @@ static bool handle_call_rl(struct expression *expr, int implied, int *recurse_cn if (sym_name_is("strlen", expr->fn)) return handle_strlen(expr, implied, recurse_cnt, res, res_sval); - if (implied == RL_EXACT || implied == RL_HARD || implied == RL_FUZZY) + if (implied == RL_EXACT || implied == RL_HARD) return false; if (custom_handle_variable) { diff --git a/usr/src/tools/smatch/src/smatch_mtag.c b/usr/src/tools/smatch/src/smatch_mtag.c index 607ede688b..fc20107140 100644 --- a/usr/src/tools/smatch/src/smatch_mtag.c +++ b/usr/src/tools/smatch/src/smatch_mtag.c @@ -68,42 +68,64 @@ mtag_t str_to_mtag(const char *str) return *tag; } -const struct { - const char *name; - int size_arg; -} allocator_info[] = { - { "kmalloc", 0 }, - { "kzalloc", 0 }, - { "devm_kmalloc", 1}, - { "devm_kzalloc", 1}, -}; - -static bool is_mtag_call(struct expression *expr) +static int save_allocator(void *_allocator, int argc, char **argv, char **azColName) +{ + char **allocator = _allocator; + + if (*allocator) { + if (strcmp(*allocator, argv[0]) == 0) + return 0; + /* should be impossible */ + free_string(*allocator); + *allocator = alloc_string("unknown"); + return 0; + } + *allocator = alloc_string(argv[0]); + return 0; +} + +char *get_allocator_info_from_tag(mtag_t tag) +{ + char *allocator = NULL; + + run_sql(save_allocator, &allocator, + "select value from mtag_info where tag = %lld and type = %d;", + tag, ALLOCATOR); + + return allocator; +} + +static char *get_allocator_info(struct expression *expr, struct smatch_state *state) { - struct expression *arg; - int i; sval_t sval; + if (expr->type != EXPR_ASSIGNMENT) + return NULL; + if (estate_get_single_value(state, &sval)) + return get_allocator_info_from_tag(sval.value); + + expr = strip_expr(expr->right); if (expr->type != EXPR_CALL || - expr->fn->type != EXPR_SYMBOL || - !expr->fn->symbol) - return false; + !expr->fn || + expr->fn->type != EXPR_SYMBOL) + return NULL; + return expr_to_str(expr->fn); +} - for (i = 0; i < ARRAY_SIZE(allocator_info); i++) { - if (strcmp(expr->fn->symbol->ident->name, allocator_info[i].name) == 0) - break; - } - if (i == ARRAY_SIZE(allocator_info)) - return false; +static void update_mtag_info(struct expression *expr, mtag_t tag, + const char *left_name, const char *tag_info, + struct smatch_state *state) +{ + char *allocator; - arg = get_argument_from_call_expr(expr->args, allocator_info[i].size_arg); - if (!get_implied_value(arg, &sval)) - return false; + sql_insert_mtag_about(tag, left_name, tag_info); - return true; + allocator = get_allocator_info(expr, state); + if (allocator) + sql_insert_mtag_info(tag, ALLOCATOR, allocator); } -struct smatch_state *swap_mtag_return(struct expression *expr, struct smatch_state *state) +struct smatch_state *get_mtag_return(struct expression *expr, struct smatch_state *state) { struct expression *left, *right; char *left_name, *right_name; @@ -114,20 +136,18 @@ struct smatch_state *swap_mtag_return(struct expression *expr, struct smatch_sta sval_t tag_sval; if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=') - return state; - - if (!estate_rl(state) || strcmp(state->name, "0,4096-ptr_max") != 0) - return state; + return NULL; + if (!is_fresh_alloc(expr->right)) + return NULL; + if (!rl_intersection(estate_rl(state), valid_ptr_rl)) + return NULL; left = strip_expr(expr->left); right = strip_expr(expr->right); - if (!is_mtag_call(right)) - return state; - left_name = expr_to_str_sym(left, &left_sym); if (!left_name || !left_sym) - return state; + return NULL; right_name = expr_to_str(right); snprintf(buf, sizeof(buf), "%s %s %s %s", get_filename(), get_function(), @@ -140,7 +160,7 @@ struct smatch_state *swap_mtag_return(struct expression *expr, struct smatch_sta rl = clone_rl(rl); add_range(&rl, tag_sval, tag_sval); - sql_insert_mtag_about(tag, left_name, buf); + update_mtag_info(expr, tag, left_name, buf, state); free_string(left_name); free_string(right_name); diff --git a/usr/src/tools/smatch/src/smatch_mtag_data.c b/usr/src/tools/smatch/src/smatch_mtag_data.c index c18a2e9725..7c690bb95b 100644 --- a/usr/src/tools/smatch/src/smatch_mtag_data.c +++ b/usr/src/tools/smatch/src/smatch_mtag_data.c @@ -81,8 +81,47 @@ static bool is_ignored_macro(struct expression *expr) return false; } +static bool is_head_next(struct expression *expr) +{ + struct symbol *type; + + /* Smatch thinks head->next == head is always true. *sad face* */ + + if (option_project != PROJ_KERNEL) + return false; + + if (expr->type != EXPR_DEREF) + return false; + if (!expr->member || !expr->member->name || + strcmp(expr->member->name, "next") != 0) + return false; + + type = get_type(expr->deref); + if (!type) + return false; + if (type->type == SYM_PTR) + type = get_real_base_type(type); + if (type->type != SYM_STRUCT) + return false; + if (!type->ident || !type->ident->name || + strcmp(type->ident->name, "list_head") != 0) + return false; + return true; +} + +mtag_t ignored_mtag; +static bool is_ignored_tag(mtag_t tag) +{ + if (tag == ignored_mtag) + return true; + return false; +} + static void insert_mtag_data(mtag_t tag, int offset, struct range_list *rl) { + if (is_ignored_tag(tag)) + return; + rl = clone_rl_permanent(rl); mem_sql(NULL, NULL, "delete from mtag_data where tag = %lld and offset = %d and type = %d", @@ -104,6 +143,16 @@ static bool invalid_type(struct symbol *type) return false; } +static bool parent_is_fresh_alloc(struct expression *expr) +{ + struct symbol *sym; + + sym = expr_to_sym(expr); + if (!sym || !sym->ident) + return false; + return is_fresh_alloc_var_sym(sym->ident->name, sym); +} + void update_mtag_data(struct expression *expr, struct smatch_state *state) { struct range_list *orig, *new; @@ -118,6 +167,8 @@ void update_mtag_data(struct expression *expr, struct smatch_state *state) return; if (is_ignored_macro(expr)) return; + if (is_head_next(expr)) + return; name = expr_to_var(expr); if (is_kernel_param(name)) { free_string(name); @@ -132,7 +183,10 @@ void update_mtag_data(struct expression *expr, struct smatch_state *state) if (offset == 0 && invalid_type(type)) return; - orig = select_orig(tag, offset); + if (parent_is_fresh_alloc(expr)) + orig = NULL; + else + orig = select_orig(tag, offset); new = rl_union(orig, estate_rl(state)); insert_mtag_data(tag, offset, new); } @@ -146,6 +200,8 @@ static void match_global_assign(struct expression *expr) if (is_ignored_macro(expr)) return; + if (is_head_next(expr->left)) + return; name = expr_to_var(expr->left); if (is_kernel_param(name)) { free_string(name); @@ -278,6 +334,7 @@ void register_mtag_data(int id) { my_id = id; + ignored_mtag = str_to_mtag("extern boot_params"); add_hook(&clear_cache, FUNC_DEF_HOOK); // if (!option_info) diff --git a/usr/src/tools/smatch/src/smatch_mtag_map.c b/usr/src/tools/smatch/src/smatch_mtag_map.c index 4ca0e00c08..5e3fab9ad1 100644 --- a/usr/src/tools/smatch/src/smatch_mtag_map.c +++ b/usr/src/tools/smatch/src/smatch_mtag_map.c @@ -29,8 +29,8 @@ static int my_id; static void match_assign(struct expression *expr) { struct expression *left, *right; - mtag_t left_tag; - int offset; + mtag_t right_tag, left_tag; + int right_offset, left_offset; sval_t sval; if (expr->op != '=') @@ -46,13 +46,14 @@ static void match_assign(struct expression *expr) if (sval_cmp(sval, valid_ptr_min_sval) < 0 || sval_cmp(sval, valid_ptr_max_sval) > 0) return; - if (sval.uvalue & MTAG_OFFSET_MASK) - return; + right_tag = sval.uvalue & ~MTAG_OFFSET_MASK; + right_offset = sval.uvalue & MTAG_OFFSET_MASK; - if (!expr_to_mtag_offset(left, &left_tag, &offset)) + if (!expr_to_mtag_offset(left, &left_tag, &left_offset) || + left_offset >= MTAG_OFFSET_MASK) return; - sql_insert_mtag_map(sval.uvalue, -offset, left_tag); + sql_insert_mtag_map(left_tag, left_offset, right_tag, right_offset); } void register_mtag_map(int id) diff --git a/usr/src/tools/smatch/src/smatch_param_to_mtag_data.c b/usr/src/tools/smatch/src/smatch_param_to_mtag_data.c index cd50dc7554..454c512e9c 100644 --- a/usr/src/tools/smatch/src/smatch_param_to_mtag_data.c +++ b/usr/src/tools/smatch/src/smatch_param_to_mtag_data.c @@ -156,8 +156,9 @@ static void assign_to_alias(struct expression *expr, int param, mtag_t tag, int // insert_mtag_data(alias, offset, rl); // FIXME: is arg_offset handled correctly? - if (expr_to_mtag_offset(gen_expr, &arg_tag, &arg_offset) && arg_offset == 0) - sql_insert_mtag_map(arg_tag, -offset, alias); + if (expr_to_mtag_offset(gen_expr, &arg_tag, &arg_offset) && + arg_offset < MTAG_OFFSET_MASK) + sql_insert_mtag_map(alias, offset, arg_tag, arg_offset); } static void call_does_mtag_assign(struct expression *expr, int param, char *key, char *value) diff --git a/usr/src/tools/smatch/src/smatch_real_absolute.c b/usr/src/tools/smatch/src/smatch_real_absolute.c index 3d98ee6356..8ea60bfba5 100644 --- a/usr/src/tools/smatch/src/smatch_real_absolute.c +++ b/usr/src/tools/smatch/src/smatch_real_absolute.c @@ -36,6 +36,11 @@ static int my_id; +void set_real_absolute(struct expression *expr, struct smatch_state *state) +{ + set_state_expr(my_id, expr, clone_estate(state)); +} + static void extra_mod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state) { struct smatch_state *abs; diff --git a/usr/src/tools/smatch/src/smatch_return_to_param.c b/usr/src/tools/smatch/src/smatch_return_to_param.c index ec8e3a9cc5..9d9d777ffa 100644 --- a/usr/src/tools/smatch/src/smatch_return_to_param.c +++ b/usr/src/tools/smatch/src/smatch_return_to_param.c @@ -28,7 +28,6 @@ #include "smatch_slist.h" #include "smatch_extra.h" -extern int check_assigned_expr_id; static int my_id; static int link_id; diff --git a/usr/src/tools/smatch/src/smatch_scripts/build_kernel_data.sh b/usr/src/tools/smatch/src/smatch_scripts/build_kernel_data.sh index 1dd9616688..4fdf9ab0f8 100755 --- a/usr/src/tools/smatch/src/smatch_scripts/build_kernel_data.sh +++ b/usr/src/tools/smatch/src/smatch_scripts/build_kernel_data.sh @@ -37,6 +37,7 @@ fi BUILD_STATUS=0 $SCRIPT_DIR/test_kernel.sh --call-tree --info --spammy --data=$DATA_DIR || BUILD_STATUS=$? +echo "smatch_warns.txt built." for i in $SCRIPT_DIR/gen_* ; do $i smatch_warns.txt -p=kernel diff --git a/usr/src/tools/smatch/src/smatch_scripts/summarize_errs.sh b/usr/src/tools/smatch/src/smatch_scripts/summarize_errs.sh index 58cf82201f..4c1fe031be 100755 --- a/usr/src/tools/smatch/src/smatch_scripts/summarize_errs.sh +++ b/usr/src/tools/smatch/src/smatch_scripts/summarize_errs.sh @@ -29,7 +29,7 @@ save_thoughts() read ans if echo $ans | grep ^$ > /dev/null ; then return - fi + fi #store the result echo $sm_err >> summary @@ -76,7 +76,7 @@ for sm_err in $TXT ; do set_title $sm_err - #grep -A1 "$file $line" *summary* 2> /dev/null + #grep -A1 "$file $line" *summary* 2> /dev/null grep -A1 -F "$last" *summary* 2> /dev/null ans="?" @@ -102,5 +102,5 @@ for sm_err in $TXT ; do vim $file +${line} save_thoughts -done +done IFS= diff --git a/usr/src/tools/smatch/src/smatch_slist.c b/usr/src/tools/smatch/src/smatch_slist.c index c95133f282..cdee9bcfe1 100644 --- a/usr/src/tools/smatch/src/smatch_slist.c +++ b/usr/src/tools/smatch/src/smatch_slist.c @@ -456,6 +456,9 @@ struct sm_state *merge_sm_states(struct sm_state *one, struct sm_state *two) struct sm_state *result; static int warned; + if (one->state->data && !has_dynamic_states(one->owner)) + sm_msg("dynamic state: %s", show_sm(one)); + if (one == two) return one; if (out_of_memory()) { diff --git a/usr/src/tools/smatch/src/smatch_states.c b/usr/src/tools/smatch/src/smatch_states.c index 7ae8f4a02b..f099b30307 100644 --- a/usr/src/tools/smatch/src/smatch_states.c +++ b/usr/src/tools/smatch/src/smatch_states.c @@ -74,6 +74,24 @@ void __print_cur_stree(void) __print_stree(cur_stree); } +bool __print_states(const char *owner) +{ + struct sm_state *sm; + bool found = false; + + if (!owner) + return false; + + FOR_EACH_SM(__get_cur_stree(), sm) { + if (!strstr(check_name(sm->owner), owner)) + continue; + sm_msg("%s", show_sm(sm)); + found = true; + } END_FOR_EACH_SM(sm); + + return found; +} + int unreachable(void) { if (!cur_stree) @@ -91,6 +109,45 @@ void __set_cur_stree_writable(void) read_only--; } +DECLARE_PTR_LIST(check_tracker_list, check_tracker_hook *); +static struct check_tracker_list **tracker_hooks; + +void add_check_tracker(const char *check_name, check_tracker_hook *fn) +{ + check_tracker_hook **p; + int owner; + + owner = id_from_name(check_name); + if (!owner) { + printf("check not found. '%s'\n", check_name); + return; + } + + p = malloc(sizeof(check_tracker_hook *)); + *p = fn; + add_ptr_list(&tracker_hooks[owner], p); +} + +static void call_tracker_hooks(int owner, const char *name, struct symbol *sym, struct smatch_state *state) +{ + struct check_tracker_list *hooks; + check_tracker_hook **fn; + + if ((unsigned short)owner == USHRT_MAX) + return; + + hooks = tracker_hooks[owner]; + FOR_EACH_PTR(hooks, fn) { + (*fn)(owner, name, sym, state); + } END_FOR_EACH_PTR(fn); +} + +void allocate_tracker_array(int num_checks) +{ + tracker_hooks = malloc(num_checks * sizeof(void *)); + memset(tracker_hooks, 0, num_checks * sizeof(void *)); +} + struct sm_state *set_state(int owner, const char *name, struct symbol *sym, struct smatch_state *state) { struct sm_state *ret; @@ -114,6 +171,8 @@ struct sm_state *set_state(int owner, const char *name, struct symbol *sym, stru show_state(state)); } + call_tracker_hooks(owner, name, sym, state); + if (owner != -1 && unreachable()) return NULL; diff --git a/usr/src/tools/smatch/src/smatch_struct_assignment.c b/usr/src/tools/smatch/src/smatch_struct_assignment.c index 2670eca445..d82122018e 100644 --- a/usr/src/tools/smatch/src/smatch_struct_assignment.c +++ b/usr/src/tools/smatch/src/smatch_struct_assignment.c @@ -151,6 +151,9 @@ static void handle_non_struct_assignments(struct expression *left, struct expres struct symbol *type; struct expression *assign; + while (right && right->type == EXPR_ASSIGNMENT) + right = strip_parens(right->left); + type = get_type(left); if (!type) return; @@ -234,7 +237,6 @@ static void __struct_members_copy(int mode, struct expression *faked, struct expression *assign; int op = '.'; - if (__in_fake_assign) return; faked_expression = faked; @@ -242,6 +244,9 @@ static void __struct_members_copy(int mode, struct expression *faked, left = strip_expr(left); right = strip_expr(right); + if (left->type == EXPR_PREOP && left->op == '*' && is_pointer(left)) + left = preop_expression(left, '('); + struct_type = get_struct_type(left); if (!struct_type) { /* diff --git a/usr/src/tools/smatch/src/smatch_type.c b/usr/src/tools/smatch/src/smatch_type.c index be54ced235..c1cc6df19f 100644 --- a/usr/src/tools/smatch/src/smatch_type.c +++ b/usr/src/tools/smatch/src/smatch_type.c @@ -551,6 +551,16 @@ int is_string(struct expression *expr) return 0; } +bool is_struct_ptr(struct symbol *type) +{ + if (!type || type->type != SYM_PTR) + return false; + type = get_real_base_type(type); + if (!type || type->type != SYM_STRUCT) + return false; + return true; +} + int is_static(struct expression *expr) { char *name; @@ -595,6 +605,23 @@ int types_equiv(struct symbol *one, struct symbol *two) return 1; } +bool type_fits(struct symbol *type, struct symbol *test) +{ + if (!type || !test) + return false; + + if (type == test) + return true; + + if (type_bits(test) > type_bits(type)) + return false; + if (type_signed(test) && !type_signed(type)) + return false; + if (type_positive_bits(test) > type_positive_bits(type)) + return false; + return true; +} + int fn_static(void) { return !!(cur_func_sym->ctype.modifiers & MOD_STATIC); @@ -685,6 +712,8 @@ static struct symbol *get_member_from_string(struct symbol_list *symbol_list, co struct symbol *get_member_type_from_key(struct expression *expr, const char *key) { struct symbol *sym; + int star = 0; + int i; if (strcmp(key, "$") == 0) return get_type(expr); @@ -702,11 +731,26 @@ struct symbol *get_member_type_from_key(struct expression *expr, const char *key if (sym->type == SYM_PTR) sym = get_real_base_type(sym); - key = key + 1; + while (*key == '*') { + key++; + star++; + } + + if (*key != '$') + return NULL; + key++; + sym = get_member_from_string(sym->symbol_list, key); if (!sym) return NULL; - return get_real_base_type(sym); + if (sym->type == SYM_RESTRICT || sym->type == SYM_NODE) + sym = get_real_base_type(sym); + for (i = 0; i < star; i++) { + if (!sym || sym->type != SYM_PTR) + return NULL; + sym = get_real_base_type(sym); + } + return sym; } struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key) diff --git a/usr/src/tools/smatch/src/smatch_type_val.c b/usr/src/tools/smatch/src/smatch_type_val.c index 16445eccdb..3c9f649272 100644 --- a/usr/src/tools/smatch/src/smatch_type_val.c +++ b/usr/src/tools/smatch/src/smatch_type_val.c @@ -337,6 +337,8 @@ static int is_ignored_function(void) return 1; if (sym_name_is("i2c_get_clientdata", expr->fn)) return 1; + if (sym_name_is("idr_find", expr->fn)) + return 1; return 0; } diff --git a/usr/src/tools/smatch/src/token.h b/usr/src/tools/smatch/src/token.h index 88f60db597..55f922f4ab 100644 --- a/usr/src/tools/smatch/src/token.h +++ b/usr/src/tools/smatch/src/token.h @@ -218,6 +218,7 @@ extern struct token eof_token_entry; extern int init_stream(const char *, int fd, const char **next_path); extern const char *stream_name(int stream); +struct ident *alloc_ident(const char *name, int len); extern struct ident *hash_ident(struct ident *); extern struct ident *built_in_ident(const char *); extern struct token *built_in_token(int, struct ident *); diff --git a/usr/src/tools/smatch/src/tokenize.c b/usr/src/tools/smatch/src/tokenize.c index aefd333b48..0021fa7049 100644 --- a/usr/src/tools/smatch/src/tokenize.c +++ b/usr/src/tools/smatch/src/tokenize.c @@ -829,7 +829,7 @@ void show_identifier_stats(void) } } -static struct ident *alloc_ident(const char *name, int len) +struct ident *alloc_ident(const char *name, int len) { struct ident *ident = __alloc_ident(len); ident->symbols = NULL; diff --git a/usr/src/tools/smatch/src/validation/sm_impossible1.c b/usr/src/tools/smatch/src/validation/sm_impossible1.c index a81cbcd0a8..cc06a496cf 100644 --- a/usr/src/tools/smatch/src/validation/sm_impossible1.c +++ b/usr/src/tools/smatch/src/validation/sm_impossible1.c @@ -19,7 +19,7 @@ int main(unsigned int x, unsigned int y) * check-command: smatch -I.. sm_impossible1.c * * check-output-start -sm_impossible1.c:12 main() [register_impossible_return] 'impossible' = 'impossible' +sm_impossible1.c:12 main() [register_impossible_return] impossible = 'impossible' sm_impossible1.c:14 main() register_impossible_return: no states * check-output-end */ diff --git a/usr/src/tools/smatch/src/validation/sm_impossible2.c b/usr/src/tools/smatch/src/validation/sm_impossible2.c index 905bec5f46..1893ba5e83 100644 --- a/usr/src/tools/smatch/src/validation/sm_impossible2.c +++ b/usr/src/tools/smatch/src/validation/sm_impossible2.c @@ -20,6 +20,6 @@ int main(unsigned int x, unsigned int y) * * check-output-start sm_impossible2.c:12 main() register_impossible_return: no states -sm_impossible2.c:14 main() [register_impossible_return] 'impossible' = 'impossible' +sm_impossible2.c:14 main() [register_impossible_return] impossible = 'impossible' * check-output-end */ diff --git a/usr/src/uts/sun4u/ics951601/Makefile b/usr/src/uts/sun4u/ics951601/Makefile index eb6443593c..aa6de449e8 100644 --- a/usr/src/uts/sun4u/ics951601/Makefile +++ b/usr/src/uts/sun4u/ics951601/Makefile @@ -23,8 +23,6 @@ # Copyright 2004 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # This makefile drives the ics951601 build. # # Path to the base of the uts directory tree (usually /usr/src/uts). @@ -36,7 +34,6 @@ UTSBASE = ../.. # MODULE = ics951601 OBJECTS = $(ICS951601_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(ICS951601_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) # @@ -44,18 +41,12 @@ ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) # include $(UTSBASE)/sun4u/Makefile.sun4u -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - LDFLAGS += -dy -N misc/i2c_svc # # Define targets # ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint INSTALL_TARGET = $(BINARY) $(ROOTMODULE) .KEEP_STATE: @@ -68,12 +59,6 @@ clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - install: $(INSTALL_DEPS) # diff --git a/usr/src/uts/sun4u/io/i2c/clients/ics951601.c b/usr/src/uts/sun4u/io/i2c/clients/ics951601.c index 5ed6a41b49..6d316c574a 100644 --- a/usr/src/uts/sun4u/io/i2c/clients/ics951601.c +++ b/usr/src/uts/sun4u/io/i2c/clients/ics951601.c @@ -222,10 +222,10 @@ ics951601_close(dev_t dev, int flags, int otyp, cred_t *credp) _NOTE(ARGUNUSED(flags, credp)) int instance; - ics951601_unit_t *icsp; + ics951601_unit_t *icsp; /* - * Make sure the close is for the right file type + * Make sure the close is for the right file type */ if (otyp != OTYP_CHR) { return (EINVAL); @@ -247,8 +247,8 @@ ics951601_close(dev_t dev, int flags, int otyp, cred_t *credp) static int ics951601_attach(dev_info_t *dip) { - ics951601_unit_t *icsp; - int instance = ddi_get_instance(dip); + ics951601_unit_t *icsp; + int instance = ddi_get_instance(dip); if (ddi_soft_state_zalloc(ics951601_soft_statep, instance) != 0) { cmn_err(CE_WARN, "%s%d failed to zalloc softstate", @@ -270,7 +270,7 @@ ics951601_attach(dev_info_t *dip) if (ddi_create_minor_node(dip, icsp->ics951601_name, S_IFCHR, - instance, ICS951601_NODE_TYPE, NULL) == DDI_FAILURE) { + instance, ICS951601_NODE_TYPE, 0) == DDI_FAILURE) { cmn_err(CE_WARN, "%s ddi_create_minor_node failed", icsp->ics951601_name); goto ATTACH_ERR; @@ -333,7 +333,7 @@ static void ics951601_detach(dev_info_t *dip) { ics951601_unit_t *icsp; - int instance; + int instance; instance = ddi_get_instance(dip); icsp = ddi_get_soft_state(ics951601_soft_statep, instance); @@ -374,7 +374,7 @@ ics951601_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) static int ics951601_suspend(dev_info_t *dip) { - ics951601_unit_t *icsp; + ics951601_unit_t *icsp; int instance = ddi_get_instance(dip); icsp = ddi_get_soft_state(ics951601_soft_statep, instance); @@ -413,9 +413,9 @@ ics951601_suspend(dev_info_t *dip) static int ics951601_resume(dev_info_t *dip) { - int instance = ddi_get_instance(dip); + int instance = ddi_get_instance(dip); ics951601_unit_t *icsp; - int err = DDI_SUCCESS; + int err = DDI_SUCCESS; icsp = (ics951601_unit_t *) ddi_get_soft_state(ics951601_soft_statep, instance); @@ -479,7 +479,7 @@ ics951601_s_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) static int ics951601_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, - int *rvalp) + int *rvalp) { _NOTE(ARGUNUSED(credp, rvalp)) diff --git a/usr/src/uts/sun4u/io/i2c/clients/pca9556.c b/usr/src/uts/sun4u/io/i2c/clients/pca9556.c index 1b972ca6d7..7fe812e0ac 100644 --- a/usr/src/uts/sun4u/io/i2c/clients/pca9556.c +++ b/usr/src/uts/sun4u/io/i2c/clients/pca9556.c @@ -177,9 +177,9 @@ _info(struct modinfo *modinfop) static int pca9556_resume(dev_info_t *dip) { - int instance = ddi_get_instance(dip); + int instance = ddi_get_instance(dip); pca9556_unit_t *pcap; - int err = DDI_SUCCESS; + int err = DDI_SUCCESS; int reg_offset, num_of_ports; int i, j; uint8_t reg, reg_num = 0; @@ -257,7 +257,7 @@ static void pca9556_detach(dev_info_t *dip) { pca9556_unit_t *pcap; - int instance = ddi_get_instance(dip); + int instance = ddi_get_instance(dip); pcap = ddi_get_soft_state(pca9556_soft_statep, instance); @@ -279,11 +279,11 @@ pca9556_detach(dev_info_t *dip) static int pca9556_attach(dev_info_t *dip) { - pca9556_unit_t *pcap; - int instance = ddi_get_instance(dip); + pca9556_unit_t *pcap; + int instance = ddi_get_instance(dip); char name[MAXNAMELEN]; char *device_name; - minor_t minor; + minor_t minor; int i, num_ports; if (ddi_soft_state_zalloc(pca9556_soft_statep, instance) != 0) { @@ -328,7 +328,7 @@ pca9556_attach(dev_info_t *dip) } if (ddi_create_minor_node(dip, name, S_IFCHR, minor, - PCA9556_NODE_TYPE, NULL) == DDI_FAILURE) { + PCA9556_NODE_TYPE, 0) == DDI_FAILURE) { cmn_err(CE_WARN, "%s: failed to create node for %s", pcap->pca9556_name, name); pca9556_detach(dip); @@ -414,8 +414,8 @@ pca9556_s_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) static int pca9556_suspend(dev_info_t *dip) { - pca9556_unit_t *pcap; - int instance = ddi_get_instance(dip); + pca9556_unit_t *pcap; + int instance = ddi_get_instance(dip); int err = DDI_SUCCESS; int reg_offset, num_of_ports; int i, j; @@ -574,7 +574,7 @@ static int pca9556_close(dev_t dev, int flags, int otyp, cred_t *credp) { int instance; - pca9556_unit_t *pcap; + pca9556_unit_t *pcap; _NOTE(ARGUNUSED(flags, credp)) @@ -599,7 +599,7 @@ pca9556_close(dev_t dev, int flags, int otyp, cred_t *credp) static int pca9556_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, - int *rvalp) + int *rvalp) { pca9556_unit_t *pcap; int err = 0; diff --git a/usr/src/uts/sun4u/io/i2c/clients/seeprom.c b/usr/src/uts/sun4u/io/i2c/clients/seeprom.c index 176051db4c..ece73f2863 100644 --- a/usr/src/uts/sun4u/io/i2c/clients/seeprom.c +++ b/usr/src/uts/sun4u/io/i2c/clients/seeprom.c @@ -167,7 +167,7 @@ seeprom_do_attach(dev_info_t *dip) "%s%d", ddi_driver_name(dip), instance); if (ddi_create_minor_node(dip, ddi_node_name(dip), S_IFCHR, - instance, SEEPROM_NODE_TYPE, NULL) == DDI_FAILURE) { + instance, SEEPROM_NODE_TYPE, 0) == DDI_FAILURE) { cmn_err(CE_WARN, "%s ddi_create_minor_node failed for '%s'", unitp->seeprom_name, ddi_node_name(dip)); ddi_soft_state_free(seepromsoft_statep, instance); diff --git a/usr/src/uts/sun4u/pca9556/Makefile b/usr/src/uts/sun4u/pca9556/Makefile index 182a32f4e1..0ffc4a3320 100644 --- a/usr/src/uts/sun4u/pca9556/Makefile +++ b/usr/src/uts/sun4u/pca9556/Makefile @@ -34,7 +34,6 @@ UTSBASE = ../.. # MODULE = pca9556 OBJECTS = $(PCA9556_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(PCA9556_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) # @@ -42,27 +41,14 @@ ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) # include $(UTSBASE)/sun4u/Makefile.sun4u -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - LDFLAGS += -dy -N misc/i2c_svc -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV - CERRWARN += $(CNOWARN_UNINIT) # # Define targets # ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint INSTALL_TARGET = $(BINARY) $(ROOTMODULE) .KEEP_STATE: @@ -75,12 +61,6 @@ clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - install: $(INSTALL_DEPS) # diff --git a/usr/src/uts/sun4u/seeprom/Makefile b/usr/src/uts/sun4u/seeprom/Makefile index 92b51e0417..b4d887a3bc 100644 --- a/usr/src/uts/sun4u/seeprom/Makefile +++ b/usr/src/uts/sun4u/seeprom/Makefile @@ -35,7 +35,6 @@ UTSBASE = ../.. # MODULE = seeprom OBJECTS = $(SEEPROM_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(SEEPROM_OBJS:%.o=$(LINTS_DIR)/%.ln) ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) # @@ -43,27 +42,14 @@ ROOTMODULE = $(ROOT_PSM_DRV_DIR)/$(MODULE) # include $(UTSBASE)/sun4u/Makefile.sun4u -# -# lint pass one enforcement -# -CFLAGS += $(CCVERBOSE) - LDFLAGS += -dy -N misc/i2c_svc -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_SUPPRESSION_DIRECTIVE_UNUSED - CERRWARN += $(CNOWARN_UNINIT) # # Define targets # ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint INSTALL_TARGET = $(BINARY) $(ROOTMODULE) .KEEP_STATE: @@ -76,12 +62,6 @@ clean: $(CLEAN_DEPS) clobber: $(CLOBBER_DEPS) -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - install: $(INSTALL_DEPS) # |