Print this page
12826 update to smatch 0.6.1-rc1-il-6

*** 22,39 **** #include "smatch_slist.h" static int my_id; 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) --- 22,47 ---- #include "smatch_slist.h" static int my_id; STATE(inc); ! STATE(start_state); STATE(dec); static struct smatch_state *unmatched_state(struct sm_state *sm) { ! /* ! * We default to decremented. For example, say we have: ! * if (p) ! * atomic_dec(p); ! * <- p is decreemented. ! * ! */ ! if ((sm->state == &dec) && ! parent_is_gone_var_sym(sm->name, sm->sym)) return sm->state; ! return &start_state; } 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)
*** 84,94 **** 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 sm_state *start_sm; struct expression *arg; char *name; struct symbol *sym; --- 92,102 ---- if (cnt == 1) return match; return NULL; } ! static void db_inc_dec(struct expression *expr, int param, const char *key, int inc_dec) { struct sm_state *start_sm; struct expression *arg; char *name; struct symbol *sym;
*** 127,205 **** // 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: if (free_at_end) free_string(name); } static void db_inc(struct expression *expr, int param, char *key, char *value) { ! db_inc_dec(expr, param, key, value, ATOMIC_INC); } static void db_dec(struct expression *expr, int param, char *key, char *value) { ! db_inc_dec(expr, param, key, value, ATOMIC_DEC); } static void match_atomic_inc(const char *fn, struct expression *expr, void *_unused) { ! db_inc_dec(expr, 0, "$->counter", "", ATOMIC_INC); } static void match_atomic_dec(const char *fn, struct expression *expr, void *_unused) { ! db_inc_dec(expr, 0, "$->counter", "", ATOMIC_DEC); } static void match_atomic_add(const char *fn, struct expression *expr, void *_unused) { struct expression *amount; sval_t sval; amount = get_argument_from_call_expr(expr->args, 0); if (get_implied_value(amount, &sval) && sval_is_negative(sval)) { ! db_inc_dec(expr, 1, "$->counter", "", ATOMIC_DEC); return; } ! db_inc_dec(expr, 1, "$->counter", "", ATOMIC_INC); } static void match_atomic_sub(const char *fn, struct expression *expr, void *_unused) { ! db_inc_dec(expr, 1, "$->counter", "", ATOMIC_DEC); } static void refcount_inc(const char *fn, struct expression *expr, void *param) { ! db_inc_dec(expr, PTR_INT(param), "$->ref.counter", "", ATOMIC_INC); } static void refcount_dec(const char *fn, struct expression *expr, void *param) { ! db_inc_dec(expr, PTR_INT(param), "$->ref.counter", "", ATOMIC_DEC); } static void match_return_info(int return_id, char *return_ranges, struct expression *expr) { struct sm_state *sm; const char *param_name; int param; FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) { ! 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; --- 135,290 ---- // 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, &start_state); else set_state(my_id, name, sym, &dec); } free: if (free_at_end) free_string(name); } + static const char *primitive_funcs[] = { + "atomic_inc_return", + "atomic_add_return", + "atomic_sub_return", + "atomic_sub_and_test", + "atomic_dec_and_test", + "_atomic_dec_and_lock", + "atomic_dec", + "atomic_long_inc", + "atomic_long_dec", + "atomic_inc", + "atomic_sub", + "refcount_inc", + "refcount_dec", + "refcount_add", + "refcount_add_not_zero", + "refcount_inc_not_zero", + "refcount_sub_and_test", + "refcount_dec_and_test", + "atomic_dec_if_positive", + }; + + static bool is_inc_dec_primitive(struct expression *expr) + { + int i; + + while (expr->type == EXPR_ASSIGNMENT) + expr = strip_expr(expr->right); + if (expr->type != EXPR_CALL) + return false; + + if (expr->fn->type != EXPR_SYMBOL) + return false; + + for (i = 0; i < ARRAY_SIZE(primitive_funcs); i++) { + if (sym_name_is(primitive_funcs[i], expr->fn)) + return true; + } + + return false; + } + static void db_inc(struct expression *expr, int param, char *key, char *value) { ! if (is_inc_dec_primitive(expr)) ! return; ! db_inc_dec(expr, param, key, ATOMIC_INC); } static void db_dec(struct expression *expr, int param, char *key, char *value) { ! if (is_inc_dec_primitive(expr)) ! return; ! db_inc_dec(expr, param, key, ATOMIC_DEC); } static void match_atomic_inc(const char *fn, struct expression *expr, void *_unused) { ! db_inc_dec(expr, 0, "$->counter", ATOMIC_INC); } static void match_atomic_dec(const char *fn, struct expression *expr, void *_unused) { ! db_inc_dec(expr, 0, "$->counter", ATOMIC_DEC); } static void match_atomic_add(const char *fn, struct expression *expr, void *_unused) { struct expression *amount; sval_t sval; amount = get_argument_from_call_expr(expr->args, 0); if (get_implied_value(amount, &sval) && sval_is_negative(sval)) { ! db_inc_dec(expr, 1, "$->counter", ATOMIC_DEC); return; } ! db_inc_dec(expr, 1, "$->counter", ATOMIC_INC); } static void match_atomic_sub(const char *fn, struct expression *expr, void *_unused) { ! db_inc_dec(expr, 1, "$->counter", ATOMIC_DEC); } static void refcount_inc(const char *fn, struct expression *expr, void *param) { ! db_inc_dec(expr, PTR_INT(param), "$->ref.counter", ATOMIC_INC); } static void refcount_dec(const char *fn, struct expression *expr, void *param) { ! db_inc_dec(expr, PTR_INT(param), "$->ref.counter", ATOMIC_DEC); } + static void pm_runtime_get_sync(const char *fn, struct expression *expr, void *param) + { + db_inc_dec(expr, PTR_INT(param), "$->power.usage_count.counter", ATOMIC_INC); + } + + static void match_implies_inc(const char *fn, struct expression *call_expr, + struct expression *assign_expr, void *param) + { + db_inc_dec(call_expr, PTR_INT(param), "$->ref.counter", ATOMIC_INC); + } + + static void match_implies_atomic_dec(const char *fn, struct expression *call_expr, + struct expression *assign_expr, void *param) + { + db_inc_dec(call_expr, PTR_INT(param), "$->counter", ATOMIC_DEC); + } + + static bool is_maybe_dec(struct sm_state *sm) + { + if (sm->state == &dec) + return true; + if (slist_has_state(sm->possible, &dec) && + !slist_has_state(sm->possible, &inc)) + return true; + return false; + } + static void match_return_info(int return_id, char *return_ranges, struct expression *expr) { struct sm_state *sm; const char *param_name; int param; + if (is_impossible_path()) + return; + FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) { ! if (sm->state != &inc && !is_maybe_dec(sm)) continue; + if (sm->state == get_state_stree(start_states, my_id, sm->name, sm->sym)) + continue; if (parent_is_gone_var_sym(sm->name, sm->sym)) continue; param = get_param_num_from_sym(sm->sym); if (param < 0) continue;
*** 219,229 **** static int success_fail_positive(struct range_list *rl) { if (!rl) return EMPTY; ! if (sval_is_negative(rl_min(rl))) return NEGATIVE; if (rl_min(rl).value == 0) return ZERO; --- 304,314 ---- static int success_fail_positive(struct range_list *rl) { if (!rl) return EMPTY; ! if (!is_whole_rl(rl) && sval_is_negative(rl_min(rl))) return NEGATIVE; if (rl_min(rl).value == 0) return ZERO;
*** 235,252 **** --- 320,346 ---- struct range_list *inc_lines = NULL; struct range_list *dec_lines = NULL; int inc_buckets[NUM_BUCKETS] = {}; int dec_buckets[NUM_BUCKETS] = {}; struct stree *stree, *orig_stree; + struct smatch_state *state; struct sm_state *return_sm; struct sm_state *sm; sval_t line = sval_type_val(&int_ctype, 0); int bucket; + /* static variable are probably just counters */ + if (sym->ctype.modifiers & MOD_STATIC && + !(sym->ctype.modifiers & MOD_TOPLEVEL)) + return; + FOR_EACH_PTR(get_all_return_strees(), stree) { orig_stree = __swap_cur_stree(stree); + if (is_impossible_path()) + goto swap_stree; + return_sm = get_sm_state(RETURN_ID, "return_ranges", NULL); if (!return_sm) goto swap_stree; line.value = return_sm->line;
*** 255,279 **** if (parent_is_gone_var_sym(name, sym)) goto swap_stree; sm = get_sm_state(my_id, name, sym); ! if (!sm) ! goto swap_stree; ! 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[bucket] = true; } ! if (sm->state == &dec || sm->state == &orig) { add_range(&dec_lines, line, line); dec_buckets[bucket] = true; } swap_stree: __swap_cur_stree(orig_stree); --- 349,375 ---- if (parent_is_gone_var_sym(name, sym)) goto swap_stree; sm = get_sm_state(my_id, name, sym); ! if (sm) ! state = sm->state; ! else ! state = &start_state; ! if (state != &inc && ! state != &dec && ! state != &start_state) goto swap_stree; bucket = success_fail_positive(estate_rl(return_sm->state)); ! if (state == &inc) { add_range(&inc_lines, line, line); inc_buckets[bucket] = true; } ! if (state == &dec || state == &start_state) { add_range(&dec_lines, line, line); dec_buckets[bucket] = true; } swap_stree: __swap_cur_stree(orig_stree);
*** 343,368 **** 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); add_function_hook("atomic_sub_and_test", &match_atomic_sub, NULL); add_function_hook("atomic_dec_and_test", &match_atomic_dec, NULL); add_function_hook("_atomic_dec_and_lock", &match_atomic_dec, NULL); add_function_hook("atomic_dec", &match_atomic_dec, NULL); add_function_hook("atomic_long_inc", &match_atomic_inc, NULL); 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_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(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); --- 439,475 ---- 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); add_function_hook("atomic_sub_and_test", &match_atomic_sub, NULL); + add_function_hook("atomic_long_sub_and_test", &match_atomic_sub, NULL); + add_function_hook("atomic64_sub_and_test", &match_atomic_sub, NULL); add_function_hook("atomic_dec_and_test", &match_atomic_dec, NULL); + add_function_hook("atomic_long_dec_and_test", &match_atomic_dec, NULL); + add_function_hook("atomic64_dec_and_test", &match_atomic_dec, NULL); add_function_hook("_atomic_dec_and_lock", &match_atomic_dec, NULL); add_function_hook("atomic_dec", &match_atomic_dec, NULL); + add_function_hook("atomic_dec_return", &match_atomic_dec, NULL); add_function_hook("atomic_long_inc", &match_atomic_inc, NULL); 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_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)); ! ! return_implies_state("refcount_add_not_zero", 1, 1, &match_implies_inc, INT_PTR(1)); ! return_implies_state("refcount_inc_not_zero", 1, 1, &match_implies_inc, INT_PTR(0)); ! ! return_implies_state("atomic_dec_if_positive", 0, INT_MAX, &match_implies_atomic_dec, 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(0)); + add_function_hook("pm_runtime_get_sync", &pm_runtime_get_sync, 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);