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 int xxx_is_array(struct expression *expr) 54 { 55 struct symbol *type; 56 57 expr = strip_expr(expr); 58 if (!expr) 59 return 0; 60 61 if (expr->type == EXPR_PREOP && expr->op == '*') { 62 expr = strip_expr(expr->unop); 63 if (!expr) 64 return 0; 65 if (expr->type == EXPR_BINOP && expr->op == '+') 66 return 1; 67 } 68 69 if (expr->type != EXPR_BINOP || expr->op != '+') 70 return 0; 71 72 type = get_type(expr->left); 73 if (!type) 74 return 0; 75 if (type->type != SYM_ARRAY && type->type != SYM_PTR) 76 return 0; 77 78 return 1; 79 } 80 81 static struct expression *xxx_get_array_base(struct expression *expr) 82 { 83 if (!xxx_is_array(expr)) 84 return NULL; 85 expr = strip_expr(expr); 86 if (expr->type == EXPR_PREOP && expr->op == '*') 87 expr = strip_expr(expr->unop); 88 if (expr->type != EXPR_BINOP || expr->op != '+') 89 return NULL; 90 return strip_parens(expr->left); 91 } 92 93 static char *get_array_ptr(struct expression *expr) 94 { 95 struct expression *array; 96 struct symbol *type; 97 char *name; 98 char buf[256]; 99 100 array = xxx_get_array_base(expr); 101 102 if (array) { 103 name = get_member_name(array); 104 if (name) 105 return name; 106 } 107 108 /* FIXME: is_array() should probably be is_array_element() */ 109 type = get_type(expr); 110 if (!array && type && type->type == SYM_ARRAY) 111 array = expr; 112 if (array) { 113 name = expr_to_var(array); 114 if (!name) 115 return NULL; 116 snprintf(buf, sizeof(buf), "%s[]", name); 117 return alloc_string(buf); 118 } 119 120 expr = get_assigned_expr(expr); 121 array = xxx_get_array_base(expr); 122 if (!array) 123 return NULL; 124 name = expr_to_var(array); 125 if (!name) 126 return NULL; 127 snprintf(buf, sizeof(buf), "%s[]", name); 128 free_string(name); 129 return alloc_string(buf); 130 } 131 132 static int is_local_symbol(struct symbol *sym) 133 { 134 if (!sym || 135 !(sym->ctype.modifiers & MOD_TOPLEVEL)) 136 return 1; 137 return 0; 138 } 139 140 static char *ptr_prefix(struct symbol *sym) 141 { 142 static char buf[128]; 143 144 145 if (is_local_symbol(sym)) 146 snprintf(buf, sizeof(buf), "%s ptr", get_function()); 147 else if (sym && toplevel(sym->scope)) 148 snprintf(buf, sizeof(buf), "%s ptr", get_base_file()); 149 else 150 snprintf(buf, sizeof(buf), "ptr"); 151 152 return buf; 153 } 154 155 char *get_returned_ptr(struct expression *expr) 156 { 157 struct symbol *type; 158 char *name; 159 char buf[256]; 160 161 if (expr->type != EXPR_CALL) 162 return NULL; 163 if (!expr->fn || expr->fn->type != EXPR_SYMBOL) 164 return NULL; 165 166 type = get_type(expr); 167 if (type && type->type == SYM_PTR) 168 type = get_real_base_type(type); 169 if (!type || type->type != SYM_FN) 170 return NULL; 171 172 name = expr_to_var(expr->fn); 173 if (!name) 174 return NULL; 175 snprintf(buf, sizeof(buf), "r %s()", name); 176 free_string(name); 177 return alloc_string(buf); 178 } 179 180 char *get_fnptr_name(struct expression *expr) 181 { 182 char *name; 183 184 if (expr_is_zero(expr)) 185 return NULL; 186 187 expr = strip_expr(expr); 188 189 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */ 190 if (expr->type == EXPR_PREOP && expr->op == '*') 191 expr = strip_expr(expr->unop); 192 193 name = get_from__symbol_get(expr); 194 if (name) 195 return name; 196 197 name = get_array_ptr(expr); 198 if (name) 199 return name; 200 201 name = get_returned_ptr(expr); 202 if (name) 203 return name; 204 205 name = get_member_name(expr); 206 if (name) 207 return name; 208 209 if (expr->type == EXPR_SYMBOL) { 210 int param; 211 char buf[256]; 212 struct symbol *sym; 213 struct symbol *type; 214 215 param = get_param_num_from_sym(expr->symbol); 216 if (param >= 0) { 217 snprintf(buf, sizeof(buf), "%s param %d", get_function(), param); 218 return alloc_string(buf); 219 } 220 221 name = expr_to_var_sym(expr, &sym); 222 if (!name) 223 return NULL; 224 type = get_type(expr); 225 if (type && type->type == SYM_PTR) { 226 snprintf(buf, sizeof(buf), "%s %s", ptr_prefix(sym), name); 227 free_string(name); 228 return alloc_string(buf); 229 } 230 return name; 231 } 232 return expr_to_var(expr); 233 } 234 235 static void match_passes_function_pointer(struct expression *expr) 236 { 237 struct expression *arg, *tmp; 238 struct symbol *type; 239 char *called_name; 240 char *fn_name; 241 char ptr_name[256]; 242 int i; 243 244 245 i = -1; 246 FOR_EACH_PTR(expr->args, arg) { 247 i++; 248 249 tmp = strip_expr(arg); 250 if (tmp->type == EXPR_PREOP && tmp->op == '&') 251 tmp = strip_expr(tmp->unop); 252 253 type = get_type(tmp); 254 if (type && type->type == SYM_PTR) 255 type = get_real_base_type(type); 256 if (!type || type->type != SYM_FN) 257 continue; 258 259 called_name = expr_to_var(expr->fn); 260 if (!called_name) 261 return; 262 fn_name = get_fnptr_name(tmp); 263 if (!fn_name) 264 goto free; 265 266 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i); 267 sql_insert_function_ptr(fn_name, ptr_name); 268 free: 269 free_string(fn_name); 270 free_string(called_name); 271 } END_FOR_EACH_PTR(arg); 272 273 } 274 275 static int get_row_count(void *_row_count, int argc, char **argv, char **azColName) 276 { 277 int *row_count = _row_count; 278 279 *row_count = 0; 280 if (argc != 1) 281 return 0; 282 *row_count = atoi(argv[0]); 283 return 0; 284 } 285 286 static int can_hold_function_ptr(struct expression *expr) 287 { 288 struct symbol *type; 289 290 type = get_type(expr); 291 if (!type) 292 return 0; 293 if (type->type == SYM_PTR || type->type == SYM_ARRAY) { 294 type = get_real_base_type(type); 295 if (!type) 296 return 0; 297 } 298 /* pointer to a pointer */ 299 if (type->type == SYM_PTR || type->type == SYM_ARRAY) { 300 type = get_real_base_type(type); 301 if (!type) 302 return 0; 303 } 304 if (type->type == SYM_FN) 305 return 1; 306 if (type == &ulong_ctype && expr->type == EXPR_DEREF) 307 return 1; 308 if (type == &void_ctype) 309 return 1; 310 return 0; 311 } 312 313 static void match_function_assign(struct expression *expr) 314 { 315 struct expression *right; 316 struct symbol *type; 317 char *fn_name; 318 char *ptr_name; 319 320 if (__in_fake_assign) 321 return; 322 323 right = strip_expr(expr->right); 324 if (right->type == EXPR_PREOP && right->op == '&') 325 right = strip_expr(right->unop); 326 327 if (right->type != EXPR_SYMBOL && 328 right->type != EXPR_DEREF && 329 right->type != EXPR_CALL) 330 return; 331 332 if (!can_hold_function_ptr(right) || 333 !can_hold_function_ptr(expr->left)) 334 return; 335 336 fn_name = get_fnptr_name(right); 337 ptr_name = get_fnptr_name(expr->left); 338 if (!fn_name || !ptr_name) 339 goto free; 340 if (strcmp(fn_name, ptr_name) == 0) 341 goto free; 342 343 344 type = get_type(right); 345 if (!type) 346 return; 347 if (type->type == SYM_PTR || type->type == SYM_ARRAY) { 348 type = get_real_base_type(type); 349 if (!type) 350 return; 351 } 352 if (type->type != SYM_FN) { 353 int count = 0; 354 355 /* look it up in function_ptr */ 356 run_sql(get_row_count, &count, 357 "select count(*) from function_ptr where ptr = '%s'", 358 fn_name); 359 if (count == 0) 360 goto free; 361 } 362 363 sql_insert_function_ptr(fn_name, ptr_name); 364 free: 365 free_string(fn_name); 366 free_string(ptr_name); 367 } 368 369 static void match_returns_function_pointer(struct expression *expr) 370 { 371 struct symbol *type; 372 char *fn_name; 373 char ptr_name[256]; 374 375 if (__inline_fn) 376 return; 377 378 type = get_real_base_type(cur_func_sym); 379 if (!type || type->type != SYM_FN) 380 return; 381 type = get_real_base_type(type); 382 if (!type || type->type != SYM_PTR) 383 return; 384 type = get_real_base_type(type); 385 if (!type || type->type != SYM_FN) 386 return; 387 388 if (expr->type == EXPR_PREOP && expr->op == '&') 389 expr = strip_expr(expr->unop); 390 391 fn_name = get_fnptr_name(expr); 392 if (!fn_name) 393 return; 394 snprintf(ptr_name, sizeof(ptr_name), "r %s()", get_function()); 395 sql_insert_function_ptr(fn_name, ptr_name); 396 } 397 398 static void print_initializer_list(struct expression_list *expr_list, 399 struct symbol *struct_type) 400 { 401 struct expression *expr; 402 struct symbol *base_type; 403 char struct_name[256]; 404 405 FOR_EACH_PTR(expr_list, expr) { 406 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) { 407 print_initializer_list(expr->idx_expression->expr_list, struct_type); 408 continue; 409 } 410 if (expr->type != EXPR_IDENTIFIER) 411 continue; 412 if (!expr->expr_ident) 413 continue; 414 if (!expr->ident_expression || 415 expr->ident_expression->type != EXPR_SYMBOL || 416 !expr->ident_expression->symbol_name) 417 continue; 418 base_type = get_type(expr->ident_expression); 419 if (!base_type || base_type->type != SYM_FN) 420 continue; 421 snprintf(struct_name, sizeof(struct_name), "(struct %s)->%s", 422 struct_type->ident->name, expr->expr_ident->name); 423 sql_insert_function_ptr(expr->ident_expression->symbol_name->name, 424 struct_name); 425 } END_FOR_EACH_PTR(expr); 426 } 427 428 static void global_variable(struct symbol *sym) 429 { 430 struct symbol *struct_type; 431 432 if (!sym->ident) 433 return; 434 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER) 435 return; 436 struct_type = get_base_type(sym); 437 if (!struct_type) 438 return; 439 if (struct_type->type == SYM_ARRAY) { 440 struct_type = get_base_type(struct_type); 441 if (!struct_type) 442 return; 443 } 444 if (struct_type->type != SYM_STRUCT || !struct_type->ident) 445 return; 446 print_initializer_list(sym->initializer->expr_list, struct_type); 447 } 448 449 void register_function_ptrs(int id) 450 { 451 my_id = id; 452 453 if (!option_info) 454 return; 455 456 add_hook(&global_variable, BASE_HOOK); 457 add_hook(&global_variable, DECLARATION_HOOK); 458 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK); 459 add_hook(&match_returns_function_pointer, RETURN_HOOK); 460 add_hook(&match_function_assign, ASSIGNMENT_HOOK); 461 add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK); 462 } 463