11f5207b7SJohn Levon /*
21f5207b7SJohn Levon  * Copyright (C) 2013 Oracle.
31f5207b7SJohn Levon  *
41f5207b7SJohn Levon  * This program is free software; you can redistribute it and/or
51f5207b7SJohn Levon  * modify it under the terms of the GNU General Public License
61f5207b7SJohn Levon  * as published by the Free Software Foundation; either version 2
71f5207b7SJohn Levon  * of the License, or (at your option) any later version.
81f5207b7SJohn Levon  *
91f5207b7SJohn Levon  * This program is distributed in the hope that it will be useful,
101f5207b7SJohn Levon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
111f5207b7SJohn Levon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
121f5207b7SJohn Levon  * GNU General Public License for more details.
131f5207b7SJohn Levon  *
141f5207b7SJohn Levon  * You should have received a copy of the GNU General Public License
151f5207b7SJohn Levon  * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
161f5207b7SJohn Levon  */
171f5207b7SJohn Levon 
181f5207b7SJohn Levon /*
191f5207b7SJohn Levon  * Track how functions are saved as various struct members or passed as
201f5207b7SJohn Levon  * parameters.
211f5207b7SJohn Levon  *
221f5207b7SJohn Levon  */
231f5207b7SJohn Levon 
241f5207b7SJohn Levon #include "scope.h"
251f5207b7SJohn Levon #include "smatch.h"
261f5207b7SJohn Levon #include "smatch_slist.h"
271f5207b7SJohn Levon 
281f5207b7SJohn Levon static int my_id;
291f5207b7SJohn Levon 
get_from__symbol_get(struct expression * expr)301f5207b7SJohn Levon static char *get_from__symbol_get(struct expression *expr)
311f5207b7SJohn Levon {
321f5207b7SJohn Levon 	struct expression *arg;
331f5207b7SJohn Levon 
341f5207b7SJohn Levon 	/*
351f5207b7SJohn Levon 	 * typeof(&dib0070_attach) __a =
361f5207b7SJohn Levon 	 * ((((typeof(&dib0070_attach)) (__symbol_get("dib0070_attach")))) ?:
371f5207b7SJohn Levon 	 *  (__request_module(true, "symbol:" "dib0070_attach"), (((typeof(&dib0070_attach))(__symbol_get("dib0070_attach"))))));
381f5207b7SJohn Levon 	 */
391f5207b7SJohn Levon 
401f5207b7SJohn Levon 	expr = strip_expr(expr);
411f5207b7SJohn Levon 
421f5207b7SJohn Levon 	if (expr->type != EXPR_CALL)
431f5207b7SJohn Levon 		return NULL;
441f5207b7SJohn Levon 	if (!sym_name_is("__symbol_get", expr->fn))
451f5207b7SJohn Levon 		return NULL;
461f5207b7SJohn Levon 	arg = get_argument_from_call_expr(expr->args, 0);
471f5207b7SJohn Levon 	if (!arg || arg->type != EXPR_STRING)
481f5207b7SJohn Levon 		return NULL;
491f5207b7SJohn Levon 
501f5207b7SJohn Levon 	return alloc_string(arg->string->data);
511f5207b7SJohn Levon }
521f5207b7SJohn Levon 
xxx_is_array(struct expression * expr)53*c85f09ccSJohn Levon static int xxx_is_array(struct expression *expr)
54*c85f09ccSJohn Levon {
55*c85f09ccSJohn Levon 	struct symbol *type;
56*c85f09ccSJohn Levon 
57*c85f09ccSJohn Levon 	expr = strip_expr(expr);
58*c85f09ccSJohn Levon 	if (!expr)
59*c85f09ccSJohn Levon 		return 0;
60*c85f09ccSJohn Levon 
61*c85f09ccSJohn Levon 	if (expr->type == EXPR_PREOP && expr->op == '*') {
62*c85f09ccSJohn Levon 		expr = strip_expr(expr->unop);
63*c85f09ccSJohn Levon 		if (!expr)
64*c85f09ccSJohn Levon 			return 0;
65*c85f09ccSJohn Levon 		if (expr->type == EXPR_BINOP && expr->op == '+')
66*c85f09ccSJohn Levon 			return 1;
67*c85f09ccSJohn Levon 	}
68*c85f09ccSJohn Levon 
69*c85f09ccSJohn Levon 	if (expr->type != EXPR_BINOP || expr->op != '+')
70*c85f09ccSJohn Levon 		return 0;
71*c85f09ccSJohn Levon 
72*c85f09ccSJohn Levon 	type = get_type(expr->left);
73*c85f09ccSJohn Levon 	if (!type)
74*c85f09ccSJohn Levon 		return 0;
75*c85f09ccSJohn Levon 	if (type->type != SYM_ARRAY && type->type != SYM_PTR)
76*c85f09ccSJohn Levon 		return 0;
77*c85f09ccSJohn Levon 
78*c85f09ccSJohn Levon 	return 1;
79*c85f09ccSJohn Levon }
80*c85f09ccSJohn Levon 
xxx_get_array_base(struct expression * expr)81*c85f09ccSJohn Levon static struct expression *xxx_get_array_base(struct expression *expr)
82*c85f09ccSJohn Levon {
83*c85f09ccSJohn Levon 	if (!xxx_is_array(expr))
84*c85f09ccSJohn Levon 		return NULL;
85*c85f09ccSJohn Levon 	expr = strip_expr(expr);
86*c85f09ccSJohn Levon 	if (expr->type == EXPR_PREOP && expr->op == '*')
87*c85f09ccSJohn Levon 		expr = strip_expr(expr->unop);
88*c85f09ccSJohn Levon 	if (expr->type != EXPR_BINOP || expr->op != '+')
89*c85f09ccSJohn Levon 		return NULL;
90*c85f09ccSJohn Levon 	return strip_parens(expr->left);
91*c85f09ccSJohn Levon }
92*c85f09ccSJohn Levon 
get_array_ptr(struct expression * expr)931f5207b7SJohn Levon static char *get_array_ptr(struct expression *expr)
941f5207b7SJohn Levon {
951f5207b7SJohn Levon 	struct expression *array;
961f5207b7SJohn Levon 	struct symbol *type;
971f5207b7SJohn Levon 	char *name;
981f5207b7SJohn Levon 	char buf[256];
991f5207b7SJohn Levon 
100*c85f09ccSJohn Levon 	array = xxx_get_array_base(expr);
1011f5207b7SJohn Levon 
1021f5207b7SJohn Levon 	if (array) {
1031f5207b7SJohn Levon 		name = get_member_name(array);
1041f5207b7SJohn Levon 		if (name)
1051f5207b7SJohn Levon 			return name;
1061f5207b7SJohn Levon 	}
1071f5207b7SJohn Levon 
1081f5207b7SJohn Levon 	/* FIXME:  is_array() should probably be is_array_element() */
1091f5207b7SJohn Levon 	type = get_type(expr);
1101f5207b7SJohn Levon 	if (!array && type && type->type == SYM_ARRAY)
1111f5207b7SJohn Levon 		array = expr;
1121f5207b7SJohn Levon 	if (array) {
1131f5207b7SJohn Levon 		name = expr_to_var(array);
1141f5207b7SJohn Levon 		if (!name)
1151f5207b7SJohn Levon 			return NULL;
1161f5207b7SJohn Levon 		snprintf(buf, sizeof(buf), "%s[]", name);
1171f5207b7SJohn Levon 		return alloc_string(buf);
1181f5207b7SJohn Levon 	}
1191f5207b7SJohn Levon 
1201f5207b7SJohn Levon 	expr = get_assigned_expr(expr);
121*c85f09ccSJohn Levon 	array = xxx_get_array_base(expr);
1221f5207b7SJohn Levon 	if (!array)
1231f5207b7SJohn Levon 		return NULL;
1241f5207b7SJohn Levon 	name = expr_to_var(array);
1251f5207b7SJohn Levon 	if (!name)
1261f5207b7SJohn Levon 		return NULL;
1271f5207b7SJohn Levon 	snprintf(buf, sizeof(buf), "%s[]", name);
1281f5207b7SJohn Levon 	free_string(name);
1291f5207b7SJohn Levon 	return alloc_string(buf);
1301f5207b7SJohn Levon }
1311f5207b7SJohn Levon 
is_local_symbol(struct symbol * sym)1321f5207b7SJohn Levon static int is_local_symbol(struct symbol *sym)
1331f5207b7SJohn Levon {
1341f5207b7SJohn Levon 	if (!sym ||
1351f5207b7SJohn Levon 	    !(sym->ctype.modifiers & MOD_TOPLEVEL))
1361f5207b7SJohn Levon 		return 1;
1371f5207b7SJohn Levon 	return 0;
1381f5207b7SJohn Levon }
1391f5207b7SJohn Levon 
ptr_prefix(struct symbol * sym)1401f5207b7SJohn Levon static char *ptr_prefix(struct symbol *sym)
1411f5207b7SJohn Levon {
1421f5207b7SJohn Levon 	static char buf[128];
1431f5207b7SJohn Levon 
1441f5207b7SJohn Levon 
1451f5207b7SJohn Levon 	if (is_local_symbol(sym))
1461f5207b7SJohn Levon 		snprintf(buf, sizeof(buf), "%s ptr", get_function());
1471f5207b7SJohn Levon 	else if (sym && toplevel(sym->scope))
1481f5207b7SJohn Levon 		snprintf(buf, sizeof(buf), "%s ptr", get_base_file());
1491f5207b7SJohn Levon 	else
1501f5207b7SJohn Levon 		snprintf(buf, sizeof(buf), "ptr");
1511f5207b7SJohn Levon 
1521f5207b7SJohn Levon 	return buf;
1531f5207b7SJohn Levon }
1541f5207b7SJohn Levon 
get_returned_ptr(struct expression * expr)1551f5207b7SJohn Levon char *get_returned_ptr(struct expression *expr)
1561f5207b7SJohn Levon {
1571f5207b7SJohn Levon 	struct symbol *type;
1581f5207b7SJohn Levon 	char *name;
1591f5207b7SJohn Levon 	char buf[256];
1601f5207b7SJohn Levon 
1611f5207b7SJohn Levon 	if (expr->type != EXPR_CALL)
1621f5207b7SJohn Levon 		return NULL;
1631f5207b7SJohn Levon 	if (!expr->fn || expr->fn->type != EXPR_SYMBOL)
1641f5207b7SJohn Levon 		return NULL;
1651f5207b7SJohn Levon 
1661f5207b7SJohn Levon 	type = get_type(expr);
1671f5207b7SJohn Levon 	if (type && type->type == SYM_PTR)
1681f5207b7SJohn Levon 		type = get_real_base_type(type);
1691f5207b7SJohn Levon 	if (!type || type->type != SYM_FN)
1701f5207b7SJohn Levon 		return NULL;
1711f5207b7SJohn Levon 
1721f5207b7SJohn Levon 	name = expr_to_var(expr->fn);
1731f5207b7SJohn Levon 	if (!name)
1741f5207b7SJohn Levon 		return NULL;
1751f5207b7SJohn Levon 	snprintf(buf, sizeof(buf), "r %s()", name);
1761f5207b7SJohn Levon 	free_string(name);
1771f5207b7SJohn Levon 	return alloc_string(buf);
1781f5207b7SJohn Levon }
1791f5207b7SJohn Levon 
get_fnptr_name(struct expression * expr)1801f5207b7SJohn Levon char *get_fnptr_name(struct expression *expr)
1811f5207b7SJohn Levon {
1821f5207b7SJohn Levon 	char *name;
1831f5207b7SJohn Levon 
184*c85f09ccSJohn Levon 	if (expr_is_zero(expr))
185efe51d0cSJohn Levon 		return NULL;
186efe51d0cSJohn Levon 
1871f5207b7SJohn Levon 	expr = strip_expr(expr);
1881f5207b7SJohn Levon 
1891f5207b7SJohn Levon 	/* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
1901f5207b7SJohn Levon 	if (expr->type == EXPR_PREOP && expr->op == '*')
1911f5207b7SJohn Levon 		expr = strip_expr(expr->unop);
1921f5207b7SJohn Levon 
1931f5207b7SJohn Levon 	name = get_from__symbol_get(expr);
1941f5207b7SJohn Levon 	if (name)
1951f5207b7SJohn Levon 		return name;
1961f5207b7SJohn Levon 
1971f5207b7SJohn Levon 	name = get_array_ptr(expr);
1981f5207b7SJohn Levon 	if (name)
1991f5207b7SJohn Levon 		return name;
2001f5207b7SJohn Levon 
2011f5207b7SJohn Levon 	name = get_returned_ptr(expr);
2021f5207b7SJohn Levon 	if (name)
2031f5207b7SJohn Levon 		return name;
2041f5207b7SJohn Levon 
2051f5207b7SJohn Levon 	name = get_member_name(expr);
2061f5207b7SJohn Levon 	if (name)
2071f5207b7SJohn Levon 		return name;
2081f5207b7SJohn Levon 
2091f5207b7SJohn Levon 	if (expr->type == EXPR_SYMBOL) {
2101f5207b7SJohn Levon 		int param;
2111f5207b7SJohn Levon 		char buf[256];
2121f5207b7SJohn Levon 		struct symbol *sym;
2131f5207b7SJohn Levon 		struct symbol *type;
2141f5207b7SJohn Levon 
2151f5207b7SJohn Levon 		param = get_param_num_from_sym(expr->symbol);
2161f5207b7SJohn Levon 		if (param >= 0) {
2171f5207b7SJohn Levon 			snprintf(buf, sizeof(buf), "%s param %d", get_function(), param);
2181f5207b7SJohn Levon 			return alloc_string(buf);
2191f5207b7SJohn Levon 		}
2201f5207b7SJohn Levon 
2211f5207b7SJohn Levon 		name = expr_to_var_sym(expr, &sym);
2221f5207b7SJohn Levon 		if (!name)
2231f5207b7SJohn Levon 			return NULL;
2241f5207b7SJohn Levon 		type = get_type(expr);
2251f5207b7SJohn Levon 		if (type && type->type == SYM_PTR) {
2261f5207b7SJohn Levon 			snprintf(buf, sizeof(buf), "%s %s", ptr_prefix(sym), name);
2271f5207b7SJohn Levon 			free_string(name);
2281f5207b7SJohn Levon 			return alloc_string(buf);
2291f5207b7SJohn Levon 		}
2301f5207b7SJohn Levon 		return name;
2311f5207b7SJohn Levon 	}
2321f5207b7SJohn Levon 	return expr_to_var(expr);
2331f5207b7SJohn Levon }
2341f5207b7SJohn Levon 
match_passes_function_pointer(struct expression * expr)2351f5207b7SJohn Levon static void match_passes_function_pointer(struct expression *expr)
2361f5207b7SJohn Levon {
2371f5207b7SJohn Levon 	struct expression *arg, *tmp;
2381f5207b7SJohn Levon 	struct symbol *type;
2391f5207b7SJohn Levon 	char *called_name;
2401f5207b7SJohn Levon 	char *fn_name;
2411f5207b7SJohn Levon 	char ptr_name[256];
2421f5207b7SJohn Levon 	int i;
2431f5207b7SJohn Levon 
2441f5207b7SJohn Levon 
2451f5207b7SJohn Levon 	i = -1;
2461f5207b7SJohn Levon 	FOR_EACH_PTR(expr->args, arg) {
2471f5207b7SJohn Levon 		i++;
2481f5207b7SJohn Levon 
2491f5207b7SJohn Levon 		tmp = strip_expr(arg);
2501f5207b7SJohn Levon 		if (tmp->type == EXPR_PREOP && tmp->op == '&')
2511f5207b7SJohn Levon 			tmp = strip_expr(tmp->unop);
2521f5207b7SJohn Levon 
2531f5207b7SJohn Levon 		type = get_type(tmp);
2541f5207b7SJohn Levon 		if (type && type->type == SYM_PTR)
2551f5207b7SJohn Levon 			type = get_real_base_type(type);
2561f5207b7SJohn Levon 		if (!type || type->type != SYM_FN)
2571f5207b7SJohn Levon 			continue;
2581f5207b7SJohn Levon 
2591f5207b7SJohn Levon 		called_name = expr_to_var(expr->fn);
2601f5207b7SJohn Levon 		if (!called_name)
2611f5207b7SJohn Levon 			return;
2621f5207b7SJohn Levon 		fn_name = get_fnptr_name(tmp);
2631f5207b7SJohn Levon 		if (!fn_name)
2641f5207b7SJohn Levon 			goto free;
2651f5207b7SJohn Levon 
2661f5207b7SJohn Levon 		snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i);
2671f5207b7SJohn Levon 		sql_insert_function_ptr(fn_name, ptr_name);
2681f5207b7SJohn Levon free:
2691f5207b7SJohn Levon 		free_string(fn_name);
2701f5207b7SJohn Levon 		free_string(called_name);
2711f5207b7SJohn Levon 	} END_FOR_EACH_PTR(arg);
2721f5207b7SJohn Levon 
2731f5207b7SJohn Levon }
2741f5207b7SJohn Levon 
get_row_count(void * _row_count,int argc,char ** argv,char ** azColName)2751f5207b7SJohn Levon static int get_row_count(void *_row_count, int argc, char **argv, char **azColName)
2761f5207b7SJohn Levon {
2771f5207b7SJohn Levon 	int *row_count = _row_count;
2781f5207b7SJohn Levon 
2791f5207b7SJohn Levon 	*row_count = 0;
2801f5207b7SJohn Levon 	if (argc != 1)
2811f5207b7SJohn Levon 		return 0;
2821f5207b7SJohn Levon 	*row_count = atoi(argv[0]);
2831f5207b7SJohn Levon 	return 0;
2841f5207b7SJohn Levon }
2851f5207b7SJohn Levon 
can_hold_function_ptr(struct expression * expr)2861f5207b7SJohn Levon static int can_hold_function_ptr(struct expression *expr)
2871f5207b7SJohn Levon {
2881f5207b7SJohn Levon 	struct symbol *type;
2891f5207b7SJohn Levon 
2901f5207b7SJohn Levon 	type = get_type(expr);
2911f5207b7SJohn Levon 	if (!type)
2921f5207b7SJohn Levon 		return 0;
2931f5207b7SJohn Levon 	if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
2941f5207b7SJohn Levon 		type = get_real_base_type(type);
2951f5207b7SJohn Levon 		if (!type)
2961f5207b7SJohn Levon 			return 0;
2971f5207b7SJohn Levon 	}
298*c85f09ccSJohn Levon 	/* pointer to a pointer */
299*c85f09ccSJohn Levon 	if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
300*c85f09ccSJohn Levon 		type = get_real_base_type(type);
301*c85f09ccSJohn Levon 		if (!type)
302*c85f09ccSJohn Levon 			return 0;
303*c85f09ccSJohn Levon 	}
3041f5207b7SJohn Levon 	if (type->type == SYM_FN)
3051f5207b7SJohn Levon 		return 1;
3061f5207b7SJohn Levon 	if (type == &ulong_ctype && expr->type == EXPR_DEREF)
3071f5207b7SJohn Levon 		return 1;
3081f5207b7SJohn Levon 	if (type == &void_ctype)
3091f5207b7SJohn Levon 		return 1;
3101f5207b7SJohn Levon 	return 0;
3111f5207b7SJohn Levon }
3121f5207b7SJohn Levon 
match_function_assign(struct expression * expr)3131f5207b7SJohn Levon static void match_function_assign(struct expression *expr)
3141f5207b7SJohn Levon {
3151f5207b7SJohn Levon 	struct expression *right;
3161f5207b7SJohn Levon 	struct symbol *type;
3171f5207b7SJohn Levon 	char *fn_name;
3181f5207b7SJohn Levon 	char *ptr_name;
3191f5207b7SJohn Levon 
3201f5207b7SJohn Levon 	if (__in_fake_assign)
3211f5207b7SJohn Levon 		return;
3221f5207b7SJohn Levon 
3231f5207b7SJohn Levon 	right = strip_expr(expr->right);
3241f5207b7SJohn Levon 	if (right->type == EXPR_PREOP && right->op == '&')
3251f5207b7SJohn Levon 		right = strip_expr(right->unop);
3261f5207b7SJohn Levon 
3271f5207b7SJohn Levon 	if (right->type != EXPR_SYMBOL &&
328*c85f09ccSJohn Levon 	    right->type != EXPR_DEREF &&
329*c85f09ccSJohn Levon 	    right->type != EXPR_CALL)
3301f5207b7SJohn Levon 		return;
3311f5207b7SJohn Levon 
3321f5207b7SJohn Levon 	if (!can_hold_function_ptr(right) ||
3331f5207b7SJohn Levon 	    !can_hold_function_ptr(expr->left))
3341f5207b7SJohn Levon 		return;
3351f5207b7SJohn Levon 
3361f5207b7SJohn Levon 	fn_name = get_fnptr_name(right);
3371f5207b7SJohn Levon 	ptr_name = get_fnptr_name(expr->left);
3381f5207b7SJohn Levon 	if (!fn_name || !ptr_name)
3391f5207b7SJohn Levon 		goto free;
3401f5207b7SJohn Levon 	if (strcmp(fn_name, ptr_name) == 0)
3411f5207b7SJohn Levon 		goto free;
3421f5207b7SJohn Levon 
3431f5207b7SJohn Levon 
3441f5207b7SJohn Levon 	type = get_type(right);
3451f5207b7SJohn Levon 	if (!type)
3461f5207b7SJohn Levon 		return;
3471f5207b7SJohn Levon 	if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
3481f5207b7SJohn Levon 		type = get_real_base_type(type);
3491f5207b7SJohn Levon 		if (!type)
3501f5207b7SJohn Levon 			return;
3511f5207b7SJohn Levon 	}
3521f5207b7SJohn Levon 	if (type->type != SYM_FN) {
3531f5207b7SJohn Levon 		int count = 0;
3541f5207b7SJohn Levon 
3551f5207b7SJohn Levon 		/* look it up in function_ptr */
3561f5207b7SJohn Levon 		run_sql(get_row_count, &count,
3571f5207b7SJohn Levon 			"select count(*) from function_ptr where ptr = '%s'",
3581f5207b7SJohn Levon 			fn_name);
3591f5207b7SJohn Levon 		if (count == 0)
3601f5207b7SJohn Levon 			goto free;
3611f5207b7SJohn Levon 	}
3621f5207b7SJohn Levon 
3631f5207b7SJohn Levon 	sql_insert_function_ptr(fn_name, ptr_name);
3641f5207b7SJohn Levon free:
3651f5207b7SJohn Levon 	free_string(fn_name);
3661f5207b7SJohn Levon 	free_string(ptr_name);
3671f5207b7SJohn Levon }
3681f5207b7SJohn Levon 
match_returns_function_pointer(struct expression * expr)3691f5207b7SJohn Levon static void match_returns_function_pointer(struct expression *expr)
3701f5207b7SJohn Levon {
3711f5207b7SJohn Levon 	struct symbol *type;
3721f5207b7SJohn Levon 	char *fn_name;
3731f5207b7SJohn Levon 	char ptr_name[256];
3741f5207b7SJohn Levon 
3751f5207b7SJohn Levon 	if (__inline_fn)
3761f5207b7SJohn Levon 		return;
3771f5207b7SJohn Levon 
3781f5207b7SJohn Levon 	type = get_real_base_type(cur_func_sym);
3791f5207b7SJohn Levon 	if (!type || type->type != SYM_FN)
3801f5207b7SJohn Levon 		return;
3811f5207b7SJohn Levon 	type = get_real_base_type(type);
3821f5207b7SJohn Levon 	if (!type || type->type != SYM_PTR)
3831f5207b7SJohn Levon 		return;
3841f5207b7SJohn Levon 	type = get_real_base_type(type);
3851f5207b7SJohn Levon 	if (!type || type->type != SYM_FN)
3861f5207b7SJohn Levon 		return;
3871f5207b7SJohn Levon 
3881f5207b7SJohn Levon 	if (expr->type == EXPR_PREOP && expr->op == '&')
3891f5207b7SJohn Levon 		expr = strip_expr(expr->unop);
3901f5207b7SJohn Levon 
3911f5207b7SJohn Levon 	fn_name = get_fnptr_name(expr);
3921f5207b7SJohn Levon 	if (!fn_name)
3931f5207b7SJohn Levon 		return;
3941f5207b7SJohn Levon 	snprintf(ptr_name, sizeof(ptr_name), "r %s()", get_function());
3951f5207b7SJohn Levon 	sql_insert_function_ptr(fn_name, ptr_name);
3961f5207b7SJohn Levon }
3971f5207b7SJohn Levon 
print_initializer_list(struct expression_list * expr_list,struct symbol * struct_type)398efe51d0cSJohn Levon static void print_initializer_list(struct expression_list *expr_list,
399efe51d0cSJohn Levon 		struct symbol *struct_type)
400efe51d0cSJohn Levon {
401efe51d0cSJohn Levon 	struct expression *expr;
402efe51d0cSJohn Levon 	struct symbol *base_type;
403efe51d0cSJohn Levon 	char struct_name[256];
404efe51d0cSJohn Levon 
405efe51d0cSJohn Levon 	FOR_EACH_PTR(expr_list, expr) {
406efe51d0cSJohn Levon 		if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
407efe51d0cSJohn Levon 			print_initializer_list(expr->idx_expression->expr_list, struct_type);
408efe51d0cSJohn Levon 			continue;
409efe51d0cSJohn Levon 		}
410efe51d0cSJohn Levon 		if (expr->type != EXPR_IDENTIFIER)
411efe51d0cSJohn Levon 			continue;
412efe51d0cSJohn Levon 		if (!expr->expr_ident)
413efe51d0cSJohn Levon 			continue;
414efe51d0cSJohn Levon 		if (!expr->ident_expression ||
415efe51d0cSJohn Levon 		    expr->ident_expression->type != EXPR_SYMBOL ||
416efe51d0cSJohn Levon 		    !expr->ident_expression->symbol_name)
417efe51d0cSJohn Levon 			continue;
418efe51d0cSJohn Levon 		base_type = get_type(expr->ident_expression);
419efe51d0cSJohn Levon 		if (!base_type || base_type->type != SYM_FN)
420efe51d0cSJohn Levon 			continue;
421efe51d0cSJohn Levon 		snprintf(struct_name, sizeof(struct_name), "(struct %s)->%s",
422efe51d0cSJohn Levon 			 struct_type->ident->name, expr->expr_ident->name);
423efe51d0cSJohn Levon 		sql_insert_function_ptr(expr->ident_expression->symbol_name->name,
424efe51d0cSJohn Levon 				        struct_name);
425efe51d0cSJohn Levon 	} END_FOR_EACH_PTR(expr);
426efe51d0cSJohn Levon }
427efe51d0cSJohn Levon 
global_variable(struct symbol * sym)428efe51d0cSJohn Levon static void global_variable(struct symbol *sym)
429efe51d0cSJohn Levon {
430efe51d0cSJohn Levon 	struct symbol *struct_type;
431efe51d0cSJohn Levon 
432efe51d0cSJohn Levon 	if (!sym->ident)
433efe51d0cSJohn Levon 		return;
434efe51d0cSJohn Levon 	if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
435efe51d0cSJohn Levon 		return;
436efe51d0cSJohn Levon 	struct_type = get_base_type(sym);
437efe51d0cSJohn Levon 	if (!struct_type)
438efe51d0cSJohn Levon 		return;
439efe51d0cSJohn Levon 	if (struct_type->type == SYM_ARRAY) {
440efe51d0cSJohn Levon 		struct_type = get_base_type(struct_type);
441efe51d0cSJohn Levon 		if (!struct_type)
442efe51d0cSJohn Levon 			return;
443efe51d0cSJohn Levon 	}
444efe51d0cSJohn Levon 	if (struct_type->type != SYM_STRUCT || !struct_type->ident)
445efe51d0cSJohn Levon 		return;
446efe51d0cSJohn Levon 	print_initializer_list(sym->initializer->expr_list, struct_type);
447efe51d0cSJohn Levon }
448efe51d0cSJohn Levon 
register_function_ptrs(int id)4491f5207b7SJohn Levon void register_function_ptrs(int id)
4501f5207b7SJohn Levon {
4511f5207b7SJohn Levon 	my_id = id;
4521f5207b7SJohn Levon 
4531f5207b7SJohn Levon 	if (!option_info)
4541f5207b7SJohn Levon 		return;
4551f5207b7SJohn Levon 
456efe51d0cSJohn Levon 	add_hook(&global_variable, BASE_HOOK);
457efe51d0cSJohn Levon 	add_hook(&global_variable, DECLARATION_HOOK);
4581f5207b7SJohn Levon 	add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK);
4591f5207b7SJohn Levon 	add_hook(&match_returns_function_pointer, RETURN_HOOK);
4601f5207b7SJohn Levon 	add_hook(&match_function_assign, ASSIGNMENT_HOOK);
4611f5207b7SJohn Levon 	add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK);
4621f5207b7SJohn Levon }
463