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