Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

objtool: Fix weak symbol hole detection for .cold functions

When ignore_unreachable_insn() looks for weak function holes which jump
to their .cold functions, it assumes the parent function comes before
the corresponding .cold function in the symbol table. That's not
necessarily the case with -ffunction-sections.

Mark all the holes beforehand (including .cold functions) so the
ordering of the discovery doesn't matter.

Acked-by: Petr Mladek <pmladek@suse.com>
Tested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

+45 -42
+43 -41
tools/objtool/check.c
··· 2507 2507 file->rodata = found; 2508 2508 } 2509 2509 2510 + static void mark_holes(struct objtool_file *file) 2511 + { 2512 + struct instruction *insn; 2513 + bool in_hole = false; 2514 + 2515 + if (!opts.link) 2516 + return; 2517 + 2518 + /* 2519 + * Whole archive runs might encounter dead code from weak symbols. 2520 + * This is where the linker will have dropped the weak symbol in 2521 + * favour of a regular symbol, but leaves the code in place. 2522 + */ 2523 + for_each_insn(file, insn) { 2524 + if (insn->sym || !find_symbol_hole_containing(insn->sec, insn->offset)) { 2525 + in_hole = false; 2526 + continue; 2527 + } 2528 + 2529 + /* Skip function padding and pfx code */ 2530 + if (!in_hole && insn->type == INSN_NOP) 2531 + continue; 2532 + 2533 + in_hole = true; 2534 + insn->hole = 1; 2535 + 2536 + /* 2537 + * If this hole jumps to a .cold function, mark it ignore. 2538 + */ 2539 + if (insn->jump_dest) { 2540 + struct symbol *dest_func = insn_func(insn->jump_dest); 2541 + 2542 + if (dest_func && dest_func->cold) 2543 + dest_func->ignore = true; 2544 + } 2545 + } 2546 + } 2547 + 2510 2548 static int decode_sections(struct objtool_file *file) 2511 2549 { 2512 2550 mark_rodata(file); ··· 2597 2559 2598 2560 if (read_unwind_hints(file)) 2599 2561 return -1; 2562 + 2563 + /* Must be after add_jump_destinations() */ 2564 + mark_holes(file); 2600 2565 2601 2566 /* 2602 2567 * Must be after add_call_destinations() such that it can override ··· 4062 4021 struct instruction *prev_insn; 4063 4022 int i; 4064 4023 4065 - if (insn->type == INSN_NOP || insn->type == INSN_TRAP || (func && func->ignore)) 4024 + if (insn->type == INSN_NOP || insn->type == INSN_TRAP || 4025 + insn->hole || (func && func->ignore)) 4066 4026 return true; 4067 4027 4068 4028 /* ··· 4073 4031 if (!strcmp(insn->sec->name, ".altinstr_replacement") || 4074 4032 !strcmp(insn->sec->name, ".altinstr_aux")) 4075 4033 return true; 4076 - 4077 - /* 4078 - * Whole archive runs might encounter dead code from weak symbols. 4079 - * This is where the linker will have dropped the weak symbol in 4080 - * favour of a regular symbol, but leaves the code in place. 4081 - * 4082 - * In this case we'll find a piece of code (whole function) that is not 4083 - * covered by a !section symbol. Ignore them. 4084 - */ 4085 - if (opts.link && !func) { 4086 - int size = find_symbol_hole_containing(insn->sec, insn->offset); 4087 - unsigned long end = insn->offset + size; 4088 - 4089 - if (!size) /* not a hole */ 4090 - return false; 4091 - 4092 - if (size < 0) /* hole until the end */ 4093 - return true; 4094 - 4095 - sec_for_each_insn_continue(file, insn) { 4096 - /* 4097 - * If we reach a visited instruction at or before the 4098 - * end of the hole, ignore the unreachable. 4099 - */ 4100 - if (insn->visited) 4101 - return true; 4102 - 4103 - if (insn->offset >= end) 4104 - break; 4105 - 4106 - /* 4107 - * If this hole jumps to a .cold function, mark it ignore too. 4108 - */ 4109 - if (insn->jump_dest && insn_func(insn->jump_dest) && 4110 - insn_func(insn->jump_dest)->cold) 4111 - insn_func(insn->jump_dest)->ignore = true; 4112 - } 4113 - 4114 - return false; 4115 - } 4116 4034 4117 4035 if (!func) 4118 4036 return false;
+2 -1
tools/objtool/include/objtool/check.h
··· 64 64 noendbr : 1, 65 65 unret : 1, 66 66 visited : 4, 67 - no_reloc : 1; 67 + no_reloc : 1, 68 + hole : 1; 68 69 /* 10 bit hole */ 69 70 70 71 struct alt_group *alt_group;