Print this page
12724 update smatch to 0.6.1-rc1-il-5
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_return_to_param.c
+++ new/usr/src/tools/smatch/src/smatch_return_to_param.c
1 1 /*
2 2 * Copyright (C) 2017 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 /*
19 19 * This is for smatch_extra.c to use. It sort of like check_assigned_expr.c but
20 20 * more limited. Say a function returns "64min-s64max[$0->data]" and the caller
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
21 21 * does "struct whatever *p = get_data(dev);" then we want to record that p is
22 22 * now the same as "dev->data". Then if we update "p->foo" it means we can
23 23 * update "dev->data->foo" as well.
24 24 *
25 25 */
26 26
27 27 #include "smatch.h"
28 28 #include "smatch_slist.h"
29 29 #include "smatch_extra.h"
30 30
31 -extern int check_assigned_expr_id;
32 31 static int my_id;
33 32 static int link_id;
34 33
35 34 static struct smatch_state *alloc_my_state(const char *name, struct symbol *sym)
36 35 {
37 36 struct smatch_state *state;
38 37
39 38 state = __alloc_smatch_state(0);
40 39 state->name = alloc_sname(name);
41 40 state->data = sym;
42 41 return state;
43 42 }
44 43
45 44 static void undef(struct sm_state *sm, struct expression *mod_expr)
46 45 {
47 46 if (__in_fake_parameter_assign)
48 47 return;
49 48 set_state(my_id, sm->name, sm->sym, &undefined);
50 49 }
51 50
52 51 char *map_call_to_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
53 52 {
54 53 struct smatch_state *state;
55 54 int skip;
56 55 char buf[256];
57 56
58 57 /* skip 'foo->'. This was checked in the caller. */
59 58 skip = sym->ident->len + 2;
60 59
61 60 state = get_state(my_id, sym->ident->name, sym);
62 61 if (!state || !state->data)
63 62 return NULL;
64 63
65 64 snprintf(buf, sizeof(buf), "%s->%s", state->name, name + skip);
66 65 *new_sym = state->data;
67 66 return alloc_string(buf);
68 67 }
69 68
70 69 static char *map_my_state_long_to_short(struct sm_state *sm, const char *name, struct symbol *sym, struct symbol **new_sym, bool stack)
71 70 {
72 71 int len;
73 72 char buf[256];
74 73
75 74 if (sm->state->data != sym)
76 75 return NULL;
77 76 len = strlen(sm->state->name);
78 77 if (strncmp(name, sm->state->name, len) != 0)
79 78 return NULL;
80 79
81 80 if (name[len] == '.')
82 81 return NULL;
83 82 if (!stack && name[len] != '-')
84 83 return NULL;
85 84 snprintf(buf, sizeof(buf), "%s%s", sm->name, name + len);
86 85 *new_sym = sm->sym;
87 86 return alloc_string(buf);
88 87 }
89 88
90 89 /*
91 90 * Normally, we expect people to consistently refer to variables by the shortest
92 91 * name. So they use "b->a" instead of "foo->bar.a" when both point to the
93 92 * same memory location. However, when we're dealing across function boundaries
94 93 * then sometimes we pass frob(foo) which sets foo->bar.a. In that case, we
95 94 * translate it to the shorter name. Smatch extra updates the shorter name,
96 95 * which in turn updates the longer name.
97 96 *
98 97 */
99 98 char *map_long_to_short_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
100 99 {
101 100 char *ret;
102 101 struct sm_state *sm;
103 102
104 103 *new_sym = NULL;
105 104
106 105 FOR_EACH_SM(__get_cur_stree(), sm) {
107 106 if (sm->owner == my_id) {
108 107 ret = map_my_state_long_to_short(sm, name, sym, new_sym, use_stack);
109 108 if (ret) {
110 109 if (local_debug)
111 110 sm_msg("%s: my_state: name = '%s' sm = '%s'",
112 111 __func__, name, show_sm(sm));
113 112 return ret;
114 113 }
115 114 continue;
116 115 }
117 116 } END_FOR_EACH_SM(sm);
118 117
119 118 return NULL;
120 119 }
121 120
122 121 char *map_call_to_param_name_sym(struct expression *expr, struct symbol **sym)
123 122 {
124 123 char *name;
125 124 struct symbol *start_sym;
126 125 struct smatch_state *state;
127 126
128 127 *sym = NULL;
129 128
130 129 name = expr_to_str_sym(expr, &start_sym);
131 130 if (!name)
132 131 return NULL;
133 132 if (expr->type == EXPR_CALL)
134 133 start_sym = expr_to_sym(expr->fn);
135 134
136 135 state = get_state(my_id, name, start_sym);
137 136 free_string(name);
138 137 if (!state || !state->data)
139 138 return NULL;
140 139
141 140 *sym = state->data;
142 141 return alloc_string(state->name);
143 142 }
144 143
145 144 static void store_mapping_helper(char *left_name, struct symbol *left_sym, struct expression *call, const char *return_string)
146 145 {
147 146 const char *p = return_string;
148 147 char *close;
149 148 int param;
150 149 struct expression *arg, *new;
151 150 char *right_name;
152 151 struct symbol *right_sym;
153 152 char buf[256];
154 153
155 154 while (*p && *p != '[')
156 155 p++;
157 156 if (!*p)
158 157 return;
159 158 p++;
160 159 if (*p != '$')
161 160 return;
162 161
163 162 snprintf(buf, sizeof(buf), "%s", p);
164 163 close = strchr(buf, ']');
165 164 if (!close)
166 165 return;
167 166 *close = '\0';
168 167
169 168 param = atoi(buf + 1);
170 169 arg = get_argument_from_call_expr(call->args, param);
171 170 if (!arg)
172 171 return;
173 172
174 173 new = gen_expression_from_key(arg, buf);
175 174 if (!new)
176 175 return;
177 176
178 177 right_name = expr_to_var_sym(new, &right_sym);
179 178 if (!right_name || !right_sym)
180 179 goto free;
181 180
182 181 set_state(my_id, left_name, left_sym, alloc_my_state(right_name, right_sym));
183 182 store_link(link_id, right_name, right_sym, left_name, left_sym);
184 183
185 184 free:
186 185 free_string(right_name);
187 186 }
188 187
189 188 void __add_return_to_param_mapping(struct expression *expr, const char *return_string)
190 189 {
191 190 struct expression *call;
192 191 char *left_name = NULL;
193 192 struct symbol *left_sym;
194 193
195 194 if (expr->type == EXPR_ASSIGNMENT) {
196 195 left_name = expr_to_var_sym(expr->left, &left_sym);
197 196 if (!left_name || !left_sym)
198 197 goto free;
199 198
200 199 call = strip_expr(expr->right);
201 200 if (call->type != EXPR_CALL)
202 201 goto free;
203 202
204 203 store_mapping_helper(left_name, left_sym, call, return_string);
205 204 goto free;
206 205 }
207 206
208 207 if (expr->type == EXPR_CALL &&
209 208 expr_get_parent_stmt(expr) &&
210 209 expr_get_parent_stmt(expr)->type == STMT_RETURN) {
211 210 call = strip_expr(expr);
212 211 left_sym = expr_to_sym(call->fn);
213 212 if (!left_sym)
214 213 return;
215 214 left_name = expr_to_str(call);
216 215 if (!left_name)
217 216 return;
218 217
219 218 store_mapping_helper(left_name, left_sym, call, return_string);
220 219 goto free;
221 220
222 221 }
223 222
224 223 free:
225 224 free_string(left_name);
226 225 }
227 226
228 227 void register_return_to_param(int id)
229 228 {
230 229 my_id = id;
231 230 set_dynamic_states(my_id);
232 231 add_modification_hook(my_id, &undef);
233 232 }
234 233
235 234 void register_return_to_param_links(int id)
236 235 {
237 236 link_id = id;
238 237 set_up_link_functions(my_id, link_id);
239 238 }
240 239
↓ open down ↓ |
199 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX