2 * Copyright (C) 2018 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 #include "smatch_extra.h"
20 #include "smatch_slist.h"
22 /* New chips will probably be able to speculate further ahead */
23 #define MAX_SPEC_STMT 200
27 struct stree
*first_halfs
;
29 struct expression
*recently_set
;
31 void set_spectre_first_half(struct expression
*expr
)
36 name
= expr_to_str(expr
);
37 snprintf(buf
, sizeof(buf
), "%p %s", expr
, name
);
40 set_state_stree(&first_halfs
, my_id
, buf
, NULL
, alloc_state_num(get_stmt_cnt()));
43 void clear_spectre_second_halfs(void)
47 FOR_EACH_MY_SM(my_id
, __get_cur_stree(), sm
) {
48 set_state(my_id
, sm
->name
, sm
->sym
, alloc_state_num(-MAX_SPEC_STMT
));
49 } END_FOR_EACH_SM(sm
);
52 static struct smatch_state
*get_spectre_first_half(struct expression
*expr
)
57 name
= expr_to_str(expr
);
58 snprintf(buf
, sizeof(buf
), "%p %s", expr
, name
);
61 return get_state_stree(first_halfs
, my_id
, buf
, NULL
);
64 static void match_assign(struct expression
*expr
)
66 struct smatch_state
*state
;
68 if (expr
->op
== SPECIAL_AND_ASSIGN
)
71 state
= get_spectre_first_half(expr
->right
);
73 set_state_expr(my_id
, expr
->left
, state
);
74 recently_set
= expr
->left
;
77 state
= get_state_expr(my_id
, expr
->right
);
80 set_state_expr(my_id
, expr
->left
, state
);
81 recently_set
= expr
->left
;
84 static void match_done(struct expression
*expr
)
86 struct smatch_state
*state
;
89 if (expr
== recently_set
)
92 state
= get_state_expr(my_id
, expr
);
96 if (get_stmt_cnt() - (long)state
->data
> MAX_SPEC_STMT
)
99 name
= expr_to_str(expr
);
100 sm_msg("warn: possible spectre second half. '%s'", name
);
103 set_state_expr(my_id
, expr
, alloc_state_num(-MAX_SPEC_STMT
));
106 static void match_end_func(struct symbol
*sym
)
108 free_stree(&first_halfs
);
111 void check_spectre_second_half(int id
)
115 if (option_project
!= PROJ_KERNEL
)
117 add_function_data((unsigned long *)&first_halfs
);
118 set_dynamic_states(my_id
);
119 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
120 add_hook(&match_done
, SYM_HOOK
);
121 add_hook(&match_done
, DEREF_HOOK
);
123 add_hook(&match_end_func
, END_FUNC_HOOK
);