On Wed, Mar 01, 2017 at 04:21:36PM +0100, Arnd Bergmann wrote: > On Wed, Mar 1, 2017 at 3:31 PM, Josh Poimboeuf <jpoim...@redhat.com> wrote: > > On Wed, Mar 01, 2017 at 10:34:42AM +0100, Arnd Bergmann wrote: > >> On Tue, Oct 11, 2016 at 10:38 PM, Arnd Bergmann <a...@arndb.de> wrote: > >> > On Tuesday, October 11, 2016 10:51:46 AM CEST Josh Poimboeuf wrote: > >> >> > >> >> 3) 0xFC244C03-config: > >> >> drivers/scsi/fnic/fnic_main.o: warning: objtool: fnic_log_q_error() > >> >> falls through to next function fnic_handle_link_event() > >> >> drivers/scsi/snic/snic_res.o: warning: objtool: .text: unexpected end > >> >> of section > >> >> > >> >> These look like another bad gcc bug which is truncating functions: > >> > > >> > Same bug for both of them? > >> > >> I ran into this one again today, after updating to the latest gcc-7.0.1: > >> > >> drivers/infiniband/sw/rxe/rxe_resp.o: warning: objtool: > >> rxe_responder()+0xfe: sibling call from callable instruction with > >> changed frame pointer > >> > >> Josh, did you get around to updating objtool the last time I reported it, > >> or > >> is it still the same problem? If this is a new variation, I can provide > >> more > >> details about the failure, otherwise I'll just ignore it for now. > > > > This one should have been fixed with: > > > > 3732710ff6f2 ("objtool: Improve rare switch jump table pattern detection") > > It was on the current linux-next, so that commit should certainly be included. > > > Can you attach the object file?
Here's the preliminary fix for this one (still needs more testing): diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c index bd12eb1..7b718bb 100644 --- a/tools/objtool/builtin-check.c +++ b/tools/objtool/builtin-check.c @@ -806,11 +806,20 @@ static struct rela *find_switch_table(struct objtool_file *file, insn->jump_dest->offset > orig_insn->offset)) break; + /* look for a rela 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; diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index 0d7983a..d897702 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c @@ -85,6 +85,18 @@ struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset) return 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) { diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h index aa1ff65..731973e 100644 --- a/tools/objtool/elf.h +++ b/tools/objtool/elf.h @@ -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);