diff --git a/bindings/gumjs/gumcmodule.c b/bindings/gumjs/gumcmodule.c index ce1c2da80..bff1508d8 100644 --- a/bindings/gumjs/gumcmodule.c +++ b/bindings/gumjs/gumcmodule.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2022 Ole André Vadla Ravnås + * Copyright (C) 2019-2023 Ole André Vadla Ravnås * * Licence: wxWindows Library Licence, Version 3.1 */ @@ -680,7 +680,8 @@ gum_fixdfdi (double value) return value; } -#elif defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8 && !defined (_MSC_VER) +#elif defined (HAVE_I386) && GLIB_SIZEOF_VOID_P == 8 && \ + !defined (_MSC_VER) && !defined (__MINGW32__) extern void * __va_arg (void * ap, int arg_type, int size, int align); diff --git a/ext/dbghelp/dbghelp.h b/ext/dbghelp/dbghelp.h index fa0dd1831..c1335afd8 100644 --- a/ext/dbghelp/dbghelp.h +++ b/ext/dbghelp/dbghelp.h @@ -3905,7 +3905,9 @@ RangeMapWrite( #include +#ifndef __MINGW32__ #include +#endif #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PKG_WER) */ diff --git a/gum/backend-x86/gumstalker-x86-glue.S b/gum/backend-x86/gumstalker-x86-glue.S index 603dcdabf..da8290bab 100644 --- a/gum/backend-x86/gumstalker-x86-glue.S +++ b/gum/backend-x86/gumstalker-x86-glue.S @@ -1,12 +1,13 @@ .text -#ifdef __APPLE__ -.globl _gum_stalker_follow_me -_gum_stalker_follow_me: +#if (defined (HAVE_WINDOWS) && defined (__i386__)) || defined (__APPLE__) +# define GUM_CSYM(x) _ ## x #else -.globl gum_stalker_follow_me -gum_stalker_follow_me: +# define GUM_CSYM(x) x #endif + +.globl GUM_CSYM (gum_stalker_follow_me) +GUM_CSYM (gum_stalker_follow_me): #ifdef i386 movl %esp, %eax subl $12, %esp @@ -14,74 +15,40 @@ pushl %eax pushl (4 + 8)(%eax) pushl (4 + 4)(%eax) pushl (4 + 0)(%eax) -#ifdef __APPLE__ -call __gum_stalker_do_follow_me -#else -call _gum_stalker_do_follow_me -#endif +call GUM_CSYM (_gum_stalker_do_follow_me) addl $28, %esp ret #else mov %rsp, %rcx -#ifdef __APPLE__ -jmp __gum_stalker_do_follow_me -#else -jmp _gum_stalker_do_follow_me -#endif +jmp GUM_CSYM (_gum_stalker_do_follow_me) #endif -#ifdef __APPLE__ -.globl _gum_stalker_activate -_gum_stalker_activate: -#else -.globl gum_stalker_activate -gum_stalker_activate: -#endif +.globl GUM_CSYM (gum_stalker_activate) +GUM_CSYM (gum_stalker_activate): #ifdef i386 movl %esp, %eax pushl %eax pushl (4 + 4)(%eax) pushl (4 + 0)(%eax) -#ifdef __APPLE__ -call __gum_stalker_do_activate -#else -call _gum_stalker_do_activate -#endif +call GUM_CSYM (_gum_stalker_do_activate) addl $12, %esp ret #else mov %rsp, %rdx -#ifdef __APPLE__ -jmp __gum_stalker_do_activate -#else -jmp _gum_stalker_do_activate -#endif +jmp GUM_CSYM (_gum_stalker_do_activate) #endif -#ifdef __APPLE__ -.globl _gum_stalker_deactivate -_gum_stalker_deactivate: -#else -.globl gum_stalker_deactivate -gum_stalker_deactivate: -#endif +.globl GUM_CSYM (gum_stalker_deactivate) +GUM_CSYM (gum_stalker_deactivate): #ifdef i386 movl %esp, %eax subl $4, %esp pushl %eax pushl (4 + 0)(%eax) -#ifdef __APPLE__ -call __gum_stalker_do_deactivate -#else -call _gum_stalker_do_deactivate -#endif +call GUM_CSYM (_gum_stalker_do_deactivate) addl $12, %esp ret #else mov %rsp, %rsi -#ifdef __APPLE__ -jmp __gum_stalker_do_deactivate -#else -jmp _gum_stalker_do_deactivate -#endif +jmp GUM_CSYM (_gum_stalker_do_deactivate) #endif diff --git a/meson.build b/meson.build index 2aeb7a70f..5c9d3d4d7 100644 --- a/meson.build +++ b/meson.build @@ -640,6 +640,12 @@ gum_incdirs = [ include_directories('libs/gum/prof'), ] +if host_os_family == 'windows' + gum_incdirs += [ + include_directories('ext/dbghelp'), + ] +endif + if host_os_family == 'darwin' gum_incdirs += [ include_directories('gum/backend-darwin'), diff --git a/tests/gumjs/script.c b/tests/gumjs/script.c index 38b0e79d1..5240ea8b4 100644 --- a/tests/gumjs/script.c +++ b/tests/gumjs/script.c @@ -2246,7 +2246,11 @@ TESTCASE (native_callback_should_support_stdcall) GUM_NOINLINE static void * sample_return_address (void) { +# ifdef MSC_VER return _ReturnAddress (); +# else + return __builtin_return_address (0); +# endif } TESTCASE (native_callback_should_get_accurate_backtraces) @@ -2273,6 +2277,7 @@ TESTCASE (native_callback_should_get_accurate_backtraces) EXPECT_SEND_MESSAGE_WITH ("\"return address ok\""); EXPECT_NO_MESSAGES (); } + #endif #ifdef HAVE_DARWIN diff --git a/tests/testutil.c b/tests/testutil.c index deab0f09f..dfb088e9c 100644 --- a/tests/testutil.c +++ b/tests/testutil.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2022 Ole André Vadla Ravnås + * Copyright (C) 2008-2023 Ole André Vadla Ravnås * Copyright (C) 2008 Christian Berentsen * * Licence: wxWindows Library Licence, Version 3.1 @@ -449,14 +449,34 @@ test_util_heap_apis (void) return _test_util_heap_apis; } -#ifdef HAVE_WINDOWS - gboolean gum_is_debugger_present (void) { +#if defined (HAVE_WINDOWS) return IsDebuggerPresent (); +#elif defined (HAVE_DARWIN) + int mib[4]; + struct kinfo_proc info; + size_t size; + + info.kp_proc.p_flag = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid (); + + size = sizeof (info); + sysctl (mib, G_N_ELEMENTS (mib), &info, &size, NULL, 0); + + return (info.kp_proc.p_flag & P_TRACED) != 0; +#else + /* FIXME */ + return FALSE; +#endif } +#if defined (_MSC_VER) + guint8 gum_try_read_and_write_at (guint8 * a, guint i, @@ -493,42 +513,93 @@ gum_try_read_and_write_at (guint8 * a, return dummy_value_to_trick_optimizer; } -#else +#elif defined (HAVE_WINDOWS) -#ifdef HAVE_DARWIN -# define GUM_SETJMP(env) setjmp (env) -# define GUM_LONGJMP(env, val) longjmp (env, val) - typedef jmp_buf gum_jmp_buf; -#else -# define GUM_SETJMP(env) sigsetjmp (env, 1) -# define GUM_LONGJMP(env, val) siglongjmp (env, val) - typedef sigjmp_buf gum_jmp_buf; -#endif +static WINAPI LONG on_exception (PEXCEPTION_POINTERS info); +static void recover_from_exception (void); -gboolean -gum_is_debugger_present (void) +static jmp_buf gum_try_read_and_write_context; +static guint64 gum_temp_stack[512]; + +guint8 +gum_try_read_and_write_at (guint8 * a, + guint i, + gboolean * exception_raised_on_read, + gboolean * exception_raised_on_write) { -#ifdef HAVE_DARWIN - int mib[4]; - struct kinfo_proc info; - size_t size; + guint8 dummy_value_to_trick_optimizer = 0; + GumExceptor * exceptor; + PVOID handler; - info.kp_proc.p_flag = 0; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid (); + if (exception_raised_on_read != NULL) + *exception_raised_on_read = FALSE; + if (exception_raised_on_write != NULL) + *exception_raised_on_write = FALSE; - size = sizeof (info); - sysctl (mib, G_N_ELEMENTS (mib), &info, &size, NULL, 0); + exceptor = gum_exceptor_obtain (); - return (info.kp_proc.p_flag & P_TRACED) != 0; -#else - /* FIXME */ - return FALSE; -#endif + handler = AddVectoredExceptionHandler (TRUE, on_exception); + + if (setjmp (gum_try_read_and_write_context) == 0) + { + dummy_value_to_trick_optimizer = a[i]; + } + else + { + if (exception_raised_on_read != NULL) + *exception_raised_on_read = TRUE; + } + + if (setjmp (gum_try_read_and_write_context) == 0) + { + a[i] = 42; + } + else + { + if (exception_raised_on_write != NULL) + *exception_raised_on_write = TRUE; + } + + RemoveVectoredExceptionHandler (handler); + + g_object_unref (exceptor); + + return dummy_value_to_trick_optimizer; +} + +static WINAPI LONG +on_exception (PEXCEPTION_POINTERS info) +{ +# if GLIB_SIZEOF_VOID_P == 8 + info->ContextRecord->Rip = GPOINTER_TO_SIZE (recover_from_exception); + info->ContextRecord->Rsp = GPOINTER_TO_SIZE (gum_temp_stack + + G_N_ELEMENTS (gum_temp_stack)); +# else + info->ContextRecord->Eip = GPOINTER_TO_SIZE (recover_from_exception); + info->ContextRecord->Esp = GPOINTER_TO_SIZE (gum_temp_stack + + G_N_ELEMENTS (gum_temp_stack)); +# endif + return EXCEPTION_CONTINUE_EXECUTION; } +static void +recover_from_exception (void) +{ + longjmp (gum_try_read_and_write_context, 1337); +} + +#else + +# ifdef HAVE_DARWIN +# define GUM_SETJMP(env) setjmp (env) +# define GUM_LONGJMP(env, val) longjmp (env, val) + typedef jmp_buf gum_jmp_buf; +# else +# define GUM_SETJMP(env) sigsetjmp (env, 1) +# define GUM_LONGJMP(env, val) siglongjmp (env, val) + typedef sigjmp_buf gum_jmp_buf; +# endif + static gum_jmp_buf gum_try_read_and_write_context; static struct sigaction gum_test_old_sigsegv; static struct sigaction gum_test_old_sigbus; @@ -590,12 +661,12 @@ gum_try_read_and_write_at (guint8 * a, sigaction (SIGSEGV, &action, &gum_test_old_sigsegv); sigaction (SIGBUS, &action, &gum_test_old_sigbus); -#ifdef HAVE_ANDROID +# ifdef HAVE_ANDROID /* Work-around for Bionic bug up to and including Android L */ sigset_t mask; sigprocmask (SIG_SETMASK, NULL, &mask); -#endif +# endif if (GUM_SETJMP (gum_try_read_and_write_context) == 0) { @@ -606,7 +677,7 @@ gum_try_read_and_write_at (guint8 * a, if (exception_raised_on_read != NULL) *exception_raised_on_read = TRUE; -#ifdef HAVE_DARWIN +# ifdef HAVE_DARWIN /* * The Darwin Exceptor backend will currently disengage on an unhandled * exception. This is because guarded Mach ports may make it impossible @@ -614,12 +685,12 @@ gum_try_read_and_write_at (guint8 * a, * this by detecting that the process has guarded ports. */ gum_exceptor_reset (exceptor); -#endif +# endif } -#ifdef HAVE_ANDROID +# ifdef HAVE_ANDROID sigprocmask (SIG_SETMASK, &mask, NULL); -#endif +# endif if (GUM_SETJMP (gum_try_read_and_write_context) == 0) { @@ -630,14 +701,14 @@ gum_try_read_and_write_at (guint8 * a, if (exception_raised_on_write != NULL) *exception_raised_on_write = TRUE; -#ifdef HAVE_DARWIN +# ifdef HAVE_DARWIN gum_exceptor_reset (exceptor); -#endif +# endif } -#ifdef HAVE_ANDROID +# ifdef HAVE_ANDROID sigprocmask (SIG_SETMASK, &mask, NULL); -#endif +# endif sigaction (SIGSEGV, &gum_test_old_sigsegv, NULL); memset (&gum_test_old_sigsegv, 0, sizeof (gum_test_old_sigsegv));