Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_local_values.c
+++ new/usr/src/tools/smatch/src/smatch_local_values.c
1 1 /*
2 2 * Copyright (C) 2013 Oracle.
3 3 *
4 4 * This program is free software; you can redistribute it and/or
5 5 * modify it under the terms of the GNU General Public License
6 6 * as published by the Free Software Foundation; either version 2
7 7 * of the License, or (at your option) any later version.
8 8 *
9 9 * This program is distributed in the hope that it will be useful,
10 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 * GNU General Public License for more details.
13 13 *
14 14 * You should have received a copy of the GNU General Public License
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 16 */
17 17
18 18 #include "scope.h"
19 19 #include "smatch.h"
20 20 #include "smatch_slist.h"
21 21 #include "smatch_extra.h"
22 22
23 23 static int my_id;
24 24
25 25 /*
26 26 * I'm going to store the states of local data at the end of each function.
27 27 * Then at the end of the file, I'll combine the possible range lists for
28 28 * each state and store the value in the on-disk database.
29 29 *
30 30 * One issue is that when I read the data back from the in-memory database at
31 31 * the end of the file, then I don't have access to type information. I'll just
32 32 * cast everything to "long long" for now, I guess. We'll see how that works.
33 33 */
34 34
35 35 static char *db_vals;
36 36 static int get_vals(void *unused, int argc, char **argv, char **azColName)
37 37 {
38 38 db_vals = alloc_string(argv[0]);
39 39 return 0;
40 40 }
41 41
42 42 static int is_array_symbol(struct expression *expr)
43 43 {
44 44 struct symbol *type;
45 45
46 46 if (!expr || expr->type != EXPR_SYMBOL)
47 47 return 0;
48 48 type = get_type(expr);
49 49 if (!type)
50 50 return 0;
51 51 if (type->type == SYM_ARRAY)
52 52 return 1;
53 53 return 0;
54 54 }
55 55
56 56 int get_local_rl(struct expression *expr, struct range_list **rl)
57 57 {
58 58 char *name;
59 59 struct range_list *tmp;
60 60
61 61 if (!is_static(expr))
62 62 return 0;
63 63 if (is_array_symbol(expr))
64 64 return 0;
65 65 name = expr_to_var(expr);
66 66 if (!name)
67 67 return 0;
68 68
69 69 db_vals = NULL;
70 70 run_sql(get_vals, NULL,
71 71 "select value from local_values where file = '%s' and variable = '%s';",
72 72 get_filename(), name);
73 73 free_string(name);
74 74 if (!db_vals)
75 75 return 0;
76 76 str_to_rl(&llong_ctype, db_vals, &tmp);
77 77 *rl = cast_rl(get_type(expr), tmp);
78 78 free_string(db_vals);
79 79
80 80 return 1;
81 81 }
82 82
83 83 int get_local_max_helper(struct expression *expr, sval_t *sval)
84 84 {
85 85 struct range_list *rl;
86 86
87 87 if (!get_local_rl(expr, &rl))
88 88 return 0;
89 89 *sval = rl_max(rl);
90 90 return 1;
91 91 }
92 92
93 93 int get_local_min_helper(struct expression *expr, sval_t *sval)
94 94 {
95 95 struct range_list *rl;
96 96
97 97 if (!get_local_rl(expr, &rl))
98 98 return 0;
99 99 *sval = rl_min(rl);
100 100 return 1;
101 101 }
102 102
103 103 static struct smatch_state *unmatched_state(struct sm_state *sm)
104 104 {
105 105 return alloc_estate_empty();
106 106 }
107 107
108 108 static void extra_mod_hook(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
109 109 {
110 110 struct smatch_state *old;
111 111 struct smatch_state *new;
112 112
113 113 if (!sym || !(sym->ctype.modifiers & MOD_STATIC))
114 114 return;
115 115 old = get_state(my_id, name, sym);
116 116 if (old)
117 117 new = merge_estates(old, state);
118 118 else
119 119 new = state;
120 120 set_state(my_id, name, sym, new);
121 121 }
122 122
123 123 static void process_states(void)
124 124 {
125 125 struct sm_state *sm;
126 126 struct smatch_state *extra;
127 127 struct range_list *rl;
128 128
129 129 FOR_EACH_SM(__get_cur_stree(), sm) {
130 130 if (sm->owner != my_id)
131 131 continue;
132 132 extra = get_state(SMATCH_EXTRA, sm->name, sm->sym);
133 133 if (extra && estate_rl(extra))
134 134 rl = rl_intersection(estate_rl(sm->state), estate_rl(extra));
135 135 else
136 136 rl = estate_rl(sm->state);
137 137 rl = cast_rl(&llong_ctype, rl);
138 138 mem_sql(NULL, NULL,
139 139 "insert into local_values values ('%s', '%s', '%s', %lu);",
140 140 get_filename(), sm->name, show_rl(rl),
141 141 (unsigned long)sm->sym);
142 142 } END_FOR_EACH_SM(sm);
143 143 }
144 144
145 145 static int get_initial_value_sym(struct symbol *sym, char *name, sval_t *sval)
146 146 {
147 147 struct expression *expr_symbol, *deref, *tmp;
148 148 char *member_name;
149 149
150 150 if (!sym)
151 151 return 0;
152 152
153 153 if (!sym->initializer) {
154 154 *sval = sval_type_val(&llong_ctype, 0);
155 155 return 1;
156 156 }
157 157 if (sym->initializer->type != EXPR_INITIALIZER)
158 158 return get_value(sym->initializer, sval);
159 159
160 160 expr_symbol = symbol_expression(sym);
161 161 FOR_EACH_PTR(sym->initializer->expr_list, tmp) {
162 162 if (tmp->type != EXPR_IDENTIFIER) /* how to handle arrays?? */
163 163 continue;
164 164 deref = member_expression(expr_symbol, '.', tmp->expr_ident);
165 165 member_name = expr_to_var(deref);
166 166 if (!member_name)
167 167 continue;
168 168 if (strcmp(name, member_name) == 0) {
169 169 free_string(member_name);
170 170 return get_value(tmp->ident_expression, sval);
171 171 }
172 172 free_string(member_name);
173 173 } END_FOR_EACH_PTR(tmp);
174 174
175 175 return 0;
176 176 }
177 177
178 178 static char *cur_name;
179 179 static struct symbol *cur_symbol;
180 180 static struct range_list *cur_rl;
181 181 static void add_current_local(void)
182 182 {
183 183 sval_t initial;
184 184
185 185 if (!get_initial_value_sym(cur_symbol, cur_name, &initial)) {
186 186 free_string(cur_name);
187 187 cur_name = NULL;
188 188 cur_rl = NULL;
189 189 return;
190 190 }
191 191 add_range(&cur_rl, initial, initial);
192 192 if (!is_whole_rl(cur_rl))
193 193 sql_insert_local_values(cur_name, show_rl(cur_rl));
194 194 free_string(cur_name);
195 195 cur_name = NULL;
196 196 cur_rl = NULL;
197 197 }
198 198
199 199 static int save_final_values(void *unused, int argc, char **argv, char **azColName)
200 200 {
201 201 char *name = argv[0];
202 202 char *sym_str = argv[1];
203 203 char *value = argv[2];
204 204 struct range_list *rl;
205 205
206 206 if (!cur_name) {
207 207 cur_name = alloc_string(name);
208 208 cur_symbol = (struct symbol *)strtoul(sym_str, NULL, 10);
209 209 } else if (strcmp(cur_name, name) != 0) {
210 210 add_current_local();
211 211 cur_name = alloc_string(name);
212 212 cur_symbol = (struct symbol *)strtoul(sym_str, NULL, 10);
213 213 cur_rl = NULL;
214 214 }
215 215
216 216 str_to_rl(&llong_ctype, value, &rl);
217 217 cur_rl = rl_union(cur_rl, rl);
218 218
219 219 return 0;
220 220 }
221 221
222 222 static void match_end_file(struct symbol_list *sym_list)
223 223 {
224 224 mem_sql(save_final_values, NULL,
225 225 "select distinct variable, symbol, value from local_values order by variable;");
226 226 if (cur_name)
↓ open down ↓ |
226 lines elided |
↑ open up ↑ |
227 227 add_current_local();
228 228 }
229 229
230 230 void register_local_values(int id)
231 231 {
232 232 my_id = id;
233 233
234 234 if (!option_info)
235 235 return;
236 236
237 + set_dynamic_states(my_id);
237 238 add_extra_mod_hook(&extra_mod_hook);
238 239 add_unmatched_state_hook(my_id, &unmatched_state);
239 240 add_merge_hook(my_id, &merge_estates);
240 241 all_return_states_hook(&process_states);
241 242 add_hook(match_end_file, END_FILE_HOOK);
242 243 mem_sql(NULL, NULL, "alter table local_values add column symbol integer;");
243 244 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX