2 * Copyright (C) 2012 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 #include "smatch_slist.h"
20 #include "smatch_extra.h"
27 } alloc_functions
[] = {
32 {"__vmalloc_node", 0},
35 DECLARE_PTR_LIST(sval_list
, sval_t
);
37 static struct sval_list
*num_list
;
38 static struct string_list
*op_list
;
40 static void push_val(sval_t sval
)
44 p
= malloc(sizeof(*p
));
46 add_ptr_list(&num_list
, p
);
49 static sval_t
pop_val()
55 sm_msg("internal bug: %s popping empty list", __func__
);
56 ret
.type
= &llong_ctype
;
60 p
= last_ptr_list((struct ptr_list
*)num_list
);
61 delete_ptr_list_last((struct ptr_list
**)&num_list
);
68 static void push_op(char c
)
74 add_ptr_list(&op_list
, p
);
83 sm_msg("internal smatch error %s", __func__
);
87 p
= last_ptr_list((struct ptr_list
*)op_list
);
89 delete_ptr_list_last((struct ptr_list
**)&op_list
);
96 static int op_precedence(char c
)
110 static int top_op_precedence()
117 p
= last_ptr_list((struct ptr_list
*)op_list
);
118 return op_precedence(p
[0]);
121 static void pop_until(char c
)
127 while (top_op_precedence() && op_precedence(c
) <= top_op_precedence()) {
131 res
= sval_binop(left
, op
, right
);
136 static void discard_stacks()
144 static int get_implied_param(struct expression
*call
, int param
, sval_t
*sval
)
146 struct expression
*arg
;
148 arg
= get_argument_from_call_expr(call
->args
, param
);
149 return get_implied_value(arg
, sval
);
152 static int read_number(struct expression
*call
, char *p
, char **end
, sval_t
*sval
)
161 param
= strtol(p
, &p
, 10);
162 if (!get_implied_param(call
, param
, sval
))
166 sval
->type
= &llong_ctype
;
167 sval
->value
= strtoll(p
, end
, 10);
174 static char *read_op(char *p
)
190 int parse_call_math(struct expression
*call
, char *math
, sval_t
*sval
)
195 /* try to implement shunting yard algorithm. */
200 sm_msg("parsing %s", c
);
202 /* read a number and push it onto the number stack */
203 if (!read_number(call
, c
, &c
, &tmp
))
208 sm_msg("val = %s remaining = %s", sval_to_str(tmp
), c
);
218 sm_msg("op = %c remaining = %s", *c
, c
);
233 static struct smatch_state
*alloc_state_sname(char *sname
)
235 struct smatch_state
*state
;
237 state
= __alloc_smatch_state(0);
239 state
->data
= INT_PTR(1);
243 static int get_arg_number(struct expression
*expr
)
249 expr
= strip_expr(expr
);
250 if (expr
->type
!= EXPR_SYMBOL
)
255 FOR_EACH_PTR(cur_func_sym
->ctype
.base_type
->arguments
, arg
) {
259 } END_FOR_EACH_PTR(arg
);
264 static int format_expr_helper(char *buf
, int remaining
, struct expression
*expr
)
276 if (expr
->type
== EXPR_BINOP
) {
277 ret
= format_expr_helper(cur
, remaining
, expr
->left
);
285 ret
= snprintf(cur
, remaining
, " %s ", show_special(expr
->op
));
291 ret
= format_expr_helper(cur
, remaining
, expr
->right
);
301 arg
= get_arg_number(expr
);
303 ret
= snprintf(cur
, remaining
, "<%d>", arg
);
310 if (get_implied_value(expr
, &sval
)) {
311 ret
= snprintf(cur
, remaining
, "%s", sval_to_str(sval
));
321 static char *format_expr(struct expression
*expr
)
326 ret
= format_expr_helper(buf
, sizeof(buf
), expr
);
330 return alloc_sname(buf
);
333 static void match_alloc(const char *fn
, struct expression
*expr
, void *_size_arg
)
335 int size_arg
= PTR_INT(_size_arg
);
336 struct expression
*right
;
337 struct expression
*size_expr
;
340 right
= strip_expr(expr
->right
);
341 size_expr
= get_argument_from_call_expr(right
->args
, size_arg
);
343 sname
= format_expr(size_expr
);
346 set_state_expr(my_id
, expr
->left
, alloc_state_sname(sname
));
349 static char *swap_format(struct expression
*call
, char *format
)
351 static char buf
[256];
354 struct expression
*arg
;
359 if (format
[0] == '<' && format
[2] == '>' && format
[3] == '\0') {
360 param
= strtol(format
+ 1, NULL
, 10);
361 arg
= get_argument_from_call_expr(call
->args
, param
);
364 return format_expr(arg
);
373 param
= strtol(p
, &p
, 10);
377 arg
= get_argument_from_call_expr(call
->args
, param
);
380 param
= get_arg_number(arg
);
382 ret
= snprintf(out
, buf
+ sizeof(buf
) - out
, "<%ld>", param
);
384 if (out
>= buf
+ sizeof(buf
))
386 } else if (get_implied_value(arg
, &sval
)) {
387 ret
= snprintf(out
, buf
+ sizeof(buf
) - out
, "%s", sval_to_str(sval
));
389 if (out
>= buf
+ sizeof(buf
))
401 return alloc_sname(buf
);
404 static char *buf_size_recipe
;
405 static int db_buf_size_callback(void *unused
, int argc
, char **argv
, char **azColName
)
410 if (!buf_size_recipe
)
411 buf_size_recipe
= alloc_sname(argv
[0]);
412 else if (strcmp(buf_size_recipe
, argv
[0]) != 0)
413 buf_size_recipe
= alloc_sname("invalid");
417 static char *get_allocation_recipe_from_call(struct expression
*expr
)
420 static char sql_filter
[1024];
423 if (is_fake_call(expr
))
425 expr
= strip_expr(expr
);
426 if (expr
->fn
->type
!= EXPR_SYMBOL
)
428 sym
= expr
->fn
->symbol
;
432 for (i
= 0; i
< ARRAY_SIZE(alloc_functions
); i
++) {
433 if (strcmp(sym
->ident
->name
, alloc_functions
[i
].func
) == 0) {
436 snprintf(buf
, sizeof(buf
), "<%d>", alloc_functions
[i
].param
);
437 buf_size_recipe
= alloc_sname(buf
);
438 return swap_format(expr
, buf_size_recipe
);
442 if (sym
->ctype
.modifiers
& MOD_STATIC
) {
443 snprintf(sql_filter
, 1024, "file = '%s' and function = '%s';",
444 get_filename(), sym
->ident
->name
);
446 snprintf(sql_filter
, 1024, "function = '%s' and static = 0;",
450 buf_size_recipe
= NULL
;
451 run_sql(db_buf_size_callback
, "select value from return_states where type=%d and %s",
452 BUF_SIZE
, sql_filter
);
453 if (!buf_size_recipe
|| strcmp(buf_size_recipe
, "invalid") == 0)
455 return swap_format(expr
, buf_size_recipe
);
458 static void match_call_assignment(struct expression
*expr
)
462 sname
= get_allocation_recipe_from_call(expr
->right
);
465 set_state_expr(my_id
, expr
->left
, alloc_state_sname(sname
));
468 static void match_returns_call(int return_id
, char *return_ranges
, struct expression
*call
)
472 sname
= get_allocation_recipe_from_call(call
);
474 sm_msg("sname = %s", sname
);
478 sql_insert_return_states(return_id
, return_ranges
, BUF_SIZE
, -1, "",
482 static void print_returned_allocations(int return_id
, char *return_ranges
, struct expression
*expr
)
484 struct smatch_state
*state
;
488 expr
= strip_expr(expr
);
492 if (expr
->type
== EXPR_CALL
) {
493 match_returns_call(return_id
, return_ranges
, expr
);
497 name
= expr_to_var_sym(expr
, &sym
);
501 state
= get_state(my_id
, name
, sym
);
502 if (!state
|| !state
->data
)
505 sql_insert_return_states(return_id
, return_ranges
, BUF_SIZE
, -1, "",
511 void register_parse_call_math(int id
)
517 for (i
= 0; i
< ARRAY_SIZE(alloc_functions
); i
++)
518 add_function_assign_hook(alloc_functions
[i
].func
, &match_alloc
,
519 INT_PTR(alloc_functions
[i
].param
));
520 add_hook(&match_call_assignment
, CALL_ASSIGNMENT_HOOK
);
521 add_split_return_callback(print_returned_allocations
);