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