1 /* 2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 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/licenses/>. 16 */ 17 18 /* 19 * objtool check: 20 * 21 * This command analyzes every .o file and ensures the validity of its stack 22 * trace metadata. It enforces a set of rules on asm code and C inline 23 * assembly code so that stack traces can be reliable. 24 * 25 * For more information, see tools/objtool/Documentation/stack-validation.txt. 26 */ 27 28 #include <string.h> 29 #include <stdlib.h> 30 #include <subcmd/parse-options.h> 31 32 #include "builtin.h" 33 #include "elf.h" 34 #include "special.h" 35 #include "arch.h" 36 #include "warn.h" 37 38 #include <linux/hashtable.h> 39 40 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 41 42 #define STATE_FP_SAVED 0x1 43 #define STATE_FP_SETUP 0x2 44 #define STATE_FENTRY 0x4 45 46 struct instruction { 47 struct list_head list; 48 struct hlist_node hash; 49 struct section *sec; 50 unsigned long offset; 51 unsigned int len, state; 52 unsigned char type; 53 unsigned long immediate; 54 bool alt_group, visited; 55 struct symbol *call_dest; 56 struct instruction *jump_dest; 57 struct list_head alts; 58 struct symbol *func; 59 }; 60 61 struct alternative { 62 struct list_head list; 63 struct instruction *insn; 64 }; 65 66 struct objtool_file { 67 struct elf *elf; 68 struct list_head insn_list; 69 DECLARE_HASHTABLE(insn_hash, 16); 70 struct section *rodata, *whitelist; 71 bool ignore_unreachables, c_file; 72 }; 73 74 const char *objname; 75 static bool nofp; 76 77 static struct instruction *find_insn(struct objtool_file *file, 78 struct section *sec, unsigned long offset) 79 { 80 struct instruction *insn; 81 82 hash_for_each_possible(file->insn_hash, insn, hash, offset) 83 if (insn->sec == sec && insn->offset == offset) 84 return insn; 85 86 return NULL; 87 } 88 89 static struct instruction *next_insn_same_sec(struct objtool_file *file, 90 struct instruction *insn) 91 { 92 struct instruction *next = list_next_entry(insn, list); 93 94 if (&next->list == &file->insn_list || next->sec != insn->sec) 95 return NULL; 96 97 return next; 98 } 99 100 #define for_each_insn(file, insn) \ 101 list_for_each_entry(insn, &file->insn_list, list) 102 103 #define func_for_each_insn(file, func, insn) \ 104 for (insn = find_insn(file, func->sec, func->offset); \ 105 insn && &insn->list != &file->insn_list && \ 106 insn->sec == func->sec && \ 107 insn->offset < func->offset + func->len; \ 108 insn = list_next_entry(insn, list)) 109 110 #define sec_for_each_insn_from(file, insn) \ 111 for (; insn; insn = next_insn_same_sec(file, insn)) 112 113 114 /* 115 * Check if the function has been manually whitelisted with the 116 * STACK_FRAME_NON_STANDARD macro, or if it should be automatically whitelisted 117 * due to its use of a context switching instruction. 118 */ 119 static bool ignore_func(struct objtool_file *file, struct symbol *func) 120 { 121 struct rela *rela; 122 struct instruction *insn; 123 124 /* check for STACK_FRAME_NON_STANDARD */ 125 if (file->whitelist && file->whitelist->rela) 126 list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) 127 if (rela->sym->sec == func->sec && 128 rela->addend == func->offset) 129 return true; 130 131 /* check if it has a context switching instruction */ 132 func_for_each_insn(file, func, insn) 133 if (insn->type == INSN_CONTEXT_SWITCH) 134 return true; 135 136 return false; 137 } 138 139 /* 140 * This checks to see if the given function is a "noreturn" function. 141 * 142 * For global functions which are outside the scope of this object file, we 143 * have to keep a manual list of them. 144 * 145 * For local functions, we have to detect them manually by simply looking for 146 * the lack of a return instruction. 147 * 148 * Returns: 149 * -1: error 150 * 0: no dead end 151 * 1: dead end 152 */ 153 static int __dead_end_function(struct objtool_file *file, struct symbol *func, 154 int recursion) 155 { 156 int i; 157 struct instruction *insn; 158 bool empty = true; 159 160 /* 161 * Unfortunately these have to be hard coded because the noreturn 162 * attribute isn't provided in ELF data. 163 */ 164 static const char * const global_noreturns[] = { 165 "__stack_chk_fail", 166 "panic", 167 "do_exit", 168 "__module_put_and_exit", 169 "complete_and_exit", 170 "kvm_spurious_fault", 171 "__reiserfs_panic", 172 "lbug_with_loc" 173 }; 174 175 if (func->bind == STB_WEAK) 176 return 0; 177 178 if (func->bind == STB_GLOBAL) 179 for (i = 0; i < ARRAY_SIZE(global_noreturns); i++) 180 if (!strcmp(func->name, global_noreturns[i])) 181 return 1; 182 183 if (!func->sec) 184 return 0; 185 186 func_for_each_insn(file, func, insn) { 187 empty = false; 188 189 if (insn->type == INSN_RETURN) 190 return 0; 191 } 192 193 if (empty) 194 return 0; 195 196 /* 197 * A function can have a sibling call instead of a return. In that 198 * case, the function's dead-end status depends on whether the target 199 * of the sibling call returns. 200 */ 201 func_for_each_insn(file, func, insn) { 202 if (insn->sec != func->sec || 203 insn->offset >= func->offset + func->len) 204 break; 205 206 if (insn->type == INSN_JUMP_UNCONDITIONAL) { 207 struct instruction *dest = insn->jump_dest; 208 struct symbol *dest_func; 209 210 if (!dest) 211 /* sibling call to another file */ 212 return 0; 213 214 if (dest->sec != func->sec || 215 dest->offset < func->offset || 216 dest->offset >= func->offset + func->len) { 217 /* local sibling call */ 218 dest_func = find_symbol_by_offset(dest->sec, 219 dest->offset); 220 if (!dest_func) 221 continue; 222 223 if (recursion == 5) { 224 WARN_FUNC("infinite recursion (objtool bug!)", 225 dest->sec, dest->offset); 226 return -1; 227 } 228 229 return __dead_end_function(file, dest_func, 230 recursion + 1); 231 } 232 } 233 234 if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts)) 235 /* sibling call */ 236 return 0; 237 } 238 239 return 1; 240 } 241 242 static int dead_end_function(struct objtool_file *file, struct symbol *func) 243 { 244 return __dead_end_function(file, func, 0); 245 } 246 247 /* 248 * Call the arch-specific instruction decoder for all the instructions and add 249 * them to the global instruction list. 250 */ 251 static int decode_instructions(struct objtool_file *file) 252 { 253 struct section *sec; 254 struct symbol *func; 255 unsigned long offset; 256 struct instruction *insn; 257 int ret; 258 259 list_for_each_entry(sec, &file->elf->sections, list) { 260 261 if (!(sec->sh.sh_flags & SHF_EXECINSTR)) 262 continue; 263 264 for (offset = 0; offset < sec->len; offset += insn->len) { 265 insn = malloc(sizeof(*insn)); 266 memset(insn, 0, sizeof(*insn)); 267 268 INIT_LIST_HEAD(&insn->alts); 269 insn->sec = sec; 270 insn->offset = offset; 271 272 ret = arch_decode_instruction(file->elf, sec, offset, 273 sec->len - offset, 274 &insn->len, &insn->type, 275 &insn->immediate); 276 if (ret) 277 return ret; 278 279 if (!insn->type || insn->type > INSN_LAST) { 280 WARN_FUNC("invalid instruction type %d", 281 insn->sec, insn->offset, insn->type); 282 return -1; 283 } 284 285 hash_add(file->insn_hash, &insn->hash, insn->offset); 286 list_add_tail(&insn->list, &file->insn_list); 287 } 288 289 list_for_each_entry(func, &sec->symbol_list, list) { 290 if (func->type != STT_FUNC) 291 continue; 292 293 if (!find_insn(file, sec, func->offset)) { 294 WARN("%s(): can't find starting instruction", 295 func->name); 296 return -1; 297 } 298 299 func_for_each_insn(file, func, insn) 300 if (!insn->func) 301 insn->func = func; 302 } 303 } 304 305 return 0; 306 } 307 308 /* 309 * Warnings shouldn't be reported for ignored functions. 310 */ 311 static void add_ignores(struct objtool_file *file) 312 { 313 struct instruction *insn; 314 struct section *sec; 315 struct symbol *func; 316 317 list_for_each_entry(sec, &file->elf->sections, list) { 318 list_for_each_entry(func, &sec->symbol_list, list) { 319 if (func->type != STT_FUNC) 320 continue; 321 322 if (!ignore_func(file, func)) 323 continue; 324 325 func_for_each_insn(file, func, insn) 326 insn->visited = true; 327 } 328 } 329 } 330 331 /* 332 * Find the destination instructions for all jumps. 333 */ 334 static int add_jump_destinations(struct objtool_file *file) 335 { 336 struct instruction *insn; 337 struct rela *rela; 338 struct section *dest_sec; 339 unsigned long dest_off; 340 341 for_each_insn(file, insn) { 342 if (insn->type != INSN_JUMP_CONDITIONAL && 343 insn->type != INSN_JUMP_UNCONDITIONAL) 344 continue; 345 346 /* skip ignores */ 347 if (insn->visited) 348 continue; 349 350 rela = find_rela_by_dest_range(insn->sec, insn->offset, 351 insn->len); 352 if (!rela) { 353 dest_sec = insn->sec; 354 dest_off = insn->offset + insn->len + insn->immediate; 355 } else if (rela->sym->type == STT_SECTION) { 356 dest_sec = rela->sym->sec; 357 dest_off = rela->addend + 4; 358 } else if (rela->sym->sec->idx) { 359 dest_sec = rela->sym->sec; 360 dest_off = rela->sym->sym.st_value + rela->addend + 4; 361 } else { 362 /* sibling call */ 363 insn->jump_dest = 0; 364 continue; 365 } 366 367 insn->jump_dest = find_insn(file, dest_sec, dest_off); 368 if (!insn->jump_dest) { 369 370 /* 371 * This is a special case where an alt instruction 372 * jumps past the end of the section. These are 373 * handled later in handle_group_alt(). 374 */ 375 if (!strcmp(insn->sec->name, ".altinstr_replacement")) 376 continue; 377 378 WARN_FUNC("can't find jump dest instruction at %s+0x%lx", 379 insn->sec, insn->offset, dest_sec->name, 380 dest_off); 381 return -1; 382 } 383 } 384 385 return 0; 386 } 387 388 /* 389 * Find the destination instructions for all calls. 390 */ 391 static int add_call_destinations(struct objtool_file *file) 392 { 393 struct instruction *insn; 394 unsigned long dest_off; 395 struct rela *rela; 396 397 for_each_insn(file, insn) { 398 if (insn->type != INSN_CALL) 399 continue; 400 401 rela = find_rela_by_dest_range(insn->sec, insn->offset, 402 insn->len); 403 if (!rela) { 404 dest_off = insn->offset + insn->len + insn->immediate; 405 insn->call_dest = find_symbol_by_offset(insn->sec, 406 dest_off); 407 if (!insn->call_dest) { 408 WARN_FUNC("can't find call dest symbol at offset 0x%lx", 409 insn->sec, insn->offset, dest_off); 410 return -1; 411 } 412 } else if (rela->sym->type == STT_SECTION) { 413 insn->call_dest = find_symbol_by_offset(rela->sym->sec, 414 rela->addend+4); 415 if (!insn->call_dest || 416 insn->call_dest->type != STT_FUNC) { 417 WARN_FUNC("can't find call dest symbol at %s+0x%x", 418 insn->sec, insn->offset, 419 rela->sym->sec->name, 420 rela->addend + 4); 421 return -1; 422 } 423 } else 424 insn->call_dest = rela->sym; 425 } 426 427 return 0; 428 } 429 430 /* 431 * The .alternatives section requires some extra special care, over and above 432 * what other special sections require: 433 * 434 * 1. Because alternatives are patched in-place, we need to insert a fake jump 435 * instruction at the end so that validate_branch() skips all the original 436 * replaced instructions when validating the new instruction path. 437 * 438 * 2. An added wrinkle is that the new instruction length might be zero. In 439 * that case the old instructions are replaced with noops. We simulate that 440 * by creating a fake jump as the only new instruction. 441 * 442 * 3. In some cases, the alternative section includes an instruction which 443 * conditionally jumps to the _end_ of the entry. We have to modify these 444 * jumps' destinations to point back to .text rather than the end of the 445 * entry in .altinstr_replacement. 446 * 447 * 4. It has been requested that we don't validate the !POPCNT feature path 448 * which is a "very very small percentage of machines". 449 */ 450 static int handle_group_alt(struct objtool_file *file, 451 struct special_alt *special_alt, 452 struct instruction *orig_insn, 453 struct instruction **new_insn) 454 { 455 struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump; 456 unsigned long dest_off; 457 458 last_orig_insn = NULL; 459 insn = orig_insn; 460 sec_for_each_insn_from(file, insn) { 461 if (insn->offset >= special_alt->orig_off + special_alt->orig_len) 462 break; 463 464 if (special_alt->skip_orig) 465 insn->type = INSN_NOP; 466 467 insn->alt_group = true; 468 last_orig_insn = insn; 469 } 470 471 if (!next_insn_same_sec(file, last_orig_insn)) { 472 WARN("%s: don't know how to handle alternatives at end of section", 473 special_alt->orig_sec->name); 474 return -1; 475 } 476 477 fake_jump = malloc(sizeof(*fake_jump)); 478 if (!fake_jump) { 479 WARN("malloc failed"); 480 return -1; 481 } 482 memset(fake_jump, 0, sizeof(*fake_jump)); 483 INIT_LIST_HEAD(&fake_jump->alts); 484 fake_jump->sec = special_alt->new_sec; 485 fake_jump->offset = -1; 486 fake_jump->type = INSN_JUMP_UNCONDITIONAL; 487 fake_jump->jump_dest = list_next_entry(last_orig_insn, list); 488 489 if (!special_alt->new_len) { 490 *new_insn = fake_jump; 491 return 0; 492 } 493 494 last_new_insn = NULL; 495 insn = *new_insn; 496 sec_for_each_insn_from(file, insn) { 497 if (insn->offset >= special_alt->new_off + special_alt->new_len) 498 break; 499 500 last_new_insn = insn; 501 502 if (insn->type != INSN_JUMP_CONDITIONAL && 503 insn->type != INSN_JUMP_UNCONDITIONAL) 504 continue; 505 506 if (!insn->immediate) 507 continue; 508 509 dest_off = insn->offset + insn->len + insn->immediate; 510 if (dest_off == special_alt->new_off + special_alt->new_len) 511 insn->jump_dest = fake_jump; 512 513 if (!insn->jump_dest) { 514 WARN_FUNC("can't find alternative jump destination", 515 insn->sec, insn->offset); 516 return -1; 517 } 518 } 519 520 if (!last_new_insn) { 521 WARN_FUNC("can't find last new alternative instruction", 522 special_alt->new_sec, special_alt->new_off); 523 return -1; 524 } 525 526 list_add(&fake_jump->list, &last_new_insn->list); 527 528 return 0; 529 } 530 531 /* 532 * A jump table entry can either convert a nop to a jump or a jump to a nop. 533 * If the original instruction is a jump, make the alt entry an effective nop 534 * by just skipping the original instruction. 535 */ 536 static int handle_jump_alt(struct objtool_file *file, 537 struct special_alt *special_alt, 538 struct instruction *orig_insn, 539 struct instruction **new_insn) 540 { 541 if (orig_insn->type == INSN_NOP) 542 return 0; 543 544 if (orig_insn->type != INSN_JUMP_UNCONDITIONAL) { 545 WARN_FUNC("unsupported instruction at jump label", 546 orig_insn->sec, orig_insn->offset); 547 return -1; 548 } 549 550 *new_insn = list_next_entry(orig_insn, list); 551 return 0; 552 } 553 554 /* 555 * Read all the special sections which have alternate instructions which can be 556 * patched in or redirected to at runtime. Each instruction having alternate 557 * instruction(s) has them added to its insn->alts list, which will be 558 * traversed in validate_branch(). 559 */ 560 static int add_special_section_alts(struct objtool_file *file) 561 { 562 struct list_head special_alts; 563 struct instruction *orig_insn, *new_insn; 564 struct special_alt *special_alt, *tmp; 565 struct alternative *alt; 566 int ret; 567 568 ret = special_get_alts(file->elf, &special_alts); 569 if (ret) 570 return ret; 571 572 list_for_each_entry_safe(special_alt, tmp, &special_alts, list) { 573 alt = malloc(sizeof(*alt)); 574 if (!alt) { 575 WARN("malloc failed"); 576 ret = -1; 577 goto out; 578 } 579 580 orig_insn = find_insn(file, special_alt->orig_sec, 581 special_alt->orig_off); 582 if (!orig_insn) { 583 WARN_FUNC("special: can't find orig instruction", 584 special_alt->orig_sec, special_alt->orig_off); 585 ret = -1; 586 goto out; 587 } 588 589 new_insn = NULL; 590 if (!special_alt->group || special_alt->new_len) { 591 new_insn = find_insn(file, special_alt->new_sec, 592 special_alt->new_off); 593 if (!new_insn) { 594 WARN_FUNC("special: can't find new instruction", 595 special_alt->new_sec, 596 special_alt->new_off); 597 ret = -1; 598 goto out; 599 } 600 } 601 602 if (special_alt->group) { 603 ret = handle_group_alt(file, special_alt, orig_insn, 604 &new_insn); 605 if (ret) 606 goto out; 607 } else if (special_alt->jump_or_nop) { 608 ret = handle_jump_alt(file, special_alt, orig_insn, 609 &new_insn); 610 if (ret) 611 goto out; 612 } 613 614 alt->insn = new_insn; 615 list_add_tail(&alt->list, &orig_insn->alts); 616 617 list_del(&special_alt->list); 618 free(special_alt); 619 } 620 621 out: 622 return ret; 623 } 624 625 static int add_switch_table(struct objtool_file *file, struct symbol *func, 626 struct instruction *insn, struct rela *table, 627 struct rela *next_table) 628 { 629 struct rela *rela = table; 630 struct instruction *alt_insn; 631 struct alternative *alt; 632 633 list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) { 634 if (rela == next_table) 635 break; 636 637 if (rela->sym->sec != insn->sec || 638 rela->addend <= func->offset || 639 rela->addend >= func->offset + func->len) 640 break; 641 642 alt_insn = find_insn(file, insn->sec, rela->addend); 643 if (!alt_insn) { 644 WARN("%s: can't find instruction at %s+0x%x", 645 file->rodata->rela->name, insn->sec->name, 646 rela->addend); 647 return -1; 648 } 649 650 alt = malloc(sizeof(*alt)); 651 if (!alt) { 652 WARN("malloc failed"); 653 return -1; 654 } 655 656 alt->insn = alt_insn; 657 list_add_tail(&alt->list, &insn->alts); 658 } 659 660 return 0; 661 } 662 663 static int add_func_switch_tables(struct objtool_file *file, 664 struct symbol *func) 665 { 666 struct instruction *insn, *prev_jump; 667 struct rela *text_rela, *rodata_rela, *prev_rela = NULL; 668 int ret; 669 670 prev_jump = NULL; 671 672 func_for_each_insn(file, func, insn) { 673 if (insn->type != INSN_JUMP_DYNAMIC) 674 continue; 675 676 text_rela = find_rela_by_dest_range(insn->sec, insn->offset, 677 insn->len); 678 if (!text_rela || text_rela->sym != file->rodata->sym) 679 continue; 680 681 /* common case: jmpq *[addr](,%rax,8) */ 682 rodata_rela = find_rela_by_dest(file->rodata, 683 text_rela->addend); 684 685 /* 686 * rare case: jmpq *[addr](%rip) 687 * 688 * This check is for a rare gcc quirk, currently only seen in 689 * three driver functions in the kernel, only with certain 690 * obscure non-distro configs. 691 * 692 * As part of an optimization, gcc makes a copy of an existing 693 * switch jump table, modifies it, and then hard-codes the jump 694 * (albeit with an indirect jump) to use a single entry in the 695 * table. The rest of the jump table and some of its jump 696 * targets remain as dead code. 697 * 698 * In such a case we can just crudely ignore all unreachable 699 * instruction warnings for the entire object file. Ideally we 700 * would just ignore them for the function, but that would 701 * require redesigning the code quite a bit. And honestly 702 * that's just not worth doing: unreachable instruction 703 * warnings are of questionable value anyway, and this is such 704 * a rare issue. 705 * 706 * kbuild reports: 707 * - https://lkml.kernel.org/r/201603231906.LWcVUpxm%25fengguang.wu@intel.com 708 * - https://lkml.kernel.org/r/201603271114.K9i45biy%25fengguang.wu@intel.com 709 * - https://lkml.kernel.org/r/201603291058.zuJ6ben1%25fengguang.wu@intel.com 710 * 711 * gcc bug: 712 * - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70604 713 */ 714 if (!rodata_rela) { 715 rodata_rela = find_rela_by_dest(file->rodata, 716 text_rela->addend + 4); 717 if (rodata_rela) 718 file->ignore_unreachables = true; 719 } 720 721 if (!rodata_rela) 722 continue; 723 724 /* 725 * We found a switch table, but we don't know yet how big it 726 * is. Don't add it until we reach the end of the function or 727 * the beginning of another switch table in the same function. 728 */ 729 if (prev_jump) { 730 ret = add_switch_table(file, func, prev_jump, prev_rela, 731 rodata_rela); 732 if (ret) 733 return ret; 734 } 735 736 prev_jump = insn; 737 prev_rela = rodata_rela; 738 } 739 740 if (prev_jump) { 741 ret = add_switch_table(file, func, prev_jump, prev_rela, NULL); 742 if (ret) 743 return ret; 744 } 745 746 return 0; 747 } 748 749 /* 750 * For some switch statements, gcc generates a jump table in the .rodata 751 * section which contains a list of addresses within the function to jump to. 752 * This finds these jump tables and adds them to the insn->alts lists. 753 */ 754 static int add_switch_table_alts(struct objtool_file *file) 755 { 756 struct section *sec; 757 struct symbol *func; 758 int ret; 759 760 if (!file->rodata || !file->rodata->rela) 761 return 0; 762 763 list_for_each_entry(sec, &file->elf->sections, list) { 764 list_for_each_entry(func, &sec->symbol_list, list) { 765 if (func->type != STT_FUNC) 766 continue; 767 768 ret = add_func_switch_tables(file, func); 769 if (ret) 770 return ret; 771 } 772 } 773 774 return 0; 775 } 776 777 static int decode_sections(struct objtool_file *file) 778 { 779 int ret; 780 781 ret = decode_instructions(file); 782 if (ret) 783 return ret; 784 785 add_ignores(file); 786 787 ret = add_jump_destinations(file); 788 if (ret) 789 return ret; 790 791 ret = add_call_destinations(file); 792 if (ret) 793 return ret; 794 795 ret = add_special_section_alts(file); 796 if (ret) 797 return ret; 798 799 ret = add_switch_table_alts(file); 800 if (ret) 801 return ret; 802 803 return 0; 804 } 805 806 static bool is_fentry_call(struct instruction *insn) 807 { 808 if (insn->type == INSN_CALL && 809 insn->call_dest->type == STT_NOTYPE && 810 !strcmp(insn->call_dest->name, "__fentry__")) 811 return true; 812 813 return false; 814 } 815 816 static bool has_modified_stack_frame(struct instruction *insn) 817 { 818 return (insn->state & STATE_FP_SAVED) || 819 (insn->state & STATE_FP_SETUP); 820 } 821 822 static bool has_valid_stack_frame(struct instruction *insn) 823 { 824 return (insn->state & STATE_FP_SAVED) && 825 (insn->state & STATE_FP_SETUP); 826 } 827 828 static unsigned int frame_state(unsigned long state) 829 { 830 return (state & (STATE_FP_SAVED | STATE_FP_SETUP)); 831 } 832 833 /* 834 * Follow the branch starting at the given instruction, and recursively follow 835 * any other branches (jumps). Meanwhile, track the frame pointer state at 836 * each instruction and validate all the rules described in 837 * tools/objtool/Documentation/stack-validation.txt. 838 */ 839 static int validate_branch(struct objtool_file *file, 840 struct instruction *first, unsigned char first_state) 841 { 842 struct alternative *alt; 843 struct instruction *insn; 844 struct section *sec; 845 struct symbol *func = NULL; 846 unsigned char state; 847 int ret; 848 849 insn = first; 850 sec = insn->sec; 851 state = first_state; 852 853 if (insn->alt_group && list_empty(&insn->alts)) { 854 WARN_FUNC("don't know how to handle branch to middle of alternative instruction group", 855 sec, insn->offset); 856 return 1; 857 } 858 859 while (1) { 860 if (file->c_file && insn->func) { 861 if (func && func != insn->func) { 862 WARN("%s() falls through to next function %s()", 863 func->name, insn->func->name); 864 return 1; 865 } 866 867 func = insn->func; 868 } 869 870 if (insn->visited) { 871 if (frame_state(insn->state) != frame_state(state)) { 872 WARN_FUNC("frame pointer state mismatch", 873 sec, insn->offset); 874 return 1; 875 } 876 877 return 0; 878 } 879 880 insn->visited = true; 881 insn->state = state; 882 883 list_for_each_entry(alt, &insn->alts, list) { 884 ret = validate_branch(file, alt->insn, state); 885 if (ret) 886 return 1; 887 } 888 889 switch (insn->type) { 890 891 case INSN_FP_SAVE: 892 if (!nofp) { 893 if (state & STATE_FP_SAVED) { 894 WARN_FUNC("duplicate frame pointer save", 895 sec, insn->offset); 896 return 1; 897 } 898 state |= STATE_FP_SAVED; 899 } 900 break; 901 902 case INSN_FP_SETUP: 903 if (!nofp) { 904 if (state & STATE_FP_SETUP) { 905 WARN_FUNC("duplicate frame pointer setup", 906 sec, insn->offset); 907 return 1; 908 } 909 state |= STATE_FP_SETUP; 910 } 911 break; 912 913 case INSN_FP_RESTORE: 914 if (!nofp) { 915 if (has_valid_stack_frame(insn)) 916 state &= ~STATE_FP_SETUP; 917 918 state &= ~STATE_FP_SAVED; 919 } 920 break; 921 922 case INSN_RETURN: 923 if (!nofp && has_modified_stack_frame(insn)) { 924 WARN_FUNC("return without frame pointer restore", 925 sec, insn->offset); 926 return 1; 927 } 928 return 0; 929 930 case INSN_CALL: 931 if (is_fentry_call(insn)) { 932 state |= STATE_FENTRY; 933 break; 934 } 935 936 ret = dead_end_function(file, insn->call_dest); 937 if (ret == 1) 938 return 0; 939 if (ret == -1) 940 return 1; 941 942 /* fallthrough */ 943 case INSN_CALL_DYNAMIC: 944 if (!nofp && !has_valid_stack_frame(insn)) { 945 WARN_FUNC("call without frame pointer save/setup", 946 sec, insn->offset); 947 return 1; 948 } 949 break; 950 951 case INSN_JUMP_CONDITIONAL: 952 case INSN_JUMP_UNCONDITIONAL: 953 if (insn->jump_dest) { 954 ret = validate_branch(file, insn->jump_dest, 955 state); 956 if (ret) 957 return 1; 958 } else if (has_modified_stack_frame(insn)) { 959 WARN_FUNC("sibling call from callable instruction with changed frame pointer", 960 sec, insn->offset); 961 return 1; 962 } /* else it's a sibling call */ 963 964 if (insn->type == INSN_JUMP_UNCONDITIONAL) 965 return 0; 966 967 break; 968 969 case INSN_JUMP_DYNAMIC: 970 if (list_empty(&insn->alts) && 971 has_modified_stack_frame(insn)) { 972 WARN_FUNC("sibling call from callable instruction with changed frame pointer", 973 sec, insn->offset); 974 return 1; 975 } 976 977 return 0; 978 979 case INSN_BUG: 980 return 0; 981 982 default: 983 break; 984 } 985 986 insn = next_insn_same_sec(file, insn); 987 if (!insn) { 988 WARN("%s: unexpected end of section", sec->name); 989 return 1; 990 } 991 } 992 993 return 0; 994 } 995 996 static bool is_gcov_insn(struct instruction *insn) 997 { 998 struct rela *rela; 999 struct section *sec; 1000 struct symbol *sym; 1001 unsigned long offset; 1002 1003 rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len); 1004 if (!rela) 1005 return false; 1006 1007 if (rela->sym->type != STT_SECTION) 1008 return false; 1009 1010 sec = rela->sym->sec; 1011 offset = rela->addend + insn->offset + insn->len - rela->offset; 1012 1013 list_for_each_entry(sym, &sec->symbol_list, list) { 1014 if (sym->type != STT_OBJECT) 1015 continue; 1016 1017 if (offset >= sym->offset && offset < sym->offset + sym->len) 1018 return (!memcmp(sym->name, "__gcov0.", 8)); 1019 } 1020 1021 return false; 1022 } 1023 1024 static bool is_kasan_insn(struct instruction *insn) 1025 { 1026 return (insn->type == INSN_CALL && 1027 !strcmp(insn->call_dest->name, "__asan_handle_no_return")); 1028 } 1029 1030 static bool is_ubsan_insn(struct instruction *insn) 1031 { 1032 return (insn->type == INSN_CALL && 1033 !strcmp(insn->call_dest->name, 1034 "__ubsan_handle_builtin_unreachable")); 1035 } 1036 1037 static bool ignore_unreachable_insn(struct symbol *func, 1038 struct instruction *insn) 1039 { 1040 int i; 1041 1042 if (insn->type == INSN_NOP) 1043 return true; 1044 1045 if (is_gcov_insn(insn)) 1046 return true; 1047 1048 /* 1049 * Check if this (or a subsequent) instruction is related to 1050 * CONFIG_UBSAN or CONFIG_KASAN. 1051 * 1052 * End the search at 5 instructions to avoid going into the weeds. 1053 */ 1054 for (i = 0; i < 5; i++) { 1055 1056 if (is_kasan_insn(insn) || is_ubsan_insn(insn)) 1057 return true; 1058 1059 if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest) { 1060 insn = insn->jump_dest; 1061 continue; 1062 } 1063 1064 if (insn->offset + insn->len >= func->offset + func->len) 1065 break; 1066 insn = list_next_entry(insn, list); 1067 } 1068 1069 return false; 1070 } 1071 1072 static int validate_functions(struct objtool_file *file) 1073 { 1074 struct section *sec; 1075 struct symbol *func; 1076 struct instruction *insn; 1077 int ret, warnings = 0; 1078 1079 list_for_each_entry(sec, &file->elf->sections, list) { 1080 list_for_each_entry(func, &sec->symbol_list, list) { 1081 if (func->type != STT_FUNC) 1082 continue; 1083 1084 insn = find_insn(file, sec, func->offset); 1085 if (!insn) 1086 continue; 1087 1088 ret = validate_branch(file, insn, 0); 1089 warnings += ret; 1090 } 1091 } 1092 1093 list_for_each_entry(sec, &file->elf->sections, list) { 1094 list_for_each_entry(func, &sec->symbol_list, list) { 1095 if (func->type != STT_FUNC) 1096 continue; 1097 1098 func_for_each_insn(file, func, insn) { 1099 if (insn->visited) 1100 continue; 1101 1102 insn->visited = true; 1103 1104 if (file->ignore_unreachables || warnings || 1105 ignore_unreachable_insn(func, insn)) 1106 continue; 1107 1108 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset); 1109 warnings++; 1110 } 1111 } 1112 } 1113 1114 return warnings; 1115 } 1116 1117 static int validate_uncallable_instructions(struct objtool_file *file) 1118 { 1119 struct instruction *insn; 1120 int warnings = 0; 1121 1122 for_each_insn(file, insn) { 1123 if (!insn->visited && insn->type == INSN_RETURN) { 1124 WARN_FUNC("return instruction outside of a callable function", 1125 insn->sec, insn->offset); 1126 warnings++; 1127 } 1128 } 1129 1130 return warnings; 1131 } 1132 1133 static void cleanup(struct objtool_file *file) 1134 { 1135 struct instruction *insn, *tmpinsn; 1136 struct alternative *alt, *tmpalt; 1137 1138 list_for_each_entry_safe(insn, tmpinsn, &file->insn_list, list) { 1139 list_for_each_entry_safe(alt, tmpalt, &insn->alts, list) { 1140 list_del(&alt->list); 1141 free(alt); 1142 } 1143 list_del(&insn->list); 1144 hash_del(&insn->hash); 1145 free(insn); 1146 } 1147 elf_close(file->elf); 1148 } 1149 1150 const char * const check_usage[] = { 1151 "objtool check [<options>] file.o", 1152 NULL, 1153 }; 1154 1155 int cmd_check(int argc, const char **argv) 1156 { 1157 struct objtool_file file; 1158 int ret, warnings = 0; 1159 1160 const struct option options[] = { 1161 OPT_BOOLEAN('f', "no-fp", &nofp, "Skip frame pointer validation"), 1162 OPT_END(), 1163 }; 1164 1165 argc = parse_options(argc, argv, options, check_usage, 0); 1166 1167 if (argc != 1) 1168 usage_with_options(check_usage, options); 1169 1170 objname = argv[0]; 1171 1172 file.elf = elf_open(objname); 1173 if (!file.elf) { 1174 fprintf(stderr, "error reading elf file %s\n", objname); 1175 return 1; 1176 } 1177 1178 INIT_LIST_HEAD(&file.insn_list); 1179 hash_init(file.insn_hash); 1180 file.whitelist = find_section_by_name(file.elf, "__func_stack_frame_non_standard"); 1181 file.rodata = find_section_by_name(file.elf, ".rodata"); 1182 file.ignore_unreachables = false; 1183 file.c_file = find_section_by_name(file.elf, ".comment"); 1184 1185 ret = decode_sections(&file); 1186 if (ret < 0) 1187 goto out; 1188 warnings += ret; 1189 1190 ret = validate_functions(&file); 1191 if (ret < 0) 1192 goto out; 1193 warnings += ret; 1194 1195 ret = validate_uncallable_instructions(&file); 1196 if (ret < 0) 1197 goto out; 1198 warnings += ret; 1199 1200 out: 1201 cleanup(&file); 1202 1203 /* ignore warnings for now until we get all the code cleaned up */ 1204 if (ret || warnings) 1205 return 0; 1206 return 0; 1207 } 1208