lkml.org 
[lkml]   [2020]   [Jan]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[RFC v5 20/57] objtool: arm64: Decode unknown instructions
Date
For aarch64, it is possible to have byte sequences that aren't valid
opcodes in the code sections. Do not report an error when the decoder
finds such a sequence, but make sure that those bytes cannot be reached
in the execution flow.

Suggested-by: Raphael Gault <raphael.gault@arm.com>
Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
tools/objtool/arch.h | 1 +
tools/objtool/arch/arm64/decode.c | 22 ++++++++++++++++++-
.../objtool/arch/arm64/include/insn_decode.h | 7 ++++++
tools/objtool/check.c | 10 ++++++++-
4 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/tools/objtool/arch.h b/tools/objtool/arch.h
index f9883c431949..0336efecb9d9 100644
--- a/tools/objtool/arch.h
+++ b/tools/objtool/arch.h
@@ -28,6 +28,7 @@ enum insn_type {
INSN_STD,
INSN_CLD,
INSN_OTHER,
+ INSN_INVALID,
};

enum op_dest_type {
diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index 4d0ab2acca27..04358f41ef1d 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -78,7 +78,9 @@ static int is_arm64(struct elf *elf)
* struct list_head *ops_list);
*/
static arm_decode_class aarch64_insn_class_decode_table[NR_INSN_CLASS] = {
- NULL,
+ [INSN_RESERVED] = arm_decode_unknown,
+ [INSN_UNKNOWN] = arm_decode_unknown,
+ [INSN_UNALLOC] = arm_decode_unknown,
};

/*
@@ -125,3 +127,21 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
WARN_FUNC("Unsupported instruction", sec, offset);
return res;
}
+
+int arm_decode_unknown(u32 instr, enum insn_type *type,
+ unsigned long *immediate, struct list_head *ops_list)
+{
+ /*
+ * There are a few reasons we might have non-valid opcodes in
+ * code sections:
+ * - For load literal, assembler can generate the data to be loaded in
+ * the code section
+ * - Compiler/assembler can generate zeroes to pad function that do not
+ * end on 8-byte alignment
+ * - Hand written assembly code might contain constants in the code
+ * section
+ */
+ *type = INSN_INVALID;
+
+ return 0;
+}
diff --git a/tools/objtool/arch/arm64/include/insn_decode.h b/tools/objtool/arch/arm64/include/insn_decode.h
index c56b72ac4633..16066f8fca0d 100644
--- a/tools/objtool/arch/arm64/include/insn_decode.h
+++ b/tools/objtool/arch/arm64/include/insn_decode.h
@@ -5,6 +5,10 @@

#include "../../../arch.h"

+#define INSN_RESERVED 0b0000
+#define INSN_UNKNOWN 0b0001
+#define INSN_UNALLOC 0b0011
+
#define NR_INSN_CLASS 16
#define INSN_CLASS(opcode) (((opcode) >> 25) & (NR_INSN_CLASS - 1))

@@ -12,4 +16,7 @@ typedef int (*arm_decode_class)(u32 instr, enum insn_type *type,
unsigned long *immediate,
struct list_head *ops_list);

+/* arm64 instruction classes */
+int arm_decode_unknown(u32 instr, enum insn_type *type,
+ unsigned long *immediate, struct list_head *ops_list);
#endif /* _ARM_INSN_DECODE_H */
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 48aec56a7760..52a8e64e15ca 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1818,6 +1818,13 @@ static int validate_branch_alt_safe(struct objtool_file *file,
while (1) {
next_insn = next_insn_same_sec(file, insn);

+ if (insn->type == INSN_INVALID) {
+ WARN("%s+0x%lx non-executable instruction, should never be reached",
+ insn->sec->name,
+ insn->offset);
+ return 1;
+ }
+
if (file->c_file && func && insn->func && func != insn->func->pfunc) {
WARN("%s() falls through to next function %s()",
func->name, insn->func->name);
@@ -2137,7 +2144,8 @@ static bool ignore_unreachable_insn(struct instruction *insn)
{
int i;

- if (insn->ignore || insn->type == INSN_NOP)
+ if (insn->ignore || insn->type == INSN_NOP ||
+ insn->type == INSN_INVALID)
return true;

/*
--
2.21.0
\
 
 \ /
  Last update: 2020-01-09 17:06    [W:0.342 / U:3.120 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site