From: Peter Zijlstra <peterz@infradead.org>
To: David Woodhouse <dwmw2@infradead.org>,
Josh Poimboeuf <jpoimboe@redhat.com>
Cc: linux-kernel@vger.kernel.org, Dave Hansen <dave.hansen@intel.com>,
Ashok Raj <ashok.raj@intel.com>,
Thomas Gleixner <tglx@linutronix.de>,
Tim Chen <tim.c.chen@linux.intel.com>,
Andy Lutomirski <luto@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Greg KH <gregkh@linuxfoundation.org>,
Andrea Arcangeli <aarcange@redhat.com>,
Andi Kleen <ak@linux.intel.com>,
Arjan Van De Ven <arjan.van.de.ven@intel.com>,
Dan Williams <dan.j.williams@intel.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Jun Nakajima <jun.nakajima@intel.com>,
Asit Mallick <asit.k.mallick@intel.com>
Subject: [PATCH v2 11/10] objtool: Even more complex static block checks
Date: Tue, 16 Jan 2018 20:49:17 +0100 [thread overview]
Message-ID: <20180116194917.GH2228@hirez.programming.kicks-ass.net> (raw)
In-Reply-To: <20180116142825.376986833@infradead.org>
Subject: objtool: Even more complex static block checks
From: Peter Zijlstra <peterz@infradead.org>
Date: Tue Jan 16 20:17:01 CET 2018
I've observed GCC transform:
f()
{
if (!static_branch_unlikely())
return;
static_assert();
A;
}
g()
{
f();
}
Into:
f()
{
static_assert();
A;
}
g()
{
if (static_branch_unlikely())
f();
}
Which results in the assertion landing at f+0. The transformation is
valid and useful; it avoids a pointless CALL+RET sequence, so we'll
have to teach objtool how to deal with this.
Do this by marking all CALL destinations with static_call when called
from a static_block and non_static_call when called outside a
static_block. This allows us to identify functions called exclusively
from a static_block and start them with a static_block.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/check.c | 77 ++++++++++++++++++++++++++++++++++++--------------
tools/objtool/elf.h | 1
2 files changed, 57 insertions(+), 21 deletions(-)
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1199,36 +1199,71 @@ static int read_retpoline_hints(struct o
return 0;
}
+static void __grow_static_block(struct instruction *insn, bool *state)
+{
+ if (!*state && !insn->static_jump_dest)
+ return;
+
+ if (insn->static_jump_dest) {
+ *state = true;
+ return;
+ }
+
+ if (insn->branch_target) {
+ *state = false;
+ return;
+
+ } else switch (insn->type) {
+ case INSN_JUMP_CONDITIONAL:
+ case INSN_JUMP_UNCONDITIONAL:
+ case INSN_JUMP_DYNAMIC:
+ case INSN_CALL_DYNAMIC:
+ case INSN_RETURN:
+ case INSN_BUG:
+ *state = false;
+ return;
+ }
+
+ insn->static_jump_dest = *state;
+}
+
static int grow_static_blocks(struct objtool_file *file)
{
- struct instruction *insn;
bool static_block = false;
+ struct symbol *func, *tmp;
+ struct instruction *insn;
+ struct section *sec;
for_each_insn(file, insn) {
- if (!static_block && !insn->static_jump_dest)
- continue;
+ __grow_static_block(insn, &static_block);
- if (insn->static_jump_dest) {
- static_block = true;
- continue;
- }
+ if (insn->type == INSN_CALL) {
+ func = insn->call_dest;
- if (insn->branch_target) {
- static_block = false;
- continue;
- } else switch (insn->type) {
- case INSN_JUMP_CONDITIONAL:
- case INSN_JUMP_UNCONDITIONAL:
- case INSN_JUMP_DYNAMIC:
- case INSN_CALL:
- case INSN_CALL_DYNAMIC:
- case INSN_RETURN:
- case INSN_BUG:
- static_block = false;
- continue;
+ if (static_block)
+ func->static_call = true;
+ else
+ func->non_static_call = true;
}
+ }
+
+ for_each_sec(file, sec) {
+ list_for_each_entry_safe(func, tmp, &sec->symbol_list, list) {
+ if (!func->static_call)
+ continue;
- insn->static_jump_dest = static_block;
+ if (func->non_static_call)
+ continue;
+
+ /* static && !non_static -- only static callers */
+
+ static_block = true;
+ func_for_each_insn(file, func, insn) {
+ __grow_static_block(insn, &static_block);
+ if (!static_block)
+ break;
+ }
+ }
}
return 0;
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -61,6 +61,7 @@ struct symbol {
unsigned char bind, type;
unsigned long offset;
unsigned int len;
+ bool static_call, non_static_call;
};
struct rela {
next prev parent reply other threads:[~2018-01-16 19:49 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-16 14:28 [PATCH v2 00/10] objtool validation of static branches and retpoline Peter Zijlstra
2018-01-16 14:28 ` [PATCH v2 01/10] x86: Reindent _static_cpu_has Peter Zijlstra
2018-01-16 15:48 ` Borislav Petkov
2018-01-16 14:28 ` [PATCH v2 02/10] x86: Update _static_cpu_has to use all named variables Peter Zijlstra
2018-01-18 11:21 ` Borislav Petkov
2018-01-18 15:09 ` Peter Zijlstra
2018-01-18 15:24 ` Borislav Petkov
2018-01-16 14:28 ` [PATCH v2 03/10] x86: Add a type field to alt_instr Peter Zijlstra
2018-01-16 22:49 ` Josh Poimboeuf
2018-01-16 22:53 ` Borislav Petkov
2018-01-16 23:06 ` Josh Poimboeuf
2018-01-18 11:32 ` Borislav Petkov
2018-01-16 14:28 ` [PATCH v2 04/10] objtool: Implement base jump_assert support Peter Zijlstra
2018-01-16 14:28 ` [PATCH v2 05/10] x86: Annotate static_cpu_has alternative Peter Zijlstra
2018-01-18 13:15 ` Borislav Petkov
2018-01-16 14:28 ` [PATCH v2 06/10] objtool: Implement jump_assert for _static_cpu_has() Peter Zijlstra
2018-01-16 23:02 ` Josh Poimboeuf
2018-01-17 9:19 ` Peter Zijlstra
2018-01-17 14:27 ` Josh Poimboeuf
2018-01-17 14:30 ` Josh Poimboeuf
2018-01-17 16:30 ` Peter Zijlstra
2018-01-16 14:28 ` [PATCH v2 07/10] x86/jump_label: Implement arch_static_assert() Peter Zijlstra
2018-01-18 13:33 ` Borislav Petkov
2018-01-18 15:31 ` Peter Zijlstra
2018-01-16 14:28 ` [PATCH v2 08/10] objtool: Add retpoline validation Peter Zijlstra
2018-01-16 14:28 ` [PATCH v2 09/10] x86: Annotate dynamic jump in head_64.S Peter Zijlstra
2018-01-16 14:28 ` [PATCH v2 10/10] objtool: More complex static jump implementation Peter Zijlstra
2018-01-16 15:20 ` Peter Zijlstra
2018-01-17 3:05 ` Josh Poimboeuf
2018-01-17 8:18 ` Peter Zijlstra
2018-01-16 19:49 ` Peter Zijlstra [this message]
2018-01-17 3:12 ` [PATCH v2 11/10] objtool: Even more complex static block checks Josh Poimboeuf
2018-01-17 8:13 ` Peter Zijlstra
2018-01-17 14:13 ` 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=20180116194917.GH2228@hirez.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=aarcange@redhat.com \
--cc=ak@linux.intel.com \
--cc=arjan.van.de.ven@intel.com \
--cc=ashok.raj@intel.com \
--cc=asit.k.mallick@intel.com \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@intel.com \
--cc=dwmw2@infradead.org \
--cc=gregkh@linuxfoundation.org \
--cc=jpoimboe@redhat.com \
--cc=jun.nakajima@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=pbonzini@redhat.com \
--cc=tglx@linutronix.de \
--cc=tim.c.chen@linux.intel.com \
--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