mtag_data: update mtag_data to use get_mtag_addr_sval()
[smatch.git] / smatch_mtag_data.c
blob1054f3a85aa8ef15f5a3dae9d41ef36c7625840b
1 /*
2 * Copyright (C) 2016 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * What we're doing here is saving all the possible values for static variables.
20 * Later on we might do globals as well.
24 #include "smatch.h"
25 #include "smatch_slist.h"
26 #include "smatch_extra.h"
28 static int my_id;
29 static struct stree *vals;
31 static int save_rl(void *_rl, int argc, char **argv, char **azColName)
33 unsigned long *rl = _rl;
35 *rl = strtoul(argv[0], NULL, 10);
36 return 0;
39 static struct range_list *select_orig_rl(sval_t sval)
41 struct range_list *rl = NULL;
42 mtag_t tag = sval.uvalue & ~MTAG_OFFSET_MASK;
43 int offset = sval.uvalue & MTAG_OFFSET_MASK;
45 mem_sql(&save_rl, &rl, "select value from mtag_data where tag = %lld and offset = %d;",
46 tag, offset);
47 return rl;
50 static int is_kernel_param(const char *name)
52 struct sm_state *tmp;
53 char buf[256];
56 * I'm ignoring these because otherwise Smatch thinks that kernel
57 * parameters are always set to the default.
61 if (option_project != PROJ_KERNEL)
62 return 0;
64 snprintf(buf, sizeof(buf), "__param_%s.arg", name);
66 FOR_EACH_SM(vals, tmp) {
67 if (strcmp(tmp->name, buf) == 0)
68 return 1;
69 } END_FOR_EACH_SM(tmp);
71 return 0;
74 void insert_mtag_data(sval_t sval, struct range_list *rl)
76 mtag_t tag = sval.uvalue & ~MTAG_OFFSET_MASK;
77 int offset = sval.uvalue & MTAG_OFFSET_MASK;
79 rl = clone_rl_permanent(rl);
81 mem_sql(NULL, NULL, "insert into mtag_data values (%lld, %d, %d, '%lu');",
82 tag, offset, DATA_VALUE, (unsigned long)rl);
85 void update_mtag_data(struct expression *expr)
87 struct range_list *orig, *new, *rl;
88 char *name;
89 sval_t sval;
91 name = expr_to_var(expr);
92 if (is_kernel_param(name)) {
93 free_string(name);
94 return;
96 free_string(name);
98 if (!get_mtag_addr_sval(expr, &sval))
99 return;
101 get_absolute_rl(expr, &rl);
103 orig = select_orig_rl(sval);
104 new = rl_union(orig, rl);
105 insert_mtag_data(sval, new);
108 static void match_global_assign(struct expression *expr)
110 struct range_list *rl;
111 sval_t sval;
112 char *name;
114 name = expr_to_var(expr->left);
115 if (is_kernel_param(name)) {
116 free_string(name);
117 return;
119 free_string(name);
121 if (!get_mtag_addr_sval(expr->left, &sval))
122 return;
124 get_absolute_rl(expr->right, &rl);
125 insert_mtag_data(sval, rl);
128 static int save_mtag_data(void *_unused, int argc, char **argv, char **azColName)
130 struct range_list *rl;
132 if (argc != 4) {
133 sm_msg("Error saving mtag data");
134 return 0;
137 rl = (struct range_list *)strtoul(argv[3], NULL, 10);
139 if (option_info) {
140 sm_msg("SQL: insert into mtag_data values ('%s', '%s', '%s', '%s');",
141 argv[0], argv[1], argv[2], show_rl(rl));
144 return 0;
147 static void match_end_file(struct symbol_list *sym_list)
149 mem_sql(&save_mtag_data, NULL, "select * from mtag_data;");
152 struct db_info {
153 struct symbol *type;
154 struct range_list *rl;
157 static int get_vals(void *_db_info, int argc, char **argv, char **azColName)
159 struct db_info *db_info = _db_info;
160 struct range_list *tmp;
162 str_to_rl(db_info->type, argv[0], &tmp);
163 if (db_info->rl)
164 db_info->rl = rl_union(db_info->rl, tmp);
165 else
166 db_info->rl = tmp;
168 return 0;
171 struct db_cache_results {
172 sval_t sval;
173 struct range_list *rl;
175 static struct db_cache_results cached_results[8];
177 static int get_rl_from_mtag_sval(sval_t sval, struct symbol *type, struct range_list **rl)
179 struct db_info db_info = {};
180 mtag_t tag;
181 int offset;
182 static int idx;
183 int ret;
184 int i;
186 for (i = 0; i < ARRAY_SIZE(cached_results); i++) {
187 if (sval.uvalue == cached_results[i].sval.uvalue) {
188 if (cached_results[i].rl) {
189 *rl = cached_results[i].rl;
190 return 1;
192 return 0;
196 tag = sval.uvalue & ~MTAG_OFFSET_MASK;
197 offset = sval.uvalue & MTAG_OFFSET_MASK;
198 if (offset == MTAG_OFFSET_MASK) {
199 ret = 0;
200 goto update_cache;
202 db_info.type = type;
204 run_sql(get_vals, &db_info,
205 "select value from mtag_data where tag = %lld and offset = %d and type = %d;",
206 tag, offset, DATA_VALUE);
207 if (!db_info.rl || is_whole_rl(db_info.rl)) {
208 db_info.rl = NULL;
209 ret = 0;
210 goto update_cache;
213 *rl = db_info.rl;
214 ret = 1;
216 update_cache:
217 cached_results[idx].sval = sval;
218 cached_results[idx].rl = db_info.rl;
219 idx = (idx + 1) % ARRAY_SIZE(cached_results);
221 return ret;
224 static void clear_cache(struct symbol *sym)
226 memset(cached_results, 0, sizeof(cached_results));
229 int get_mtag_rl(struct expression *expr, struct range_list **rl)
231 struct symbol *type;
232 sval_t sval;
234 if (!get_mtag_addr_sval(expr, &sval))
235 return 0;
237 type = get_type(expr);
238 if (!type)
239 return 0;
241 return get_rl_from_mtag_sval(sval, type, rl);
244 void register_mtag_data(int id)
246 my_id = id;
248 add_hook(&clear_cache, END_FUNC_HOOK);
250 // if (!option_info)
251 // return;
252 add_hook(&match_global_assign, GLOBAL_ASSIGNMENT_HOOK);
253 add_hook(&match_end_file, END_FILE_HOOK);