diff mbox

[VERY,RFC,3/5] tools/fuzz: introduce x86 instruction emulator target

Message ID 1481205281-18256-4-git-send-email-wei.liu2@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Wei Liu Dec. 8, 2016, 1:54 p.m. UTC
Instruction emulator fuzzing code is from code previous written by
Andrew and George. Adapted to llvm fuzzer and hook up the build system.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: George Dunlap <george.dunlap@citrix.com>
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>
---
 .gitignore                                         |   1 +
 tools/fuzz/x86_instruction_emulator/Makefile       |  33 ++
 .../x86-insn-emulator-fuzzer.c                     | 335 +++++++++++++++++++++
 3 files changed, 369 insertions(+)
 create mode 100644 tools/fuzz/x86_instruction_emulator/Makefile
 create mode 100644 tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c

Comments

Jan Beulich Dec. 8, 2016, 3:03 p.m. UTC | #1
>>> On 08.12.16 at 14:54, <wei.liu2@citrix.com> wrote:
> Instruction emulator fuzzing code is from code previous written by
> Andrew and George. Adapted to llvm fuzzer and hook up the build system.

With this, how much of the new code could be shared between
Google's fuzzer and AFL, for which George had put this together
originally afaik? Or are we now no longer planning on having an
AFL target?

> --- /dev/null
> +++ b/tools/fuzz/x86_instruction_emulator/Makefile
> @@ -0,0 +1,33 @@
> +XEN_ROOT=$(CURDIR)/../../..
> +include $(XEN_ROOT)/tools/Rules.mk
> +
> +x86-instruction-emulator-fuzzer-all: x86-insn-emulator.a x86-insn-emulator-fuzzer.o
> +
> +x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h:
> +	[ -L x86_emulate ] || ln -sf $(XEN_ROOT)/xen/arch/x86/x86_emulate .
> +
> +x86_emulate.c:
> +	[ -L x86_emulate.c ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.c
> +
> +x86_emulate.h:
> +	[ -L x86_emulate.h ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.h

I think these two could easily be a single (pattern) rule, with (slightly
unusually) the file extension being the stem.

> --- /dev/null
> +++ b/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c
> @@ -0,0 +1,335 @@
> +#include <errno.h>
> +#include <limits.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdint.h>
> +#include <inttypes.h>
> +#include <xen/xen.h>
> +#include <unistd.h>
> +#include <assert.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <sys/mman.h>
> +
> +#define __packed __attribute__((packed))
> +#define ASSERT assert

This should not be needed anymore if you included ...

> +#include "x86_emulate/x86_emulate.h"

"x86_emulate.h" instead. And __packed, if its really needed,
should then also be added to that header.

> +/* EFLAGS bit definitions. */
> +#define EFLG_OF (1<<11)
> +#define EFLG_DF (1<<10)
> +#define EFLG_SF (1<<7)
> +#define EFLG_ZF (1<<6)
> +#define EFLG_AF (1<<4)
> +#define EFLG_PF (1<<2)
> +#define EFLG_CF (1<<0)

These appear to be unused.

> +static unsigned char data[4096];
> +static unsigned int data_index = 0;
> +static unsigned int data_max;
> +
> +int data_read(const char *why, void *dst, unsigned int bytes) {
> +

static? And the brace put on the otherwise stray blank line.

> +static int emul_read(

May I suggest to prefix all of these fuzz_ instead of emul_?

> +#define cpu_has_sse2 ({ \
> +    unsigned int eax = 1, ecx = 0, edx; \
> +    emul_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
> +    (edx & (1U << 26)) != 0; \
> +})

This appears to be unused again.

> +#define cpu_has_avx2 ({ \
> +    unsigned int eax = 1, ebx, ecx = 0; \
> +    emul_cpuid(&eax, &ebx, &ecx, &eax, NULL); \
> +    if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
> +        ebx = 0; \
> +    else { \
> +        eax = 7, ecx = 0; \
> +        cpuid(&eax, &ebx, &ecx, &eax, NULL); \
> +    } \
> +    (ebx & (1U << 5)) != 0; \
> +})

Same here.

> +static int emul_read_cr(
> +    unsigned int reg,
> +    unsigned long *val,
> +    struct x86_emulate_ctxt *ctxt)
> +{
> +    /* Fake just enough state for the emulator's _get_fpu() to be happy. */
> +    switch ( reg )
> +    {
> +    case 0:
> +        *val = 0x00000001; /* PE */
> +        return X86EMUL_OKAY;
> +
> +    case 4:
> +        /* OSFXSR, OSXMMEXCPT, and maybe OSXSAVE */
> +        *val = 0x00000600 | (cpu_has_xsave ? 0x00040000 : 0);
> +        return X86EMUL_OKAY;
> +    }
> +
> +    return X86EMUL_UNHANDLEABLE;
> +}

Looks suspiciously similar to existing code. We may want to share
such stuff, to avoid having to update it in multiple places.

> +int emul_get_fpu(

static?

> +struct x86_emulate_ops emulops = {

again

> +bool make_stack_executable(void) {
> +    unsigned long sp;
> +    bool stack_exec;
> +
> +    /*
> +     * Mark the entire stack executable so that the stub executions
> +     * don't fault
> +     */
> +#define MMAP_SZ 16384
> +
> +#ifdef __x86_64__
> +    asm ("movq %%rsp, %0" : "=g" (sp));
> +#else
> +    asm ("movl %%esp, %0" : "=g" (sp));
> +#endif
> +
> +    stack_exec = mprotect((void *)(sp & -0x1000L) - (MMAP_SZ - 0x1000),
> +                          MMAP_SZ, PROT_READ|PROT_WRITE|PROT_EXEC) == 0;
> +    if ( !stack_exec )
> +        printf("Warning: Stack could not be made executable (%d).\n", errno);
> +
> +    return stack_exec;
> +}

This too looks like it would want sharing.

Jan
Wei Liu Dec. 8, 2016, 3:15 p.m. UTC | #2
On Thu, Dec 08, 2016 at 08:03:04AM -0700, Jan Beulich wrote:
> >>> On 08.12.16 at 14:54, <wei.liu2@citrix.com> wrote:
> > Instruction emulator fuzzing code is from code previous written by
> > Andrew and George. Adapted to llvm fuzzer and hook up the build system.
> 
> With this, how much of the new code could be shared between
> Google's fuzzer and AFL, for which George had put this together
> originally afaik? Or are we now no longer planning on having an
> AFL target?

We could share the majority of the code. I started by stripping unused
code in their patch (and as you already saw, not quite complete yet).

When Google oss-fuzz supports AFL, we can easily add that support in.
Ultimately it is only the entry function is a bit different. All the
stub functions should work the same.

Regarding all comments below, I will fix them all together in the next
round.

Wei.
Wei Liu Dec. 8, 2016, 5:25 p.m. UTC | #3
On Thu, Dec 08, 2016 at 08:03:04AM -0700, Jan Beulich wrote:
[...]
> 
> > +static int emul_read_cr(
> > +    unsigned int reg,
> > +    unsigned long *val,
> > +    struct x86_emulate_ctxt *ctxt)
> > +{
> > +    /* Fake just enough state for the emulator's _get_fpu() to be happy. */
> > +    switch ( reg )
> > +    {
> > +    case 0:
> > +        *val = 0x00000001; /* PE */
> > +        return X86EMUL_OKAY;
> > +
> > +    case 4:
> > +        /* OSFXSR, OSXMMEXCPT, and maybe OSXSAVE */
> > +        *val = 0x00000600 | (cpu_has_xsave ? 0x00040000 : 0);
> > +        return X86EMUL_OKAY;
> > +    }
> > +
> > +    return X86EMUL_UNHANDLEABLE;
> > +}
> 
> Looks suspiciously similar to existing code. We may want to share
> such stuff, to avoid having to update it in multiple places.
> 

Share with what? Do you mean the real emulator code?

Wei.
Wei Liu Dec. 8, 2016, 5:57 p.m. UTC | #4
On Thu, Dec 08, 2016 at 08:03:04AM -0700, Jan Beulich wrote:
> >>> On 08.12.16 at 14:54, <wei.liu2@citrix.com> wrote:
> > Instruction emulator fuzzing code is from code previous written by
> > Andrew and George. Adapted to llvm fuzzer and hook up the build system.
> 
> With this, how much of the new code could be shared between
> Google's fuzzer and AFL, for which George had put this together
> originally afaik? Or are we now no longer planning on having an
> AFL target?
> 
> > --- /dev/null
> > +++ b/tools/fuzz/x86_instruction_emulator/Makefile
> > @@ -0,0 +1,33 @@
> > +XEN_ROOT=$(CURDIR)/../../..
> > +include $(XEN_ROOT)/tools/Rules.mk
> > +
> > +x86-instruction-emulator-fuzzer-all: x86-insn-emulator.a x86-insn-emulator-fuzzer.o
> > +
> > +x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h:
> > +	[ -L x86_emulate ] || ln -sf $(XEN_ROOT)/xen/arch/x86/x86_emulate .
> > +
> > +x86_emulate.c:
> > +	[ -L x86_emulate.c ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.c
> > +
> > +x86_emulate.h:
> > +	[ -L x86_emulate.h ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.h
> 
> I think these two could easily be a single (pattern) rule, with (slightly
> unusually) the file extension being the stem.

I think it is better to have them explicitly spelled out, because using
something like

x86_emulate.%:
	[ -L x86_emulate.$* ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.$*

would cause the x86_emulate.o compiled in tools/tests/x86_emulator be
linked here, too, due to another rule we have:

x86_emulate.o: x86_emulate.c x86_emulate.h x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h 

Please let me know if you have some other ideas to deal with this.

Wei.
Jan Beulich Dec. 9, 2016, 8:05 a.m. UTC | #5
>>> On 08.12.16 at 18:25, <wei.liu2@citrix.com> wrote:
> On Thu, Dec 08, 2016 at 08:03:04AM -0700, Jan Beulich wrote:
> [...]
>> 
>> > +static int emul_read_cr(
>> > +    unsigned int reg,
>> > +    unsigned long *val,
>> > +    struct x86_emulate_ctxt *ctxt)
>> > +{
>> > +    /* Fake just enough state for the emulator's _get_fpu() to be happy. */
>> > +    switch ( reg )
>> > +    {
>> > +    case 0:
>> > +        *val = 0x00000001; /* PE */
>> > +        return X86EMUL_OKAY;
>> > +
>> > +    case 4:
>> > +        /* OSFXSR, OSXMMEXCPT, and maybe OSXSAVE */
>> > +        *val = 0x00000600 | (cpu_has_xsave ? 0x00040000 : 0);
>> > +        return X86EMUL_OKAY;
>> > +    }
>> > +
>> > +    return X86EMUL_UNHANDLEABLE;
>> > +}
>> 
>> Looks suspiciously similar to existing code. We may want to share
>> such stuff, to avoid having to update it in multiple places.
> 
> Share with what? Do you mean the real emulator code?

The real emulator test code, yes.

Jan
Jan Beulich Dec. 9, 2016, 8:09 a.m. UTC | #6
>>> On 08.12.16 at 18:57, <wei.liu2@citrix.com> wrote:
> On Thu, Dec 08, 2016 at 08:03:04AM -0700, Jan Beulich wrote:
>> >>> On 08.12.16 at 14:54, <wei.liu2@citrix.com> wrote:
>> > Instruction emulator fuzzing code is from code previous written by
>> > Andrew and George. Adapted to llvm fuzzer and hook up the build system.
>> 
>> With this, how much of the new code could be shared between
>> Google's fuzzer and AFL, for which George had put this together
>> originally afaik? Or are we now no longer planning on having an
>> AFL target?
>> 
>> > --- /dev/null
>> > +++ b/tools/fuzz/x86_instruction_emulator/Makefile
>> > @@ -0,0 +1,33 @@
>> > +XEN_ROOT=$(CURDIR)/../../..
>> > +include $(XEN_ROOT)/tools/Rules.mk
>> > +
>> > +x86-instruction-emulator-fuzzer-all: x86-insn-emulator.a x86-insn-emulator-fuzzer.o
>> > +
>> > +x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h:
>> > +	[ -L x86_emulate ] || ln -sf $(XEN_ROOT)/xen/arch/x86/x86_emulate .
>> > +
>> > +x86_emulate.c:
>> > +	[ -L x86_emulate.c ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.c
>> > +
>> > +x86_emulate.h:
>> > +	[ -L x86_emulate.h ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.h
>> 
>> I think these two could easily be a single (pattern) rule, with (slightly
>> unusually) the file extension being the stem.
> 
> I think it is better to have them explicitly spelled out, because using
> something like
> 
> x86_emulate.%:
> 	[ -L x86_emulate.$* ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.$*
> 
> would cause the x86_emulate.o compiled in tools/tests/x86_emulator be
> linked here, too, due to another rule we have:
> 
> x86_emulate.o: x86_emulate.c x86_emulate.h x86_emulate/x86_emulate.c 
> x86_emulate/x86_emulate.h 

Good point.

> Please let me know if you have some other ideas to deal with this.

A static pattern rule may then still be better than repeating the
same thing twice (and later perhaps even more often, i.e. once
we gain shared helper routine source/header files):

x86_emulate.c x86_emulate.h: %:
	[ -L $* ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/$*

Jan
Wei Liu Dec. 9, 2016, 10:30 a.m. UTC | #7
On Fri, Dec 09, 2016 at 01:09:45AM -0700, Jan Beulich wrote:
> >>> On 08.12.16 at 18:57, <wei.liu2@citrix.com> wrote:
> > On Thu, Dec 08, 2016 at 08:03:04AM -0700, Jan Beulich wrote:
> >> >>> On 08.12.16 at 14:54, <wei.liu2@citrix.com> wrote:
> >> > Instruction emulator fuzzing code is from code previous written by
> >> > Andrew and George. Adapted to llvm fuzzer and hook up the build system.
> >> 
> >> With this, how much of the new code could be shared between
> >> Google's fuzzer and AFL, for which George had put this together
> >> originally afaik? Or are we now no longer planning on having an
> >> AFL target?
> >> 
> >> > --- /dev/null
> >> > +++ b/tools/fuzz/x86_instruction_emulator/Makefile
> >> > @@ -0,0 +1,33 @@
> >> > +XEN_ROOT=$(CURDIR)/../../..
> >> > +include $(XEN_ROOT)/tools/Rules.mk
> >> > +
> >> > +x86-instruction-emulator-fuzzer-all: x86-insn-emulator.a x86-insn-emulator-fuzzer.o
> >> > +
> >> > +x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h:
> >> > +	[ -L x86_emulate ] || ln -sf $(XEN_ROOT)/xen/arch/x86/x86_emulate .
> >> > +
> >> > +x86_emulate.c:
> >> > +	[ -L x86_emulate.c ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.c
> >> > +
> >> > +x86_emulate.h:
> >> > +	[ -L x86_emulate.h ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.h
> >> 
> >> I think these two could easily be a single (pattern) rule, with (slightly
> >> unusually) the file extension being the stem.
> > 
> > I think it is better to have them explicitly spelled out, because using
> > something like
> > 
> > x86_emulate.%:
> > 	[ -L x86_emulate.$* ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.$*
> > 
> > would cause the x86_emulate.o compiled in tools/tests/x86_emulator be
> > linked here, too, due to another rule we have:
> > 
> > x86_emulate.o: x86_emulate.c x86_emulate.h x86_emulate/x86_emulate.c 
> > x86_emulate/x86_emulate.h 
> 
> Good point.
> 
> > Please let me know if you have some other ideas to deal with this.
> 
> A static pattern rule may then still be better than repeating the
> same thing twice (and later perhaps even more often, i.e. once
> we gain shared helper routine source/header files):
> 
> x86_emulate.c x86_emulate.h: %:
> 	[ -L $* ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/$*
> 

This is a good idea. I've made the change to my code.

Wei.
Wei Liu Dec. 9, 2016, 10:51 a.m. UTC | #8
On Fri, Dec 09, 2016 at 01:05:19AM -0700, Jan Beulich wrote:
> >>> On 08.12.16 at 18:25, <wei.liu2@citrix.com> wrote:
> > On Thu, Dec 08, 2016 at 08:03:04AM -0700, Jan Beulich wrote:
> > [...]
> >> 
> >> > +static int emul_read_cr(
> >> > +    unsigned int reg,
> >> > +    unsigned long *val,
> >> > +    struct x86_emulate_ctxt *ctxt)
> >> > +{
> >> > +    /* Fake just enough state for the emulator's _get_fpu() to be happy. */
> >> > +    switch ( reg )
> >> > +    {
> >> > +    case 0:
> >> > +        *val = 0x00000001; /* PE */
> >> > +        return X86EMUL_OKAY;
> >> > +
> >> > +    case 4:
> >> > +        /* OSFXSR, OSXMMEXCPT, and maybe OSXSAVE */
> >> > +        *val = 0x00000600 | (cpu_has_xsave ? 0x00040000 : 0);
> >> > +        return X86EMUL_OKAY;
> >> > +    }
> >> > +
> >> > +    return X86EMUL_UNHANDLEABLE;
> >> > +}
> >> 
> >> Looks suspiciously similar to existing code. We may want to share
> >> such stuff, to avoid having to update it in multiple places.
> > 
> > Share with what? Do you mean the real emulator code?
> 
> The real emulator test code, yes.
> 

OK. I will refactor the code a bit. Let's start with sharing the two
places you point out and make further improvements as we go along.

Wei.

> Jan
>
diff mbox

Patch

diff --git a/.gitignore b/.gitignore
index a2f34a1..d507243 100644
--- a/.gitignore
+++ b/.gitignore
@@ -145,6 +145,7 @@  tools/flask/utils/flask-loadpolicy
 tools/flask/utils/flask-setenforce
 tools/flask/utils/flask-set-bool
 tools/flask/utils/flask-label-pci
+tools/fuzz/x86_instruction_emulator/x86_emulate*
 tools/helpers/_paths.h
 tools/helpers/init-xenstore-domain
 tools/helpers/xen-init-dom0
diff --git a/tools/fuzz/x86_instruction_emulator/Makefile b/tools/fuzz/x86_instruction_emulator/Makefile
new file mode 100644
index 0000000..374c84a
--- /dev/null
+++ b/tools/fuzz/x86_instruction_emulator/Makefile
@@ -0,0 +1,33 @@ 
+XEN_ROOT=$(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+x86-instruction-emulator-fuzzer-all: x86-insn-emulator.a x86-insn-emulator-fuzzer.o
+
+x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h:
+	[ -L x86_emulate ] || ln -sf $(XEN_ROOT)/xen/arch/x86/x86_emulate .
+
+x86_emulate.c:
+	[ -L x86_emulate.c ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.c
+
+x86_emulate.h:
+	[ -L x86_emulate.h ] || ln -sf $(XEN_ROOT)/tools/tests/x86_emulator/x86_emulate.h
+
+CFLAGS += $(CFLAGS_xeninclude)
+
+x86_emulate.o: x86_emulate.c x86_emulate.h x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
+
+x86-insn-emulator.a: x86_emulate.o
+	$(AR) rc $@ $^
+
+x86-insn-emulator-fuzzer.o: x86-insn-emulator-fuzzer.c
+
+# Common targets
+.PHONY: all
+all: x86-instruction-emulator-fuzzer-all
+
+.PHONY: distclean
+distclean: clean
+
+.PHONY: clean
+clean:
+	rm -f *.a *.o
diff --git a/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c b/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c
new file mode 100644
index 0000000..01ee7a4
--- /dev/null
+++ b/tools/fuzz/x86_instruction_emulator/x86-insn-emulator-fuzzer.c
@@ -0,0 +1,335 @@ 
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <xen/xen.h>
+#include <unistd.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#define __packed __attribute__((packed))
+#define ASSERT assert
+
+#include "x86_emulate/x86_emulate.h"
+
+/* EFLAGS bit definitions. */
+#define EFLG_OF (1<<11)
+#define EFLG_DF (1<<10)
+#define EFLG_SF (1<<7)
+#define EFLG_ZF (1<<6)
+#define EFLG_AF (1<<4)
+#define EFLG_PF (1<<2)
+#define EFLG_CF (1<<0)
+
+static unsigned char data[4096];
+static unsigned int data_index = 0;
+static unsigned int data_max;
+
+int data_read(const char *why, void *dst, unsigned int bytes) {
+
+    if ( data_index + bytes > data_max )
+        return X86EMUL_EXCEPTION;
+
+    memcpy(dst,  data+data_index, bytes);
+    data_index += bytes;
+
+    return X86EMUL_OKAY;
+}
+
+static int emul_read(
+    unsigned int seg,
+    unsigned long offset,
+    void *p_data,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return data_read("read", p_data, bytes);
+}
+
+static int emul_fetch(
+    unsigned int seg,
+    unsigned long offset,
+    void *p_data,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return data_read("fetch", p_data, bytes);
+}
+
+static int emul_write(
+    unsigned int seg,
+    unsigned long offset,
+    void *p_data,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return X86EMUL_OKAY;
+}
+
+static int emul_cmpxchg(
+    unsigned int seg,
+    unsigned long offset,
+    void *old,
+    void *new,
+    unsigned int bytes,
+    struct x86_emulate_ctxt *ctxt)
+{
+    return X86EMUL_OKAY;
+}
+
+static int emul_cpuid(
+    unsigned int *eax,
+    unsigned int *ebx,
+    unsigned int *ecx,
+    unsigned int *edx,
+    struct x86_emulate_ctxt *ctxt)
+{
+    unsigned int leaf = *eax;
+
+    asm ("cpuid" : "+a" (*eax), "+c" (*ecx), "=d" (*edx), "=b" (*ebx));
+
+    /* The emulator doesn't itself use MOVBE, so we can always run the test. */
+    if ( leaf == 1 )
+        *ecx |= 1U << 22;
+
+    return X86EMUL_OKAY;
+}
+
+#define cache_line_size() ({ \
+    unsigned int eax = 1, ebx, ecx = 0, edx; \
+    emul_cpuid(&eax, &ebx, &ecx, &edx, NULL); \
+    edx & (1U << 19) ? (ebx >> 5) & 0x7f8 : 0; \
+})
+
+#define cpu_has_mmx ({ \
+    unsigned int eax = 1, ecx = 0, edx; \
+    emul_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
+    (edx & (1U << 23)) != 0; \
+})
+
+#define cpu_has_sse ({ \
+    unsigned int eax = 1, ecx = 0, edx; \
+    emul_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
+    (edx & (1U << 25)) != 0; \
+})
+
+#define cpu_has_sse2 ({ \
+    unsigned int eax = 1, ecx = 0, edx; \
+    emul_cpuid(&eax, &ecx, &ecx, &edx, NULL); \
+    (edx & (1U << 26)) != 0; \
+})
+
+#define cpu_has_xsave ({ \
+    unsigned int eax = 1, ecx = 0; \
+    emul_cpuid(&eax, &eax, &ecx, &eax, NULL); \
+    /* Intentionally checking OSXSAVE here. */ \
+    (ecx & (1U << 27)) != 0; \
+})
+
+static inline uint64_t xgetbv(uint32_t xcr)
+{
+    uint32_t lo, hi;
+
+    asm ( ".byte 0x0f, 0x01, 0xd0" : "=a" (lo), "=d" (hi) : "c" (xcr) );
+
+    return ((uint64_t)hi << 32) | lo;
+}
+
+#define cpu_has_avx ({ \
+    unsigned int eax = 1, ecx = 0; \
+    emul_cpuid(&eax, &eax, &ecx, &eax, NULL); \
+    if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
+        ecx = 0; \
+    (ecx & (1U << 28)) != 0; \
+})
+
+#define cpu_has_avx2 ({ \
+    unsigned int eax = 1, ebx, ecx = 0; \
+    emul_cpuid(&eax, &ebx, &ecx, &eax, NULL); \
+    if ( !(ecx & (1U << 27)) || ((xgetbv(0) & 6) != 6) ) \
+        ebx = 0; \
+    else { \
+        eax = 7, ecx = 0; \
+        cpuid(&eax, &ebx, &ecx, &eax, NULL); \
+    } \
+    (ebx & (1U << 5)) != 0; \
+})
+
+static int emul_read_cr(
+    unsigned int reg,
+    unsigned long *val,
+    struct x86_emulate_ctxt *ctxt)
+{
+    /* Fake just enough state for the emulator's _get_fpu() to be happy. */
+    switch ( reg )
+    {
+    case 0:
+        *val = 0x00000001; /* PE */
+        return X86EMUL_OKAY;
+
+    case 4:
+        /* OSFXSR, OSXMMEXCPT, and maybe OSXSAVE */
+        *val = 0x00000600 | (cpu_has_xsave ? 0x00040000 : 0);
+        return X86EMUL_OKAY;
+    }
+
+    return X86EMUL_UNHANDLEABLE;
+}
+
+int emul_get_fpu(
+    void (*exception_callback)(void *, struct cpu_user_regs *),
+    void *exception_callback_arg,
+    enum x86_emulate_fpu_type type,
+    struct x86_emulate_ctxt *ctxt)
+{
+    switch ( type )
+    {
+    case X86EMUL_FPU_fpu:
+        break;
+    case X86EMUL_FPU_mmx:
+        if ( cpu_has_mmx )
+            break;
+    case X86EMUL_FPU_xmm:
+        if ( cpu_has_sse )
+            break;
+    case X86EMUL_FPU_ymm:
+        if ( cpu_has_avx )
+            break;
+    default:
+        return X86EMUL_UNHANDLEABLE;
+    }
+    return X86EMUL_OKAY;
+}
+
+struct x86_emulate_ops emulops = {
+    .read       = emul_read,
+    .insn_fetch = emul_fetch,
+    .write      = emul_write,
+    .cmpxchg    = emul_cmpxchg,
+    .cpuid      = emul_cpuid,
+    .read_cr    = emul_read_cr,
+    .get_fpu    = emul_get_fpu,
+};
+
+bool make_stack_executable(void) {
+    unsigned long sp;
+    bool stack_exec;
+
+    /*
+     * Mark the entire stack executable so that the stub executions
+     * don't fault
+     */
+#define MMAP_SZ 16384
+
+#ifdef __x86_64__
+    asm ("movq %%rsp, %0" : "=g" (sp));
+#else
+    asm ("movl %%esp, %0" : "=g" (sp));
+#endif
+
+    stack_exec = mprotect((void *)(sp & -0x1000L) - (MMAP_SZ - 0x1000),
+                          MMAP_SZ, PROT_READ|PROT_WRITE|PROT_EXEC) == 0;
+    if ( !stack_exec )
+        printf("Warning: Stack could not be made executable (%d).\n", errno);
+
+    return stack_exec;
+}
+
+#define CANONICALIZE(x)   \
+    do {                                               \
+        uint64_t _y = (x);                             \
+        if ( _y & (1ULL<<47) ) {                       \
+            _y |= (~0ULL)<<48;                          \
+        } else {                                        \
+            _y &= (1ULL<<48)-1;                         \
+        }                                               \
+        printf("Canonicalized %" PRIx64 " to %" PRIx64 "\n", x, _y);    \
+        (x) = _y;                                       \
+    } while(0)
+
+#define ADDR_SIZE_SHIFT 60
+#define ADDR_SIZE_64 (2ULL<<ADDR_SIZE_SHIFT)
+#define ADDR_SIZE_32 (1ULL<<ADDR_SIZE_SHIFT)
+#define ADDR_SIZE_16 (0)
+
+int LLVMFuzzerTestOneInput(const uint8_t *data_p, size_t size) {
+    struct cpu_user_regs regs = {};
+    struct x86_emulate_ctxt ctxt =
+        {
+            .regs = &regs,
+            .addr_size = 8 * sizeof(void *),
+            .sp_size = 8 * sizeof(void *),
+        };
+
+    int nr = 0;
+    int rc;
+    unsigned x;
+    const uint8_t *p = data_p;
+
+    make_stack_executable();
+
+    memset(data, 0, sizeof(data));
+
+    nr = size < sizeof(regs) ? size : sizeof(regs);
+
+    memcpy(&regs, p, nr);
+    p += sizeof(regs);
+    nr += sizeof(regs);
+
+    if (nr <= size) {
+        memcpy(data, p, size - nr);
+        data_max = size - nr;
+    }
+
+    ctxt.force_writeback = 0;
+
+    /* Zero 'private' entries */
+    regs.error_code = 0;
+    regs.entry_vector = 0;
+
+    /* Use the upper bits of regs.eip to determine addr_size */
+    x = (regs.rip >> ADDR_SIZE_SHIFT) & 0x3;
+    if (x == 3)
+        x = 2;
+    ctxt.addr_size = 16 << x;
+    printf("addr_size: %d\n", ctxt.addr_size);
+
+    /* Use the upper bit of regs.rsp to determine sp_size (if appropriate) */
+    if ( ctxt.addr_size == 64) {
+        ctxt.sp_size = 64;
+    } else {
+        /* If addr_size isn't 64-bits, sp_size can only be 16 or 32 bits */
+        x = (regs.rsp >> ADDR_SIZE_SHIFT) & 0x1;
+        ctxt.sp_size = 16 << x;
+    }
+    printf("sp_size: %d\n", ctxt.sp_size);
+    CANONICALIZE(regs.rip);
+    CANONICALIZE(regs.rsp);
+    CANONICALIZE(regs.rbp);
+
+    /* Zero all segments for now */
+    regs.cs = regs.ss = regs.es = regs.ds = regs.fs = regs.gs = 0;
+
+    do {
+        rc = x86_emulate(&ctxt, &emulops);
+        printf("Emulation result: %d\n", rc);
+    } while (rc == X86EMUL_OKAY);
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */