[v6 PATCH 14/21] x86/insn-eval: Add wrapper function for 16-bit and 32-bit address encodings

Ricardo Neri ricardo.neri-calderon at linux.intel.com
Tue Mar 7 18:32:47 CST 2017


Convert the function insn_get_add_ref into a wrapper function that calls
the correct static address-decoding function depending on the size of the
address. In this way, callers do not need to worry about calling the
correct function and decreases the number of functions that need to be
exposed.

To this end, the original 32/64-bit insn_get_addr_ref is renamed as
insn_get_addr_ref_32_64 to reflect the type of address encodings that it
handles.

Documentation is added to the new wrapper function and the documentation
for the 32/64-bit address decoding function is improved.

Cc: Dave Hansen <dave.hansen at linux.intel.com>
Cc: Adam Buchbinder <adam.buchbinder at gmail.com>
Cc: Colin Ian King <colin.king at canonical.com>
Cc: Lorenzo Stoakes <lstoakes at gmail.com>
Cc: Qiaowei Ren <qiaowei.ren at intel.com>
Cc: Arnaldo Carvalho de Melo <acme at redhat.com>
Cc: Masami Hiramatsu <mhiramat at kernel.org>
Cc: Adrian Hunter <adrian.hunter at intel.com>
Cc: Kees Cook <keescook at chromium.org>
Cc: Thomas Garnier <thgarnie at google.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Borislav Petkov <bp at suse.de>
Cc: Dmitry Vyukov <dvyukov at google.com>
Cc: Ravi V. Shankar <ravi.v.shankar at intel.com>
Cc: x86 at kernel.org
Signed-off-by: Ricardo Neri <ricardo.neri-calderon at linux.intel.com>
---
 arch/x86/lib/insn-eval.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c
index cb1076d..e633588 100644
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -705,12 +705,21 @@ static inline long __to_signed_long(unsigned long val, int long_bytes)
 #endif
 }
 
-/*
- * return the address being referenced be instruction
- * for rm=3 returning the content of the rm reg
- * for rm!=3 calculates the address using SIB and Disp
+/**
+ * insn_get_addr_ref_32_64 - Obtain a 32/64-bit address referred by instruction
+ * @insn:	Instruction struct with ModRM and SiB bytes and displacement
+ * @regs:	Set of registers referred by the instruction
+ *
+ * This function is to be used with 32-bit and 64-bit address encodings. Obtain
+ * the memory address referred by the instruction's ModRM bytes and
+ * displacement. Also, the segment used as base is determined by either any
+ * segment override prefixes in insn or the default segment of the registers
+ * involved in the linear address computation.
+ *
+ * Return: linear address referenced by instruction and registers
  */
-void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
+static void __user *insn_get_addr_ref_32_64(struct insn *insn,
+					    struct pt_regs *regs)
 {
 	unsigned long linear_addr, seg_base_addr;
 	long eff_addr, base, indx, tmp;
@@ -795,3 +804,29 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
 out_err:
 	return (void __user *)-1;
 }
+
+/**
+ * insn_get_addr_ref - Obtain the linear address referred by instruction
+ * @insn:	Instruction structure containing ModRM byte and displacement
+ * @regs:	Set of registers referred by the instruction
+ *
+ * Obtain the memory address referred by the instruction's ModRM bytes and
+ * displacement. Also, the segment used as base is determined by either any
+ * segment override prefixes in insn or the default segment of the registers
+ * involved in the address computation.
+ *
+ * Return: linear address referenced by instruction and registers
+ */
+void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
+{
+	switch (insn->addr_bytes) {
+	case 2:
+		return insn_get_addr_ref_16(insn, regs);
+	case 4:
+		/* fall through */
+	case 8:
+		return insn_get_addr_ref_32_64(insn, regs);
+	default:
+		return (void __user *)-1;
+	}
+}
-- 
2.9.3




More information about the wine-devel mailing list