Commit-ID:  b18cbc614b4ddca4019ecd2e6663d54bd495d413
Gitweb:     https://git.kernel.org/tip/b18cbc614b4ddca4019ecd2e6663d54bd495d413
Author:     Josh Poimboeuf <jpoim...@redhat.com>
AuthorDate: Mon, 29 Jan 2018 22:00:40 -0600
Committer:  Ingo Molnar <mi...@kernel.org>
CommitDate: Tue, 30 Jan 2018 07:55:05 +0100

objtool: Add support for alternatives at the end of a section

Now that the previous patch gave objtool the ability to read retpoline
alternatives, it shows a new warning:

  arch/x86/entry/entry_64.o: warning: objtool: .entry_trampoline: don't know 
how to handle alternatives at end of section

This is due to the JMP_NOSPEC in entry_SYSCALL_64_trampoline().

Previously, objtool ignored this situation because it wasn't needed, and
it would have required a bit of extra code.  Now that this case exists,
add proper support for it.

Signed-off-by: Josh Poimboeuf <jpoim...@redhat.com>
Cc: Andy Lutomirski <l...@kernel.org>
Cc: Borislav Petkov <b...@alien8.de>
Cc: Dave Hansen <dave.han...@linux.intel.com>
Cc: David Woodhouse <dw...@infradead.org>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Cc: Guenter Roeck <li...@roeck-us.net>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Juergen Gross <jgr...@suse.com>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Link: 
http://lkml.kernel.org/r/2a30a3c2158af47d891a76e69bb1ef347e0443fd.1517284349.git.jpoim...@redhat.com
Signed-off-by: Ingo Molnar <mi...@kernel.org>
---
 tools/objtool/check.c | 53 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index bc3490d..9cd028a 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -594,7 +594,7 @@ static int handle_group_alt(struct objtool_file *file,
                            struct instruction *orig_insn,
                            struct instruction **new_insn)
 {
-       struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump;
+       struct instruction *last_orig_insn, *last_new_insn, *insn, *fake_jump = 
NULL;
        unsigned long dest_off;
 
        last_orig_insn = NULL;
@@ -610,28 +610,30 @@ static int handle_group_alt(struct objtool_file *file,
                last_orig_insn = insn;
        }
 
-       if (!next_insn_same_sec(file, last_orig_insn)) {
-               WARN("%s: don't know how to handle alternatives at end of 
section",
-                    special_alt->orig_sec->name);
-               return -1;
-       }
-
-       fake_jump = malloc(sizeof(*fake_jump));
-       if (!fake_jump) {
-               WARN("malloc failed");
-               return -1;
+       if (next_insn_same_sec(file, last_orig_insn)) {
+               fake_jump = malloc(sizeof(*fake_jump));
+               if (!fake_jump) {
+                       WARN("malloc failed");
+                       return -1;
+               }
+               memset(fake_jump, 0, sizeof(*fake_jump));
+               INIT_LIST_HEAD(&fake_jump->alts);
+               clear_insn_state(&fake_jump->state);
+
+               fake_jump->sec = special_alt->new_sec;
+               fake_jump->offset = -1;
+               fake_jump->type = INSN_JUMP_UNCONDITIONAL;
+               fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
+               fake_jump->ignore = true;
        }
-       memset(fake_jump, 0, sizeof(*fake_jump));
-       INIT_LIST_HEAD(&fake_jump->alts);
-       clear_insn_state(&fake_jump->state);
-
-       fake_jump->sec = special_alt->new_sec;
-       fake_jump->offset = -1;
-       fake_jump->type = INSN_JUMP_UNCONDITIONAL;
-       fake_jump->jump_dest = list_next_entry(last_orig_insn, list);
-       fake_jump->ignore = true;
 
        if (!special_alt->new_len) {
+               if (!fake_jump) {
+                       WARN("%s: empty alternative at end of section",
+                            special_alt->orig_sec->name);
+                       return -1;
+               }
+
                *new_insn = fake_jump;
                return 0;
        }
@@ -654,8 +656,14 @@ static int handle_group_alt(struct objtool_file *file,
                        continue;
 
                dest_off = insn->offset + insn->len + insn->immediate;
-               if (dest_off == special_alt->new_off + special_alt->new_len)
+               if (dest_off == special_alt->new_off + special_alt->new_len) {
+                       if (!fake_jump) {
+                               WARN("%s: alternative jump to end of section",
+                                    special_alt->orig_sec->name);
+                               return -1;
+                       }
                        insn->jump_dest = fake_jump;
+               }
 
                if (!insn->jump_dest) {
                        WARN_FUNC("can't find alternative jump destination",
@@ -670,7 +678,8 @@ static int handle_group_alt(struct objtool_file *file,
                return -1;
        }
 
-       list_add(&fake_jump->list, &last_new_insn->list);
+       if (fake_jump)
+               list_add(&fake_jump->list, &last_new_insn->list);
 
        return 0;
 }

Reply via email to