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.

Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull objtool fixes from Ingo Molnar:
"A handful of objtool fixes: two improvements to how warnings are
printed plus a false positive warning fix, and build environment fix"

* 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
objtool: Fix Makefile to properly see if libelf is supported
objtool: Detect falling through to the next function
objtool: Add workaround for GCC switch jump table bug

+103 -35
+2 -1
Makefile
··· 1008 1008 prepare: prepare0 prepare-objtool 1009 1009 1010 1010 ifdef CONFIG_STACK_VALIDATION 1011 - has_libelf := $(shell echo "int main() {}" | $(HOSTCC) -xc -o /dev/null -lelf - &> /dev/null && echo 1 || echo 0) 1011 + has_libelf := $(call try-run,\ 1012 + echo "int main() {}" | $(HOSTCC) -xc -o /dev/null -lelf -,1,0) 1012 1013 ifeq ($(has_libelf),1) 1013 1014 objtool_target := tools/objtool FORCE 1014 1015 else
+29 -9
tools/objtool/Documentation/stack-validation.txt
··· 299 299 Errors in .c files 300 300 ------------------ 301 301 302 - If you're getting an objtool error in a compiled .c file, chances are 303 - the file uses an asm() statement which has a "call" instruction. An 304 - asm() statement with a call instruction must declare the use of the 305 - stack pointer in its output operand. For example, on x86_64: 302 + 1. c_file.o: warning: objtool: funcA() falls through to next function funcB() 306 303 307 - register void *__sp asm("rsp"); 308 - asm volatile("call func" : "+r" (__sp)); 304 + This means that funcA() doesn't end with a return instruction or an 305 + unconditional jump, and that objtool has determined that the function 306 + can fall through into the next function. There could be different 307 + reasons for this: 309 308 310 - Otherwise the stack frame may not get created before the call. 309 + 1) funcA()'s last instruction is a call to a "noreturn" function like 310 + panic(). In this case the noreturn function needs to be added to 311 + objtool's hard-coded global_noreturns array. Feel free to bug the 312 + objtool maintainer, or you can submit a patch. 311 313 312 - Another possible cause for errors in C code is if the Makefile removes 313 - -fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options. 314 + 2) funcA() uses the unreachable() annotation in a section of code 315 + that is actually reachable. 316 + 317 + 3) If funcA() calls an inline function, the object code for funcA() 318 + might be corrupt due to a gcc bug. For more details, see: 319 + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70646 320 + 321 + 2. If you're getting any other objtool error in a compiled .c file, it 322 + may be because the file uses an asm() statement which has a "call" 323 + instruction. An asm() statement with a call instruction must declare 324 + the use of the stack pointer in its output operand. For example, on 325 + x86_64: 326 + 327 + register void *__sp asm("rsp"); 328 + asm volatile("call func" : "+r" (__sp)); 329 + 330 + Otherwise the stack frame may not get created before the call. 331 + 332 + 3. Another possible cause for errors in C code is if the Makefile removes 333 + -fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options. 314 334 315 335 Also see the above section for .S file errors for more information what 316 336 the individual error messages mean.
+72 -25
tools/objtool/builtin-check.c
··· 54 54 struct symbol *call_dest; 55 55 struct instruction *jump_dest; 56 56 struct list_head alts; 57 + struct symbol *func; 57 58 }; 58 59 59 60 struct alternative { ··· 67 66 struct list_head insn_list; 68 67 DECLARE_HASHTABLE(insn_hash, 16); 69 68 struct section *rodata, *whitelist; 69 + bool ignore_unreachables, c_file; 70 70 }; 71 71 72 72 const char *objname; ··· 230 228 } 231 229 } 232 230 233 - if (insn->type == INSN_JUMP_DYNAMIC) 231 + if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts)) 234 232 /* sibling call */ 235 233 return 0; 236 234 } ··· 250 248 static int decode_instructions(struct objtool_file *file) 251 249 { 252 250 struct section *sec; 251 + struct symbol *func; 253 252 unsigned long offset; 254 253 struct instruction *insn; 255 254 int ret; ··· 283 280 284 281 hash_add(file->insn_hash, &insn->hash, insn->offset); 285 282 list_add_tail(&insn->list, &file->insn_list); 283 + } 284 + 285 + list_for_each_entry(func, &sec->symbol_list, list) { 286 + if (func->type != STT_FUNC) 287 + continue; 288 + 289 + if (!find_insn(file, sec, func->offset)) { 290 + WARN("%s(): can't find starting instruction", 291 + func->name); 292 + return -1; 293 + } 294 + 295 + func_for_each_insn(file, func, insn) 296 + if (!insn->func) 297 + insn->func = func; 286 298 } 287 299 } 288 300 ··· 682 664 text_rela->addend); 683 665 684 666 /* 685 - * TODO: Document where this is needed, or get rid of it. 686 - * 687 667 * rare case: jmpq *[addr](%rip) 668 + * 669 + * This check is for a rare gcc quirk, currently only seen in 670 + * three driver functions in the kernel, only with certain 671 + * obscure non-distro configs. 672 + * 673 + * As part of an optimization, gcc makes a copy of an existing 674 + * switch jump table, modifies it, and then hard-codes the jump 675 + * (albeit with an indirect jump) to use a single entry in the 676 + * table. The rest of the jump table and some of its jump 677 + * targets remain as dead code. 678 + * 679 + * In such a case we can just crudely ignore all unreachable 680 + * instruction warnings for the entire object file. Ideally we 681 + * would just ignore them for the function, but that would 682 + * require redesigning the code quite a bit. And honestly 683 + * that's just not worth doing: unreachable instruction 684 + * warnings are of questionable value anyway, and this is such 685 + * a rare issue. 686 + * 687 + * kbuild reports: 688 + * - https://lkml.kernel.org/r/201603231906.LWcVUpxm%25fengguang.wu@intel.com 689 + * - https://lkml.kernel.org/r/201603271114.K9i45biy%25fengguang.wu@intel.com 690 + * - https://lkml.kernel.org/r/201603291058.zuJ6ben1%25fengguang.wu@intel.com 691 + * 692 + * gcc bug: 693 + * - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70604 688 694 */ 689 - if (!rodata_rela) 695 + if (!rodata_rela) { 690 696 rodata_rela = find_rela_by_dest(file->rodata, 691 697 text_rela->addend + 4); 698 + if (rodata_rela) 699 + file->ignore_unreachables = true; 700 + } 692 701 693 702 if (!rodata_rela) 694 703 continue; ··· 776 731 static int decode_sections(struct objtool_file *file) 777 732 { 778 733 int ret; 779 - 780 - file->whitelist = find_section_by_name(file->elf, "__func_stack_frame_non_standard"); 781 - file->rodata = find_section_by_name(file->elf, ".rodata"); 782 734 783 735 ret = decode_instructions(file); 784 736 if (ret) ··· 841 799 struct alternative *alt; 842 800 struct instruction *insn; 843 801 struct section *sec; 802 + struct symbol *func = NULL; 844 803 unsigned char state; 845 804 int ret; 846 805 ··· 856 813 } 857 814 858 815 while (1) { 816 + if (file->c_file && insn->func) { 817 + if (func && func != insn->func) { 818 + WARN("%s() falls through to next function %s()", 819 + func->name, insn->func->name); 820 + return 1; 821 + } 822 + 823 + func = insn->func; 824 + } 825 + 859 826 if (insn->visited) { 860 827 if (frame_state(insn->state) != frame_state(state)) { 861 828 WARN_FUNC("frame pointer state mismatch", ··· 875 822 876 823 return 0; 877 824 } 878 - 879 - /* 880 - * Catch a rare case where a noreturn function falls through to 881 - * the next function. 882 - */ 883 - if (is_fentry_call(insn) && (state & STATE_FENTRY)) 884 - return 0; 885 825 886 826 insn->visited = true; 887 827 insn->state = state; ··· 1081 1035 continue; 1082 1036 1083 1037 insn = find_insn(file, sec, func->offset); 1084 - if (!insn) { 1085 - WARN("%s(): can't find starting instruction", 1086 - func->name); 1087 - warnings++; 1038 + if (!insn) 1088 1039 continue; 1089 - } 1090 1040 1091 1041 ret = validate_branch(file, insn, 0); 1092 1042 warnings += ret; ··· 1098 1056 if (insn->visited) 1099 1057 continue; 1100 1058 1101 - if (!ignore_unreachable_insn(func, insn) && 1102 - !warnings) { 1103 - WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset); 1104 - warnings++; 1105 - } 1106 - 1107 1059 insn->visited = true; 1060 + 1061 + if (file->ignore_unreachables || warnings || 1062 + ignore_unreachable_insn(func, insn)) 1063 + continue; 1064 + 1065 + WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset); 1066 + warnings++; 1108 1067 } 1109 1068 } 1110 1069 } ··· 1176 1133 1177 1134 INIT_LIST_HEAD(&file.insn_list); 1178 1135 hash_init(file.insn_hash); 1136 + file.whitelist = find_section_by_name(file.elf, "__func_stack_frame_non_standard"); 1137 + file.rodata = find_section_by_name(file.elf, ".rodata"); 1138 + file.ignore_unreachables = false; 1139 + file.c_file = find_section_by_name(file.elf, ".comment"); 1179 1140 1180 1141 ret = decode_sections(&file); 1181 1142 if (ret < 0)