19 * What we're doing here is saving all the possible values for static variables.
20 * Later on we might do globals as well.
21 *
22 */
23
24 #include "smatch.h"
25 #include "smatch_slist.h"
26 #include "smatch_extra.h"
27
28 static int my_id;
29 static struct stree *vals;
30
31 static int save_rl(void *_rl, int argc, char **argv, char **azColName)
32 {
33 unsigned long *rl = _rl;
34
35 *rl = strtoul(argv[0], NULL, 10);
36 return 0;
37 }
38
39 static struct range_list *select_orig_rl(sval_t sval)
40 {
41 struct range_list *rl = NULL;
42 mtag_t tag = sval.uvalue & ~MTAG_OFFSET_MASK;
43 int offset = sval.uvalue & MTAG_OFFSET_MASK;
44
45 mem_sql(&save_rl, &rl, "select value from mtag_data where tag = %lld and offset = %d;",
46 tag, offset);
47 return rl;
48 }
49
50 static int is_kernel_param(const char *name)
51 {
52 struct sm_state *tmp;
53 char buf[256];
54
55 /*
56 * I'm ignoring these because otherwise Smatch thinks that kernel
57 * parameters are always set to the default.
58 *
59 */
60
61 if (option_project != PROJ_KERNEL)
62 return 0;
63
64 snprintf(buf, sizeof(buf), "__param_%s.arg", name);
65
66 FOR_EACH_SM(vals, tmp) {
67 if (strcmp(tmp->name, buf) == 0)
68 return 1;
69 } END_FOR_EACH_SM(tmp);
70
71 return 0;
72 }
73
74 void insert_mtag_data(sval_t sval, struct range_list *rl)
75 {
76 mtag_t tag = sval.uvalue & ~MTAG_OFFSET_MASK;
77 int offset = sval.uvalue & MTAG_OFFSET_MASK;
78
79 rl = clone_rl_permanent(rl);
80
81 mem_sql(NULL, NULL, "delete from mtag_data where tag = %lld and offset = %d and type = %d",
82 tag, offset, DATA_VALUE);
83 mem_sql(NULL, NULL, "insert into mtag_data values (%lld, %d, %d, '%lu');",
84 tag, offset, DATA_VALUE, (unsigned long)rl);
85 }
86
87 void update_mtag_data(struct expression *expr)
88 {
89 struct range_list *orig, *new, *rl;
90 char *name;
91 sval_t sval;
92
93 name = expr_to_var(expr);
94 if (is_kernel_param(name)) {
95 free_string(name);
96 return;
97 }
98 free_string(name);
99
100 if (!get_mtag_addr_sval(expr, &sval))
101 return;
102
103 get_absolute_rl(expr, &rl);
104
105 orig = select_orig_rl(sval);
106 new = rl_union(orig, rl);
107 insert_mtag_data(sval, new);
108 }
109
110 static void match_global_assign(struct expression *expr)
111 {
112 struct range_list *rl;
113 sval_t sval;
114 char *name;
115
116 name = expr_to_var(expr->left);
117 if (is_kernel_param(name)) {
118 free_string(name);
119 return;
120 }
121 free_string(name);
122
123 if (!get_mtag_addr_sval(expr->left, &sval))
124 return;
125
126 get_absolute_rl(expr->right, &rl);
127 insert_mtag_data(sval, rl);
128 }
129
130 static int save_mtag_data(void *_unused, int argc, char **argv, char **azColName)
131 {
132 struct range_list *rl;
133
134 if (argc != 4) {
135 sm_msg("Error saving mtag data");
136 return 0;
137 }
138 if (!option_info)
139 return 0;
140
141 rl = (struct range_list *)strtoul(argv[3], NULL, 10);
142 sm_msg("SQL: insert into mtag_data values ('%s', '%s', '%s', '%s');",
143 argv[0], argv[1], argv[2], show_rl(rl));
144
145 return 0;
146 }
147
154 struct db_info {
155 struct symbol *type;
156 struct range_list *rl;
157 };
158
159 static int get_vals(void *_db_info, int argc, char **argv, char **azColName)
160 {
161 struct db_info *db_info = _db_info;
162 struct range_list *tmp;
163
164 str_to_rl(db_info->type, argv[0], &tmp);
165 if (db_info->rl)
166 db_info->rl = rl_union(db_info->rl, tmp);
167 else
168 db_info->rl = tmp;
169
170 return 0;
171 }
172
173 struct db_cache_results {
174 sval_t sval;
175 struct range_list *rl;
176 };
177 static struct db_cache_results cached_results[8];
178
179 static int get_rl_from_mtag_sval(sval_t sval, struct symbol *type, struct range_list **rl)
180 {
181 struct db_info db_info = {};
182 mtag_t tag;
183 int offset;
184 static int idx;
185 int ret;
186 int i;
187
188 for (i = 0; i < ARRAY_SIZE(cached_results); i++) {
189 if (sval.uvalue == cached_results[i].sval.uvalue) {
190 if (cached_results[i].rl) {
191 *rl = cached_results[i].rl;
192 return 1;
193 }
194 return 0;
195 }
196 }
197
198 tag = sval.uvalue & ~MTAG_OFFSET_MASK;
199 offset = sval.uvalue & MTAG_OFFSET_MASK;
200 if (offset == MTAG_OFFSET_MASK) {
201 ret = 0;
202 goto update_cache;
203 }
204 db_info.type = type;
205
206 run_sql(get_vals, &db_info,
207 "select value from mtag_data where tag = %lld and offset = %d and type = %d;",
208 tag, offset, DATA_VALUE);
209 if (!db_info.rl || is_whole_rl(db_info.rl)) {
210 db_info.rl = NULL;
211 ret = 0;
212 goto update_cache;
213 }
214
215 *rl = db_info.rl;
216 ret = 1;
217
218 update_cache:
219 cached_results[idx].sval = sval;
220 cached_results[idx].rl = db_info.rl;
221 idx = (idx + 1) % ARRAY_SIZE(cached_results);
222
223 return ret;
224 }
225
226 static void clear_cache(struct symbol *sym)
227 {
228 memset(cached_results, 0, sizeof(cached_results));
229 }
230
231 int get_mtag_rl(struct expression *expr, struct range_list **rl)
232 {
233 struct symbol *type;
234 sval_t sval;
235
236 if (!get_mtag_addr_sval(expr, &sval))
237 return 0;
238
239 type = get_type(expr);
240 if (!type)
241 return 0;
242
243 return get_rl_from_mtag_sval(sval, type, rl);
244 }
245
246 void register_mtag_data(int id)
247 {
248 my_id = id;
249
250 add_hook(&clear_cache, FUNC_DEF_HOOK);
251
252 // if (!option_info)
253 // return;
254 add_hook(&match_global_assign, GLOBAL_ASSIGNMENT_HOOK);
255 add_hook(&match_end_file, END_FILE_HOOK);
256 }
257
|
19 * What we're doing here is saving all the possible values for static variables.
20 * Later on we might do globals as well.
21 *
22 */
23
24 #include "smatch.h"
25 #include "smatch_slist.h"
26 #include "smatch_extra.h"
27
28 static int my_id;
29 static struct stree *vals;
30
31 static int save_rl(void *_rl, int argc, char **argv, char **azColName)
32 {
33 unsigned long *rl = _rl;
34
35 *rl = strtoul(argv[0], NULL, 10);
36 return 0;
37 }
38
39 static struct range_list *select_orig(mtag_t tag, int offset)
40 {
41 struct range_list *rl = NULL;
42
43 mem_sql(&save_rl, &rl, "select value from mtag_data where tag = %lld and offset = %d;",
44 tag, offset);
45 return rl;
46 }
47
48 static int is_kernel_param(const char *name)
49 {
50 struct sm_state *tmp;
51 char buf[256];
52
53 /*
54 * I'm ignoring these because otherwise Smatch thinks that kernel
55 * parameters are always set to the default.
56 *
57 */
58
59 if (option_project != PROJ_KERNEL)
60 return 0;
61
62 snprintf(buf, sizeof(buf), "__param_%s.arg", name);
63
64 FOR_EACH_SM(vals, tmp) {
65 if (strcmp(tmp->name, buf) == 0)
66 return 1;
67 } END_FOR_EACH_SM(tmp);
68
69 return 0;
70 }
71
72 static void insert_mtag_data(mtag_t tag, int offset, struct range_list *rl)
73 {
74 rl = clone_rl_permanent(rl);
75
76 mem_sql(NULL, NULL, "delete from mtag_data where tag = %lld and offset = %d and type = %d",
77 tag, offset, DATA_VALUE);
78 mem_sql(NULL, NULL, "insert into mtag_data values (%lld, %d, %d, '%lu');",
79 tag, offset, DATA_VALUE, (unsigned long)rl);
80 }
81
82 void update_mtag_data(struct expression *expr)
83 {
84 struct range_list *orig, *new, *rl;
85 struct symbol *type;
86 char *name;
87 mtag_t tag;
88 int offset;
89
90 name = expr_to_var(expr);
91 if (is_kernel_param(name)) {
92 free_string(name);
93 return;
94 }
95 free_string(name);
96
97 if (!expr_to_mtag_offset(expr, &tag, &offset))
98 return;
99
100 type = get_type(expr);
101 if ((offset == 0) &&
102 (!type || type == &void_ctype ||
103 type->type == SYM_STRUCT || type->type == SYM_UNION || type->type == SYM_ARRAY))
104 return;
105
106 get_absolute_rl(expr, &rl);
107
108 orig = select_orig(tag, offset);
109 new = rl_union(orig, rl);
110 insert_mtag_data(tag, offset, new);
111 }
112
113 static void match_global_assign(struct expression *expr)
114 {
115 struct range_list *rl;
116 mtag_t tag;
117 int offset;
118 char *name;
119
120 name = expr_to_var(expr->left);
121 if (is_kernel_param(name)) {
122 free_string(name);
123 return;
124 }
125 free_string(name);
126
127 if (!expr_to_mtag_offset(expr->left, &tag, &offset))
128 return;
129
130 get_absolute_rl(expr->right, &rl);
131 insert_mtag_data(tag, offset, rl);
132 }
133
134 static int save_mtag_data(void *_unused, int argc, char **argv, char **azColName)
135 {
136 struct range_list *rl;
137
138 if (argc != 4) {
139 sm_msg("Error saving mtag data");
140 return 0;
141 }
142 if (!option_info)
143 return 0;
144
145 rl = (struct range_list *)strtoul(argv[3], NULL, 10);
146 sm_msg("SQL: insert into mtag_data values ('%s', '%s', '%s', '%s');",
147 argv[0], argv[1], argv[2], show_rl(rl));
148
149 return 0;
150 }
151
158 struct db_info {
159 struct symbol *type;
160 struct range_list *rl;
161 };
162
163 static int get_vals(void *_db_info, int argc, char **argv, char **azColName)
164 {
165 struct db_info *db_info = _db_info;
166 struct range_list *tmp;
167
168 str_to_rl(db_info->type, argv[0], &tmp);
169 if (db_info->rl)
170 db_info->rl = rl_union(db_info->rl, tmp);
171 else
172 db_info->rl = tmp;
173
174 return 0;
175 }
176
177 struct db_cache_results {
178 mtag_t tag;
179 struct range_list *rl;
180 };
181 static struct db_cache_results cached_results[8];
182
183 static int get_rl_from_mtag_offset(mtag_t tag, int offset, struct symbol *type, struct range_list **rl)
184 {
185 struct db_info db_info = {};
186 mtag_t merged = tag | offset;
187 static int idx;
188 int ret;
189 int i;
190
191 if (!type || type == &void_ctype ||
192 (type->type == SYM_STRUCT || type->type == SYM_ARRAY || type->type == SYM_UNION))
193 return 0;
194
195 for (i = 0; i < ARRAY_SIZE(cached_results); i++) {
196 if (merged == cached_results[i].tag) {
197 if (cached_results[i].rl) {
198 *rl = cached_results[i].rl;
199 return 1;
200 }
201 return 0;
202 }
203 }
204
205 db_info.type = type;
206
207 run_sql(get_vals, &db_info,
208 "select value from mtag_data where tag = %lld and offset = %d and type = %d;",
209 tag, offset, DATA_VALUE);
210 if (!db_info.rl || is_whole_rl(db_info.rl)) {
211 db_info.rl = NULL;
212 ret = 0;
213 goto update_cache;
214 }
215
216 *rl = db_info.rl;
217 ret = 1;
218
219 update_cache:
220 cached_results[idx].tag = merged;
221 cached_results[idx].rl = db_info.rl;
222 idx = (idx + 1) % ARRAY_SIZE(cached_results);
223
224 return ret;
225 }
226
227 static void clear_cache(struct symbol *sym)
228 {
229 memset(cached_results, 0, sizeof(cached_results));
230 }
231
232 int get_mtag_rl(struct expression *expr, struct range_list **rl)
233 {
234 struct symbol *type;
235 mtag_t tag;
236 int offset;
237
238 if (!expr_to_mtag_offset(expr, &tag, &offset))
239 return 0;
240 if (offset >= MTAG_OFFSET_MASK)
241 return 0;
242
243 type = get_type(expr);
244 if (!type)
245 return 0;
246
247 return get_rl_from_mtag_offset(tag, offset, type, rl);
248 }
249
250 void register_mtag_data(int id)
251 {
252 my_id = id;
253
254 add_hook(&clear_cache, FUNC_DEF_HOOK);
255
256 // if (!option_info)
257 // return;
258 add_hook(&match_global_assign, GLOBAL_ASSIGNMENT_HOOK);
259 add_hook(&match_end_file, END_FILE_HOOK);
260 }
261
|