diff --git a/core/arch/aarch64/aarch64.asm b/core/arch/aarch64/aarch64.asm index 88a289c0df5..232247ec8ac 100644 --- a/core/arch/aarch64/aarch64.asm +++ b/core/arch/aarch64/aarch64.asm @@ -587,14 +587,14 @@ GLOBAL_LABEL(main_signal_handler:) #if defined(MACOS) && defined(AARCH64) DECLARE_FUNC(dynamorio_sigreturn) GLOBAL_LABEL(dynamorio_sigreturn:) - /* TODO i#5383: Get correct syscall number for svc. */ - brk 0xb001 /* For now we break with a unique code. */ + mov w16, #184 /* SYS_sigreturn. */ + svc #0x80 END_FUNC(dynamorio_sigreturn) DECLARE_FUNC(dynamorio_sys_exit) GLOBAL_LABEL(dynamorio_sys_exit:) - /* TODO i#5383: Get correct syscall number for svc. */ - brk 0xb002 /* For now we break with a unique code. */ + mov w16, #1 /* SYS_exit. */ + svc #0x80 END_FUNC(dynamorio_sys_exit) DECLARE_FUNC(new_bsdthread_intercept) @@ -607,9 +607,17 @@ GLOBAL_LABEL(new_bsdthread_intercept:) #ifdef MACOS DECLARE_FUNC(main_signal_handler) GLOBAL_LABEL(main_signal_handler:) - /* see sendsig_set_thread_state64 in unix_signal.c */ - mov ARG6, sp - b GLOBAL_REF(main_signal_handler_C) /* chain call */ + /* See sendsig_set_thread_state64 in unix_signal.c */ + mov ARG7, sp + /* Save 3 args (ucxt=5th, style=2nd, token=6th) for sigreturn. */ + stp ARG5, ARG6, [sp, #-32]! + str ARG2, [sp, #16] + mov ARG6, ARG7 + bl GLOBAL_REF(main_signal_handler_C) + ldr ARG2, [sp, #16] + ldp ARG1, ARG3, [sp], #32 + CALLC0(GLOBAL_REF(dynamorio_sigreturn)) + bl GLOBAL_REF(unexpected_return) END_FUNC(main_signal_handler) #endif diff --git a/core/unix/os.c b/core/unix/os.c index f131532d859..ed7981d64b5 100644 --- a/core/unix/os.c +++ b/core/unix/os.c @@ -5422,13 +5422,15 @@ syscall_successful(priv_mcontext_t *mc, int normalized_sysnum) * We defer to drsyscall. */ return ((ptr_int_t)MCXT_SYSCALL_RES(mc) >= 0); - } else + } else { # ifdef X86 return !TEST(EFLAGS_CF, mc->xflags); +# elif defined(AARCH64) + return !TEST(EFLAGS_C, mc->xflags); # else - return -1; +# error NYI # endif - + } #else if (normalized_sysnum == IF_X64_ELSE(SYS_mmap, SYS_mmap2) || # if !defined(ARM) && !defined(X64) @@ -5450,11 +5452,17 @@ set_success_return_val(dcontext_t *dcontext, reg_t val) { /* since always coming from d_r_dispatch now, only need to set mcontext */ priv_mcontext_t *mc = get_mcontext(dcontext); -#if defined(MACOS) && defined(X86) +#ifdef MACOS /* On MacOS, success is determined by CF, except for Mach syscalls, but * there it doesn't hurt to set CF. */ +# ifdef X86 mc->xflags &= ~(EFLAGS_CF); +# elif defined(AARCH64) + mc->xflags &= ~(EFLAGS_C); +# else +# error NYI +# endif #endif MCXT_SYSCALL_RES(mc) = val; } @@ -5464,9 +5472,15 @@ static inline void set_failure_return_val(dcontext_t *dcontext, uint errno_val) { priv_mcontext_t *mc = get_mcontext(dcontext); -#if defined(MACOS) && defined(X86) +#ifdef MACOS /* On MacOS, success is determined by CF, and errno is positive */ +# ifdef X86 mc->xflags |= EFLAGS_CF; +# elif defined(AARCH64) + mc->xflags |= EFLAGS_C; +# else +# error NYI +# endif MCXT_SYSCALL_RES(mc) = errno_val; #else MCXT_SYSCALL_RES(mc) = -(int)errno_val; diff --git a/core/unix/signal.c b/core/unix/signal.c index 63b752c0312..6ff6a40269d 100644 --- a/core/unix/signal.c +++ b/core/unix/signal.c @@ -340,7 +340,7 @@ dump_unmasked(dcontext_t *dcontext, const char *where) LOG(THREAD, LOG_ASYNCH, 3, "%s: threads_unmasked: ", where); for (int i = 1; i <= MAX_SIGNUM; i++) { LOG(THREAD, LOG_ASYNCH, 3, "[%d]=%d ", i, info->sighand->threads_unmasked[i]); - if (i % 16 == 0) + if (i % 16 == 0 || i == MAX_SIGNUM) LOG(THREAD, LOG_ASYNCH, 3, "\n"); } } @@ -3050,13 +3050,11 @@ set_sigcxt_stolen_reg(sigcontext_t *sc, reg_t val) *(&sc->SC_R0 + (dr_reg_stolen - DR_REG_R0)) = val; } -# ifndef MACOS /* TODO i#5383: Add full signal support. */ static reg_t get_sigcxt_stolen_reg(sigcontext_t *sc) { return *(&sc->SC_R0 + (dr_reg_stolen - DR_REG_R0)); } -# endif # ifndef AARCH64 static dr_isa_mode_t @@ -4043,7 +4041,7 @@ transfer_from_sig_handler_to_fcache_return(dcontext_t *dcontext, kernel_ucontext * still go to the private fcache_return for simplicity. */ sc->SC_XIP = (ptr_uint_t)fcache_return_routine(dcontext); -#if defined(AARCHXX) && !defined(MACOS) +#if defined(AARCHXX) /* We do not have to set dr_reg_stolen in dcontext's mcontext here * because dcontext's mcontext is stale and we used the mcontext * created from recreate_app_state_internal with the original sigcontext. @@ -6276,10 +6274,7 @@ execute_handler_from_dispatch(dcontext_t *dcontext, int sig) dump_sigcontext(dcontext, sc); LOG(THREAD, LOG_ASYNCH, 3, "\n"); } -# ifndef MACOS IF_AARCHXX(ASSERT(get_sigcxt_stolen_reg(sc) != (reg_t)*get_dr_tls_base_addr())); -# endif - #endif /* FIXME: other state? debug regs? * if no syscall allowed between main_ (when frame created) and @@ -6384,7 +6379,17 @@ execute_handler_from_dispatch(dcontext_t *dcontext, int sig) /* Set up args to handler: int sig, kernel_siginfo_t *siginfo, * kernel_ucontext_t *ucxt. */ -#if defined(MACOS64) && defined(X86) +#if defined(MACOS64) && defined(AARCH64) + mcontext->r0 = (reg_t)info->sighand->action[sig]->handler; + int infostyle = TEST(SA_SIGINFO, info->sighand->action[sig]->flags) + ? SIGHAND_STYLE_UC_FLAVOR + : SIGHAND_STYLE_UC_TRAD; + mcontext->r1 = infostyle; + mcontext->r2 = sig; + mcontext->r3 = (reg_t) & ((sigframe_rt_t *)xsp)->info; + mcontext->r4 = (reg_t) & ((sigframe_rt_t *)xsp)->uc; + mcontext->lr = (reg_t)dynamorio_sigreturn; +#elif defined(MACOS64) && defined(X86) mcontext->xdi = (reg_t)info->sighand->action[sig]->handler; int infostyle = TEST(SA_SIGINFO, info->sighand->action[sig]->flags) ? SIGHAND_STYLE_UC_FLAVOR @@ -7347,7 +7352,7 @@ handle_sigreturn(dcontext_t *dcontext, void *ucxt_param, int style) * look like whatever would happen to the app... */ ASSERT((app_pc)sc->SC_XIP != next_pc); -# if defined(AARCHXX) && !defined(MACOS) +# if defined(AARCHXX) ASSERT(get_sigcxt_stolen_reg(sc) != (reg_t)*get_dr_tls_base_addr()); /* We're called from DR and are not yet in the cache, so we want to set the * mcontext slot, not the TLS slot, to set the stolen reg value. diff --git a/core/unix/signal_macos.c b/core/unix/signal_macos.c index 658007eee80..db6d1c35750 100644 --- a/core/unix/signal_macos.c +++ b/core/unix/signal_macos.c @@ -1,5 +1,5 @@ /* ******************************************************************************* - * Copyright (c) 2013-2022 Google, Inc. All rights reserved. + * Copyright (c) 2013-2023 Google, Inc. All rights reserved. * *******************************************************************************/ /* @@ -152,10 +152,14 @@ void sigcontext_to_mcontext_simd(priv_mcontext_t *mc, sig_full_cxt_t *sc_full) { #ifdef AARCH64 - ASSERT_NOT_IMPLEMENTED(false); -#endif - -#ifdef X86 + _STRUCT_ARM_NEON_STATE64 *fpc = (_STRUCT_ARM_NEON_STATE64 *)sc_full->fp_simd_state; + if (fpc == NULL) + return; + mc->fpsr = fpc->__fpsr; + mc->fpcr = fpc->__fpcr; + ASSERT(sizeof(mc->simd) == sizeof(fpc->__v)); + memcpy(&mc->simd, &fpc->__v, sizeof(mc->simd)); +#elif defined(X86) /* We assume that _STRUCT_X86_FLOAT_STATE* matches exactly the first * half of _STRUCT_X86_AVX_STATE*, and similarly for AVX and AVX512. */ @@ -190,8 +194,15 @@ sigcontext_to_mcontext_simd(priv_mcontext_t *mc, sig_full_cxt_t *sc_full) void mcontext_to_sigcontext_simd(sig_full_cxt_t *sc_full, priv_mcontext_t *mc) { - IF_AARCHXX(ASSERT_NOT_REACHED()); -#ifdef X86 +#ifdef AARCH64 + _STRUCT_ARM_NEON_STATE64 *fpc = (_STRUCT_ARM_NEON_STATE64 *)sc_full->fp_simd_state; + if (fpc == NULL) + return; + fpc->__fpsr = mc->fpsr; + fpc->__fpcr = mc->fpcr; + ASSERT(sizeof(mc->simd) == sizeof(fpc->__v)); + memcpy(&fpc->__v, &mc->simd, sizeof(mc->simd)); +#elif defined(X86) sigcontext_t *sc = sc_full->sc; int i; for (i = 0; i < proc_num_simd_registers(); i++) { @@ -223,8 +234,19 @@ mcontext_to_sigcontext_simd(sig_full_cxt_t *sc_full, priv_mcontext_t *mc) static void dump_fpstate(dcontext_t *dcontext, sigcontext_t *sc) { - IF_AARCHXX(ASSERT_NOT_REACHED()); -#ifdef X86 +#ifdef AARCH64 + _STRUCT_ARM_NEON_STATE64 *fpc = &sc->__ns; + LOG(THREAD, LOG_ASYNCH, 1, "\tfpsr=0x%08x\n", fpc->__fpsr); + LOG(THREAD, LOG_ASYNCH, 1, "\tfpcr=0x%08x\n", fpc->__fpcr); + int i, j; + for (i = 0; i < sizeof(fpc->__v) / sizeof(fpc->__v[0]); i++) { + LOG(THREAD, LOG_ASYNCH, 1, "\tv[%d] = 0x", i); + for (j = 0; j < 4; j++) { + LOG(THREAD, LOG_ASYNCH, 1, "%08x", *(((uint *)&fpc->__v[i]) + j)); + } + LOG(THREAD, LOG_ASYNCH, 1, "\n"); + } +#elif defined(X86) int i, j; LOG(THREAD, LOG_ASYNCH, 1, "\tfcw=0x%04x\n", *(ushort *)&sc->__fs.__fpu_fcw); LOG(THREAD, LOG_ASYNCH, 1, "\tfsw=0x%04x\n", *(ushort *)&sc->__fs.__fpu_fsw); @@ -306,8 +328,17 @@ dump_sigcontext(dcontext_t *dcontext, sigcontext_t *sc) LOG(THREAD, LOG_ASYNCH, 1, "\terr=0x%08x\n", sc->__es.__err); LOG(THREAD, LOG_ASYNCH, 1, "\tfaultvaddr=" PFX "\n", sc->__es.__faultvaddr); #else - /* TODO i#5383: NYI. */ - LOG(THREAD, LOG_ASYNCH, 1, "\tTODO: AARCH64 DUMP\n"); + LOG(THREAD, LOG_ASYNCH, 1, "\tfault=" PFX "\n", sc->__es.__far); + LOG(THREAD, LOG_ASYNCH, 1, "\tesr=0x08x\n", sc->__es.__esr); + LOG(THREAD, LOG_ASYNCH, 1, "\tcount=0x%08x\n", sc->__es.__exception); + int i; + for (i = 0; i < 29; i++) + LOG(THREAD, LOG_ASYNCH, 1, "\tr%d=" PFX "\n", i, sc->__ss.__x[i]); + LOG(THREAD, LOG_ASYNCH, 1, "\tfp=" PFX "\n", sc->__ss.__fp); + LOG(THREAD, LOG_ASYNCH, 1, "\tlr=" PFX "\n", sc->__ss.__lr); + LOG(THREAD, LOG_ASYNCH, 1, "\tsp=" PFX "\n", sc->__ss.__sp); + LOG(THREAD, LOG_ASYNCH, 1, "\tpc=" PFX "\n", sc->__ss.__pc); + LOG(THREAD, LOG_ASYNCH, 1, "\tcpsr=0x%08x\n", sc->__ss.__cpsr); #endif dump_fpstate(dcontext, sc); diff --git a/core/unix/signal_private.h b/core/unix/signal_private.h index ebe540ce131..251145be0f9 100644 --- a/core/unix/signal_private.h +++ b/core/unix/signal_private.h @@ -1,5 +1,5 @@ /* ********************************************************** - * Copyright (c) 2011-2022 Google, Inc. All rights reserved. + * Copyright (c) 2011-2023 Google, Inc. All rights reserved. * Copyright (c) 2008-2010 VMware, Inc. All rights reserved. * **********************************************************/ @@ -288,7 +288,11 @@ typedef struct rt_sigframe { # endif #elif defined(MACOS) -# ifdef X64 +# ifdef AARCH64 + kernel_siginfo_t info; + struct __darwin_ucontext64 uc; + struct __darwin_mcontext64 mc; +# elif defined(X64) /* Kernel places padding to align to 16 (via an inefficient alignment macro!), * and then skips the retaddr slot to align to 8. */ @@ -299,13 +303,9 @@ typedef struct rt_sigframe { * like on Linux? We would get the size by counting from "info". * Also, should we change this to sigcontext_t. */ -# if defined(AARCH64) - struct __darwin_mcontext64 mc; -# else struct __darwin_mcontext_avx64 mc; /* sigcontext, "struct mcontext_avx64" to kernel */ -# endif - kernel_siginfo_t info; /* matches user-mode sys/signal.h struct */ - struct __darwin_ucontext64 uc; /* "struct user_ucontext64" to kernel */ + kernel_siginfo_t info; /* matches user-mode sys/signal.h struct */ + struct __darwin_ucontext64 uc; /* "struct user_ucontext64" to kernel */ # else app_pc retaddr; app_pc handler; diff --git a/core/unix/tls_macos.c b/core/unix/tls_macos.c index 7e87be10ca0..eed925d23b0 100644 --- a/core/unix/tls_macos.c +++ b/core/unix/tls_macos.c @@ -193,6 +193,15 @@ get_app_tls_swap_slot_addr(void) } #endif +#ifdef AARCH64 +/* Shared with Linux AArch64 code. */ +byte ** +get_dr_tls_base_addr(void) +{ + return get_app_tls_swap_slot_addr(); +} +#endif + void tls_thread_init(os_local_state_t *os_tls, byte *segment) { diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index 22947cbe0da..e11a61a3836 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -1221,8 +1221,13 @@ function(runtest_cmd outcmd outops key native standalone_dr dr_ops_aux separate_ prefix_cmd_if_necessary(cmd OFF ${cmd}) # We set LD_LIBRARY_PATH for native api/ apps since we're not setting # rpath (to make it easier to try different trees) - set(cmd ${cmd} -env LD_LIBRARY_PATH - "${MAIN_LIBRARY_OUTPUT_DIRECTORY}:${EXT_LIBRARY_OUTPUT_DIRECTORY}:$ENV{LD_LIBRARY_PATH}") + if (APPLE) + set(libvar "DYLD_LIBRARY_PATH") + else () + set(libvar "LD_LIBRARY_PATH") + endif () + set(cmd ${cmd} -env ${libvar} + "${MAIN_LIBRARY_OUTPUT_DIRECTORY}:${EXT_LIBRARY_OUTPUT_DIRECTORY}:$ENV{${libvar}}") # add dr_ops last to avoid needing extra \ on ; string(REPLACE ";" " " dr_ops_string "${dr_ops}") set(${outcmd} ${cmd} -env DYNAMORIO_OPTIONS "${dr_ops_string}" PARENT_SCOPE) diff --git a/suite/tests/tools.c b/suite/tests/tools.c index 7af41b4305c..64873b3561b 100644 --- a/suite/tests/tools.c +++ b/suite/tests/tools.c @@ -41,6 +41,10 @@ # ifdef MACOS # include # include +# ifdef AARCH64 +void +pthread_jit_write_protect_np(int enabled); +# endif # endif # define ASSERT_NOT_IMPLEMENTED() \ @@ -170,8 +174,16 @@ char * allocate_mem(size_t size, int prot) { # ifdef UNIX - char *res = (char *)mmap((void *)0, size, get_os_prot_word(prot), - MAP_PRIVATE | MAP_ANON, -1, 0); + int flags = MAP_PRIVATE | MAP_ANON; +# if defined(MACOS) && defined(AARCH64) +# ifdef MACOS + if (TEST(ALLOW_EXEC, prot)) { + flags |= MAP_JIT; + pthread_jit_write_protect_np(0); + } +# endif +# endif + char *res = (char *)mmap((void *)0, size, get_os_prot_word(prot), flags, -1, 0); if (res == MAP_FAILED) return NULL; return res; @@ -201,6 +213,12 @@ protect_mem(void *start, size_t len, int prot) void *page_start = (void *)(((ptr_int_t)start) & ~(PAGE_SIZE - 1)); int page_len = (len + ((ptr_int_t)start - (ptr_int_t)page_start) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); +# ifdef MACOS + if (TEST(ALLOW_EXEC, prot) && !TEST(ALLOW_WRITE, prot)) { + pthread_jit_write_protect_np(1); + return; + } +# endif if (mprotect(page_start, page_len, get_os_prot_word(prot)) != 0) { print("Error on mprotect: %d\n", errno); }