lkml.org 
[lkml]   [2018]   [Jan]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
From
Subject[PATCH 18/35] objtool: Another static block fail
I've observed GCC generate:

sym:
NOP/JMP 1f (static_branch)
JMP 2f
1: /* crud */
JMP 3f
2: /* other crud */

3: RETQ


This means we need to follow unconditional jumps; be conservative and
only follow if its a unique jump.

(I've not yet figured out which CONFIG option is responsible for this,
a normal defconfig build does not generate crap like this)

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/check.c | 33 +++++++++++++++++++++++++++++++--
tools/objtool/check.h | 3 ++-
2 files changed, 33 insertions(+), 3 deletions(-)

--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -521,7 +521,7 @@ static int add_jump_destinations(struct
return -1;
}

- insn->jump_dest->branch_target = true;
+ insn->jump_dest->branch_target++;
}

return 0;
@@ -1207,6 +1207,8 @@ static int read_retpoline_hints(struct o
return 0;
}

+static void jmp_grow_static_block(struct objtool_file *file, struct instruction *insn);
+
static bool __grow_static_block(struct objtool_file *file,
struct instruction *insn, bool ign_bt)
{
@@ -1216,7 +1218,8 @@ static bool __grow_static_block(struct o

switch (insn->type) {
case INSN_JUMP_UNCONDITIONAL:
- /* mark this instruction, terminate this section */
+ /* follow the jump, mark this instruction, terminate this section */
+ jmp_grow_static_block(file, insn->jump_dest);
insn->static_jump_dest = true;
return false;

@@ -1238,6 +1241,32 @@ static bool __grow_static_block(struct o
return true;
}

+static void jmp_grow_static_block(struct objtool_file *file, struct instruction *insn)
+{
+ bool ignore = true;
+
+ /* !jump_dest */
+ if (!insn)
+ return;
+
+ /* more than a single site jumps here, can't be certain */
+ if (insn->branch_target > 1)
+ return;
+
+ for (; &insn->list != &file->insn_list;
+ insn = list_next_entry(insn, list)) {
+
+ /*
+ * Per definition the first insn of a jump is a branch target,
+ * don't terminate because of that.
+ */
+ if (!__grow_static_block(file, insn, ignore))
+ break;
+
+ ignore = false;
+ }
+}
+
static int grow_static_blocks(struct objtool_file *file)
{
bool static_block = false;
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -45,7 +45,8 @@ struct instruction {
unsigned char type;
unsigned long immediate;
bool alt_group, visited, dead_end, ignore, hint, save, restore, ignore_alts;
- bool static_jump_dest, retpoline_safe, branch_target;
+ bool static_jump_dest, retpoline_safe;
+ int branch_target;
struct symbol *call_dest;
struct instruction *jump_dest;
struct list_head alts;

\
 
 \ /
  Last update: 2018-01-18 15:58    [W:0.284 / U:0.576 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site