* [RFC][PATCH v2 1/7] objtool: Allow UNWIND_HINT to suppress dodgy stack modifications
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
@ 2021-02-11 17:30 ` Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 2/7] objtool,x86: Renumber CFI_reg Peter Zijlstra
` (8 subsequent siblings)
9 siblings, 2 replies; 25+ messages in thread
From: Peter Zijlstra @ 2021-02-11 17:30 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel, peterz
rewind_stack_do_exit()
UNWIND_HINT_FUNC
/* Prevent any naive code from trying to unwind to our caller. */
xorl %ebp, %ebp
movq PER_CPU_VAR(cpu_current_top_of_stack), %rax
leaq -PTREGS_SIZE(%rax), %rsp
UNWIND_HINT_REGS
call do_exit
Does unspeakable things to the stack, which objtool currently fails to
detect due to a limitation in instruction decoding. This will be
rectified after which the above will result in:
arch/x86/entry/entry_64.o: warning: objtool: .text+0xab: unsupported stack register modification
Allow the UNWIND_HINT on the next instruction to suppress this, it
will overwrite the state anyway.
Suggested-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/check.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1918,8 +1918,9 @@ static void restore_reg(struct cfi_state
* 41 5d pop %r13
* c3 retq
*/
-static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
- struct stack_op *op)
+static int update_cfi_state(struct instruction *insn,
+ struct instruction *next_insn,
+ struct cfi_state *cfi, struct stack_op *op)
{
struct cfi_reg *cfa = &cfi->cfa;
struct cfi_reg *regs = cfi->regs;
@@ -2106,7 +2107,7 @@ static int update_cfi_state(struct instr
break;
}
- if (op->dest.reg == cfi->cfa.base) {
+ if (op->dest.reg == cfi->cfa.base && !(next_insn && next_insn->hint)) {
WARN_FUNC("unsupported stack register modification",
insn->sec, insn->offset);
return -1;
@@ -2378,13 +2379,15 @@ static int propagate_alt_cfi(struct objt
return 0;
}
-static int handle_insn_ops(struct instruction *insn, struct insn_state *state)
+static int handle_insn_ops(struct instruction *insn,
+ struct instruction *next_insn,
+ struct insn_state *state)
{
struct stack_op *op;
list_for_each_entry(op, &insn->stack_ops, list) {
- if (update_cfi_state(insn, &state->cfi, op))
+ if (update_cfi_state(insn, next_insn, &state->cfi, op))
return 1;
if (op->dest.type == OP_DEST_PUSHF) {
@@ -2678,7 +2681,7 @@ static int validate_branch(struct objtoo
return 0;
}
- if (handle_insn_ops(insn, &state))
+ if (handle_insn_ops(insn, next_insn, &state))
return 1;
switch (insn->type) {
^ permalink raw reply [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool: Allow UNWIND_HINT to suppress dodgy stack modifications
2021-02-11 17:30 ` [RFC][PATCH v2 1/7] objtool: Allow UNWIND_HINT to suppress dodgy stack modifications Peter Zijlstra
@ 2021-03-03 8:45 ` tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-03 8:45 UTC (permalink / raw)
To: linux-tip-commits
Cc: Josh Poimboeuf, Peter Zijlstra (Intel),
Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 8c0cca513be9e3dd9c17b55b72b66751f3487577
Gitweb: https://git.kernel.org/tip/8c0cca513be9e3dd9c17b55b72b66751f3487577
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Thu, 11 Feb 2021 13:03:28 +01:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 03 Mar 2021 09:38:29 +01:00
objtool: Allow UNWIND_HINT to suppress dodgy stack modifications
rewind_stack_do_exit()
UNWIND_HINT_FUNC
/* Prevent any naive code from trying to unwind to our caller. */
xorl %ebp, %ebp
movq PER_CPU_VAR(cpu_current_top_of_stack), %rax
leaq -PTREGS_SIZE(%rax), %rsp
UNWIND_HINT_REGS
call do_exit
Does unspeakable things to the stack, which objtool currently fails to
detect due to a limitation in instruction decoding. This will be
rectified after which the above will result in:
arch/x86/entry/entry_64.o: warning: objtool: .text+0xab: unsupported stack register modification
Allow the UNWIND_HINT on the next instruction to suppress this, it
will overwrite the state anyway.
Suggested-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173626.918498579@infradead.org
---
tools/objtool/check.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 068cdb4..12b8f0f 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1959,8 +1959,9 @@ static void restore_reg(struct cfi_state *cfi, unsigned char reg)
* 41 5d pop %r13
* c3 retq
*/
-static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
- struct stack_op *op)
+static int update_cfi_state(struct instruction *insn,
+ struct instruction *next_insn,
+ struct cfi_state *cfi, struct stack_op *op)
{
struct cfi_reg *cfa = &cfi->cfa;
struct cfi_reg *regs = cfi->regs;
@@ -2161,7 +2162,7 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
break;
}
- if (op->dest.reg == cfi->cfa.base) {
+ if (op->dest.reg == cfi->cfa.base && !(next_insn && next_insn->hint)) {
WARN_FUNC("unsupported stack register modification",
insn->sec, insn->offset);
return -1;
@@ -2433,13 +2434,15 @@ static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn
return 0;
}
-static int handle_insn_ops(struct instruction *insn, struct insn_state *state)
+static int handle_insn_ops(struct instruction *insn,
+ struct instruction *next_insn,
+ struct insn_state *state)
{
struct stack_op *op;
list_for_each_entry(op, &insn->stack_ops, list) {
- if (update_cfi_state(insn, &state->cfi, op))
+ if (update_cfi_state(insn, next_insn, &state->cfi, op))
return 1;
if (op->dest.type == OP_DEST_PUSHF) {
@@ -2719,7 +2722,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
return 0;
}
- if (handle_insn_ops(insn, &state))
+ if (handle_insn_ops(insn, next_insn, &state))
return 1;
switch (insn->type) {
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool: Allow UNWIND_HINT to suppress dodgy stack modifications
2021-02-11 17:30 ` [RFC][PATCH v2 1/7] objtool: Allow UNWIND_HINT to suppress dodgy stack modifications Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
@ 2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-06 11:48 UTC (permalink / raw)
To: linux-tip-commits
Cc: Josh Poimboeuf, Peter Zijlstra (Intel),
Ingo Molnar, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: d54dba41999498b38a40940e1123019d50b26496
Gitweb: https://git.kernel.org/tip/d54dba41999498b38a40940e1123019d50b26496
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Thu, 11 Feb 2021 13:03:28 +01:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 06 Mar 2021 12:44:22 +01:00
objtool: Allow UNWIND_HINT to suppress dodgy stack modifications
rewind_stack_do_exit()
UNWIND_HINT_FUNC
/* Prevent any naive code from trying to unwind to our caller. */
xorl %ebp, %ebp
movq PER_CPU_VAR(cpu_current_top_of_stack), %rax
leaq -PTREGS_SIZE(%rax), %rsp
UNWIND_HINT_REGS
call do_exit
Does unspeakable things to the stack, which objtool currently fails to
detect due to a limitation in instruction decoding. This will be
rectified after which the above will result in:
arch/x86/entry/entry_64.o: warning: objtool: .text+0xab: unsupported stack register modification
Allow the UNWIND_HINT on the next instruction to suppress this, it
will overwrite the state anyway.
Suggested-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173626.918498579@infradead.org
---
tools/objtool/check.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 068cdb4..12b8f0f 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1959,8 +1959,9 @@ static void restore_reg(struct cfi_state *cfi, unsigned char reg)
* 41 5d pop %r13
* c3 retq
*/
-static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
- struct stack_op *op)
+static int update_cfi_state(struct instruction *insn,
+ struct instruction *next_insn,
+ struct cfi_state *cfi, struct stack_op *op)
{
struct cfi_reg *cfa = &cfi->cfa;
struct cfi_reg *regs = cfi->regs;
@@ -2161,7 +2162,7 @@ static int update_cfi_state(struct instruction *insn, struct cfi_state *cfi,
break;
}
- if (op->dest.reg == cfi->cfa.base) {
+ if (op->dest.reg == cfi->cfa.base && !(next_insn && next_insn->hint)) {
WARN_FUNC("unsupported stack register modification",
insn->sec, insn->offset);
return -1;
@@ -2433,13 +2434,15 @@ static int propagate_alt_cfi(struct objtool_file *file, struct instruction *insn
return 0;
}
-static int handle_insn_ops(struct instruction *insn, struct insn_state *state)
+static int handle_insn_ops(struct instruction *insn,
+ struct instruction *next_insn,
+ struct insn_state *state)
{
struct stack_op *op;
list_for_each_entry(op, &insn->stack_ops, list) {
- if (update_cfi_state(insn, &state->cfi, op))
+ if (update_cfi_state(insn, next_insn, &state->cfi, op))
return 1;
if (op->dest.type == OP_DEST_PUSHF) {
@@ -2719,7 +2722,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
return 0;
}
- if (handle_insn_ops(insn, &state))
+ if (handle_insn_ops(insn, next_insn, &state))
return 1;
switch (insn->type) {
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [RFC][PATCH v2 2/7] objtool,x86: Renumber CFI_reg
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 1/7] objtool: Allow UNWIND_HINT to suppress dodgy stack modifications Peter Zijlstra
@ 2021-02-11 17:30 ` Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 3/7] objtool,x86: Rewrite LEA decode Peter Zijlstra
` (7 subsequent siblings)
9 siblings, 2 replies; 25+ messages in thread
From: Peter Zijlstra @ 2021-02-11 17:30 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel, peterz
Make them match the instruction encoding numbering.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/arch/x86/include/arch/cfi_regs.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/tools/objtool/arch/x86/include/arch/cfi_regs.h
+++ b/tools/objtool/arch/x86/include/arch/cfi_regs.h
@@ -4,13 +4,13 @@
#define _OBJTOOL_CFI_REGS_H
#define CFI_AX 0
-#define CFI_DX 1
-#define CFI_CX 2
+#define CFI_CX 1
+#define CFI_DX 2
#define CFI_BX 3
-#define CFI_SI 4
-#define CFI_DI 5
-#define CFI_BP 6
-#define CFI_SP 7
+#define CFI_SP 4
+#define CFI_BP 5
+#define CFI_SI 6
+#define CFI_DI 7
#define CFI_R8 8
#define CFI_R9 9
#define CFI_R10 10
^ permalink raw reply [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Renumber CFI_reg
2021-02-11 17:30 ` [RFC][PATCH v2 2/7] objtool,x86: Renumber CFI_reg Peter Zijlstra
@ 2021-03-03 8:45 ` tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-03 8:45 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 5e506daa2d148f735f90b2018ca6ef6e52144fad
Gitweb: https://git.kernel.org/tip/5e506daa2d148f735f90b2018ca6ef6e52144fad
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 09 Feb 2021 20:18:21 +01:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 03 Mar 2021 09:38:29 +01:00
objtool,x86: Renumber CFI_reg
Make them match the instruction encoding numbering.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.033720313@infradead.org
---
tools/objtool/arch/x86/include/arch/cfi_regs.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/objtool/arch/x86/include/arch/cfi_regs.h b/tools/objtool/arch/x86/include/arch/cfi_regs.h
index 79bc517..0579d22 100644
--- a/tools/objtool/arch/x86/include/arch/cfi_regs.h
+++ b/tools/objtool/arch/x86/include/arch/cfi_regs.h
@@ -4,13 +4,13 @@
#define _OBJTOOL_CFI_REGS_H
#define CFI_AX 0
-#define CFI_DX 1
-#define CFI_CX 2
+#define CFI_CX 1
+#define CFI_DX 2
#define CFI_BX 3
-#define CFI_SI 4
-#define CFI_DI 5
-#define CFI_BP 6
-#define CFI_SP 7
+#define CFI_SP 4
+#define CFI_BP 5
+#define CFI_SI 6
+#define CFI_DI 7
#define CFI_R8 8
#define CFI_R9 9
#define CFI_R10 10
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Renumber CFI_reg
2021-02-11 17:30 ` [RFC][PATCH v2 2/7] objtool,x86: Renumber CFI_reg Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
@ 2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-06 11:48 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Ingo Molnar, Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: d473b18b2ef62563fb874f9cae6e123f99129e3f
Gitweb: https://git.kernel.org/tip/d473b18b2ef62563fb874f9cae6e123f99129e3f
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 09 Feb 2021 20:18:21 +01:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 06 Mar 2021 12:44:22 +01:00
objtool,x86: Renumber CFI_reg
Make them match the instruction encoding numbering.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.033720313@infradead.org
---
tools/objtool/arch/x86/include/arch/cfi_regs.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/objtool/arch/x86/include/arch/cfi_regs.h b/tools/objtool/arch/x86/include/arch/cfi_regs.h
index 79bc517..0579d22 100644
--- a/tools/objtool/arch/x86/include/arch/cfi_regs.h
+++ b/tools/objtool/arch/x86/include/arch/cfi_regs.h
@@ -4,13 +4,13 @@
#define _OBJTOOL_CFI_REGS_H
#define CFI_AX 0
-#define CFI_DX 1
-#define CFI_CX 2
+#define CFI_CX 1
+#define CFI_DX 2
#define CFI_BX 3
-#define CFI_SI 4
-#define CFI_DI 5
-#define CFI_BP 6
-#define CFI_SP 7
+#define CFI_SP 4
+#define CFI_BP 5
+#define CFI_SI 6
+#define CFI_DI 7
#define CFI_R8 8
#define CFI_R9 9
#define CFI_R10 10
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [RFC][PATCH v2 3/7] objtool,x86: Rewrite LEA decode
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 1/7] objtool: Allow UNWIND_HINT to suppress dodgy stack modifications Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 2/7] objtool,x86: Renumber CFI_reg Peter Zijlstra
@ 2021-02-11 17:30 ` Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 4/7] objtool,x86: Rewrite LEAVE Peter Zijlstra
` (6 subsequent siblings)
9 siblings, 2 replies; 25+ messages in thread
From: Peter Zijlstra @ 2021-02-11 17:30 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel, peterz
Current LEA decoding is a bunch of special cases, properly decode the
instruction, with exception of full SIB and RIP-relative modes.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/arch/x86/decode.c | 83 +++++++++++-----------------------------
1 file changed, 24 insertions(+), 59 deletions(-)
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -91,9 +91,10 @@ int arch_decode_instruction(const struct
{
struct insn insn;
int x86_64, sign;
- unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0,
- rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0,
- modrm_reg = 0, sib = 0;
+ unsigned char op1, op2,
+ rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
+ modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
+ sib = 0;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -328,68 +329,32 @@ int arch_decode_instruction(const struct
break;
case 0x8d:
- if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
-
- ADD_OP(op) {
- if (!insn.displacement.value) {
- /* lea (%rsp), reg */
- op->src.type = OP_SRC_REG;
- } else {
- /* lea disp(%rsp), reg */
- op->src.type = OP_SRC_ADD;
- op->src.offset = insn.displacement.value;
- }
- op->src.reg = CFI_SP;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
- }
-
- } else if (rex == 0x48 && modrm == 0x65) {
-
- /* lea disp(%rbp), %rsp */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_BP;
- op->src.offset = insn.displacement.value;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
- }
-
- } else if (rex == 0x49 && modrm == 0x62 &&
- insn.displacement.value == -8) {
+ /* skip non 64bit ops */
+ if (!rex_w)
+ break;
- /*
- * lea -0x8(%r10), %rsp
- *
- * Restoring rsp back to its original value after a
- * stack realignment.
- */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_R10;
- op->src.offset = -8;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
- }
+ /* skip nontrivial SIB */
+ if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ break;
- } else if (rex == 0x49 && modrm == 0x65 &&
- insn.displacement.value == -16) {
+ /* skip RIP relative displacement */
+ if (modrm_rm == 5 && modrm_mod == 0)
+ break;
- /*
- * lea -0x10(%r13), %rsp
- *
- * Restoring rsp back to its original value after a
- * stack realignment.
- */
- ADD_OP(op) {
+ /* lea disp(%src), %dst */
+ ADD_OP(op) {
+ op->src.offset = insn.displacement.value;
+ if (!op->src.offset) {
+ /* lea (%src), %dst */
+ op->src.type = OP_SRC_REG;
+ } else {
+ /* lea disp(%src), %dst */
op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_R13;
- op->src.offset = -16;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
}
+ op->src.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
}
-
break;
case 0x8f:
^ permalink raw reply [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Rewrite LEA decode
2021-02-11 17:30 ` [RFC][PATCH v2 3/7] objtool,x86: Rewrite LEA decode Peter Zijlstra
@ 2021-03-03 8:45 ` tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-03 8:45 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 7ee93978f459ace4e0fe30af582d343d5fb6421a
Gitweb: https://git.kernel.org/tip/7ee93978f459ace4e0fe30af582d343d5fb6421a
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 09 Feb 2021 21:29:16 +01:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 03 Mar 2021 09:38:29 +01:00
objtool,x86: Rewrite LEA decode
Current LEA decoding is a bunch of special cases, properly decode the
instruction, with exception of full SIB and RIP-relative modes.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.143250641@infradead.org
---
tools/objtool/arch/x86/decode.c | 86 ++++++++++----------------------
1 file changed, 28 insertions(+), 58 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 549813c..d8f0138 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -91,9 +91,10 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
{
struct insn insn;
int x86_64, sign;
- unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0,
- rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0,
- modrm_reg = 0, sib = 0;
+ unsigned char op1, op2,
+ rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
+ modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
+ sib = 0;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -328,68 +329,37 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
case 0x8d:
- if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
-
- ADD_OP(op) {
- if (!insn.displacement.value) {
- /* lea (%rsp), reg */
- op->src.type = OP_SRC_REG;
- } else {
- /* lea disp(%rsp), reg */
- op->src.type = OP_SRC_ADD;
- op->src.offset = insn.displacement.value;
- }
- op->src.reg = CFI_SP;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
- }
-
- } else if (rex == 0x48 && modrm == 0x65) {
-
- /* lea disp(%rbp), %rsp */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_BP;
- op->src.offset = insn.displacement.value;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
- }
+ if (modrm_mod == 3) {
+ WARN("invalid LEA encoding at %s:0x%lx", sec->name, offset);
+ break;
+ }
- } else if (rex == 0x49 && modrm == 0x62 &&
- insn.displacement.value == -8) {
+ /* skip non 64bit ops */
+ if (!rex_w)
+ break;
- /*
- * lea -0x8(%r10), %rsp
- *
- * Restoring rsp back to its original value after a
- * stack realignment.
- */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_R10;
- op->src.offset = -8;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
- }
+ /* skip nontrivial SIB */
+ if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ break;
- } else if (rex == 0x49 && modrm == 0x65 &&
- insn.displacement.value == -16) {
+ /* skip RIP relative displacement */
+ if (modrm_rm == 5 && modrm_mod == 0)
+ break;
- /*
- * lea -0x10(%r13), %rsp
- *
- * Restoring rsp back to its original value after a
- * stack realignment.
- */
- ADD_OP(op) {
+ /* lea disp(%src), %dst */
+ ADD_OP(op) {
+ op->src.offset = insn.displacement.value;
+ if (!op->src.offset) {
+ /* lea (%src), %dst */
+ op->src.type = OP_SRC_REG;
+ } else {
+ /* lea disp(%src), %dst */
op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_R13;
- op->src.offset = -16;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
}
+ op->src.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
}
-
break;
case 0x8f:
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Rewrite LEA decode
2021-02-11 17:30 ` [RFC][PATCH v2 3/7] objtool,x86: Rewrite LEA decode Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
@ 2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-06 11:48 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Ingo Molnar, Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 2ee0c363492f1acc1082125218e6a80c0d7d502b
Gitweb: https://git.kernel.org/tip/2ee0c363492f1acc1082125218e6a80c0d7d502b
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 09 Feb 2021 21:29:16 +01:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 06 Mar 2021 12:44:23 +01:00
objtool,x86: Rewrite LEA decode
Current LEA decoding is a bunch of special cases, properly decode the
instruction, with exception of full SIB and RIP-relative modes.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.143250641@infradead.org
---
tools/objtool/arch/x86/decode.c | 86 ++++++++++----------------------
1 file changed, 28 insertions(+), 58 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 549813c..d8f0138 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -91,9 +91,10 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
{
struct insn insn;
int x86_64, sign;
- unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0,
- rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0,
- modrm_reg = 0, sib = 0;
+ unsigned char op1, op2,
+ rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
+ modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
+ sib = 0;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -328,68 +329,37 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
case 0x8d:
- if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
-
- ADD_OP(op) {
- if (!insn.displacement.value) {
- /* lea (%rsp), reg */
- op->src.type = OP_SRC_REG;
- } else {
- /* lea disp(%rsp), reg */
- op->src.type = OP_SRC_ADD;
- op->src.offset = insn.displacement.value;
- }
- op->src.reg = CFI_SP;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
- }
-
- } else if (rex == 0x48 && modrm == 0x65) {
-
- /* lea disp(%rbp), %rsp */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_BP;
- op->src.offset = insn.displacement.value;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
- }
+ if (modrm_mod == 3) {
+ WARN("invalid LEA encoding at %s:0x%lx", sec->name, offset);
+ break;
+ }
- } else if (rex == 0x49 && modrm == 0x62 &&
- insn.displacement.value == -8) {
+ /* skip non 64bit ops */
+ if (!rex_w)
+ break;
- /*
- * lea -0x8(%r10), %rsp
- *
- * Restoring rsp back to its original value after a
- * stack realignment.
- */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_R10;
- op->src.offset = -8;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
- }
+ /* skip nontrivial SIB */
+ if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ break;
- } else if (rex == 0x49 && modrm == 0x65 &&
- insn.displacement.value == -16) {
+ /* skip RIP relative displacement */
+ if (modrm_rm == 5 && modrm_mod == 0)
+ break;
- /*
- * lea -0x10(%r13), %rsp
- *
- * Restoring rsp back to its original value after a
- * stack realignment.
- */
- ADD_OP(op) {
+ /* lea disp(%src), %dst */
+ ADD_OP(op) {
+ op->src.offset = insn.displacement.value;
+ if (!op->src.offset) {
+ /* lea (%src), %dst */
+ op->src.type = OP_SRC_REG;
+ } else {
+ /* lea disp(%src), %dst */
op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_R13;
- op->src.offset = -16;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
}
+ op->src.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
}
-
break;
case 0x8f:
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [RFC][PATCH v2 4/7] objtool,x86: Rewrite LEAVE
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
` (2 preceding siblings ...)
2021-02-11 17:30 ` [RFC][PATCH v2 3/7] objtool,x86: Rewrite LEA decode Peter Zijlstra
@ 2021-02-11 17:30 ` Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 5/7] objtool,x86: Simplify register decode Peter Zijlstra
` (5 subsequent siblings)
9 siblings, 2 replies; 25+ messages in thread
From: Peter Zijlstra @ 2021-02-11 17:30 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel, peterz
Since we can now have multiple stack-ops per instruction, we don't
need to special case LEAVE and can simply emit the composite
operations.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/arch/x86/decode.c | 14 +++++++++++---
tools/objtool/check.c | 24 ++----------------------
tools/objtool/include/objtool/arch.h | 1 -
3 files changed, 13 insertions(+), 26 deletions(-)
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -441,9 +441,17 @@ int arch_decode_instruction(const struct
* mov bp, sp
* pop bp
*/
- ADD_OP(op)
- op->dest.type = OP_DEST_LEAVE;
-
+ ADD_OP(op) {
+ op->src.type = OP_SRC_REG;
+ op->src.reg = CFI_BP;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_SP;
+ }
+ ADD_OP(op) {
+ op->src.type = OP_SRC_POP;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_BP;
+ }
break;
case 0xe3:
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1931,7 +1931,7 @@ static int update_cfi_state(struct instr
}
else if (op->src.reg == CFI_BP && op->dest.reg == CFI_SP &&
- cfa->base == CFI_BP) {
+ (cfa->base == CFI_BP || cfa->base == cfi->drap_reg)) {
/*
* mov %rbp, %rsp
@@ -2114,7 +2114,7 @@ static int update_cfi_state(struct instr
cfa->offset = 0;
cfi->drap_offset = -1;
- } else if (regs[op->dest.reg].offset == -cfi->stack_size) {
+ } else if (cfi->stack_size == -regs[op->dest.reg].offset) {
/* pop %reg */
restore_reg(cfi, op->dest.reg);
@@ -2254,26 +2254,6 @@ static int update_cfi_state(struct instr
}
break;
-
- case OP_DEST_LEAVE:
- if ((!cfi->drap && cfa->base != CFI_BP) ||
- (cfi->drap && cfa->base != cfi->drap_reg)) {
- WARN_FUNC("leave instruction with modified stack frame",
- insn->sec, insn->offset);
- return -1;
- }
-
- /* leave (mov %rbp, %rsp; pop %rbp) */
-
- cfi->stack_size = -cfi->regs[CFI_BP].offset - 8;
- restore_reg(cfi, CFI_BP);
-
- if (!cfi->drap) {
- cfa->base = CFI_SP;
- cfa->offset -= 8;
- }
-
- break;
case OP_DEST_MEM:
if (op->src.type != OP_SRC_POP && op->src.type != OP_SRC_POPF) {
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
@@ -35,7 +35,6 @@ enum op_dest_type {
OP_DEST_MEM,
OP_DEST_PUSH,
OP_DEST_PUSHF,
- OP_DEST_LEAVE,
};
struct op_dest {
^ permalink raw reply [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Rewrite LEAVE
2021-02-11 17:30 ` [RFC][PATCH v2 4/7] objtool,x86: Rewrite LEAVE Peter Zijlstra
@ 2021-03-03 8:45 ` tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-03 8:45 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: a91451516348221f2477205eca9e813830e01fa3
Gitweb: https://git.kernel.org/tip/a91451516348221f2477205eca9e813830e01fa3
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 09 Feb 2021 21:41:13 +01:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 03 Mar 2021 09:38:30 +01:00
objtool,x86: Rewrite LEAVE
Since we can now have multiple stack-ops per instruction, we don't
need to special case LEAVE and can simply emit the composite
operations.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.253273977@infradead.org
---
tools/objtool/arch/x86/decode.c | 14 +++++++++++---
tools/objtool/check.c | 24 ++----------------------
tools/objtool/include/objtool/arch.h | 1 -
3 files changed, 13 insertions(+), 26 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index d8f0138..47b9acf 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -446,9 +446,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
* mov bp, sp
* pop bp
*/
- ADD_OP(op)
- op->dest.type = OP_DEST_LEAVE;
-
+ ADD_OP(op) {
+ op->src.type = OP_SRC_REG;
+ op->src.reg = CFI_BP;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_SP;
+ }
+ ADD_OP(op) {
+ op->src.type = OP_SRC_POP;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_BP;
+ }
break;
case 0xe3:
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 12b8f0f..a0f762a 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2020,7 +2020,7 @@ static int update_cfi_state(struct instruction *insn,
}
else if (op->src.reg == CFI_BP && op->dest.reg == CFI_SP &&
- cfa->base == CFI_BP) {
+ (cfa->base == CFI_BP || cfa->base == cfi->drap_reg)) {
/*
* mov %rbp, %rsp
@@ -2217,7 +2217,7 @@ static int update_cfi_state(struct instruction *insn,
cfa->offset = 0;
cfi->drap_offset = -1;
- } else if (regs[op->dest.reg].offset == -cfi->stack_size) {
+ } else if (cfi->stack_size == -regs[op->dest.reg].offset) {
/* pop %reg */
restore_reg(cfi, op->dest.reg);
@@ -2358,26 +2358,6 @@ static int update_cfi_state(struct instruction *insn,
break;
- case OP_DEST_LEAVE:
- if ((!cfi->drap && cfa->base != CFI_BP) ||
- (cfi->drap && cfa->base != cfi->drap_reg)) {
- WARN_FUNC("leave instruction with modified stack frame",
- insn->sec, insn->offset);
- return -1;
- }
-
- /* leave (mov %rbp, %rsp; pop %rbp) */
-
- cfi->stack_size = -cfi->regs[CFI_BP].offset - 8;
- restore_reg(cfi, CFI_BP);
-
- if (!cfi->drap) {
- cfa->base = CFI_SP;
- cfa->offset -= 8;
- }
-
- break;
-
case OP_DEST_MEM:
if (op->src.type != OP_SRC_POP && op->src.type != OP_SRC_POPF) {
WARN_FUNC("unknown stack-related memory operation",
diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
index 6ff0685..ff21f38 100644
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
@@ -35,7 +35,6 @@ enum op_dest_type {
OP_DEST_MEM,
OP_DEST_PUSH,
OP_DEST_PUSHF,
- OP_DEST_LEAVE,
};
struct op_dest {
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Rewrite LEAVE
2021-02-11 17:30 ` [RFC][PATCH v2 4/7] objtool,x86: Rewrite LEAVE Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
@ 2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-06 11:48 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Ingo Molnar, Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: ffc7e74f36a2c7424da262a32a0bbe59669677ef
Gitweb: https://git.kernel.org/tip/ffc7e74f36a2c7424da262a32a0bbe59669677ef
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 09 Feb 2021 21:41:13 +01:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 06 Mar 2021 12:44:23 +01:00
objtool,x86: Rewrite LEAVE
Since we can now have multiple stack-ops per instruction, we don't
need to special case LEAVE and can simply emit the composite
operations.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.253273977@infradead.org
---
tools/objtool/arch/x86/decode.c | 14 +++++++++++---
tools/objtool/check.c | 24 ++----------------------
tools/objtool/include/objtool/arch.h | 1 -
3 files changed, 13 insertions(+), 26 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index d8f0138..47b9acf 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -446,9 +446,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
* mov bp, sp
* pop bp
*/
- ADD_OP(op)
- op->dest.type = OP_DEST_LEAVE;
-
+ ADD_OP(op) {
+ op->src.type = OP_SRC_REG;
+ op->src.reg = CFI_BP;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_SP;
+ }
+ ADD_OP(op) {
+ op->src.type = OP_SRC_POP;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_BP;
+ }
break;
case 0xe3:
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 12b8f0f..a0f762a 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2020,7 +2020,7 @@ static int update_cfi_state(struct instruction *insn,
}
else if (op->src.reg == CFI_BP && op->dest.reg == CFI_SP &&
- cfa->base == CFI_BP) {
+ (cfa->base == CFI_BP || cfa->base == cfi->drap_reg)) {
/*
* mov %rbp, %rsp
@@ -2217,7 +2217,7 @@ static int update_cfi_state(struct instruction *insn,
cfa->offset = 0;
cfi->drap_offset = -1;
- } else if (regs[op->dest.reg].offset == -cfi->stack_size) {
+ } else if (cfi->stack_size == -regs[op->dest.reg].offset) {
/* pop %reg */
restore_reg(cfi, op->dest.reg);
@@ -2358,26 +2358,6 @@ static int update_cfi_state(struct instruction *insn,
break;
- case OP_DEST_LEAVE:
- if ((!cfi->drap && cfa->base != CFI_BP) ||
- (cfi->drap && cfa->base != cfi->drap_reg)) {
- WARN_FUNC("leave instruction with modified stack frame",
- insn->sec, insn->offset);
- return -1;
- }
-
- /* leave (mov %rbp, %rsp; pop %rbp) */
-
- cfi->stack_size = -cfi->regs[CFI_BP].offset - 8;
- restore_reg(cfi, CFI_BP);
-
- if (!cfi->drap) {
- cfa->base = CFI_SP;
- cfa->offset -= 8;
- }
-
- break;
-
case OP_DEST_MEM:
if (op->src.type != OP_SRC_POP && op->src.type != OP_SRC_POPF) {
WARN_FUNC("unknown stack-related memory operation",
diff --git a/tools/objtool/include/objtool/arch.h b/tools/objtool/include/objtool/arch.h
index 6ff0685..ff21f38 100644
--- a/tools/objtool/include/objtool/arch.h
+++ b/tools/objtool/include/objtool/arch.h
@@ -35,7 +35,6 @@ enum op_dest_type {
OP_DEST_MEM,
OP_DEST_PUSH,
OP_DEST_PUSHF,
- OP_DEST_LEAVE,
};
struct op_dest {
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [RFC][PATCH v2 5/7] objtool,x86: Simplify register decode
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
` (3 preceding siblings ...)
2021-02-11 17:30 ` [RFC][PATCH v2 4/7] objtool,x86: Rewrite LEAVE Peter Zijlstra
@ 2021-02-11 17:30 ` Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 6/7] objtool,x86: Support %riz encodings Peter Zijlstra
` (4 subsequent siblings)
9 siblings, 2 replies; 25+ messages in thread
From: Peter Zijlstra @ 2021-02-11 17:30 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel, peterz
Since the CFI_reg number now matches the instruction encoding order do
away with the op_to_cfi_reg[] and use direct assignment.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/arch/x86/decode.c | 79 +++++++++++++++++++---------------------
1 file changed, 39 insertions(+), 40 deletions(-)
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -17,17 +17,6 @@
#include <objtool/arch.h>
#include <objtool/warn.h>
-static unsigned char op_to_cfi_reg[][2] = {
- {CFI_AX, CFI_R8},
- {CFI_CX, CFI_R9},
- {CFI_DX, CFI_R10},
- {CFI_BX, CFI_R11},
- {CFI_SP, CFI_R12},
- {CFI_BP, CFI_R13},
- {CFI_SI, CFI_R14},
- {CFI_DI, CFI_R15},
-};
-
static int is_x86_64(const struct elf *elf)
{
switch (elf->ehdr.e_machine) {
@@ -94,7 +83,7 @@ int arch_decode_instruction(const struct
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
- sib = 0;
+ sib = 0 /* , sib_scale = 0, sib_index = 0, sib_base = 0 */;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -130,23 +119,29 @@ int arch_decode_instruction(const struct
if (insn.modrm.nbytes) {
modrm = insn.modrm.bytes[0];
modrm_mod = X86_MODRM_MOD(modrm);
- modrm_reg = X86_MODRM_REG(modrm);
- modrm_rm = X86_MODRM_RM(modrm);
+ modrm_reg = X86_MODRM_REG(modrm) + 8*rex_r;
+ modrm_rm = X86_MODRM_RM(modrm) + 8*rex_b;
}
- if (insn.sib.nbytes)
+ if (insn.sib.nbytes) {
sib = insn.sib.bytes[0];
+ /*
+ sib_scale = X86_SIB_SCALE(sib);
+ sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
+ sib_base = X86_SIB_BASE(sib) + 8*rex_b;
+ */
+ }
switch (op1) {
case 0x1:
case 0x29:
- if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
+ if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
/* add/sub reg, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_ADD;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG;
op->dest.reg = CFI_SP;
}
@@ -158,7 +153,7 @@ int arch_decode_instruction(const struct
/* push reg */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
+ op->src.reg = (op1 & 0x7) + 8*rex_b;
op->dest.type = OP_DEST_PUSH;
}
@@ -170,7 +165,7 @@ int arch_decode_instruction(const struct
ADD_OP(op) {
op->src.type = OP_SRC_POP;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
+ op->dest.reg = (op1 & 0x7) + 8*rex_b;
}
break;
@@ -223,7 +218,7 @@ int arch_decode_instruction(const struct
break;
case 0x89:
- if (rex_w && !rex_r && modrm_reg == 4) {
+ if (rex_w && modrm_reg == CFI_SP) {
if (modrm_mod == 3) {
/* mov %rsp, reg */
@@ -231,17 +226,17 @@ int arch_decode_instruction(const struct
op->src.type = OP_SRC_REG;
op->src.reg = CFI_SP;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.reg = modrm_rm;
}
break;
} else {
/* skip nontrivial SIB */
- if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
break;
/* skip RIP relative displacement */
- if (modrm_rm == 5 && modrm_mod == 0)
+ if ((modrm_rm & 7) == 5 && modrm_mod == 0)
break;
/* mov %rsp, disp(%reg) */
@@ -249,7 +244,7 @@ int arch_decode_instruction(const struct
op->src.type = OP_SRC_REG;
op->src.reg = CFI_SP;
op->dest.type = OP_DEST_REG_INDIRECT;
- op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.reg = modrm_rm;
op->dest.offset = insn.displacement.value;
}
break;
@@ -258,12 +253,12 @@ int arch_decode_instruction(const struct
break;
}
- if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
+ if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
/* mov reg, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG;
op->dest.reg = CFI_SP;
}
@@ -272,13 +267,12 @@ int arch_decode_instruction(const struct
/* fallthrough */
case 0x88:
- if (!rex_b &&
- (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) {
+ if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov reg, disp(%rbp) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG_INDIRECT;
op->dest.reg = CFI_BP;
op->dest.offset = insn.displacement.value;
@@ -286,12 +280,12 @@ int arch_decode_instruction(const struct
break;
}
- if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {
+ if (rex_w && modrm_rm == CFI_SP && sib == 0x24) {
/* mov reg, disp(%rsp) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG_INDIRECT;
op->dest.reg = CFI_SP;
op->dest.offset = insn.displacement.value;
@@ -302,7 +296,10 @@ int arch_decode_instruction(const struct
break;
case 0x8b:
- if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) {
+ if (!rex_w)
+ break;
+
+ if (modrm_mod == 1 && modrm_rm == CFI_BP) {
/* mov disp(%rbp), reg */
ADD_OP(op) {
@@ -310,11 +307,12 @@ int arch_decode_instruction(const struct
op->src.reg = CFI_BP;
op->src.offset = insn.displacement.value;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
+ break;
+ }
- } else if (rex_w && !rex_b && sib == 0x24 &&
- modrm_mod != 3 && modrm_rm == 4) {
+ if (modrm_mod != 3 && modrm_rm == CFI_SP && sib == 0x24) {
/* mov disp(%rsp), reg */
ADD_OP(op) {
@@ -322,8 +320,9 @@ int arch_decode_instruction(const struct
op->src.reg = CFI_SP;
op->src.offset = insn.displacement.value;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
+ break;
}
break;
@@ -334,11 +333,11 @@ int arch_decode_instruction(const struct
break;
/* skip nontrivial SIB */
- if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
break;
/* skip RIP relative displacement */
- if (modrm_rm == 5 && modrm_mod == 0)
+ if ((modrm_rm & 7) == 5 && modrm_mod == 0)
break;
/* lea disp(%src), %dst */
@@ -351,9 +350,9 @@ int arch_decode_instruction(const struct
/* lea disp(%src), %dst */
op->src.type = OP_SRC_ADD;
}
- op->src.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->src.reg = modrm_rm;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
break;
^ permalink raw reply [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Simplify register decode
2021-02-11 17:30 ` [RFC][PATCH v2 5/7] objtool,x86: Simplify register decode Peter Zijlstra
@ 2021-03-03 8:45 ` tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-03 8:45 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 9d5a2c2caa10fc135d7020e76baa6a17c52e608f
Gitweb: https://git.kernel.org/tip/9d5a2c2caa10fc135d7020e76baa6a17c52e608f
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 09 Feb 2021 19:59:43 +01:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 03 Mar 2021 09:38:30 +01:00
objtool,x86: Simplify register decode
Since the CFI_reg number now matches the instruction encoding order do
away with the op_to_cfi_reg[] and use direct assignment.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.362004522@infradead.org
---
tools/objtool/arch/x86/decode.c | 79 +++++++++++++++-----------------
1 file changed, 39 insertions(+), 40 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 47b9acf..5ce7dc4 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -17,17 +17,6 @@
#include <objtool/arch.h>
#include <objtool/warn.h>
-static unsigned char op_to_cfi_reg[][2] = {
- {CFI_AX, CFI_R8},
- {CFI_CX, CFI_R9},
- {CFI_DX, CFI_R10},
- {CFI_BX, CFI_R11},
- {CFI_SP, CFI_R12},
- {CFI_BP, CFI_R13},
- {CFI_SI, CFI_R14},
- {CFI_DI, CFI_R15},
-};
-
static int is_x86_64(const struct elf *elf)
{
switch (elf->ehdr.e_machine) {
@@ -94,7 +83,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
- sib = 0;
+ sib = 0 /* , sib_scale = 0, sib_index = 0, sib_base = 0 */;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -130,23 +119,29 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
if (insn.modrm.nbytes) {
modrm = insn.modrm.bytes[0];
modrm_mod = X86_MODRM_MOD(modrm);
- modrm_reg = X86_MODRM_REG(modrm);
- modrm_rm = X86_MODRM_RM(modrm);
+ modrm_reg = X86_MODRM_REG(modrm) + 8*rex_r;
+ modrm_rm = X86_MODRM_RM(modrm) + 8*rex_b;
}
- if (insn.sib.nbytes)
+ if (insn.sib.nbytes) {
sib = insn.sib.bytes[0];
+ /*
+ sib_scale = X86_SIB_SCALE(sib);
+ sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
+ sib_base = X86_SIB_BASE(sib) + 8*rex_b;
+ */
+ }
switch (op1) {
case 0x1:
case 0x29:
- if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
+ if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
/* add/sub reg, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_ADD;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG;
op->dest.reg = CFI_SP;
}
@@ -158,7 +153,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
/* push reg */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
+ op->src.reg = (op1 & 0x7) + 8*rex_b;
op->dest.type = OP_DEST_PUSH;
}
@@ -170,7 +165,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
ADD_OP(op) {
op->src.type = OP_SRC_POP;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
+ op->dest.reg = (op1 & 0x7) + 8*rex_b;
}
break;
@@ -223,7 +218,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
case 0x89:
- if (rex_w && !rex_r && modrm_reg == 4) {
+ if (rex_w && modrm_reg == CFI_SP) {
if (modrm_mod == 3) {
/* mov %rsp, reg */
@@ -231,17 +226,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->src.type = OP_SRC_REG;
op->src.reg = CFI_SP;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.reg = modrm_rm;
}
break;
} else {
/* skip nontrivial SIB */
- if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
break;
/* skip RIP relative displacement */
- if (modrm_rm == 5 && modrm_mod == 0)
+ if ((modrm_rm & 7) == 5 && modrm_mod == 0)
break;
/* mov %rsp, disp(%reg) */
@@ -249,7 +244,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->src.type = OP_SRC_REG;
op->src.reg = CFI_SP;
op->dest.type = OP_DEST_REG_INDIRECT;
- op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.reg = modrm_rm;
op->dest.offset = insn.displacement.value;
}
break;
@@ -258,12 +253,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
+ if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
/* mov reg, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG;
op->dest.reg = CFI_SP;
}
@@ -272,13 +267,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
/* fallthrough */
case 0x88:
- if (!rex_b &&
- (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) {
+ if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov reg, disp(%rbp) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG_INDIRECT;
op->dest.reg = CFI_BP;
op->dest.offset = insn.displacement.value;
@@ -286,12 +280,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {
+ if (rex_w && modrm_rm == CFI_SP && sib == 0x24) {
/* mov reg, disp(%rsp) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG_INDIRECT;
op->dest.reg = CFI_SP;
op->dest.offset = insn.displacement.value;
@@ -302,7 +296,10 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
case 0x8b:
- if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) {
+ if (!rex_w)
+ break;
+
+ if (modrm_mod == 1 && modrm_rm == CFI_BP) {
/* mov disp(%rbp), reg */
ADD_OP(op) {
@@ -310,11 +307,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->src.reg = CFI_BP;
op->src.offset = insn.displacement.value;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
+ break;
+ }
- } else if (rex_w && !rex_b && sib == 0x24 &&
- modrm_mod != 3 && modrm_rm == 4) {
+ if (modrm_mod != 3 && modrm_rm == CFI_SP && sib == 0x24) {
/* mov disp(%rsp), reg */
ADD_OP(op) {
@@ -322,8 +320,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->src.reg = CFI_SP;
op->src.offset = insn.displacement.value;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
+ break;
}
break;
@@ -339,11 +338,11 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
/* skip nontrivial SIB */
- if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
break;
/* skip RIP relative displacement */
- if (modrm_rm == 5 && modrm_mod == 0)
+ if ((modrm_rm & 7) == 5 && modrm_mod == 0)
break;
/* lea disp(%src), %dst */
@@ -356,9 +355,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
/* lea disp(%src), %dst */
op->src.type = OP_SRC_ADD;
}
- op->src.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->src.reg = modrm_rm;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
break;
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Simplify register decode
2021-02-11 17:30 ` [RFC][PATCH v2 5/7] objtool,x86: Simplify register decode Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
@ 2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-06 11:48 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Ingo Molnar, Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 16ef7f159c503c7befec7018ee0e82fdc311721e
Gitweb: https://git.kernel.org/tip/16ef7f159c503c7befec7018ee0e82fdc311721e
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Tue, 09 Feb 2021 19:59:43 +01:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 06 Mar 2021 12:44:23 +01:00
objtool,x86: Simplify register decode
Since the CFI_reg number now matches the instruction encoding order do
away with the op_to_cfi_reg[] and use direct assignment.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.362004522@infradead.org
---
tools/objtool/arch/x86/decode.c | 79 +++++++++++++++-----------------
1 file changed, 39 insertions(+), 40 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 47b9acf..5ce7dc4 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -17,17 +17,6 @@
#include <objtool/arch.h>
#include <objtool/warn.h>
-static unsigned char op_to_cfi_reg[][2] = {
- {CFI_AX, CFI_R8},
- {CFI_CX, CFI_R9},
- {CFI_DX, CFI_R10},
- {CFI_BX, CFI_R11},
- {CFI_SP, CFI_R12},
- {CFI_BP, CFI_R13},
- {CFI_SI, CFI_R14},
- {CFI_DI, CFI_R15},
-};
-
static int is_x86_64(const struct elf *elf)
{
switch (elf->ehdr.e_machine) {
@@ -94,7 +83,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
- sib = 0;
+ sib = 0 /* , sib_scale = 0, sib_index = 0, sib_base = 0 */;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -130,23 +119,29 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
if (insn.modrm.nbytes) {
modrm = insn.modrm.bytes[0];
modrm_mod = X86_MODRM_MOD(modrm);
- modrm_reg = X86_MODRM_REG(modrm);
- modrm_rm = X86_MODRM_RM(modrm);
+ modrm_reg = X86_MODRM_REG(modrm) + 8*rex_r;
+ modrm_rm = X86_MODRM_RM(modrm) + 8*rex_b;
}
- if (insn.sib.nbytes)
+ if (insn.sib.nbytes) {
sib = insn.sib.bytes[0];
+ /*
+ sib_scale = X86_SIB_SCALE(sib);
+ sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
+ sib_base = X86_SIB_BASE(sib) + 8*rex_b;
+ */
+ }
switch (op1) {
case 0x1:
case 0x29:
- if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
+ if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
/* add/sub reg, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_ADD;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG;
op->dest.reg = CFI_SP;
}
@@ -158,7 +153,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
/* push reg */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
+ op->src.reg = (op1 & 0x7) + 8*rex_b;
op->dest.type = OP_DEST_PUSH;
}
@@ -170,7 +165,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
ADD_OP(op) {
op->src.type = OP_SRC_POP;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
+ op->dest.reg = (op1 & 0x7) + 8*rex_b;
}
break;
@@ -223,7 +218,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
case 0x89:
- if (rex_w && !rex_r && modrm_reg == 4) {
+ if (rex_w && modrm_reg == CFI_SP) {
if (modrm_mod == 3) {
/* mov %rsp, reg */
@@ -231,17 +226,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->src.type = OP_SRC_REG;
op->src.reg = CFI_SP;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.reg = modrm_rm;
}
break;
} else {
/* skip nontrivial SIB */
- if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
break;
/* skip RIP relative displacement */
- if (modrm_rm == 5 && modrm_mod == 0)
+ if ((modrm_rm & 7) == 5 && modrm_mod == 0)
break;
/* mov %rsp, disp(%reg) */
@@ -249,7 +244,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->src.type = OP_SRC_REG;
op->src.reg = CFI_SP;
op->dest.type = OP_DEST_REG_INDIRECT;
- op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->dest.reg = modrm_rm;
op->dest.offset = insn.displacement.value;
}
break;
@@ -258,12 +253,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
+ if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
/* mov reg, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG;
op->dest.reg = CFI_SP;
}
@@ -272,13 +267,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
/* fallthrough */
case 0x88:
- if (!rex_b &&
- (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) {
+ if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov reg, disp(%rbp) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG_INDIRECT;
op->dest.reg = CFI_BP;
op->dest.offset = insn.displacement.value;
@@ -286,12 +280,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {
+ if (rex_w && modrm_rm == CFI_SP && sib == 0x24) {
/* mov reg, disp(%rsp) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
- op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->src.reg = modrm_reg;
op->dest.type = OP_DEST_REG_INDIRECT;
op->dest.reg = CFI_SP;
op->dest.offset = insn.displacement.value;
@@ -302,7 +296,10 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
case 0x8b:
- if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) {
+ if (!rex_w)
+ break;
+
+ if (modrm_mod == 1 && modrm_rm == CFI_BP) {
/* mov disp(%rbp), reg */
ADD_OP(op) {
@@ -310,11 +307,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->src.reg = CFI_BP;
op->src.offset = insn.displacement.value;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
+ break;
+ }
- } else if (rex_w && !rex_b && sib == 0x24 &&
- modrm_mod != 3 && modrm_rm == 4) {
+ if (modrm_mod != 3 && modrm_rm == CFI_SP && sib == 0x24) {
/* mov disp(%rsp), reg */
ADD_OP(op) {
@@ -322,8 +320,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->src.reg = CFI_SP;
op->src.offset = insn.displacement.value;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
+ break;
}
break;
@@ -339,11 +338,11 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
/* skip nontrivial SIB */
- if (modrm_rm == 4 && !(sib == 0x24 && rex_b == rex_x))
+ if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
break;
/* skip RIP relative displacement */
- if (modrm_rm == 5 && modrm_mod == 0)
+ if ((modrm_rm & 7) == 5 && modrm_mod == 0)
break;
/* lea disp(%src), %dst */
@@ -356,9 +355,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
/* lea disp(%src), %dst */
op->src.type = OP_SRC_ADD;
}
- op->src.reg = op_to_cfi_reg[modrm_rm][rex_b];
+ op->src.reg = modrm_rm;
op->dest.type = OP_DEST_REG;
- op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
+ op->dest.reg = modrm_reg;
}
break;
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [RFC][PATCH v2 6/7] objtool,x86: Support %riz encodings
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
` (4 preceding siblings ...)
2021-02-11 17:30 ` [RFC][PATCH v2 5/7] objtool,x86: Simplify register decode Peter Zijlstra
@ 2021-02-11 17:30 ` Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
2021-02-11 17:30 ` [RFC][PATCH v2 7/7] objtool,x86: Rewrite ADD/SUB/AND Peter Zijlstra
` (3 subsequent siblings)
9 siblings, 2 replies; 25+ messages in thread
From: Peter Zijlstra @ 2021-02-11 17:30 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel, peterz
When there's a SIB byte, the register otherwise denoted by r/m will
then be denoted by SIB.base REX.b will now extend this. SIB.index == SP
is magic and notes an index value zero.
This means that there's a bunch of alternative (longer) encodings for
the same thing. Eg. 'ModRM.mod != 3, ModRM.r/m = AX' can be encoded as
'ModRM.mod != 3, ModRM.r/m = SP, SIB.base = AX, SIB.index = SP' which is actually 4
different encodings because the value of SIB.scale is irrelevant,
giving rise to 5 different but equal encodings.
Support these encodings and clean up the SIB handling in general.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/arch/x86/decode.c | 67 ++++++++++++++++++++++++++++------------
1 file changed, 48 insertions(+), 19 deletions(-)
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -72,6 +72,25 @@ unsigned long arch_jump_destination(stru
return -1; \
else for (list_add_tail(&op->list, ops_list); op; op = NULL)
+/*
+ * Helpers to decode ModRM/SIB:
+ *
+ * r/m| AX CX DX BX | SP | BP | SI DI |
+ * | R8 R9 R10 R11 | R12 | R13 | R14 R15 |
+ * Mod+----------------+-----+-----+---------+
+ * 00 | [r/m] |[SIB]|[IP+]| [r/m] |
+ * 01 | [r/m + d8] |[S+d]| [r/m + d8] |
+ * 10 | [r/m + d32] |[S+D]| [r/m + d32] |
+ * 11 | r/ m |
+ *
+ */
+#define is_RIP() ((modrm_rm & 7) == CFI_BP && modrm_mod == 0)
+#define have_SIB() ((modrm_rm & 7) == CFI_SP && modrm_mod != 3)
+
+#define rm_is(reg) (have_SIB() ? \
+ sib_base == (reg) && sib_index == CFI_SP : \
+ modrm_rm == (reg))
+
int arch_decode_instruction(const struct elf *elf, const struct section *sec,
unsigned long offset, unsigned int maxlen,
unsigned int *len, enum insn_type *type,
@@ -83,7 +102,7 @@ int arch_decode_instruction(const struct
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
- sib = 0 /* , sib_scale = 0, sib_index = 0, sib_base = 0 */;
+ sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -125,11 +144,9 @@ int arch_decode_instruction(const struct
if (insn.sib.nbytes) {
sib = insn.sib.bytes[0];
- /*
- sib_scale = X86_SIB_SCALE(sib);
+ /* sib_scale = X86_SIB_SCALE(sib); */
sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
sib_base = X86_SIB_BASE(sib) + 8*rex_b;
- */
}
switch (op1) {
@@ -218,7 +235,10 @@ int arch_decode_instruction(const struct
break;
case 0x89:
- if (rex_w && modrm_reg == CFI_SP) {
+ if (!rex_w)
+ break;
+
+ if (modrm_reg == CFI_SP) {
if (modrm_mod == 3) {
/* mov %rsp, reg */
@@ -231,14 +251,17 @@ int arch_decode_instruction(const struct
break;
} else {
- /* skip nontrivial SIB */
- if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
- break;
-
/* skip RIP relative displacement */
- if ((modrm_rm & 7) == 5 && modrm_mod == 0)
+ if (is_RIP())
break;
+ /* skip nontrivial SIB */
+ if (have_SIB()) {
+ modrm_rm = sib_base;
+ if (sib_index != CFI_SP)
+ break;
+ }
+
/* mov %rsp, disp(%reg) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
@@ -253,7 +276,7 @@ int arch_decode_instruction(const struct
break;
}
- if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
+ if (modrm_mod == 3 && modrm_rm == CFI_SP) {
/* mov reg, %rsp */
ADD_OP(op) {
@@ -267,6 +290,9 @@ int arch_decode_instruction(const struct
/* fallthrough */
case 0x88:
+ if (!rex_w)
+ break;
+
if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov reg, disp(%rbp) */
@@ -280,7 +306,7 @@ int arch_decode_instruction(const struct
break;
}
- if (rex_w && modrm_rm == CFI_SP && sib == 0x24) {
+ if (modrm_mod != 3 && rm_is(CFI_SP)) {
/* mov reg, disp(%rsp) */
ADD_OP(op) {
@@ -299,7 +325,7 @@ int arch_decode_instruction(const struct
if (!rex_w)
break;
- if (modrm_mod == 1 && modrm_rm == CFI_BP) {
+ if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov disp(%rbp), reg */
ADD_OP(op) {
@@ -312,7 +338,7 @@ int arch_decode_instruction(const struct
break;
}
- if (modrm_mod != 3 && modrm_rm == CFI_SP && sib == 0x24) {
+ if (modrm_mod != 3 && rm_is(CFI_SP)) {
/* mov disp(%rsp), reg */
ADD_OP(op) {
@@ -332,14 +358,17 @@ int arch_decode_instruction(const struct
if (!rex_w)
break;
- /* skip nontrivial SIB */
- if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
- break;
-
/* skip RIP relative displacement */
- if ((modrm_rm & 7) == 5 && modrm_mod == 0)
+ if (is_RIP())
break;
+ /* skip nontrivial SIB */
+ if (have_SIB()) {
+ modrm_rm = sib_base;
+ if (sib_index != CFI_SP)
+ break;
+ }
+
/* lea disp(%src), %dst */
ADD_OP(op) {
op->src.offset = insn.displacement.value;
^ permalink raw reply [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Support %riz encodings
2021-02-11 17:30 ` [RFC][PATCH v2 6/7] objtool,x86: Support %riz encodings Peter Zijlstra
@ 2021-03-03 8:45 ` tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-03 8:45 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 0a8bef63e5bf4496251f7bac4ddadb5f5f489932
Gitweb: https://git.kernel.org/tip/0a8bef63e5bf4496251f7bac4ddadb5f5f489932
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Wed, 10 Feb 2021 11:47:35 +01:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 03 Mar 2021 09:38:30 +01:00
objtool,x86: Support %riz encodings
When there's a SIB byte, the register otherwise denoted by r/m will
then be denoted by SIB.base REX.b will now extend this. SIB.index == SP
is magic and notes an index value zero.
This means that there's a bunch of alternative (longer) encodings for
the same thing. Eg. 'ModRM.mod != 3, ModRM.r/m = AX' can be encoded as
'ModRM.mod != 3, ModRM.r/m = SP, SIB.base = AX, SIB.index = SP' which is actually 4
different encodings because the value of SIB.scale is irrelevant,
giving rise to 5 different but equal encodings.
Support these encodings and clean up the SIB handling in general.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.472967498@infradead.org
---
tools/objtool/arch/x86/decode.c | 67 ++++++++++++++++++++++----------
1 file changed, 48 insertions(+), 19 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 5ce7dc4..78ae5be 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -72,6 +72,25 @@ unsigned long arch_jump_destination(struct instruction *insn)
return -1; \
else for (list_add_tail(&op->list, ops_list); op; op = NULL)
+/*
+ * Helpers to decode ModRM/SIB:
+ *
+ * r/m| AX CX DX BX | SP | BP | SI DI |
+ * | R8 R9 R10 R11 | R12 | R13 | R14 R15 |
+ * Mod+----------------+-----+-----+---------+
+ * 00 | [r/m] |[SIB]|[IP+]| [r/m] |
+ * 01 | [r/m + d8] |[S+d]| [r/m + d8] |
+ * 10 | [r/m + d32] |[S+D]| [r/m + d32] |
+ * 11 | r/ m |
+ *
+ */
+#define is_RIP() ((modrm_rm & 7) == CFI_BP && modrm_mod == 0)
+#define have_SIB() ((modrm_rm & 7) == CFI_SP && modrm_mod != 3)
+
+#define rm_is(reg) (have_SIB() ? \
+ sib_base == (reg) && sib_index == CFI_SP : \
+ modrm_rm == (reg))
+
int arch_decode_instruction(const struct elf *elf, const struct section *sec,
unsigned long offset, unsigned int maxlen,
unsigned int *len, enum insn_type *type,
@@ -83,7 +102,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
- sib = 0 /* , sib_scale = 0, sib_index = 0, sib_base = 0 */;
+ sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -125,11 +144,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
if (insn.sib.nbytes) {
sib = insn.sib.bytes[0];
- /*
- sib_scale = X86_SIB_SCALE(sib);
+ /* sib_scale = X86_SIB_SCALE(sib); */
sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
sib_base = X86_SIB_BASE(sib) + 8*rex_b;
- */
}
switch (op1) {
@@ -218,7 +235,10 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
case 0x89:
- if (rex_w && modrm_reg == CFI_SP) {
+ if (!rex_w)
+ break;
+
+ if (modrm_reg == CFI_SP) {
if (modrm_mod == 3) {
/* mov %rsp, reg */
@@ -231,14 +251,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
} else {
- /* skip nontrivial SIB */
- if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
- break;
-
/* skip RIP relative displacement */
- if ((modrm_rm & 7) == 5 && modrm_mod == 0)
+ if (is_RIP())
break;
+ /* skip nontrivial SIB */
+ if (have_SIB()) {
+ modrm_rm = sib_base;
+ if (sib_index != CFI_SP)
+ break;
+ }
+
/* mov %rsp, disp(%reg) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
@@ -253,7 +276,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
+ if (modrm_mod == 3 && modrm_rm == CFI_SP) {
/* mov reg, %rsp */
ADD_OP(op) {
@@ -267,6 +290,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
/* fallthrough */
case 0x88:
+ if (!rex_w)
+ break;
+
if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov reg, disp(%rbp) */
@@ -280,7 +306,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (rex_w && modrm_rm == CFI_SP && sib == 0x24) {
+ if (modrm_mod != 3 && rm_is(CFI_SP)) {
/* mov reg, disp(%rsp) */
ADD_OP(op) {
@@ -299,7 +325,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
if (!rex_w)
break;
- if (modrm_mod == 1 && modrm_rm == CFI_BP) {
+ if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov disp(%rbp), reg */
ADD_OP(op) {
@@ -312,7 +338,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (modrm_mod != 3 && modrm_rm == CFI_SP && sib == 0x24) {
+ if (modrm_mod != 3 && rm_is(CFI_SP)) {
/* mov disp(%rsp), reg */
ADD_OP(op) {
@@ -337,14 +363,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
if (!rex_w)
break;
- /* skip nontrivial SIB */
- if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
- break;
-
/* skip RIP relative displacement */
- if ((modrm_rm & 7) == 5 && modrm_mod == 0)
+ if (is_RIP())
break;
+ /* skip nontrivial SIB */
+ if (have_SIB()) {
+ modrm_rm = sib_base;
+ if (sib_index != CFI_SP)
+ break;
+ }
+
/* lea disp(%src), %dst */
ADD_OP(op) {
op->src.offset = insn.displacement.value;
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Support %riz encodings
2021-02-11 17:30 ` [RFC][PATCH v2 6/7] objtool,x86: Support %riz encodings Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
@ 2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-06 11:48 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Ingo Molnar, Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 78df6245c3c82484200b9f8e306dc86fb19e9c02
Gitweb: https://git.kernel.org/tip/78df6245c3c82484200b9f8e306dc86fb19e9c02
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Wed, 10 Feb 2021 11:47:35 +01:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 06 Mar 2021 12:44:23 +01:00
objtool,x86: Support %riz encodings
When there's a SIB byte, the register otherwise denoted by r/m will
then be denoted by SIB.base REX.b will now extend this. SIB.index == SP
is magic and notes an index value zero.
This means that there's a bunch of alternative (longer) encodings for
the same thing. Eg. 'ModRM.mod != 3, ModRM.r/m = AX' can be encoded as
'ModRM.mod != 3, ModRM.r/m = SP, SIB.base = AX, SIB.index = SP' which is actually 4
different encodings because the value of SIB.scale is irrelevant,
giving rise to 5 different but equal encodings.
Support these encodings and clean up the SIB handling in general.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.472967498@infradead.org
---
tools/objtool/arch/x86/decode.c | 67 ++++++++++++++++++++++----------
1 file changed, 48 insertions(+), 19 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 5ce7dc4..78ae5be 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -72,6 +72,25 @@ unsigned long arch_jump_destination(struct instruction *insn)
return -1; \
else for (list_add_tail(&op->list, ops_list); op; op = NULL)
+/*
+ * Helpers to decode ModRM/SIB:
+ *
+ * r/m| AX CX DX BX | SP | BP | SI DI |
+ * | R8 R9 R10 R11 | R12 | R13 | R14 R15 |
+ * Mod+----------------+-----+-----+---------+
+ * 00 | [r/m] |[SIB]|[IP+]| [r/m] |
+ * 01 | [r/m + d8] |[S+d]| [r/m + d8] |
+ * 10 | [r/m + d32] |[S+D]| [r/m + d32] |
+ * 11 | r/ m |
+ *
+ */
+#define is_RIP() ((modrm_rm & 7) == CFI_BP && modrm_mod == 0)
+#define have_SIB() ((modrm_rm & 7) == CFI_SP && modrm_mod != 3)
+
+#define rm_is(reg) (have_SIB() ? \
+ sib_base == (reg) && sib_index == CFI_SP : \
+ modrm_rm == (reg))
+
int arch_decode_instruction(const struct elf *elf, const struct section *sec,
unsigned long offset, unsigned int maxlen,
unsigned int *len, enum insn_type *type,
@@ -83,7 +102,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
- sib = 0 /* , sib_scale = 0, sib_index = 0, sib_base = 0 */;
+ sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0;
struct stack_op *op = NULL;
struct symbol *sym;
@@ -125,11 +144,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
if (insn.sib.nbytes) {
sib = insn.sib.bytes[0];
- /*
- sib_scale = X86_SIB_SCALE(sib);
+ /* sib_scale = X86_SIB_SCALE(sib); */
sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
sib_base = X86_SIB_BASE(sib) + 8*rex_b;
- */
}
switch (op1) {
@@ -218,7 +235,10 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
case 0x89:
- if (rex_w && modrm_reg == CFI_SP) {
+ if (!rex_w)
+ break;
+
+ if (modrm_reg == CFI_SP) {
if (modrm_mod == 3) {
/* mov %rsp, reg */
@@ -231,14 +251,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
} else {
- /* skip nontrivial SIB */
- if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
- break;
-
/* skip RIP relative displacement */
- if ((modrm_rm & 7) == 5 && modrm_mod == 0)
+ if (is_RIP())
break;
+ /* skip nontrivial SIB */
+ if (have_SIB()) {
+ modrm_rm = sib_base;
+ if (sib_index != CFI_SP)
+ break;
+ }
+
/* mov %rsp, disp(%reg) */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
@@ -253,7 +276,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
+ if (modrm_mod == 3 && modrm_rm == CFI_SP) {
/* mov reg, %rsp */
ADD_OP(op) {
@@ -267,6 +290,9 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
/* fallthrough */
case 0x88:
+ if (!rex_w)
+ break;
+
if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov reg, disp(%rbp) */
@@ -280,7 +306,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (rex_w && modrm_rm == CFI_SP && sib == 0x24) {
+ if (modrm_mod != 3 && rm_is(CFI_SP)) {
/* mov reg, disp(%rsp) */
ADD_OP(op) {
@@ -299,7 +325,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
if (!rex_w)
break;
- if (modrm_mod == 1 && modrm_rm == CFI_BP) {
+ if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
/* mov disp(%rbp), reg */
ADD_OP(op) {
@@ -312,7 +338,7 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
break;
}
- if (modrm_mod != 3 && modrm_rm == CFI_SP && sib == 0x24) {
+ if (modrm_mod != 3 && rm_is(CFI_SP)) {
/* mov disp(%rsp), reg */
ADD_OP(op) {
@@ -337,14 +363,17 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
if (!rex_w)
break;
- /* skip nontrivial SIB */
- if ((modrm_rm & 7) == 4 && !(sib == 0x24 && rex_b == rex_x))
- break;
-
/* skip RIP relative displacement */
- if ((modrm_rm & 7) == 5 && modrm_mod == 0)
+ if (is_RIP())
break;
+ /* skip nontrivial SIB */
+ if (have_SIB()) {
+ modrm_rm = sib_base;
+ if (sib_index != CFI_SP)
+ break;
+ }
+
/* lea disp(%src), %dst */
ADD_OP(op) {
op->src.offset = insn.displacement.value;
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [RFC][PATCH v2 7/7] objtool,x86: Rewrite ADD/SUB/AND
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
` (5 preceding siblings ...)
2021-02-11 17:30 ` [RFC][PATCH v2 6/7] objtool,x86: Support %riz encodings Peter Zijlstra
@ 2021-02-11 17:30 ` Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
2021-02-11 18:30 ` [RFC][PATCH v2 0/7] objtool x86 decoder fixes Nick Desaulniers
` (2 subsequent siblings)
9 siblings, 2 replies; 25+ messages in thread
From: Peter Zijlstra @ 2021-02-11 17:30 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel, peterz
Support sign extending and imm8 forms.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/arch/x86/decode.c | 70 +++++++++++++++++++++++++++++-----------
1 file changed, 51 insertions(+), 19 deletions(-)
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -98,13 +98,14 @@ int arch_decode_instruction(const struct
struct list_head *ops_list)
{
struct insn insn;
- int x86_64, sign;
+ int x86_64;
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0;
struct stack_op *op = NULL;
struct symbol *sym;
+ u64 imm;
x86_64 = is_x86_64(elf);
if (x86_64 == -1)
@@ -200,12 +201,54 @@ int arch_decode_instruction(const struct
*type = INSN_JUMP_CONDITIONAL;
break;
- case 0x81:
- case 0x83:
- if (rex != 0x48)
+ case 0x80 ... 0x83:
+ /*
+ * 1000 00sw : mod OP r/m : immediate
+ *
+ * s - sign extend immediate
+ * w - imm8 / imm32
+ *
+ * OP: 000 ADD 100 AND
+ * 001 OR 101 SUB
+ * 010 ADC 110 XOR
+ * 011 SBB 111 CMP
+ */
+
+ /* 64bit only */
+ if (!rex_w)
+ break;
+
+ /* %rsp target only */
+ if (!(modrm_mod == 3 && modrm_rm == CFI_SP))
break;
- if (modrm == 0xe4) {
+ imm = insn.immediate.value;
+ if (op1 & 2) { /* sign extend */
+ if (op1 & 1) { /* imm32 */
+ imm <<= 32;
+ imm = (s64)imm >> 32;
+ } else { /* imm8 */
+ imm <<= 56;
+ imm = (s64)imm >> 56;
+ }
+ }
+
+ switch (modrm_reg & 7) {
+ case 5:
+ imm = -imm;
+ /* fallthrough */
+ case 0:
+ /* add/sub imm, %rsp */
+ ADD_OP(op) {
+ op->src.type = OP_SRC_ADD;
+ op->src.reg = CFI_SP;
+ op->src.offset = imm;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_SP;
+ }
+ break;
+
+ case 4:
/* and imm, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_AND;
@@ -215,23 +258,12 @@ int arch_decode_instruction(const struct
op->dest.reg = CFI_SP;
}
break;
- }
- if (modrm == 0xc4)
- sign = 1;
- else if (modrm == 0xec)
- sign = -1;
- else
+ default:
+ /* WARN ? */
break;
-
- /* add/sub imm, %rsp */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_SP;
- op->src.offset = insn.immediate.value * sign;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
}
+
break;
case 0x89:
^ permalink raw reply [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Rewrite ADD/SUB/AND
2021-02-11 17:30 ` [RFC][PATCH v2 7/7] objtool,x86: Rewrite ADD/SUB/AND Peter Zijlstra
@ 2021-03-03 8:45 ` tip-bot2 for Peter Zijlstra
2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-03 8:45 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: e1bba6c8930b56c4afe88aa875f3d20d1cef4fe1
Gitweb: https://git.kernel.org/tip/e1bba6c8930b56c4afe88aa875f3d20d1cef4fe1
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Wed, 10 Feb 2021 14:11:30 +01:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 03 Mar 2021 09:38:31 +01:00
objtool,x86: Rewrite ADD/SUB/AND
Support sign extending and imm8 forms.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.588366777@infradead.org
---
tools/objtool/arch/x86/decode.c | 70 +++++++++++++++++++++++---------
1 file changed, 51 insertions(+), 19 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 78ae5be..b42e5ec 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -98,13 +98,14 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
struct list_head *ops_list)
{
struct insn insn;
- int x86_64, sign;
+ int x86_64;
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0;
struct stack_op *op = NULL;
struct symbol *sym;
+ u64 imm;
x86_64 = is_x86_64(elf);
if (x86_64 == -1)
@@ -200,12 +201,54 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
*type = INSN_JUMP_CONDITIONAL;
break;
- case 0x81:
- case 0x83:
- if (rex != 0x48)
+ case 0x80 ... 0x83:
+ /*
+ * 1000 00sw : mod OP r/m : immediate
+ *
+ * s - sign extend immediate
+ * w - imm8 / imm32
+ *
+ * OP: 000 ADD 100 AND
+ * 001 OR 101 SUB
+ * 010 ADC 110 XOR
+ * 011 SBB 111 CMP
+ */
+
+ /* 64bit only */
+ if (!rex_w)
break;
- if (modrm == 0xe4) {
+ /* %rsp target only */
+ if (!(modrm_mod == 3 && modrm_rm == CFI_SP))
+ break;
+
+ imm = insn.immediate.value;
+ if (op1 & 2) { /* sign extend */
+ if (op1 & 1) { /* imm32 */
+ imm <<= 32;
+ imm = (s64)imm >> 32;
+ } else { /* imm8 */
+ imm <<= 56;
+ imm = (s64)imm >> 56;
+ }
+ }
+
+ switch (modrm_reg & 7) {
+ case 5:
+ imm = -imm;
+ /* fallthrough */
+ case 0:
+ /* add/sub imm, %rsp */
+ ADD_OP(op) {
+ op->src.type = OP_SRC_ADD;
+ op->src.reg = CFI_SP;
+ op->src.offset = imm;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_SP;
+ }
+ break;
+
+ case 4:
/* and imm, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_AND;
@@ -215,23 +258,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->dest.reg = CFI_SP;
}
break;
- }
- if (modrm == 0xc4)
- sign = 1;
- else if (modrm == 0xec)
- sign = -1;
- else
+ default:
+ /* WARN ? */
break;
-
- /* add/sub imm, %rsp */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_SP;
- op->src.offset = insn.immediate.value * sign;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
}
+
break;
case 0x89:
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [tip: objtool/core] objtool,x86: Rewrite ADD/SUB/AND
2021-02-11 17:30 ` [RFC][PATCH v2 7/7] objtool,x86: Rewrite ADD/SUB/AND Peter Zijlstra
2021-03-03 8:45 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
@ 2021-03-06 11:48 ` tip-bot2 for Peter Zijlstra
1 sibling, 0 replies; 25+ messages in thread
From: tip-bot2 for Peter Zijlstra @ 2021-03-06 11:48 UTC (permalink / raw)
To: linux-tip-commits
Cc: Peter Zijlstra (Intel),
Ingo Molnar, Josh Poimboeuf, Nick Desaulniers, x86, linux-kernel
The following commit has been merged into the objtool/core branch of tip:
Commit-ID: 961d83b9073b1ce5834af50d3c69e5e2461c6fd3
Gitweb: https://git.kernel.org/tip/961d83b9073b1ce5834af50d3c69e5e2461c6fd3
Author: Peter Zijlstra <peterz@infradead.org>
AuthorDate: Wed, 10 Feb 2021 14:11:30 +01:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 06 Mar 2021 12:44:23 +01:00
objtool,x86: Rewrite ADD/SUB/AND
Support sign extending and imm8 forms.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://lkml.kernel.org/r/20210211173627.588366777@infradead.org
---
tools/objtool/arch/x86/decode.c | 70 +++++++++++++++++++++++---------
1 file changed, 51 insertions(+), 19 deletions(-)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 78ae5be..b42e5ec 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -98,13 +98,14 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
struct list_head *ops_list)
{
struct insn insn;
- int x86_64, sign;
+ int x86_64;
unsigned char op1, op2,
rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0,
modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0,
sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0;
struct stack_op *op = NULL;
struct symbol *sym;
+ u64 imm;
x86_64 = is_x86_64(elf);
if (x86_64 == -1)
@@ -200,12 +201,54 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
*type = INSN_JUMP_CONDITIONAL;
break;
- case 0x81:
- case 0x83:
- if (rex != 0x48)
+ case 0x80 ... 0x83:
+ /*
+ * 1000 00sw : mod OP r/m : immediate
+ *
+ * s - sign extend immediate
+ * w - imm8 / imm32
+ *
+ * OP: 000 ADD 100 AND
+ * 001 OR 101 SUB
+ * 010 ADC 110 XOR
+ * 011 SBB 111 CMP
+ */
+
+ /* 64bit only */
+ if (!rex_w)
break;
- if (modrm == 0xe4) {
+ /* %rsp target only */
+ if (!(modrm_mod == 3 && modrm_rm == CFI_SP))
+ break;
+
+ imm = insn.immediate.value;
+ if (op1 & 2) { /* sign extend */
+ if (op1 & 1) { /* imm32 */
+ imm <<= 32;
+ imm = (s64)imm >> 32;
+ } else { /* imm8 */
+ imm <<= 56;
+ imm = (s64)imm >> 56;
+ }
+ }
+
+ switch (modrm_reg & 7) {
+ case 5:
+ imm = -imm;
+ /* fallthrough */
+ case 0:
+ /* add/sub imm, %rsp */
+ ADD_OP(op) {
+ op->src.type = OP_SRC_ADD;
+ op->src.reg = CFI_SP;
+ op->src.offset = imm;
+ op->dest.type = OP_DEST_REG;
+ op->dest.reg = CFI_SP;
+ }
+ break;
+
+ case 4:
/* and imm, %rsp */
ADD_OP(op) {
op->src.type = OP_SRC_AND;
@@ -215,23 +258,12 @@ int arch_decode_instruction(const struct elf *elf, const struct section *sec,
op->dest.reg = CFI_SP;
}
break;
- }
- if (modrm == 0xc4)
- sign = 1;
- else if (modrm == 0xec)
- sign = -1;
- else
+ default:
+ /* WARN ? */
break;
-
- /* add/sub imm, %rsp */
- ADD_OP(op) {
- op->src.type = OP_SRC_ADD;
- op->src.reg = CFI_SP;
- op->src.offset = insn.immediate.value * sign;
- op->dest.type = OP_DEST_REG;
- op->dest.reg = CFI_SP;
}
+
break;
case 0x89:
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [RFC][PATCH v2 0/7] objtool x86 decoder fixes
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
` (6 preceding siblings ...)
2021-02-11 17:30 ` [RFC][PATCH v2 7/7] objtool,x86: Rewrite ADD/SUB/AND Peter Zijlstra
@ 2021-02-11 18:30 ` Nick Desaulniers
2021-02-11 20:17 ` Josh Poimboeuf
2021-02-12 8:53 ` [RFC][PATCH v2 8/7] objtool,x86: More ModRM sugar Peter Zijlstra
9 siblings, 0 replies; 25+ messages in thread
From: Nick Desaulniers @ 2021-02-11 18:30 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Josh Poimboeuf, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
Miroslav Benes, Julien Thierry, Masami Hiramatsu, LKML
On Thu, Feb 11, 2021 at 9:40 AM Peter Zijlstra <peterz@infradead.org> wrote:
>
> Hi,
>
> Since I had to look at instruction decoding for the stack swizzle thing, I
> ended up with a few more changes to the objtool x86 decoder.
>
> These patches are lightly tested (they build defconfig and allmodconfig using
> GCC10), but older versions have seen some robot exposure and other compilers.
Did a quick test of x86_64 defconfig on -next with
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/?h=objtool/core&id=2a512829840eb97a8b52eca7058e56d484468f2d
and ToT LLVM. No new warnings/issues observed during a build.
Tested-by: Nick Desaulniers <ndesaulniers@google.com>
>
> v2:
> - actually Cc'ed LKML :/
>
--
Thanks,
~Nick Desaulniers
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC][PATCH v2 0/7] objtool x86 decoder fixes
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
` (7 preceding siblings ...)
2021-02-11 18:30 ` [RFC][PATCH v2 0/7] objtool x86 decoder fixes Nick Desaulniers
@ 2021-02-11 20:17 ` Josh Poimboeuf
2021-02-12 8:53 ` [RFC][PATCH v2 8/7] objtool,x86: More ModRM sugar Peter Zijlstra
9 siblings, 0 replies; 25+ messages in thread
From: Josh Poimboeuf @ 2021-02-11 20:17 UTC (permalink / raw)
To: Peter Zijlstra
Cc: x86, Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel
On Thu, Feb 11, 2021 at 06:30:44PM +0100, Peter Zijlstra wrote:
> Hi,
>
> Since I had to look at instruction decoding for the stack swizzle thing, I
> ended up with a few more changes to the objtool x86 decoder.
>
> These patches are lightly tested (they build defconfig and allmodconfig using
> GCC10), but older versions have seen some robot exposure and other compilers.
>
> v2:
> - actually Cc'ed LKML :/
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
--
Josh
^ permalink raw reply [flat|nested] 25+ messages in thread
* [RFC][PATCH v2 8/7] objtool,x86: More ModRM sugar
2021-02-11 17:30 [RFC][PATCH v2 0/7] objtool x86 decoder fixes Peter Zijlstra
` (8 preceding siblings ...)
2021-02-11 20:17 ` Josh Poimboeuf
@ 2021-02-12 8:53 ` Peter Zijlstra
9 siblings, 0 replies; 25+ messages in thread
From: Peter Zijlstra @ 2021-02-12 8:53 UTC (permalink / raw)
To: Josh Poimboeuf, x86
Cc: Miroslav Benes, Julien Thierry, Nick Desaulniers,
Masami Hiramatsu, linux-kernel
I promise, I'll stop poking at it more :-)
---
Subject: objtool,x86: More ModRM sugar
From: Peter Zijlstra <peterz@infradead.org>
Date: Fri Feb 12 09:13:00 CET 2021
Better helpers to decode ModRM.
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
tools/objtool/arch/x86/decode.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -82,15 +82,21 @@ unsigned long arch_jump_destination(stru
* 01 | [r/m + d8] |[S+d]| [r/m + d8] |
* 10 | [r/m + d32] |[S+D]| [r/m + d32] |
* 11 | r/ m |
- *
*/
+
+#define mod_is_mem() (modrm_mod != 3)
+#define mod_is_reg() (modrm_mod == 3)
+
#define is_RIP() ((modrm_rm & 7) == CFI_BP && modrm_mod == 0)
-#define have_SIB() ((modrm_rm & 7) == CFI_SP && modrm_mod != 3)
+#define have_SIB() ((modrm_rm & 7) == CFI_SP && mod_is_mem())
#define rm_is(reg) (have_SIB() ? \
sib_base == (reg) && sib_index == CFI_SP : \
modrm_rm == (reg))
+#define rm_is_mem(reg) (mod_is_mem() && !is_RIP() && rm_is(reg))
+#define rm_is_reg(reg) (mod_is_reg() && modrm_rm == (reg))
+
int arch_decode_instruction(const struct elf *elf, const struct section *sec,
unsigned long offset, unsigned int maxlen,
unsigned int *len, enum insn_type *type,
@@ -154,7 +160,7 @@ int arch_decode_instruction(const struct
case 0x1:
case 0x29:
- if (rex_w && modrm_mod == 3 && modrm_rm == CFI_SP) {
+ if (rex_w && rm_is_reg(CFI_SP)) {
/* add/sub reg, %rsp */
ADD_OP(op) {
@@ -219,7 +225,7 @@ int arch_decode_instruction(const struct
break;
/* %rsp target only */
- if (!(modrm_mod == 3 && modrm_rm == CFI_SP))
+ if (!rm_is_reg(CFI_SP))
break;
imm = insn.immediate.value;
@@ -272,7 +278,7 @@ int arch_decode_instruction(const struct
if (modrm_reg == CFI_SP) {
- if (modrm_mod == 3) {
+ if (mod_is_reg()) {
/* mov %rsp, reg */
ADD_OP(op) {
op->src.type = OP_SRC_REG;
@@ -308,7 +314,7 @@ int arch_decode_instruction(const struct
break;
}
- if (modrm_mod == 3 && modrm_rm == CFI_SP) {
+ if (rm_is_reg(CFI_SP)) {
/* mov reg, %rsp */
ADD_OP(op) {
@@ -325,7 +331,7 @@ int arch_decode_instruction(const struct
if (!rex_w)
break;
- if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
+ if (rm_is_mem(CFI_BP)) {
/* mov reg, disp(%rbp) */
ADD_OP(op) {
@@ -338,7 +344,7 @@ int arch_decode_instruction(const struct
break;
}
- if (modrm_mod != 3 && rm_is(CFI_SP)) {
+ if (rm_is_mem(CFI_SP)) {
/* mov reg, disp(%rsp) */
ADD_OP(op) {
@@ -357,7 +363,7 @@ int arch_decode_instruction(const struct
if (!rex_w)
break;
- if ((modrm_mod == 1 || modrm_mod == 2) && modrm_rm == CFI_BP) {
+ if (rm_is_mem(CFI_BP)) {
/* mov disp(%rbp), reg */
ADD_OP(op) {
@@ -370,7 +376,7 @@ int arch_decode_instruction(const struct
break;
}
- if (modrm_mod != 3 && rm_is(CFI_SP)) {
+ if (rm_is_mem(CFI_SP)) {
/* mov disp(%rsp), reg */
ADD_OP(op) {
@@ -386,7 +392,7 @@ int arch_decode_instruction(const struct
break;
case 0x8d:
- if (modrm_mod == 3) {
+ if (mod_is_reg()) {
WARN("invalid LEA encoding at %s:0x%lx", sec->name, offset);
break;
}
^ permalink raw reply [flat|nested] 25+ messages in thread