[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200109160300.26150-13-jthierry@redhat.com>
Date: Thu, 9 Jan 2020 16:02:15 +0000
From: Julien Thierry <jthierry@...hat.com>
To: linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org
Cc: jpoimboe@...hat.com, peterz@...radead.org, raphael.gault@....com,
catalin.marinas@....com, will@...nel.org,
Julien Thierry <jthierry@...hat.com>
Subject: [RFC v5 12/57] objtool: check: Allow jumps from an alternative group to itself
Alternatives can contain instructions that jump to another instruction
in the same alternative group. This is actually a common pattern on
arm64.
Keep track of instructions jumping within their own alternative group
and carry on validating such branches.
Signed-off-by: Julien Thierry <jthierry@...hat.com>
---
tools/objtool/check.c | 48 ++++++++++++++++++++++++++++++++++---------
tools/objtool/check.h | 1 +
2 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 8f2ff030936d..c7b3f1e2a628 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -722,6 +722,14 @@ static int handle_group_alt(struct objtool_file *file,
sec_for_each_insn_from(file, insn) {
if (insn->offset >= special_alt->orig_off + special_alt->orig_len)
break;
+ /* Is insn a jump to an instruction within the alt_group */
+ if (insn->jump_dest && insn->sec == insn->jump_dest->sec &&
+ (insn->type == INSN_JUMP_CONDITIONAL ||
+ insn->type == INSN_JUMP_UNCONDITIONAL)) {
+ dest_off = insn->jump_dest->offset;
+ insn->intra_group_jump = special_alt->orig_off <= dest_off &&
+ dest_off < special_alt->orig_off + special_alt->orig_len;
+ }
insn->alt_group = true;
last_orig_insn = insn;
@@ -1853,14 +1861,33 @@ static int validate_sibling_call(struct instruction *insn, struct insn_state *st
return validate_call(insn, state);
}
+static int validate_branch_alt_safe(struct objtool_file *file,
+ struct symbol *func,
+ struct instruction *first,
+ struct insn_state state);
+
+static int validate_branch(struct objtool_file *file, struct symbol *func,
+ struct instruction *first, struct insn_state state)
+{
+ if (first->alt_group && list_empty(&first->alts)) {
+ WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
+ first->sec, first->offset);
+ return 1;
+ }
+
+ return validate_branch_alt_safe(file, func, first, state);
+}
+
/*
* Follow the branch starting at the given instruction, and recursively follow
* any other branches (jumps). Meanwhile, track the frame pointer state at
* each instruction and validate all the rules described in
* tools/objtool/Documentation/stack-validation.txt.
*/
-static int validate_branch(struct objtool_file *file, struct symbol *func,
- struct instruction *first, struct insn_state state)
+static int validate_branch_alt_safe(struct objtool_file *file,
+ struct symbol *func,
+ struct instruction *first,
+ struct insn_state state)
{
struct alternative *alt;
struct instruction *insn, *next_insn;
@@ -1871,12 +1898,6 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
insn = first;
sec = insn->sec;
- if (insn->alt_group && list_empty(&insn->alts)) {
- WARN_FUNC("don't know how to handle branch to middle of alternative instruction group",
- sec, insn->offset);
- return 1;
- }
-
while (1) {
next_insn = next_insn_same_sec(file, insn);
@@ -2023,8 +2044,15 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
return ret;
} else if (insn->jump_dest) {
- ret = validate_branch(file, func,
- insn->jump_dest, state);
+ if (insn->intra_group_jump)
+ ret = validate_branch_alt_safe(file,
+ func,
+ insn->jump_dest,
+ state);
+ else
+ ret = validate_branch(file, func,
+ insn->jump_dest,
+ state);
if (ret) {
if (backtrace)
BT_FUNC("(branch)", insn);
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
index af87b55db454..d13ee02f28a4 100644
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -46,6 +46,7 @@ struct instruction {
struct stack_op stack_op;
struct insn_state state;
struct orc_entry orc;
+ bool intra_group_jump;
};
struct objtool_file {
--
2.21.0
Powered by blists - more mailing lists