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_mtag_data.c
+++ new/usr/src/tools/smatch/src/smatch_mtag_data.c
1 1 /*
2 2 * Copyright (C) 2016 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 * What we're doing here is saving all the possible values for static variables.
20 20 * Later on we might do globals as well.
21 21 *
22 22 */
23 23
24 24 #include "smatch.h"
25 25 #include "smatch_slist.h"
26 26 #include "smatch_extra.h"
27 27
28 28 static int my_id;
29 29 static struct stree *vals;
30 30
31 31 static int save_rl(void *_rl, int argc, char **argv, char **azColName)
32 32 {
33 33 unsigned long *rl = _rl;
34 34
35 35 *rl = strtoul(argv[0], NULL, 10);
36 36 return 0;
37 37 }
38 38
39 39 static struct range_list *select_orig(mtag_t tag, int offset)
40 40 {
41 41 struct range_list *rl = NULL;
42 42
43 43 mem_sql(&save_rl, &rl, "select value from mtag_data where tag = %lld and offset = %d;",
44 44 tag, offset);
45 45 return rl;
46 46 }
47 47
48 48 static int is_kernel_param(const char *name)
49 49 {
50 50 struct sm_state *tmp;
51 51 char buf[256];
52 52
53 53 /*
54 54 * I'm ignoring these because otherwise Smatch thinks that kernel
55 55 * parameters are always set to the default.
56 56 *
57 57 */
58 58
59 59 if (option_project != PROJ_KERNEL)
60 60 return 0;
61 61
62 62 snprintf(buf, sizeof(buf), "__param_%s.arg", name);
63 63
64 64 FOR_EACH_SM(vals, tmp) {
65 65 if (strcmp(tmp->name, buf) == 0)
66 66 return 1;
67 67 } END_FOR_EACH_SM(tmp);
68 68
69 69 return 0;
70 70 }
71 71
72 72 static bool is_ignored_macro(struct expression *expr)
73 73 {
↓ open down ↓ |
73 lines elided |
↑ open up ↑ |
74 74 char *macro;
75 75
76 76 macro = get_macro_name(expr->pos);
77 77 if (!macro)
78 78 return false;
79 79 if (strcmp(macro, "EXPORT_SYMBOL") == 0)
80 80 return true;
81 81 return false;
82 82 }
83 83
84 +static bool is_head_next(struct expression *expr)
85 +{
86 + struct symbol *type;
87 +
88 + /* Smatch thinks head->next == head is always true. *sad face* */
89 +
90 + if (option_project != PROJ_KERNEL)
91 + return false;
92 +
93 + if (expr->type != EXPR_DEREF)
94 + return false;
95 + if (!expr->member || !expr->member->name ||
96 + strcmp(expr->member->name, "next") != 0)
97 + return false;
98 +
99 + type = get_type(expr->deref);
100 + if (!type)
101 + return false;
102 + if (type->type == SYM_PTR)
103 + type = get_real_base_type(type);
104 + if (type->type != SYM_STRUCT)
105 + return false;
106 + if (!type->ident || !type->ident->name ||
107 + strcmp(type->ident->name, "list_head") != 0)
108 + return false;
109 + return true;
110 +}
111 +
112 +mtag_t ignored_mtag;
113 +static bool is_ignored_tag(mtag_t tag)
114 +{
115 + if (tag == ignored_mtag)
116 + return true;
117 + return false;
118 +}
119 +
84 120 static void insert_mtag_data(mtag_t tag, int offset, struct range_list *rl)
85 121 {
122 + if (is_ignored_tag(tag))
123 + return;
124 +
86 125 rl = clone_rl_permanent(rl);
87 126
88 127 mem_sql(NULL, NULL, "delete from mtag_data where tag = %lld and offset = %d and type = %d",
89 128 tag, offset, DATA_VALUE);
90 129 mem_sql(NULL, NULL, "insert into mtag_data values (%lld, %d, %d, '%lu');",
91 130 tag, offset, DATA_VALUE, (unsigned long)rl);
92 131 }
93 132
94 133 static bool invalid_type(struct symbol *type)
95 134 {
96 135 if (!type)
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
97 136 return true;
98 137 if (type == &void_ctype)
99 138 return true;
100 139 if (type->type == SYM_STRUCT ||
101 140 type->type == SYM_ARRAY ||
102 141 type->type == SYM_UNION)
103 142 return true;
104 143 return false;
105 144 }
106 145
146 +static bool parent_is_fresh_alloc(struct expression *expr)
147 +{
148 + struct symbol *sym;
149 +
150 + sym = expr_to_sym(expr);
151 + if (!sym || !sym->ident)
152 + return false;
153 + return is_fresh_alloc_var_sym(sym->ident->name, sym);
154 +}
155 +
107 156 void update_mtag_data(struct expression *expr, struct smatch_state *state)
108 157 {
109 158 struct range_list *orig, *new;
110 159 struct symbol *type;
111 160 char *name;
112 161 mtag_t tag;
113 162 int offset;
114 163
115 164 if (!expr)
116 165 return;
117 166 if (is_local_variable(expr))
118 167 return;
119 168 if (is_ignored_macro(expr))
120 169 return;
170 + if (is_head_next(expr))
171 + return;
121 172 name = expr_to_var(expr);
122 173 if (is_kernel_param(name)) {
123 174 free_string(name);
124 175 return;
125 176 }
126 177 free_string(name);
127 178
128 179 if (!expr_to_mtag_offset(expr, &tag, &offset))
129 180 return;
130 181
131 182 type = get_type(expr);
132 183 if (offset == 0 && invalid_type(type))
133 184 return;
134 185
135 - orig = select_orig(tag, offset);
186 + if (parent_is_fresh_alloc(expr))
187 + orig = NULL;
188 + else
189 + orig = select_orig(tag, offset);
136 190 new = rl_union(orig, estate_rl(state));
137 191 insert_mtag_data(tag, offset, new);
138 192 }
139 193
140 194 static void match_global_assign(struct expression *expr)
141 195 {
142 196 struct range_list *rl;
143 197 mtag_t tag;
144 198 int offset;
145 199 char *name;
146 200
147 201 if (is_ignored_macro(expr))
148 202 return;
203 + if (is_head_next(expr->left))
204 + return;
149 205 name = expr_to_var(expr->left);
150 206 if (is_kernel_param(name)) {
151 207 free_string(name);
152 208 return;
153 209 }
154 210 free_string(name);
155 211
156 212 if (!expr_to_mtag_offset(expr->left, &tag, &offset))
157 213 return;
158 214
159 215 get_absolute_rl(expr->right, &rl);
160 216 insert_mtag_data(tag, offset, rl);
161 217 }
162 218
163 219 static int save_mtag_data(void *_unused, int argc, char **argv, char **azColName)
164 220 {
165 221 struct range_list *rl;
166 222
167 223 if (argc != 4) {
168 224 sm_msg("Error saving mtag data");
169 225 return 0;
170 226 }
171 227 if (!option_info)
172 228 return 0;
173 229
174 230 rl = (struct range_list *)strtoul(argv[3], NULL, 10);
175 231 sm_msg("SQL: insert into mtag_data values ('%s', '%s', '%s', '%s');",
176 232 argv[0], argv[1], argv[2], show_rl(rl));
177 233
178 234 return 0;
179 235 }
180 236
181 237 static void match_end_file(struct symbol_list *sym_list)
182 238 {
183 239 mem_sql(&save_mtag_data, NULL, "select * from mtag_data where type = %d;",
184 240 DATA_VALUE);
185 241 }
186 242
187 243 struct db_info {
188 244 struct symbol *type;
189 245 struct range_list *rl;
190 246 };
191 247
192 248 static int get_vals(void *_db_info, int argc, char **argv, char **azColName)
193 249 {
194 250 struct db_info *db_info = _db_info;
195 251 struct range_list *tmp;
196 252
197 253 str_to_rl(db_info->type, argv[0], &tmp);
198 254 if (db_info->rl)
199 255 db_info->rl = rl_union(db_info->rl, tmp);
200 256 else
201 257 db_info->rl = tmp;
202 258
203 259 return 0;
204 260 }
205 261
206 262 struct db_cache_results {
207 263 mtag_t tag;
208 264 struct range_list *rl;
209 265 };
210 266 static struct db_cache_results cached_results[8];
211 267
212 268 static int get_rl_from_mtag_offset(mtag_t tag, int offset, struct symbol *type, struct range_list **rl)
213 269 {
214 270 struct db_info db_info = {};
215 271 mtag_t merged = tag | offset;
216 272 static int idx;
217 273 int ret;
218 274 int i;
219 275
220 276 for (i = 0; i < ARRAY_SIZE(cached_results); i++) {
221 277 if (merged == cached_results[i].tag) {
222 278 if (cached_results[i].rl) {
223 279 *rl = cached_results[i].rl;
224 280 return 1;
225 281 }
226 282 return 0;
227 283 }
228 284 }
229 285
230 286 db_info.type = type;
231 287
232 288 run_sql(get_vals, &db_info,
233 289 "select value from mtag_data where tag = %lld and offset = %d and type = %d;",
234 290 tag, offset, DATA_VALUE);
235 291 if (!db_info.rl || is_whole_rl(db_info.rl)) {
236 292 db_info.rl = NULL;
237 293 ret = 0;
238 294 goto update_cache;
239 295 }
240 296
241 297 *rl = db_info.rl;
242 298 ret = 1;
243 299
244 300 update_cache:
245 301 cached_results[idx].tag = merged;
246 302 cached_results[idx].rl = db_info.rl;
247 303 idx = (idx + 1) % ARRAY_SIZE(cached_results);
248 304
249 305 return ret;
250 306 }
251 307
252 308 static void clear_cache(struct symbol *sym)
253 309 {
254 310 memset(cached_results, 0, sizeof(cached_results));
255 311 }
256 312
257 313 int get_mtag_rl(struct expression *expr, struct range_list **rl)
258 314 {
259 315 struct symbol *type;
260 316 mtag_t tag;
261 317 int offset;
262 318
263 319 if (is_local_variable(expr))
264 320 return 0;
265 321 if (!expr_to_mtag_offset(expr, &tag, &offset))
266 322 return 0;
267 323 if (offset >= MTAG_OFFSET_MASK)
268 324 return 0;
269 325
270 326 type = get_type(expr);
↓ open down ↓ |
112 lines elided |
↑ open up ↑ |
271 327 if (invalid_type(type))
272 328 return 0;
273 329
274 330 return get_rl_from_mtag_offset(tag, offset, type, rl);
275 331 }
276 332
277 333 void register_mtag_data(int id)
278 334 {
279 335 my_id = id;
280 336
337 + ignored_mtag = str_to_mtag("extern boot_params");
281 338 add_hook(&clear_cache, FUNC_DEF_HOOK);
282 339
283 340 // if (!option_info)
284 341 // return;
285 342 add_hook(&match_global_assign, GLOBAL_ASSIGNMENT_HOOK);
286 343 add_hook(&match_end_file, END_FILE_HOOK);
287 344 }
288 345
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX