Skip to content

Commit

Permalink
windows: Improve support for building with MinGW
Browse files Browse the repository at this point in the history
  • Loading branch information
oleavr committed Nov 14, 2023
1 parent 91cc571 commit d6300bb
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 92 deletions.
5 changes: 3 additions & 2 deletions bindings/gumjs/gumcmodule.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2022 Ole André Vadla Ravnås <[email protected]>
* Copyright (C) 2019-2023 Ole André Vadla Ravnås <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
*/
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions ext/dbghelp/dbghelp.h
Original file line number Diff line number Diff line change
Expand Up @@ -3905,7 +3905,9 @@ RangeMapWrite(
#include <poppack.h>


#ifndef __MINGW32__
#include <minidumpapiset.h>
#endif


#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PKG_WER) */
Expand Down
65 changes: 16 additions & 49 deletions gum/backend-x86/gumstalker-x86-glue.S
Original file line number Diff line number Diff line change
@@ -1,87 +1,54 @@
.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
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
6 changes: 6 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down
5 changes: 5 additions & 0 deletions tests/gumjs/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
153 changes: 112 additions & 41 deletions tests/testutil.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2022 Ole André Vadla Ravnås <[email protected]>
* Copyright (C) 2008-2023 Ole André Vadla Ravnås <[email protected]>
* Copyright (C) 2008 Christian Berentsen <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -606,20 +677,20 @@ 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
* to forward to the previous handler. We may potentially improve on
* 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)
{
Expand All @@ -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));
Expand Down

0 comments on commit d6300bb

Please sign in to comment.