1 /* 2 * Copyright (C) 2013 Oracle. 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 /* 19 * Track how functions are saved as various struct members or passed as 20 * parameters. 21 * 22 */ 23 24 #include "scope.h" 25 #include "smatch.h" 26 #include "smatch_slist.h" 27 28 static int my_id; 29 30 static char *get_from__symbol_get(struct expression *expr) 31 { 32 struct expression *arg; 33 34 /* 35 * typeof(&dib0070_attach) __a = 36 * ((((typeof(&dib0070_attach)) (__symbol_get("dib0070_attach")))) ?: 37 * (__request_module(true, "symbol:" "dib0070_attach"), (((typeof(&dib0070_attach))(__symbol_get("dib0070_attach")))))); 38 */ 39 40 expr = strip_expr(expr); 41 42 if (expr->type != EXPR_CALL) 43 return NULL; 44 if (!sym_name_is("__symbol_get", expr->fn)) 45 return NULL; 46 arg = get_argument_from_call_expr(expr->args, 0); 47 if (!arg || arg->type != EXPR_STRING) 48 return NULL; 49 50 return alloc_string(arg->string->data); 51 } 52 53 static char *get_array_ptr(struct expression *expr) 54 { 55 struct expression *array; 56 struct symbol *type; 57 char *name; 58 char buf[256]; 59 60 array = get_array_base(expr); 61 62 if (array) { 63 name = get_member_name(array); 64 if (name) 65 return name; 66 } 67 68 /* FIXME: is_array() should probably be is_array_element() */ 69 type = get_type(expr); 70 if (!array && type && type->type == SYM_ARRAY) 71 array = expr; 72 if (array) { 73 name = expr_to_var(array); 74 if (!name) 75 return NULL; 76 snprintf(buf, sizeof(buf), "%s[]", name); 77 return alloc_string(buf); 78 } 79 80 expr = get_assigned_expr(expr); 81 array = get_array_base(expr); 82 if (!array) 83 return NULL; 84 name = expr_to_var(array); 85 if (!name) 86 return NULL; 87 snprintf(buf, sizeof(buf), "%s[]", name); 88 free_string(name); 89 return alloc_string(buf); 90 } 91 92 static int is_local_symbol(struct symbol *sym) 93 { 94 if (!sym || 95 !(sym->ctype.modifiers & MOD_TOPLEVEL)) 96 return 1; 97 return 0; 98 } 99 100 static char *ptr_prefix(struct symbol *sym) 101 { 102 static char buf[128]; 103 104 105 if (is_local_symbol(sym)) 106 snprintf(buf, sizeof(buf), "%s ptr", get_function()); 107 else if (sym && toplevel(sym->scope)) 108 snprintf(buf, sizeof(buf), "%s ptr", get_base_file()); 109 else 110 snprintf(buf, sizeof(buf), "ptr"); 111 112 return buf; 113 } 114 115 char *get_returned_ptr(struct expression *expr) 116 { 117 struct symbol *type; 118 char *name; 119 char buf[256]; 120 121 if (expr->type != EXPR_CALL) 122 return NULL; 123 if (!expr->fn || expr->fn->type != EXPR_SYMBOL) 124 return NULL; 125 126 type = get_type(expr); 127 if (type && type->type == SYM_PTR) 128 type = get_real_base_type(type); 129 if (!type || type->type != SYM_FN) 130 return NULL; 131 132 name = expr_to_var(expr->fn); 133 if (!name) 134 return NULL; 135 snprintf(buf, sizeof(buf), "r %s()", name); 136 free_string(name); 137 return alloc_string(buf); 138 } 139 140 char *get_fnptr_name(struct expression *expr) 141 { 142 char *name; 143 144 expr = strip_expr(expr); 145 146 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */ 147 if (expr->type == EXPR_PREOP && expr->op == '*') 148 expr = strip_expr(expr->unop); 149 150 name = get_from__symbol_get(expr); 151 if (name) 152 return name; 153 154 name = get_array_ptr(expr); 155 if (name) 156 return name; 157 158 name = get_returned_ptr(expr); 159 if (name) 160 return name; 161 162 name = get_member_name(expr); 163 if (name) 164 return name; 165 166 if (expr->type == EXPR_SYMBOL) { 167 int param; 168 char buf[256]; 169 struct symbol *sym; 170 struct symbol *type; 171 172 param = get_param_num_from_sym(expr->symbol); 173 if (param >= 0) { 174 snprintf(buf, sizeof(buf), "%s param %d", get_function(), param); 175 return alloc_string(buf); 176 } 177 178 name = expr_to_var_sym(expr, &sym); 179 if (!name) 180 return NULL; 181 type = get_type(expr); 182 if (type && type->type == SYM_PTR) { 183 snprintf(buf, sizeof(buf), "%s %s", ptr_prefix(sym), name); 184 free_string(name); 185 return alloc_string(buf); 186 } 187 return name; 188 } 189 return expr_to_var(expr); 190 } 191 192 static void match_passes_function_pointer(struct expression *expr) 193 { 194 struct expression *arg, *tmp; 195 struct symbol *type; 196 char *called_name; 197 char *fn_name; 198 char ptr_name[256]; 199 int i; 200 201 202 i = -1; 203 FOR_EACH_PTR(expr->args, arg) { 204 i++; 205 206 tmp = strip_expr(arg); 207 if (tmp->type == EXPR_PREOP && tmp->op == '&') 208 tmp = strip_expr(tmp->unop); 209 210 type = get_type(tmp); 211 if (type && type->type == SYM_PTR) 212 type = get_real_base_type(type); 213 if (!type || type->type != SYM_FN) 214 continue; 215 216 called_name = expr_to_var(expr->fn); 217 if (!called_name) 218 return; 219 fn_name = get_fnptr_name(tmp); 220 if (!fn_name) 221 goto free; 222 223 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i); 224 sql_insert_function_ptr(fn_name, ptr_name); 225 free: 226 free_string(fn_name); 227 free_string(called_name); 228 } END_FOR_EACH_PTR(arg); 229 230 } 231 232 static int get_row_count(void *_row_count, int argc, char **argv, char **azColName) 233 { 234 int *row_count = _row_count; 235 236 *row_count = 0; 237 if (argc != 1) 238 return 0; 239 *row_count = atoi(argv[0]); 240 return 0; 241 } 242 243 static int can_hold_function_ptr(struct expression *expr) 244 { 245 struct symbol *type; 246 247 type = get_type(expr); 248 if (!type) 249 return 0; 250 if (type->type == SYM_PTR || type->type == SYM_ARRAY) { 251 type = get_real_base_type(type); 252 if (!type) 253 return 0; 254 } 255 if (type->type == SYM_FN) 256 return 1; 257 if (type == &ulong_ctype && expr->type == EXPR_DEREF) 258 return 1; 259 if (type == &void_ctype) 260 return 1; 261 return 0; 262 } 263 264 static void match_function_assign(struct expression *expr) 265 { 266 struct expression *right; 267 struct symbol *type; 268 char *fn_name; 269 char *ptr_name; 270 271 if (__in_fake_assign) 272 return; 273 274 right = strip_expr(expr->right); 275 if (right->type == EXPR_PREOP && right->op == '&') 276 right = strip_expr(right->unop); 277 278 if (right->type != EXPR_SYMBOL && 279 right->type != EXPR_DEREF) 280 return; 281 282 if (!can_hold_function_ptr(right) || 283 !can_hold_function_ptr(expr->left)) 284 return; 285 286 fn_name = get_fnptr_name(right); 287 ptr_name = get_fnptr_name(expr->left); 288 if (!fn_name || !ptr_name) 289 goto free; 290 if (strcmp(fn_name, ptr_name) == 0) 291 goto free; 292 293 294 type = get_type(right); 295 if (!type) 296 return; 297 if (type->type == SYM_PTR || type->type == SYM_ARRAY) { 298 type = get_real_base_type(type); 299 if (!type) 300 return; 301 } 302 if (type->type != SYM_FN) { 303 int count = 0; 304 305 /* look it up in function_ptr */ 306 run_sql(get_row_count, &count, 307 "select count(*) from function_ptr where ptr = '%s'", 308 fn_name); 309 if (count == 0) 310 goto free; 311 } 312 313 sql_insert_function_ptr(fn_name, ptr_name); 314 free: 315 free_string(fn_name); 316 free_string(ptr_name); 317 } 318 319 static void match_returns_function_pointer(struct expression *expr) 320 { 321 struct symbol *type; 322 char *fn_name; 323 char ptr_name[256]; 324 325 if (__inline_fn) 326 return; 327 328 type = get_real_base_type(cur_func_sym); 329 if (!type || type->type != SYM_FN) 330 return; 331 type = get_real_base_type(type); 332 if (!type || type->type != SYM_PTR) 333 return; 334 type = get_real_base_type(type); 335 if (!type || type->type != SYM_FN) 336 return; 337 338 if (expr->type == EXPR_PREOP && expr->op == '&') 339 expr = strip_expr(expr->unop); 340 341 fn_name = get_fnptr_name(expr); 342 if (!fn_name) 343 return; 344 snprintf(ptr_name, sizeof(ptr_name), "r %s()", get_function()); 345 sql_insert_function_ptr(fn_name, ptr_name); 346 } 347 348 void register_function_ptrs(int id) 349 { 350 my_id = id; 351 352 if (!option_info) 353 return; 354 355 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK); 356 add_hook(&match_returns_function_pointer, RETURN_HOOK); 357 add_hook(&match_function_assign, ASSIGNMENT_HOOK); 358 add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK); 359 } 360