function_hooks: introduce early add_function_hook_early()
[smatch.git] / check_ida_alloc.c
blob7f1f7463d404833936815d3b0f6e8912550f04ec
1 /*
2 * Copyright (C) 2022 Christophe Jaillet.
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 * The 'max' parameter of ida_alloc_max() and ida_alloc_range() is not interpreted
20 * as it was in the deprecated ida_simple_get().
22 * The 'max' value in the new functions is inclusive but it was exclusive before.
23 * So, in older code, this parameter was often a power of 2, such as 1 << 16, so
24 * that the maximum possible value was 0xffff.
26 * Now a power of 2 value is spurious.
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include "parse.h"
31 #include "smatch.h"
33 static int my_id;
35 static bool implied_power_of_two(struct expression *expr)
37 sval_t sval;
39 if (!get_implied_value(expr, &sval))
40 return false;
41 if (!(sval.uvalue & (sval.uvalue - 1)))
42 return true;
43 return false;
46 static bool is_power_of_two(struct expression *expr)
48 expr = strip_expr(expr);
50 if (expr->type == EXPR_BINOP &&
51 expr->op == SPECIAL_LEFTSHIFT &&
52 is_power_of_two(expr->left))
53 return true;
55 if (implied_power_of_two(expr))
56 return true;
58 return false;
61 static void match_ida_alloc(const char *fn, struct expression *expr, void *_arg_nr)
63 int arg_nr = PTR_INT(_arg_nr);
64 struct expression *arg_expr;
66 arg_expr = get_argument_from_call_expr(expr->args, arg_nr);
67 arg_expr = strip_expr(arg_expr);
69 if (is_power_of_two(arg_expr))
70 sm_error("Calling %s() with a 'max' argument which is a power of 2. -1 missing?",
71 fn);
74 void check_ida_alloc(int id)
76 if (option_project != PROJ_KERNEL)
77 return;
79 my_id = id;
81 add_function_hook("ida_alloc_max", &match_ida_alloc, INT_PTR(1));
82 add_function_hook("ida_alloc_range", &match_ida_alloc, INT_PTR(2));