1/*
2 * Copyright (C) 2009 Dan Carpenter.
3 *
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.
8 *
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.
13 *
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
16 */
17
18#include "smatch.h"
19
20static int my_id;
21
22static void match_dma_func(const char *fn, struct expression *expr, void *param)
23{
24	struct expression *arg;
25	struct symbol *sym;
26	char *name;
27
28	arg = get_argument_from_call_expr(expr->args, PTR_INT(param));
29	arg = strip_expr(arg);
30	if (!arg)
31		return;
32	if (arg->type == EXPR_PREOP && arg->op == '&') {
33		if (arg->unop->type != EXPR_SYMBOL)
34			return;
35		name = expr_to_str(arg);
36		sm_error("doing dma on the stack (%s)", name);
37		free_string(name);
38		return;
39	}
40	if (arg->type != EXPR_SYMBOL)
41		return;
42	sym = get_type(arg);
43	if (!sym || sym->type != SYM_ARRAY)
44		return;
45	if (get_param_num(arg) >= 0)
46		return;
47	name = expr_to_var(arg);
48	sm_error("doing dma on the stack (%s)", name);
49	free_string(name);
50}
51
52static void register_funcs_from_file(void)
53{
54	struct token *token;
55	const char *func;
56	int arg;
57
58	token = get_tokens_file("kernel.dma_funcs");
59	if (!token)
60		return;
61	if (token_type(token) != TOKEN_STREAMBEGIN)
62		return;
63	token = token->next;
64	while (token_type(token) != TOKEN_STREAMEND) {
65		if (token_type(token) != TOKEN_IDENT)
66			return;
67		func = show_ident(token->ident);
68		token = token->next;
69		if (token_type(token) != TOKEN_NUMBER)
70			return;
71		arg = atoi(token->number);
72		add_function_hook(func, &match_dma_func, INT_PTR(arg));
73		token = token->next;
74	}
75	clear_token_alloc();
76}
77
78void check_dma_on_stack(int id)
79{
80	if (option_project != PROJ_KERNEL)
81		return;
82	my_id = id;
83	register_funcs_from_file();
84}
85