Patch "objtool: Fix another GCC jump table detection issue" has been added to the 4.9-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
objtool: Fix another GCC jump table detection issue
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
objtool-fix-another-gcc-jump-table-detection-issue.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
5c51f4ae84df0f9df33ac08aa5be50061a8b4242Mon Sep 17 00:00:00 2001
From: Josh Poimboeuf <[email protected]>
Date: Thu, 2 Mar 2017 16:57:23 -0600
Subject: objtool: Fix another GCC jump table detection issue
From: Josh Poimboeuf <[email protected]>
commit 5c51f4ae84df0f9df33ac08aa5be50061a8b4242 upstream.
Arnd Bergmann reported a (false positive) objtool warning:
drivers/infiniband/sw/rxe/rxe_resp.o: warning: objtool: rxe_responder()+0xfe: sibling call from callable instruction with changed frame pointer
The issue is in find_switch_table(). It tries to find a switch statement's jump table by walking backwards from an indirect jump instruction, looking for a relocation to the .rodata section. In this case it stopped walking prematurely: the first .rodata relocation it encountered was for a variable (resp_state_name) instead of a jump table, so it just assumed there wasn't a jump table.
The fix is to ignore any .rodata relocation which refers to an ELF object symbol. This works because the jump tables are anonymous and have no symbols associated with them.
--- tools/objtool/builtin-check.c | 15 ++++++++++++--- tools/objtool/elf.c | 12 ++++++++++++ tools/objtool/elf.h | 1 + 3 files changed, 25 insertions(+), 3 deletions(-)
tools/objtool/builtin-check.c +12 -3
@@ -757,11 +757,20 @@ static struct rela *find_switch_table(st insn->jump_dest->offset > orig_insn->offset)) break; +/* look for a relocation which references .rodata */ text_rela =find_rela_by_dest_range (insn->sec, insn->offset, insn->len); -if (text_rela && text_rela->sym == file->rodata->sym) -return find_rela_by_dest (file->rodata, - text_rela->addend); +if (!text_rela || text_rela->sym != file->rodata->sym) +continue ; + +/* +* Make sure the .rodata address isn't associated with a +* symbol. gcc jump tables are anonymous data. +*/ +if (find_symbol_containing (file->rodata, text_rela->addend)) +continue ; + +return find_rela_by_dest (file->rodata, text_rela->addend); }return NULL ;
tools/objtool/elf.c +12 -0
@@ -85,6 +85,18 @@ struct symbol *find_symbol_by_offset(strreturn NULL ; } +struct symbol *find_symbol_containing (struct section *sec,unsigned long offset) +{ +struct symbol *sym; + +list_for_each_entry (sym, &sec->symbol_list, list) +if (sym->type !=STT_SECTION && + offset >= sym->offset && offset < sym->offset + sym->len) +return sym; + +return NULL ; +} +struct rela *find_rela_by_dest_range (struct section *sec,unsigned long offset,unsigned int len) {
tools/objtool/elf.h +1 -0
@@ -79,6 +79,7 @@ struct elf {struct elf *elf_open (const char *name);struct section *find_section_by_name (struct elf *elf,const char *name);struct symbol *find_symbol_by_offset (struct section *sec,unsigned long offset); +struct symbol *find_symbol_containing (struct section *sec,unsigned long offset);struct rela *find_rela_by_dest (struct section *sec,unsigned long offset);struct rela *find_rela_by_dest_range (struct section *sec,unsigned long offset,unsigned int len);
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/x86-mm-fix-boot-crash-caused-by-incorrect-loop-count-calculation-in-sync_global_pgds.patch queue-4.9/objtool-fix-another-gcc-jump-table-detection-issue.patch queue-4.9/x86-mpx-correctly-report-do_mpx_bt_fault-failures-to-user-space.patch queue-4.9/x86-mm-fix-flush_tlb_page-on-xen.patch queue-4.9/objtool-fix-iret-s-opcode.patch