mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
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 <jpoimboe@redhat.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Woodhouse <dwmw2@infradead.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Guenter Roeck <linux@roeck-us.net> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Juergen Gross <jgross@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/2a30a3c2158af47d891a76e69bb1ef347e0443fd.1517284349.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
a845c7cf4b
commit
17bc33914b
1 changed files with 30 additions and 21 deletions
|
@ -594,7 +594,7 @@ static int handle_group_alt(struct objtool_file *file,
|
||||||
struct instruction *orig_insn,
|
struct instruction *orig_insn,
|
||||||
struct instruction **new_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;
|
unsigned long dest_off;
|
||||||
|
|
||||||
last_orig_insn = NULL;
|
last_orig_insn = NULL;
|
||||||
|
@ -610,28 +610,30 @@ static int handle_group_alt(struct objtool_file *file,
|
||||||
last_orig_insn = insn;
|
last_orig_insn = insn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!next_insn_same_sec(file, last_orig_insn)) {
|
if (next_insn_same_sec(file, last_orig_insn)) {
|
||||||
WARN("%s: don't know how to handle alternatives at end of section",
|
fake_jump = malloc(sizeof(*fake_jump));
|
||||||
special_alt->orig_sec->name);
|
if (!fake_jump) {
|
||||||
return -1;
|
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 = malloc(sizeof(*fake_jump));
|
fake_jump->sec = special_alt->new_sec;
|
||||||
if (!fake_jump) {
|
fake_jump->offset = -1;
|
||||||
WARN("malloc failed");
|
fake_jump->type = INSN_JUMP_UNCONDITIONAL;
|
||||||
return -1;
|
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 (!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;
|
*new_insn = fake_jump;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -654,8 +656,14 @@ static int handle_group_alt(struct objtool_file *file,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dest_off = insn->offset + insn->len + insn->immediate;
|
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;
|
insn->jump_dest = fake_jump;
|
||||||
|
}
|
||||||
|
|
||||||
if (!insn->jump_dest) {
|
if (!insn->jump_dest) {
|
||||||
WARN_FUNC("can't find alternative jump destination",
|
WARN_FUNC("can't find alternative jump destination",
|
||||||
|
@ -670,7 +678,8 @@ static int handle_group_alt(struct objtool_file *file,
|
||||||
return -1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue