Print this page
new smatch
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_modification_hooks.c
+++ new/usr/src/tools/smatch/src/smatch_modification_hooks.c
1 1 /*
2 2 * Copyright (C) 2009 Dan Carpenter.
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 /*
19 19 * There are a number of ways that variables are modified:
20 20 * 1) assignment
21 21 * 2) increment/decrement
22 22 * 3) assembly
23 23 * 4) inside functions.
24 24 *
25 25 * For setting stuff inside a function then, of course, it's more accurate if
26 26 * you have the cross function database built. Otherwise we are super
27 27 * aggressive about marking things as modified and if you have "frob(foo);" then
28 28 * we assume "foo->bar" is modified.
29 29 */
30 30
31 31 #include <stdlib.h>
32 32 #include <stdio.h>
33 33 #include "smatch.h"
34 34 #include "smatch_extra.h"
35 35 #include "smatch_slist.h"
36 36
37 37 enum {
38 38 EARLY = 0,
39 39 LATE = 1,
40 40 BOTH = 2
41 41 };
42 42
43 43 static modification_hook **hooks;
44 44 static modification_hook **hooks_late;
45 45
46 46 ALLOCATOR(modification_data, "modification data");
47 47
48 48 static int my_id;
49 49 static struct smatch_state *alloc_my_state(struct expression *expr, struct smatch_state *prev)
50 50 {
51 51 struct smatch_state *state;
52 52 struct modification_data *data;
53 53 char *name;
54 54
55 55 expr = strip_expr(expr);
56 56 name = expr_to_str(expr);
57 57 if (!name)
58 58 return NULL;
59 59
60 60 state = __alloc_smatch_state(0);
61 61 state->name = alloc_sname(name);
62 62 free_string(name);
63 63
64 64 data = __alloc_modification_data(0);
65 65 data->prev = prev;
66 66 data->cur = expr;
67 67 state->data = data;
68 68
69 69 return state;
70 70 }
71 71
72 72 void add_modification_hook(int owner, modification_hook *call_back)
73 73 {
74 74 if (hooks[owner])
75 75 sm_fatal("multiple modification hooks for %s", check_name(owner));
76 76 hooks[owner] = call_back;
77 77 }
78 78
79 79 void add_modification_hook_late(int owner, modification_hook *call_back)
80 80 {
81 81 if (hooks_late[owner])
82 82 sm_fatal("multiple late modification hooks for %s", check_name(owner));
83 83 hooks_late[owner] = call_back;
84 84 }
85 85
86 86 static int matches(char *name, struct symbol *sym, struct sm_state *sm)
87 87 {
88 88 int len;
89 89
90 90 if (sym != sm->sym)
91 91 return false;
92 92
93 93 len = strlen(name);
94 94 if (strncmp(sm->name, name, len) == 0) {
95 95 if (sm->name[len] == '\0')
96 96 return true;
97 97 if (sm->name[len] == '-' || sm->name[len] == '.')
98 98 return true;
99 99 }
100 100 if (sm->name[0] != '*')
101 101 return false;
102 102 if (strncmp(sm->name + 1, name, len) == 0) {
103 103 if (sm->name[len + 1] == '\0')
104 104 return true;
105 105 if (sm->name[len + 1] == '-' || sm->name[len + 1] == '.')
106 106 return true;
107 107 }
108 108 return false;
109 109 }
110 110
111 111 static void call_modification_hooks_name_sym(char *name, struct symbol *sym, struct expression *mod_expr, int late)
112 112 {
113 113 struct sm_state *sm;
114 114 struct smatch_state *prev;
115 115 int match;
116 116
117 117 prev = get_state(my_id, name, sym);
118 118
119 119 if (cur_func_sym && !__in_fake_assign)
120 120 set_state(my_id, name, sym, alloc_my_state(mod_expr, prev));
121 121
122 122 FOR_EACH_SM(__get_cur_stree(), sm) {
123 123 if (sm->owner > num_checks)
124 124 continue;
125 125 match = matches(name, sym, sm);
126 126 if (!match)
127 127 continue;
128 128
129 129 if (late == EARLY || late == BOTH) {
130 130 if (hooks[sm->owner])
131 131 (hooks[sm->owner])(sm, mod_expr);
132 132 }
133 133 if (late == LATE || late == BOTH) {
134 134 if (hooks_late[sm->owner])
135 135 (hooks_late[sm->owner])(sm, mod_expr);
↓ open down ↓ |
135 lines elided |
↑ open up ↑ |
136 136 }
137 137
138 138 } END_FOR_EACH_SM(sm);
139 139 }
140 140
141 141 static void call_modification_hooks(struct expression *expr, struct expression *mod_expr, int late)
142 142 {
143 143 char *name;
144 144 struct symbol *sym;
145 145
146 - if (late == LATE)
147 - update_mtag_data(expr);
148 -
149 146 name = expr_to_known_chunk_sym(expr, &sym);
150 147 if (!name)
151 148 goto free;
152 149 call_modification_hooks_name_sym(name, sym, mod_expr, late);
153 150 free:
154 151 free_string(name);
155 152 }
156 153
157 154 static void db_param_add(struct expression *expr, int param, char *key, char *value)
158 155 {
159 - struct expression *arg, *gen_expr;
156 + struct expression *arg;
160 157 char *name, *other_name;
161 158 struct symbol *sym, *other_sym;
162 159
163 160 while (expr->type == EXPR_ASSIGNMENT)
164 161 expr = strip_expr(expr->right);
165 162 if (expr->type != EXPR_CALL)
166 163 return;
167 164
168 165 arg = get_argument_from_call_expr(expr->args, param);
169 166 if (!arg)
170 167 return;
171 168
172 - gen_expr = gen_expression_from_key(arg, key);
173 - if (gen_expr)
174 - update_mtag_data(gen_expr);
175 -
176 169 name = get_variable_from_key(arg, key, &sym);
177 170 if (!name || !sym)
178 171 goto free;
179 172
180 173 __in_fake_assign++;
181 174 call_modification_hooks_name_sym(name, sym, expr, BOTH);
182 175 __in_fake_assign--;
183 176
184 177 other_name = get_other_name_sym(name, sym, &other_sym);
185 178 if (other_name) {
186 179 __in_fake_assign++;
187 180 call_modification_hooks_name_sym(other_name, other_sym, expr, BOTH);
188 181 __in_fake_assign--;
189 182 free_string(other_name);
190 183 }
191 184
192 185 free:
193 186 free_string(name);
194 187 }
195 188
196 189 static void match_assign(struct expression *expr, int late)
197 190 {
198 191 call_modification_hooks(expr->left, expr, late);
199 192 }
200 193
201 194 static void unop_expr(struct expression *expr, int late)
202 195 {
203 196 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT)
204 197 return;
205 198
206 199 call_modification_hooks(expr->unop, expr, late);
207 200 }
208 201
209 202 static void match_call(struct expression *expr)
210 203 {
211 204 struct expression *arg, *tmp;
212 205
213 206 /* If we have the DB then trust the DB */
214 207 if (!option_no_db)
215 208 return;
216 209
217 210 FOR_EACH_PTR(expr->args, arg) {
218 211 tmp = strip_expr(arg);
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
219 212 if (tmp->type == EXPR_PREOP && tmp->op == '&')
220 213 call_modification_hooks(tmp->unop, expr, BOTH);
221 214 else
222 215 call_modification_hooks(deref_expression(tmp), expr, BOTH);
223 216 } END_FOR_EACH_PTR(arg);
224 217 }
225 218
226 219 static void asm_expr(struct statement *stmt, int late)
227 220 {
228 221 struct expression *expr;
229 - int state = 0;
230 222
231 223 FOR_EACH_PTR(stmt->asm_outputs, expr) {
232 - switch (state) {
233 - case 0: /* identifier */
234 - case 1: /* constraint */
235 - state++;
224 + if (expr->type != EXPR_ASM_OPERAND)
236 225 continue;
237 - case 2: /* expression */
238 - state = 0;
239 - call_modification_hooks(expr, NULL, late);
240 - continue;
241 - }
226 + call_modification_hooks(expr->expr, NULL, late);
242 227 } END_FOR_EACH_PTR(expr);
243 228 }
244 229
245 -
246 230 static void match_assign_early(struct expression *expr)
247 231 {
248 232 match_assign(expr, EARLY);
249 233 }
250 234
251 235 static void unop_expr_early(struct expression *expr)
252 236 {
253 237 unop_expr(expr, EARLY);
254 238 }
255 239
256 240 static void asm_expr_early(struct statement *stmt)
257 241 {
258 242 asm_expr(stmt, EARLY);
259 243 }
260 244
261 245 static void match_assign_late(struct expression *expr)
262 246 {
263 247 match_assign(expr, LATE);
264 248 }
265 249
266 250 static void unop_expr_late(struct expression *expr)
267 251 {
268 252 unop_expr(expr, LATE);
269 253 }
270 254
271 255 static void asm_expr_late(struct statement *stmt)
272 256 {
273 257 asm_expr(stmt, LATE);
274 258 }
275 259
276 260 struct smatch_state *get_modification_state(struct expression *expr)
277 261 {
278 262 return get_state_expr(my_id, expr);
279 263 }
280 264
281 265 void register_modification_hooks(int id)
282 266 {
283 267 my_id = id;
284 268
285 269 set_dynamic_states(my_id);
286 270
287 271 hooks = malloc((num_checks + 1) * sizeof(*hooks));
288 272 memset(hooks, 0, (num_checks + 1) * sizeof(*hooks));
289 273 hooks_late = malloc((num_checks + 1) * sizeof(*hooks));
290 274 memset(hooks_late, 0, (num_checks + 1) * sizeof(*hooks));
291 275
292 276 add_hook(&match_assign_early, ASSIGNMENT_HOOK);
293 277 add_hook(&unop_expr_early, OP_HOOK);
294 278 add_hook(&asm_expr_early, ASM_HOOK);
295 279 }
296 280
297 281 void register_modification_hooks_late(int id)
298 282 {
299 283 add_hook(&match_call, FUNCTION_CALL_HOOK);
300 284
301 285 select_return_states_hook(PARAM_ADD, &db_param_add);
302 286 select_return_states_hook(PARAM_SET, &db_param_add);
303 287
304 288 add_hook(&match_assign_late, ASSIGNMENT_HOOK_AFTER);
305 289 add_hook(&unop_expr_late, OP_HOOK);
306 290 add_hook(&asm_expr_late, ASM_HOOK);
307 291 }
308 292
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX