35 #include "smatch_slist.h"
36
37 enum {
38 EARLY = 0,
39 LATE = 1,
40 BOTH = 2
41 };
42
43 static modification_hook **hooks;
44 static modification_hook **hooks_late;
45
46 ALLOCATOR(modification_data, "modification data");
47
48 static int my_id;
49 static struct smatch_state *alloc_my_state(struct expression *expr, struct smatch_state *prev)
50 {
51 struct smatch_state *state;
52 struct modification_data *data;
53 char *name;
54
55 state = __alloc_smatch_state(0);
56 expr = strip_expr(expr);
57 name = expr_to_str(expr);
58 state->name = alloc_sname(name);
59 free_string(name);
60
61 data = __alloc_modification_data(0);
62 data->prev = prev;
63 data->cur = expr;
64 state->data = data;
65
66 return state;
67 }
68
69 void add_modification_hook(int owner, modification_hook *call_back)
70 {
71 if (hooks[owner])
72 sm_fatal("multiple modification hooks for %s", check_name(owner));
73 hooks[owner] = call_back;
74 }
75
76 void add_modification_hook_late(int owner, modification_hook *call_back)
77 {
161 expr = strip_expr(expr->right);
162 if (expr->type != EXPR_CALL)
163 return;
164
165 arg = get_argument_from_call_expr(expr->args, param);
166 if (!arg)
167 return;
168
169 gen_expr = gen_expression_from_key(arg, key);
170 if (gen_expr)
171 update_mtag_data(gen_expr);
172
173 name = get_variable_from_key(arg, key, &sym);
174 if (!name || !sym)
175 goto free;
176
177 __in_fake_assign++;
178 call_modification_hooks_name_sym(name, sym, expr, BOTH);
179 __in_fake_assign--;
180
181 other_name = map_long_to_short_name_sym(name, sym, &other_sym);
182 if (other_name) {
183 __in_fake_assign++;
184 call_modification_hooks_name_sym(other_name, other_sym, expr, BOTH);
185 __in_fake_assign--;
186 free_string(other_name);
187 }
188
189 free:
190 free_string(name);
191 }
192
193 static void match_assign(struct expression *expr, int late)
194 {
195 call_modification_hooks(expr->left, expr, late);
196 }
197
198 static void unop_expr(struct expression *expr, int late)
199 {
200 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT)
201 return;
262
263 static void unop_expr_late(struct expression *expr)
264 {
265 unop_expr(expr, LATE);
266 }
267
268 static void asm_expr_late(struct statement *stmt)
269 {
270 asm_expr(stmt, LATE);
271 }
272
273 struct smatch_state *get_modification_state(struct expression *expr)
274 {
275 return get_state_expr(my_id, expr);
276 }
277
278 void register_modification_hooks(int id)
279 {
280 my_id = id;
281
282 hooks = malloc((num_checks + 1) * sizeof(*hooks));
283 memset(hooks, 0, (num_checks + 1) * sizeof(*hooks));
284 hooks_late = malloc((num_checks + 1) * sizeof(*hooks));
285 memset(hooks_late, 0, (num_checks + 1) * sizeof(*hooks));
286
287 add_hook(&match_assign_early, ASSIGNMENT_HOOK);
288 add_hook(&unop_expr_early, OP_HOOK);
289 add_hook(&asm_expr_early, ASM_HOOK);
290 }
291
292 void register_modification_hooks_late(int id)
293 {
294 add_hook(&match_call, FUNCTION_CALL_HOOK);
295
296 select_return_states_hook(PARAM_ADD, &db_param_add);
297 select_return_states_hook(PARAM_SET, &db_param_add);
298
299 add_hook(&match_assign_late, ASSIGNMENT_HOOK_AFTER);
300 add_hook(&unop_expr_late, OP_HOOK);
301 add_hook(&asm_expr_late, ASM_HOOK);
|
35 #include "smatch_slist.h"
36
37 enum {
38 EARLY = 0,
39 LATE = 1,
40 BOTH = 2
41 };
42
43 static modification_hook **hooks;
44 static modification_hook **hooks_late;
45
46 ALLOCATOR(modification_data, "modification data");
47
48 static int my_id;
49 static struct smatch_state *alloc_my_state(struct expression *expr, struct smatch_state *prev)
50 {
51 struct smatch_state *state;
52 struct modification_data *data;
53 char *name;
54
55 expr = strip_expr(expr);
56 name = expr_to_str(expr);
57 if (!name)
58 return NULL;
59
60 state = __alloc_smatch_state(0);
61 state->name = alloc_sname(name);
62 free_string(name);
63
64 data = __alloc_modification_data(0);
65 data->prev = prev;
66 data->cur = expr;
67 state->data = data;
68
69 return state;
70 }
71
72 void add_modification_hook(int owner, modification_hook *call_back)
73 {
74 if (hooks[owner])
75 sm_fatal("multiple modification hooks for %s", check_name(owner));
76 hooks[owner] = call_back;
77 }
78
79 void add_modification_hook_late(int owner, modification_hook *call_back)
80 {
164 expr = strip_expr(expr->right);
165 if (expr->type != EXPR_CALL)
166 return;
167
168 arg = get_argument_from_call_expr(expr->args, param);
169 if (!arg)
170 return;
171
172 gen_expr = gen_expression_from_key(arg, key);
173 if (gen_expr)
174 update_mtag_data(gen_expr);
175
176 name = get_variable_from_key(arg, key, &sym);
177 if (!name || !sym)
178 goto free;
179
180 __in_fake_assign++;
181 call_modification_hooks_name_sym(name, sym, expr, BOTH);
182 __in_fake_assign--;
183
184 other_name = get_other_name_sym(name, sym, &other_sym);
185 if (other_name) {
186 __in_fake_assign++;
187 call_modification_hooks_name_sym(other_name, other_sym, expr, BOTH);
188 __in_fake_assign--;
189 free_string(other_name);
190 }
191
192 free:
193 free_string(name);
194 }
195
196 static void match_assign(struct expression *expr, int late)
197 {
198 call_modification_hooks(expr->left, expr, late);
199 }
200
201 static void unop_expr(struct expression *expr, int late)
202 {
203 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT)
204 return;
265
266 static void unop_expr_late(struct expression *expr)
267 {
268 unop_expr(expr, LATE);
269 }
270
271 static void asm_expr_late(struct statement *stmt)
272 {
273 asm_expr(stmt, LATE);
274 }
275
276 struct smatch_state *get_modification_state(struct expression *expr)
277 {
278 return get_state_expr(my_id, expr);
279 }
280
281 void register_modification_hooks(int id)
282 {
283 my_id = id;
284
285 set_dynamic_states(my_id);
286
287 hooks = malloc((num_checks + 1) * sizeof(*hooks));
288 memset(hooks, 0, (num_checks + 1) * sizeof(*hooks));
289 hooks_late = malloc((num_checks + 1) * sizeof(*hooks));
290 memset(hooks_late, 0, (num_checks + 1) * sizeof(*hooks));
291
292 add_hook(&match_assign_early, ASSIGNMENT_HOOK);
293 add_hook(&unop_expr_early, OP_HOOK);
294 add_hook(&asm_expr_early, ASM_HOOK);
295 }
296
297 void register_modification_hooks_late(int id)
298 {
299 add_hook(&match_call, FUNCTION_CALL_HOOK);
300
301 select_return_states_hook(PARAM_ADD, &db_param_add);
302 select_return_states_hook(PARAM_SET, &db_param_add);
303
304 add_hook(&match_assign_late, ASSIGNMENT_HOOK_AFTER);
305 add_hook(&unop_expr_late, OP_HOOK);
306 add_hook(&asm_expr_late, ASM_HOOK);
|