|
@@ -314,3 +314,115 @@ enum decode_reg_type {
|
|
* case coverage checks.
|
|
* case coverage checks.
|
|
*/
|
|
*/
|
|
REG_TYPE_NOPCX, /* Register must not be PC */
|
|
REG_TYPE_NOPCX, /* Register must not be PC */
|
|
|
|
+ REG_TYPE_NOSPPCX, /* Register must not be SP or PC */
|
|
|
|
+
|
|
|
|
+ /* Alias to allow '0' arg to be used in REGS macro. */
|
|
|
|
+ REG_TYPE_0 = REG_TYPE_NONE
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define REGS(r16, r12, r8, r4, r0) \
|
|
|
|
+ ((REG_TYPE_##r16) << 16) + \
|
|
|
|
+ ((REG_TYPE_##r12) << 12) + \
|
|
|
|
+ ((REG_TYPE_##r8) << 8) + \
|
|
|
|
+ ((REG_TYPE_##r4) << 4) + \
|
|
|
|
+ (REG_TYPE_##r0)
|
|
|
|
+
|
|
|
|
+union decode_item {
|
|
|
|
+ u32 bits;
|
|
|
|
+ const union decode_item *table;
|
|
|
|
+ kprobe_insn_handler_t *handler;
|
|
|
|
+ kprobe_decode_insn_t *decoder;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#define DECODE_END \
|
|
|
|
+ {.bits = DECODE_TYPE_END}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct decode_header {
|
|
|
|
+ union decode_item type_regs;
|
|
|
|
+ union decode_item mask;
|
|
|
|
+ union decode_item value;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define DECODE_HEADER(_type, _mask, _value, _regs) \
|
|
|
|
+ {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \
|
|
|
|
+ {.bits = (_mask)}, \
|
|
|
|
+ {.bits = (_value)}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct decode_table {
|
|
|
|
+ struct decode_header header;
|
|
|
|
+ union decode_item table;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define DECODE_TABLE(_mask, _value, _table) \
|
|
|
|
+ DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \
|
|
|
|
+ {.table = (_table)}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct decode_custom {
|
|
|
|
+ struct decode_header header;
|
|
|
|
+ union decode_item decoder;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define DECODE_CUSTOM(_mask, _value, _decoder) \
|
|
|
|
+ DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \
|
|
|
|
+ {.decoder = (_decoder)}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct decode_simulate {
|
|
|
|
+ struct decode_header header;
|
|
|
|
+ union decode_item handler;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \
|
|
|
|
+ DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \
|
|
|
|
+ {.handler = (_handler)}
|
|
|
|
+
|
|
|
|
+#define DECODE_SIMULATE(_mask, _value, _handler) \
|
|
|
|
+ DECODE_SIMULATEX(_mask, _value, _handler, 0)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct decode_emulate {
|
|
|
|
+ struct decode_header header;
|
|
|
|
+ union decode_item handler;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \
|
|
|
|
+ DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \
|
|
|
|
+ {.handler = (_handler)}
|
|
|
|
+
|
|
|
|
+#define DECODE_EMULATE(_mask, _value, _handler) \
|
|
|
|
+ DECODE_EMULATEX(_mask, _value, _handler, 0)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct decode_or {
|
|
|
|
+ struct decode_header header;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define DECODE_OR(_mask, _value) \
|
|
|
|
+ DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct decode_reject {
|
|
|
|
+ struct decode_header header;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+#define DECODE_REJECT(_mask, _value) \
|
|
|
|
+ DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_THUMB2_KERNEL
|
|
|
|
+extern const union decode_item kprobe_decode_thumb16_table[];
|
|
|
|
+extern const union decode_item kprobe_decode_thumb32_table[];
|
|
|
|
+#else
|
|
|
|
+extern const union decode_item kprobe_decode_arm_table[];
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
|
|
|
|
+ const union decode_item *table, bool thumb16);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+#endif /* _ARM_KERNEL_KPROBES_H */
|