From: tip-bot for Josh Poimboeuf <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: fengguang.wu@intel.com, tglx@linutronix.de, jpoimboe@redhat.com,
namhyung@gmail.com, luto@kernel.org, acme@kernel.org,
jslaby@suse.cz, palves@redhat.com, akpm@linux-foundation.org,
bp@alien8.de, bernd@petrovitsch.priv.at, hpa@zytor.com,
mmarek@suse.cz, chris.j.arges@canonical.com,
peterz@infradead.org, acme@infradead.org,
torvalds@linux-foundation.org, mingo@kernel.org,
linux-kernel@vger.kernel.org
Subject: [tip:core/objtool] objtool: Fix false positive warnings for functions with multiple switch statements
Date: Wed, 9 Mar 2016 03:45:29 -0800 [thread overview]
Message-ID: <tip-8133fbb4240ae2918d993defa0f6824864412f56@git.kernel.org> (raw)
In-Reply-To: <2d7eecc6bc52d301f494b80f5fd62c2b6c895658.1457502970.git.jpoimboe@redhat.com>
Commit-ID: 8133fbb4240ae2918d993defa0f6824864412f56
Gitweb: http://git.kernel.org/tip/8133fbb4240ae2918d993defa0f6824864412f56
Author: Josh Poimboeuf <jpoimboe@redhat.com>
AuthorDate: Wed, 9 Mar 2016 00:06:58 -0600
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 9 Mar 2016 10:48:09 +0100
objtool: Fix false positive warnings for functions with multiple switch statements
Ingo reported [1] some false positive objtool warnings:
drivers/net/wireless/realtek/rtlwifi/base.o: warning: objtool: rtlwifi_rate_mapping()+0x2e7: frame pointer state mismatch
drivers/net/wireless/realtek/rtlwifi/base.o: warning: objtool: rtlwifi_rate_mapping()+0x2f3: frame pointer state mismatch
...
And so did the 0-day bot [2]:
drivers/gpu/drm/radeon/cik.o: warning: objtool: cik_tiling_mode_table_init()+0x6ce: call without frame pointer save/setup
drivers/gpu/drm/radeon/cik.o: warning: objtool: cik_tiling_mode_table_init()+0x72b: call without frame pointer save/setup
...
Both sets of warnings involve functions which have multiple switch
statements. When there's more than one switch statement in a function,
objtool interprets all the switch jump tables as a single table. If the
targets of one jump table assume a stack frame and the targets of
another one don't, it prints false positive warnings.
Fix the bug by detecting the size of each switch jump table. For
multiple tables, each one ends where the next one begins.
[1] https://lkml.kernel.org/r/20160308103716.GA9618@gmail.com
[2] https://lists.01.org/pipermail/kbuild-all/2016-March/018124.html
Reported-by: Ingo Molnar <mingo@kernel.org>
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Bernd Petrovitsch <bernd@petrovitsch.priv.at>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Chris J Arges <chris.j.arges@canonical.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Michal Marek <mmarek@suse.cz>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Pedro Alves <palves@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: live-patching@vger.kernel.org
Link: http://lkml.kernel.org/r/2d7eecc6bc52d301f494b80f5fd62c2b6c895658.1457502970.git.jpoimboe@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
tools/objtool/builtin-check.c | 145 +++++++++++++++++++++++++++++-------------
1 file changed, 100 insertions(+), 45 deletions(-)
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index cdbdd7d..cf1e48d 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -61,6 +61,7 @@ struct alternative {
struct objtool_file {
struct elf *elf;
struct list_head insn_list;
+ struct section *rodata;
};
const char *objname;
@@ -599,73 +600,125 @@ out:
return ret;
}
-/*
- * For some switch statements, gcc generates a jump table in the .rodata
- * section which contains a list of addresses within the function to jump to.
- * This finds these jump tables and adds them to the insn->alts lists.
- */
-static int add_switch_table_alts(struct objtool_file *file)
+static int add_switch_table(struct objtool_file *file, struct symbol *func,
+ struct instruction *insn, struct rela *table,
+ struct rela *next_table)
{
- struct instruction *insn, *alt_insn;
- struct rela *rodata_rela, *text_rela;
- struct section *rodata;
- struct symbol *func;
+ struct rela *rela = table;
+ struct instruction *alt_insn;
struct alternative *alt;
- for_each_insn(file, insn) {
+ list_for_each_entry_from(rela, &file->rodata->rela->rela_list, list) {
+ if (rela == next_table)
+ break;
+
+ if (rela->sym->sec != insn->sec ||
+ rela->addend <= func->offset ||
+ rela->addend >= func->offset + func->len)
+ break;
+
+ alt_insn = find_insn(file, insn->sec, rela->addend);
+ if (!alt_insn) {
+ WARN("%s: can't find instruction at %s+0x%x",
+ file->rodata->rela->name, insn->sec->name,
+ rela->addend);
+ return -1;
+ }
+
+ alt = malloc(sizeof(*alt));
+ if (!alt) {
+ WARN("malloc failed");
+ return -1;
+ }
+
+ alt->insn = alt_insn;
+ list_add_tail(&alt->list, &insn->alts);
+ }
+
+ return 0;
+}
+
+static int add_func_switch_tables(struct objtool_file *file,
+ struct symbol *func)
+{
+ struct instruction *insn, *prev_jump;
+ struct rela *text_rela, *rodata_rela, *prev_rela;
+ int ret;
+
+ prev_jump = NULL;
+
+ func_for_each_insn(file, func, insn) {
if (insn->type != INSN_JUMP_DYNAMIC)
continue;
text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
insn->len);
- if (!text_rela || strcmp(text_rela->sym->name, ".rodata"))
- continue;
-
- rodata = find_section_by_name(file->elf, ".rodata");
- if (!rodata || !rodata->rela)
+ if (!text_rela || text_rela->sym != file->rodata->sym)
continue;
/* common case: jmpq *[addr](,%rax,8) */
- rodata_rela = find_rela_by_dest(rodata, text_rela->addend);
+ rodata_rela = find_rela_by_dest(file->rodata,
+ text_rela->addend);
- /* rare case: jmpq *[addr](%rip) */
+ /*
+ * TODO: Document where this is needed, or get rid of it.
+ *
+ * rare case: jmpq *[addr](%rip)
+ */
if (!rodata_rela)
- rodata_rela = find_rela_by_dest(rodata,
+ rodata_rela = find_rela_by_dest(file->rodata,
text_rela->addend + 4);
+
if (!rodata_rela)
continue;
- func = find_containing_func(insn->sec, insn->offset);
- if (!func) {
- WARN_FUNC("can't find containing func",
- insn->sec, insn->offset);
- return -1;
+ /*
+ * We found a switch table, but we don't know yet how big it
+ * is. Don't add it until we reach the end of the function or
+ * the beginning of another switch table in the same function.
+ */
+ if (prev_jump) {
+ ret = add_switch_table(file, func, prev_jump, prev_rela,
+ rodata_rela);
+ if (ret)
+ return ret;
}
- list_for_each_entry_from(rodata_rela, &rodata->rela->rela_list,
- list) {
- if (rodata_rela->sym->sec != insn->sec ||
- rodata_rela->addend <= func->offset ||
- rodata_rela->addend >= func->offset + func->len)
- break;
+ prev_jump = insn;
+ prev_rela = rodata_rela;
+ }
- alt_insn = find_insn(file, insn->sec,
- rodata_rela->addend);
- if (!alt_insn) {
- WARN("%s: can't find instruction at %s+0x%x",
- rodata->rela->name, insn->sec->name,
- rodata_rela->addend);
- return -1;
- }
+ if (prev_jump) {
+ ret = add_switch_table(file, func, prev_jump, prev_rela, NULL);
+ if (ret)
+ return ret;
+ }
- alt = malloc(sizeof(*alt));
- if (!alt) {
- WARN("malloc failed");
- return -1;
- }
+ return 0;
+}
- alt->insn = alt_insn;
- list_add_tail(&alt->list, &insn->alts);
+/*
+ * For some switch statements, gcc generates a jump table in the .rodata
+ * section which contains a list of addresses within the function to jump to.
+ * This finds these jump tables and adds them to the insn->alts lists.
+ */
+static int add_switch_table_alts(struct objtool_file *file)
+{
+ struct section *sec;
+ struct symbol *func;
+ int ret;
+
+ if (!file->rodata || !file->rodata->rela)
+ return 0;
+
+ list_for_each_entry(sec, &file->elf->sections, list) {
+ list_for_each_entry(func, &sec->symbol_list, list) {
+ if (func->type != STT_FUNC)
+ continue;
+
+ ret = add_func_switch_tables(file, func);
+ if (ret)
+ return ret;
}
}
@@ -676,6 +729,8 @@ static int decode_sections(struct objtool_file *file)
{
int ret;
+ file->rodata = find_section_by_name(file->elf, ".rodata");
+
ret = decode_instructions(file);
if (ret)
return ret;
next prev parent reply other threads:[~2016-03-09 11:46 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-29 4:22 [PATCH v19 00/10] Compile-time stack metadata validation Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 01/10] objtool: Mark non-standard files and directories Josh Poimboeuf
2016-02-29 10:58 ` [tip:core/objtool] objtool: Mark non-standard object " tip-bot for Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 02/10] objtool: Add STACK_FRAME_NON_STANDARD macro Josh Poimboeuf
2016-02-29 10:58 ` [tip:core/objtool] objtool: Add STACK_FRAME_NON_STANDARD() macro tip-bot for Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 03/10] x86/xen: Mark xen_cpuid() stack frame as non-standard Josh Poimboeuf
2016-02-29 10:59 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 04/10] bpf: Mark __bpf_prog_run() " Josh Poimboeuf
2016-02-29 10:59 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 05/10] sched: Mark __schedule() " Josh Poimboeuf
2016-02-29 10:59 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 06/10] sched: always inline context_switch() Josh Poimboeuf
2016-02-29 11:00 ` [tip:core/objtool] sched: Always " tip-bot for Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 07/10] x86/kprobes: Mark kretprobe_trampoline() stack frame as non-standard Josh Poimboeuf
2016-02-29 11:00 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 08/10] objtool: Compile-time stack metadata validation Josh Poimboeuf
2016-02-29 11:01 ` [tip:core/objtool] objtool: Add tool to perform compile-time " tip-bot for Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 09/10] objtool: Add CONFIG_STACK_VALIDATION option Josh Poimboeuf
2016-02-29 11:01 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-03 14:12 ` Sebastian Andrzej Siewior
2016-03-03 14:56 ` Josh Poimboeuf
2016-02-29 4:22 ` [PATCH v19 10/10] objtool: Enable stack metadata validation on x86_64 Josh Poimboeuf
2016-02-29 11:01 ` [tip:core/objtool] objtool: Enable stack metadata validation on 64-bit x86 tip-bot for Josh Poimboeuf
2016-03-08 10:37 ` [PATCH v19 00/10] Compile-time stack metadata validation Ingo Molnar
2016-03-08 12:29 ` Josh Poimboeuf
2016-03-08 13:44 ` Ingo Molnar
2016-03-08 14:21 ` Josh Poimboeuf
2016-03-08 15:15 ` Ingo Molnar
2016-03-08 15:49 ` Ingo Molnar
2016-03-09 6:06 ` [PATCH 00/11] Various objtool fixes Josh Poimboeuf
2016-03-09 6:06 ` [PATCH 01/11] objtool: Prevent infinite recursion in noreturn detection Josh Poimboeuf
2016-03-09 11:42 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-09 6:06 ` [PATCH 02/11] objtool: Detect infinite recursion Josh Poimboeuf
2016-03-09 11:43 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-09 6:06 ` [PATCH 03/11] objtool: Compile with debugging symbols Josh Poimboeuf
2016-03-09 11:43 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-09 6:06 ` [PATCH 04/11] objtool: Fix false positive warnings related to sibling calls Josh Poimboeuf
2016-03-09 11:43 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-09 6:06 ` [PATCH 05/11] objtool: Add helper macros for traversing instructions Josh Poimboeuf
2016-03-09 11:44 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-09 6:06 ` [PATCH 06/11] objtool: Remove superflous INIT_LIST_HEAD Josh Poimboeuf
2016-03-09 11:44 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-09 6:06 ` [PATCH 07/11] objtool: Rename some variables and functions Josh Poimboeuf
2016-03-09 11:45 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-09 6:06 ` [PATCH 08/11] objtool: Fix false positive warnings for functions with multiple switch statements Josh Poimboeuf
2016-03-09 11:45 ` tip-bot for Josh Poimboeuf [this message]
2016-03-09 6:06 ` [PATCH 09/11] tools/objtool: Copy hashtable.h into tools directory Josh Poimboeuf
2016-03-09 9:47 ` Ingo Molnar
2016-03-09 16:09 ` Josh Poimboeuf
2016-03-09 18:39 ` Ingo Molnar
2016-03-09 11:45 ` [tip:core/objtool] tools: " tip-bot for Josh Poimboeuf
2016-03-09 6:07 ` [PATCH 10/11] objtool: Add several performance improvements Josh Poimboeuf
2016-03-09 11:46 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
2016-03-09 6:07 ` [PATCH 11/11] objtool: Only print one warning per function Josh Poimboeuf
2016-03-09 11:46 ` [tip:core/objtool] " tip-bot for Josh Poimboeuf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=tip-8133fbb4240ae2918d993defa0f6824864412f56@git.kernel.org \
--to=tipbot@zytor.com \
--cc=acme@infradead.org \
--cc=acme@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=bernd@petrovitsch.priv.at \
--cc=bp@alien8.de \
--cc=chris.j.arges@canonical.com \
--cc=fengguang.wu@intel.com \
--cc=hpa@zytor.com \
--cc=jpoimboe@redhat.com \
--cc=jslaby@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tip-commits@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@kernel.org \
--cc=mmarek@suse.cz \
--cc=namhyung@gmail.com \
--cc=palves@redhat.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome