diff mbox series

[RFC,v5,26/57] objtool: arm64: Decode brk instruction

Message ID 20200109160300.26150-27-jthierry@redhat.com (mailing list archive)
State New, archived
Headers show
Series objtool: Add support for arm64 | expand

Commit Message

Julien Thierry Jan. 9, 2020, 4:02 p.m. UTC
Add decoding brk instructions. Associate known immediate values with
their kernel/compiler semantics.

Suggested-by: Raphael Gault <raphael.gault@arm.com>
Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 tools/objtool/arch/arm64/decode.c | 33 +++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
diff mbox series

Patch

diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
index aa00de725686..1609750cc4b9 100644
--- a/tools/objtool/arch/arm64/decode.c
+++ b/tools/objtool/arch/arm64/decode.c
@@ -507,6 +507,7 @@  int arm_decode_except_gen(u32 instr, enum insn_type *type,
 #define INSN_SVC	0b00000001
 #define INSN_HVC	0b00000010
 #define INSN_SMC	0b00000011
+#define INSN_BRK	0b00100000
 
 	switch (decode_field) {
 	case INSN_SVC:
@@ -518,6 +519,38 @@  int arm_decode_except_gen(u32 instr, enum insn_type *type,
 		 */
 		*type = INSN_NOP;
 		return 0;
+	case INSN_BRK:
+		/* Based on arch/arm64/include/asm/brk-imm.h */
+		switch (imm16) {
+		case 0x004: /* KPROBES_BRK_IMM */
+		case 0x005: /* UPROBES_BRK_IMM */
+		case 0x400: /* KGDB_DYN_DBG_BRK_IMM */
+		case 0x401: /* KGDB_COMPILED_DBG_BRK_IMM */
+			*type = INSN_OTHER;
+			break;
+		case 0x800: /* BUG_BRK_IMM */
+			/*
+			 * brk #0x800 is generated by the BUG()/WARN() linux API
+			 * and is thus a particular case. Since those are not
+			 * necessarily compiled in, the surrounding code should
+			 * work properly without it. We thus consider it as a
+			 * nop.
+			 */
+			*type = INSN_NOP;
+			break;
+		case 0x3e8:
+			/*
+			 * Similar to the use of "ud2" on x86, GCC inserts
+			 * "brk #0x38e" instructions for certain divide-by-zero
+			 * cases.
+			 */
+			*type = INSN_BUG;
+			break;
+		default:
+			*type = INSN_CONTEXT_SWITCH;
+			break;
+		}
+		return 0;
 	default:
 		return arm_decode_unknown(instr, type, immediate, ops_list);
 	}