[WIP] Reorganise Emulation Code

The goal of this commit is to have a buildable proof-of-concept for how I plan to reorganize the syscall code (and other miscellaneous code) in the emulation folder.

Note, It not expected for Darling to sucessfully execute the shell in this commit.
This commit is contained in:
Thomas A. 2024-10-15 21:53:17 -07:00
parent 814a90cae0
commit a3bfa8cca1
317 changed files with 4519 additions and 4557 deletions

View File

@ -8,7 +8,7 @@ endif(COMMAND cmake_policy)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(emulation/linux)
add_subdirectory(emulation)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3 -w -fblocks -ffreestanding")
@ -41,8 +41,11 @@ add_circular(system_kernel FAT
$<TARGET_OBJECTS:libsyscall>
$<TARGET_OBJECTS:libsyscall_dynamic>
#$<TARGET_OBJECTS:kqueue>
$<TARGET_OBJECTS:emulation>
$<TARGET_OBJECTS:mach_server_client>
$<TARGET_OBJECTS:emulation_common>
$<TARGET_OBJECTS:emulation_conversion>
$<TARGET_OBJECTS:emulation_darling>
$<TARGET_OBJECTS:emulation_linux_api>
$<TARGET_OBJECTS:emulation_xnu_syscall>
SIBLINGS
system_c
compiler_rt
@ -56,15 +59,21 @@ make_fat(system_kernel)
add_library(system_kernel_static32 STATIC
$<TARGET_OBJECTS:libsyscall_32>
$<TARGET_OBJECTS:libsyscall>
$<TARGET_OBJECTS:emulation_dyld>
$<TARGET_OBJECTS:mach_server_client_dyld>
$<TARGET_OBJECTS:emulation_common>
$<TARGET_OBJECTS:emulation_conversion>
$<TARGET_OBJECTS:emulation_darling_dyld>
$<TARGET_OBJECTS:emulation_linux_api>
$<TARGET_OBJECTS:emulation_xnu_syscall_dyld>
)
add_library(system_kernel_static64 STATIC
$<TARGET_OBJECTS:libsyscall_64>
$<TARGET_OBJECTS:libsyscall>
$<TARGET_OBJECTS:emulation_dyld>
$<TARGET_OBJECTS:mach_server_client_dyld>
$<TARGET_OBJECTS:emulation_common>
$<TARGET_OBJECTS:emulation_conversion>
$<TARGET_OBJECTS:emulation_darling_dyld>
$<TARGET_OBJECTS:emulation_linux_api>
$<TARGET_OBJECTS:emulation_xnu_syscall_dyld>
)
target_link_libraries(system_kernel_static32 PRIVATE

View File

@ -0,0 +1,24 @@
project(emulation)
# By default we don't want to expose these methods to normal macOS apps/frameworks
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-int-conversion -Wno-compare-distinct-pointer-types")
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_BINARY_DIR}/src/startup # include src/startup for rtsig.h
${CMAKE_BINARY_DIR}/src/external/darlingserver/include
${CMAKE_SOURCE_DIR}/src/external/darlingserver/include
${CMAKE_SOURCE_DIR}/src/libsimple/include
)
# Some projects may include build time checks for `VARIANT_DYLD`. It's important that
# those projects also have a `*_dyld` varient as well.
add_subdirectory(common)
add_subdirectory(conversion)
add_subdirectory(darling)
add_subdirectory(linux_api)
add_subdirectory(xnu_syscall)

View File

@ -0,0 +1,8 @@
project(emulation_common)
set(common_sources
simple.c
)
add_darling_object_library(emulation_common ${common_sources})
make_fat(emulation_common)

View File

@ -0,0 +1,15 @@
#ifndef DARLING_EMULATION_COMMON_BASE_H
#define DARLING_EMULATION_COMMON_BASE_H
#define VISIBLE __attribute__((visibility("default")))
#define WEAK __attribute__((weak))
#ifdef __cplusplus
#define CPP_EXTERN_C_BEGIN extern "C" {
#define CPP_EXTERN_C_END }
#else
#define CPP_EXTERN_C_BEGIN
#define CPP_EXTERN_C_END
#endif
#endif // DARLING_EMULATION_COMMON_BASE_H

View File

@ -1,17 +1,19 @@
#include "base.h"
#include "simple.h"
#include <stdarg.h>
#include <stddef.h>
#include <linux-syscalls/linux.h>
#include "mach/lkm.h"
#include "signal/kill.h"
#include "unistd/getpid.h"
#include <sys/signal.h>
#include <darlingserver/rpc.h>
#include <emulation/common/base.h>
#include <emulation/linux_api/linux_syscall.h>
#include <emulation/xnu_syscall/bsd/impl/signal/kill.h>
#include <emulation/xnu_syscall/bsd/impl/unistd/getpid.h>
extern char* memchr(char* buf, int c, __SIZE_TYPE__ n);
__attribute__ ((visibility ("default")))
VISIBLE
int __simple_strlen(const char* text)
{
int len = 0;
@ -30,7 +32,7 @@ if (VALUE != NULL) { \
DO; \
}
__attribute__ ((visibility ("default")))
VISIBLE
int __simple_vsnprintf(char* buf, size_t max_length, const char* format, va_list vl)
{
size_t offset = 0;
@ -358,13 +360,13 @@ int __simple_vsnprintf(char* buf, size_t max_length, const char* format, va_list
return offset;
}
__attribute__ ((visibility ("default")))
VISIBLE
int __simple_vsprintf(char* buf, const char* format, va_list vl)
{
return __simple_vsnprintf(buf, SIZE_MAX, format, vl);
}
__attribute__ ((visibility ("default")))
VISIBLE
void __simple_printf(const char* format, ...)
{
char buffer[512];
@ -377,7 +379,7 @@ void __simple_printf(const char* format, ...)
LINUX_SYSCALL3(__NR_write, 1, buffer, __simple_strlen(buffer));
}
__attribute__ ((visibility ("default")))
VISIBLE
void __simple_kprintf(const char* format, ...)
{
va_list vl;
@ -386,7 +388,7 @@ void __simple_kprintf(const char* format, ...)
va_end(vl);
}
__attribute__ ((visibility ("default")))
VISIBLE
void __simple_fprintf(int fd, const char* format, ...)
{
char buffer[512];
@ -399,7 +401,7 @@ void __simple_fprintf(int fd, const char* format, ...)
LINUX_SYSCALL3(__NR_write, fd, buffer, __simple_strlen(buffer));
}
__attribute__ ((visibility ("default")))
VISIBLE
void __simple_vprintf(const char* format, va_list args)
{
char buffer[512];
@ -407,7 +409,7 @@ void __simple_vprintf(const char* format, va_list args)
LINUX_SYSCALL3(__NR_write, 1, buffer, __simple_strlen(buffer));
}
__attribute__ ((visibility ("default")))
VISIBLE
void __simple_vkprintf(const char* format, va_list args)
{
char buffer[512];
@ -415,7 +417,7 @@ void __simple_vkprintf(const char* format, va_list args)
dserver_rpc_kprintf(buffer, __simple_strlen(buffer));
}
__attribute__ ((visibility ("default")))
VISIBLE
void __simple_vfprintf(int fd, const char* format, va_list args)
{
char buffer[512];
@ -423,7 +425,7 @@ void __simple_vfprintf(int fd, const char* format, va_list args)
LINUX_SYSCALL3(__NR_write, fd, buffer, __simple_strlen(buffer));
}
__attribute__ ((visibility ("default")))
VISIBLE
int __simple_sprintf(char *buffer, const char* format, ...)
{
va_list vl;
@ -435,7 +437,7 @@ int __simple_sprintf(char *buffer, const char* format, ...)
return ret;
}
__attribute__ ((visibility ("default")))
VISIBLE
int __simple_snprintf(char* buffer, size_t max_length, const char* format, ...)
{
va_list args;
@ -467,7 +469,7 @@ static int isdigit16(char c)
return 0;
}
__attribute__ ((visibility ("default")))
VISIBLE
unsigned long long __simple_atoi(const char* str, const char** endp)
{
unsigned long long value = 0;
@ -484,7 +486,7 @@ unsigned long long __simple_atoi(const char* str, const char** endp)
return value;
}
__attribute__ ((visibility ("default")))
VISIBLE
unsigned long long __simple_atoi16(const char* str, const char** endp)
{
unsigned long long value = 0;
@ -516,13 +518,13 @@ extern long sys_read(int fd, void* buf, __SIZE_TYPE__ n);
# define min(a,b) ((a) < (b) ? (a) : (b))
#endif
__attribute__ ((visibility ("default")))
VISIBLE
void __simple_readline_init(struct simple_readline_buf* buf)
{
buf->used = 0;
}
__attribute__ ((visibility ("default")))
VISIBLE
char* __simple_readline(int fd, struct simple_readline_buf* buf, char* out, int max_out)
{
char* nl = NULL;
@ -573,7 +575,7 @@ have_nl:
return out;
}
__attribute__ ((visibility ("default")))
VISIBLE
void __simple_abort(void) {
sys_kill(sys_getpid(), SIGABRT, 1);
__builtin_unreachable();

View File

@ -1,14 +1,14 @@
#ifndef LINUX_DEBUG_H
#define LINUX_DEBUG_H
#ifndef DARLING_EMULATION_COMMON_SIMPLE_H
#define DARLING_EMULATION_COMMON_SIMPLE_H
#include <stdarg.h>
#include <stddef.h>
#include <darling/emulation/common/base.h>
// everything in this header can be used outside of libsystem_kernel
#ifdef __cplusplus
extern "C" {
#endif
CPP_EXTERN_C_BEGIN
void __simple_printf(const char* format, ...) __attribute__((format(printf, 1, 2)));
void __simple_kprintf(const char* format, ...) __attribute__((format(printf, 1, 2)));
@ -37,9 +37,6 @@ char* __simple_readline(int fd, struct simple_readline_buf* buf, char* out, int
__attribute__((noreturn))
void __simple_abort(void);
#ifdef __cplusplus
};
#endif
#endif
CPP_EXTERN_C_END
#endif // DARLING_EMULATION_COMMON_SIMPLE_H

View File

@ -0,0 +1,15 @@
project(emulation_conversion)
set(conversion_sources
at.c
errno.c
signal.c
stat.c
network/common.c
signal/context.c
signal/sigaction.c
signal/sigexc.c
)
add_darling_object_library(emulation_conversion ${conversion_sources})
make_fat(emulation_conversion)

View File

@ -1,5 +1,4 @@
#include "common_at.h"
#include "bsdthread/per_thread_wd.h"
#include "at.h"
int atflags_bsd_to_linux(int flags)
{
@ -25,10 +24,3 @@ int atflags_bsd_to_linux(int flags)
return linux_flags;
}
int atfd(int fd)
{
if (fd == BSD_AT_FDCWD)
return get_perthread_wd();
return fd;
}

View File

@ -1,5 +1,5 @@
#ifndef _COMMON_AT_H
#define _COMMON_AT_H
#ifndef DARLING_EMULATION_CONVERSION_AT_H
#define DARLING_EMULATION_CONVERSION_AT_H
// Common declarations for the *at family of system calls
@ -23,5 +23,4 @@ int atflags_bsd_to_linux(int flags);
int atfd(int fd);
#endif
#endif // DARLING_EMULATION_CONVERSION_AT_H

View File

@ -1,10 +1,9 @@
#include "errno.h"
#include "base.h"
#include "duct_errno.h"
#include <stddef.h>
#include <sys/errno.h>
static const int linux_to_darwin[512] = {
[LINUX_EPERM] = EPERM,
[LINUX_ENOENT] = ENOENT,
[LINUX_ESRCH] = ESRCH,

View File

@ -0,0 +1,134 @@
#ifndef DARLING_EMULATION_CONVERSION_ERRNO_H
#define DARLING_EMULATION_CONVERSION_ERRNO_H
#define LINUX_EPERM 1
#define LINUX_ENOENT 2
#define LINUX_ESRCH 3
#define LINUX_EINTR 4
#define LINUX_EIO 5
#define LINUX_ENXIO 6
#define LINUX_ENOEXEC 8
#define LINUX_EBADF 9
#define LINUX_ECHILD 10
#define LINUX_EAGAIN 11
#define LINUX_ENOMEM 12
#define LINUX_EACCES 13
#define LINUX_EFAULT 14
#define LINUX_ENOTBLK 15
#define LINUX_EBUSY 16
#define LINUX_EEXIST 17
#define LINUX_EXDEV 18
#define LINUX_ENODEV 19
#define LINUX_ENOTDIR 20
#define LINUX_EISDIR 21
#define LINUX_EINVAL 22
#define LINUX_ENFILE 23
#define LINUX_EMFILE 24
#define LINUX_ENOTTY 25
#define LINUX_ETXTBSY 26
#define LINUX_EFBIG 27
#define LINUX_ENOSPC 28
#define LINUX_ESPIPE 29
#define LINUX_EROFS 30
#define LINUX_EMLINK 31
#define LINUX_EPIPE 32
#define LINUX_EDOM 33
#define LINUX_ERANGE 34
#define LINUX_EDEADLK 35
#define LINUX_ENAMETOOLONG 36
#define LINUX_ENOLCK 37
#define LINUX_ENOSYS 38
#define LINUX_ENOTEMPTY 39
#define LINUX_ELOOP 40
#define LINUX_ENOMSG 42
#define LINUX_EIDRM 43
#define LINUX_ECHRNG 44
#define LINUX_ELNRNG 48
#define LINUX_EUNATCH 49
#define LINUX_ENOCSI 50
#define LINUX_EBADE 52
#define LINUX_EBADR 53
#define LINUX_EXFULL 54
#define LINUX_ENOANO 55
#define LINUX_EBADRQC 56
#define LINUX_EBADSLT 57
#define LINUX_EBFONT 59
#define LINUX_ENOSTR 60
#define LINUX_ENODATA 61
#define LINUX_ETIME 62
#define LINUX_ENOSR 63
#define LINUX_ENONET 64
#define LINUX_ENOPKG 65
#define LINUX_EREMOTE 66
#define LINUX_ENOLINK 67
#define LINUX_EADV 68
#define LINUX_ESRMNT 69
#define LINUX_ECOMM 70
#define LINUX_EPROTO 71
#define LINUX_EMULTIHOP 72
#define LINUX_EDOTDOT 73
#define LINUX_EBADMSG 74
#define LINUX_EOVERFLOW 75
#define LINUX_ENOTUNIQ 76
#define LINUX_EBADFD 77
#define LINUX_EREMCHG 78
#define LINUX_ELIBACC 79
#define LINUX_ELIBBAD 80
#define LINUX_ELIBSCN 81
#define LINUX_ELIBMAX 82
#define LINUX_ELIBEXEC 83
#define LINUX_EILSEQ 84
#define LINUX_ERESTART 85
#define LINUX_ESTRPIPE 86
#define LINUX_EUSERS 87
#define LINUX_ENOTSOCK 88
#define LINUX_EDESTADDRREQ 89
#define LINUX_EMSGSIZE 90
#define LINUX_EPROTOTYPE 91
#define LINUX_ENOPROTOOPT 92
#define LINUX_EPROTONOSUPPORT 93
#define LINUX_ESOCKTNOSUPPORT 94
#define LINUX_EOPNOTSUPP 95
#define LINUX_EPFNOSUPPORT 96
#define LINUX_EAFNOSUPPORT 97
#define LINUX_EADDRINUSE 98
#define LINUX_EADDRNOTAVAIL 99
#define LINUX_ENETDOWN 100
#define LINUX_ENETUNREACH 101
#define LINUX_ENETRESET 102
#define LINUX_ECONNABORTED 103
#define LINUX_ECONNRESET 104
#define LINUX_ENOBUFS 105
#define LINUX_EISCONN 106
#define LINUX_ENOTCONN 107
#define LINUX_ESHUTDOWN 108
#define LINUX_ETOOMANYREFS 109
#define LINUX_ETIMEDOUT 110
#define LINUX_ECONNREFUSED 111
#define LINUX_EHOSTDOWN 112
#define LINUX_EHOSTUNREACH 113
#define LINUX_EALREADY 114
#define LINUX_EINPROGRESS 115
#define LINUX_ESTALE 116
#define LINUX_EUCLEAN 117
#define LINUX_ENOTNAM 118
#define LINUX_ENAVAIL 119
#define LINUX_EISNAM 120
#define LINUX_EREMOTEIO 121
#define LINUX_EDQUOT 122
#define LINUX_ENOMEDIUM 123
#define LINUX_EMEDIUMTYPE 124
#define LINUX_ECANCELED 125
#define LINUX_ENOKEY 126
#define LINUX_EKEYEXPIRED 127
#define LINUX_EKEYREVOKED 128
#define LINUX_EKEYREJECTED 129
#define LINUX_EOWNERDEAD 130
#define LINUX_ENOTRECOVERABLE 131
#define LINUX_ERFKILL 132
#define LINUX_EHWPOISON 133
#define LINUX_ENOTSUP LINUX_EOPNOTSUPP
int errno_linux_to_bsd(int err);
#endif // DARLING_EMULATION_CONVERSION_ERRNO_H

View File

@ -1,5 +1,5 @@
#ifndef DUCT_MMAN_H
#define DUCT_MMAN_H
#ifndef DARLING_EMULATION_CONVERSION_MMAN_H
#define DARLING_EMULATION_CONVERSION_MMAN_H
#define LINUX_PROT_READ 0x1
#define LINUX_PROT_WRITE 0x2
@ -50,5 +50,4 @@
#include <sys/mman.h>
#endif
#endif // DARLING_EMULATION_CONVERSION_MMAN_H

View File

@ -1,5 +1,5 @@
#ifndef NETWORK_DUCT_H
#define NETWORK_DUCT_H
#ifndef DARLING_EMULATION_CONVERSION_NETWORK_H
#define DARLING_EMULATION_CONVERSION_NETWORK_H
int sfamily_linux_to_bsd(int family);
int sfamily_bsd_to_linux(int family);
@ -69,5 +69,4 @@ int sockaddr_fixup_from_linux(struct sockaddr_fixup* out, const void* linux_sock
#define BSD_MSG_RCVMORE 0x4000
#define BSD_MSG_NEEDSA 0x10000
#endif
#endif // DARLING_EMULATION_CONVERSION_NETWORK_H

View File

@ -1,9 +1,12 @@
#include "duct.h"
#include "../errno.h"
#include "../vchroot_expand.h"
#include "../bsdthread/per_thread_wd.h"
#include "../network.h"
#include <sys/socket.h>
#include <emulation/conversion/errno.h>
#include <emulation/darling/server/vchroot_userspace.h>
#include <emulation/darling/tsd/perthread_wd.h>
#include <emulation/xnu_syscall/shared/bsdthread/cancelable.h>
int sfamily_linux_to_bsd(int family)
{
switch (family)
@ -141,4 +144,4 @@ int sockaddr_fixup_from_linux(struct sockaddr_fixup* out, const void* linux_sock
}
return ret;
};
}

View File

@ -1,4 +1,4 @@
#include "duct_signals.h"
#include "signal.h"
int signum_linux_to_bsd(int signum)
{

View File

@ -1,5 +1,6 @@
#ifndef LINUX_DUCT_SIGNALS_H
#define LINUX_DUCT_SIGNALS_H
#ifndef DARLING_EMULATION_CONVERSION_SIGNAL_H
#define DARLING_EMULATION_CONVERSION_SIGNAL_H
#define __sigset_t_defined
#include <sys/signal.h>
@ -38,6 +39,7 @@
#define LINUX_SIGPWR 30
#define LINUX_SIGSYS 31
#define LINUX_SIGUNUSED 31
#define LINUX_SIGRTMIN 32
#define LINUX_SA_NOCLDSTOP 0x00000001u
#define LINUX_SA_NOCLDWAIT 0x00000002u
#define LINUX_SA_SIGINFO 0x00000004u
@ -60,5 +62,4 @@ int signum_bsd_to_linux(int signum);
void sigset_linux_to_bsd(const linux_sigset_t* linux, sigset_t* bsd);
void sigset_bsd_to_linux(const sigset_t* bsd, linux_sigset_t* linux);
#endif
#endif // DARLING_EMULATION_CONVERSION_SIGNAL_H

View File

@ -0,0 +1,280 @@
#include <emulation/common/simple.h>
#include <emulation/conversion/signal/sigexc.h>
#define DEBUG_SIGEXC
#ifdef DEBUG_SIGEXC
#define kern_printf(...) __simple_kprintf(__VA_ARGS__)
#else
#define kern_printf(...)
#endif
#define DUMPREG(regname) kern_printf("sigexc: " #regname ": 0x%llx\n", regs->regname);
// TODO: The code here is copied from both sigaction.c and sigexc.c, one thing that bothers me is that
// there is a lot of unnecessary code duplication...
void ucontext_linux_to_bsd(const struct linux_ucontext* lc, struct bsd_ucontext* bc, struct bsd_mcontext* bm)
{
bc->uc_onstack = 1;
bc->uc_mcsize = sizeof(struct bsd_mcontext);
bc->uc_mcontext = bm;
sigset_linux_to_bsd(&lc->uc_sigmask, &bc->uc_sigmask);
bc->uc_stack.ss_flags = lc->uc_stack.ss_flags;
bc->uc_stack.ss_size = lc->uc_stack.ss_size;
bc->uc_stack.ss_sp = lc->uc_stack.ss_sp;
bm->es.trapno = lc->uc_mcontext.gregs.trapno;
bm->es.cpu = 0;
bm->es.err = lc->uc_mcontext.gregs.err;
#ifdef __x86_64__
bm->es.faultvaddr = lc->uc_mcontext.gregs.rip;
#else
bm->es.faultvaddr = lc->uc_mcontext.gregs.eip;
#endif
#define copyreg(__name) bm->ss.__name = lc->uc_mcontext.gregs.__name
#ifdef __x86_64__
copyreg(rax); copyreg(rbx); copyreg(rcx); copyreg(rdx); copyreg(rdi); copyreg(rsi);
copyreg(rbp); copyreg(rsp); copyreg(r8); copyreg(r9); copyreg(r10);
copyreg(r11); copyreg(r12); copyreg(r13); copyreg(r14); copyreg(r15); copyreg(rip);
copyreg(cs); copyreg(fs); copyreg(gs);
bm->ss.rflags = lc->uc_mcontext.gregs.efl;
#elif defined(__i386__)
copyreg(eax); copyreg(ebx); copyreg(ecx); copyreg(edx); copyreg(edi); copyreg(esi);
copyreg(ebp); copyreg(esp);
copyreg(eip); copyreg(cs); copyreg(ds); copyreg(es); copyreg(fs); copyreg(gs);
bm->ss.eflags = lc->uc_mcontext.gregs.efl;
bm->ss.ss = 0;
#else
#warning Missing code for current arch
#endif
#undef copyreg
}
void mcontext_bsd_to_linux(const struct bsd_mcontext* bm, struct linux_mcontext* lm)
{
#define copyreg(__name) lm->gregs.__name = bm->ss.__name
#ifdef __x86_64__
copyreg(rax); copyreg(rbx); copyreg(rcx); copyreg(rdx); copyreg(rdi); copyreg(rsi);
copyreg(rbp); copyreg(rsp); copyreg(r8); copyreg(r9); copyreg(r10);
copyreg(r11); copyreg(r12); copyreg(r13); copyreg(r14); copyreg(r15); copyreg(rip);
copyreg(cs); copyreg(fs); copyreg(gs);
lm->gregs.efl = bm->ss.rflags;
#elif defined(__i386__)
copyreg(eax); copyreg(ebx); copyreg(ecx); copyreg(edx); copyreg(edi); copyreg(esi);
copyreg(ebp); copyreg(esp);
copyreg(eip); copyreg(cs); copyreg(ds); copyreg(es); copyreg(fs); copyreg(gs);
lm->gregs.efl = bm->ss.eflags;
#else
#warning Missing code for current arch
#endif
#undef copyreg
}
#if defined(__x86_64__)
void mcontext_to_thread_state(const struct linux_gregset* regs, x86_thread_state64_t* s)
{
s->__rax = regs->rax;
s->__rbx = regs->rbx;
s->__rcx = regs->rcx;
s->__rdx = regs->rdx;
s->__rdi = regs->rdi;
s->__rsi = regs->rsi;
s->__rbp = regs->rbp;
s->__rsp = regs->rsp;
s->__r8 = regs->r8;
s->__r9 = regs->r9;
s->__r10 = regs->r10;
s->__r11 = regs->r11;
s->__r12 = regs->r12;
s->__r13 = regs->r13;
s->__r14 = regs->r14;
s->__r15 = regs->r15;
s->__rip = regs->rip;
s->__rflags = regs->efl;
s->__cs = regs->cs;
s->__fs = regs->fs;
s->__gs = regs->gs;
kern_printf("sigexc: saving to kernel:\n");
DUMPREG(rip);
DUMPREG(efl);
DUMPREG(rax);
DUMPREG(rbx);
DUMPREG(rcx);
DUMPREG(rdx);
DUMPREG(rdi);
DUMPREG(rsi);
DUMPREG(rbp);
DUMPREG(rsp);
}
void mcontext_to_float_state(const linux_fpregset_t fx, x86_float_state64_t* s)
{
// fpregs is NULL on WSL1. See https://github.com/microsoft/WSL/issues/2555.
if (fx == NULL)
{
memset(s, 0, sizeof(x86_float_state64_t));
return;
}
kern_printf("sigexc: fcw out: 0x%x", fx->cwd);
kern_printf("sigexc: xmm0 out: 0x%x", fx->_xmm[0].element[0]);
*((uint16_t*)&s->__fpu_fcw) = fx->cwd;
*((uint16_t*)&s->__fpu_fsw) = fx->swd;
s->__fpu_ftw = fx->ftw;
s->__fpu_fop = fx->fop;
s->__fpu_ip = fx->rip;
s->__fpu_cs = 0;
s->__fpu_dp = fx->rdp;
s->__fpu_ds = 0;
s->__fpu_mxcsr = fx->mxcsr;
s->__fpu_mxcsrmask = fx->mxcr_mask;
memcpy(&s->__fpu_stmm0, fx->_st, 128);
memcpy(&s->__fpu_xmm0, fx->_xmm, 256);
}
void thread_state_to_mcontext(const x86_thread_state64_t* s, struct linux_gregset* regs)
{
regs->rax = s->__rax;
regs->rbx = s->__rbx;
regs->rcx = s->__rcx;
regs->rdx = s->__rdx;
regs->rdi = s->__rdi;
regs->rsi = s->__rsi;
regs->rbp = s->__rbp;
regs->rsp = s->__rsp;
regs->r8 = s->__r8;
regs->r9 = s->__r9;
regs->r10 = s->__r10;
regs->r11 = s->__r11;
regs->r12 = s->__r12;
regs->r13 = s->__r13;
regs->r14 = s->__r14;
regs->r15 = s->__r15;
regs->rip = s->__rip;
regs->efl = s->__rflags;
regs->cs = s->__cs;
regs->fs = s->__fs;
regs->gs = s->__gs;
kern_printf("sigexc: restored from kernel:\n");
DUMPREG(rip);
DUMPREG(efl);
DUMPREG(rax);
DUMPREG(rbx);
DUMPREG(rcx);
DUMPREG(rdx);
DUMPREG(rdi);
DUMPREG(rsi);
DUMPREG(rbp);
DUMPREG(rsp);
}
void float_state_to_mcontext(const x86_float_state64_t* s, linux_fpregset_t fx)
{
if (fx == NULL)
{
return;
}
fx->cwd = *((uint16_t*)&s->__fpu_fcw);
fx->swd = *((uint16_t*)&s->__fpu_fsw);
fx->ftw = s->__fpu_ftw;
fx->fop = s->__fpu_fop;
fx->rip = s->__fpu_ip;
fx->rdp = s->__fpu_dp;
fx->mxcsr = s->__fpu_mxcsr;
fx->mxcr_mask = s->__fpu_mxcsrmask;
memcpy(fx->_st, &s->__fpu_stmm0, 128);
memcpy(fx->_xmm, &s->__fpu_xmm0, 256);
kern_printf("sigexc: fcw in: 0x%x", fx->cwd);
kern_printf("sigexc: xmm0 in: 0x%x", fx->_xmm[0].element[0]);
}
#elif defined(__i386__)
void mcontext_to_thread_state(const struct linux_gregset* regs, x86_thread_state32_t* s)
{
s->__eax = regs->eax;
s->__ebx = regs->ebx;
s->__ecx = regs->ecx;
s->__edx = regs->edx;
s->__edi = regs->edi;
s->__esi = regs->esi;
s->__ebp = regs->ebp;
s->__esp = regs->esp;
s->__ss = regs->ss;
s->__eflags = regs->efl;
s->__eip = regs->eip;
s->__cs = regs->cs;
s->__ds = regs->ds;
s->__es = regs->es;
s->__fs = regs->fs;
s->__gs = regs->gs;
}
void mcontext_to_float_state(const linux_fpregset_t fx, x86_float_state32_t* s)
{
*((uint16_t*)&s->__fpu_fcw) = fx->cw;
*((uint16_t*)&s->__fpu_fsw) = fx->sw;
s->__fpu_ftw = fx->tag;
s->__fpu_fop = 0;
s->__fpu_ip = fx->ipoff;
s->__fpu_cs = fx->cssel;
s->__fpu_dp = fx->dataoff;
s->__fpu_ds = fx->datasel;
s->__fpu_mxcsr = fx->mxcsr;
s->__fpu_mxcsrmask = 0;
memcpy(&s->__fpu_stmm0, fx->_st, 128);
memcpy(&s->__fpu_xmm0, fx->_xmm, 128);
memset(((char*) &s->__fpu_xmm0) + 128, 0, 128);
}
void thread_state_to_mcontext(const x86_thread_state32_t* s, struct linux_gregset* regs)
{
regs->eax = s->__eax;
regs->ebx = s->__ebx;
regs->ecx = s->__ecx;
regs->edx = s->__edx;
regs->edi = s->__edi;
regs->esi = s->__esi;
regs->ebp = s->__ebp;
regs->esp = s->__esp;
regs->ss = s->__ss;
regs->efl = s->__eflags;
regs->eip = s->__eip;
regs->cs = s->__cs;
regs->ds = s->__ds;
regs->es = s->__es;
regs->fs = s->__fs;
regs->gs = s->__gs;
}
void float_state_to_mcontext(const x86_float_state32_t* s, linux_fpregset_t fx)
{
fx->cw = *((uint16_t*)&s->__fpu_fcw);
fx->sw = *((uint16_t*)&s->__fpu_fsw);
fx->tag = s->__fpu_ftw;
fx->ipoff = s->__fpu_ip;
fx->cssel = s->__fpu_cs;
fx->dataoff = s->__fpu_dp;
fx->datasel = s->__fpu_ds;
fx->mxcsr = s->__fpu_mxcsr;
memcpy(fx->_st, &s->__fpu_stmm0, 128);
memcpy(fx->_xmm, &s->__fpu_xmm0, 128);
}
#endif

View File

@ -1,106 +1,14 @@
#ifndef LINUX_SIGACTION_H
#define LINUX_SIGACTION_H
#include "duct_signals.h"
#include "sigaltstack.h"
#ifndef DARLING_EMULATION_CONVERSION_CONTEXT_H
#define DARLING_EMULATION_CONVERSION_CONTEXT_H
#undef sa_sigaction
#include <_libkernel_init.h>
#define BSD_SA_ONSTACK 0x0001
#define BSD_SA_RESTART 0x0002
#define BSD_SA_RESETHAND 0x0004
#define BSD_SA_NOCLDSTOP 0x0008
#define BSD_SA_NODEFER 0x0010
#define BSD_SA_NOCLDWAIT 0x0020
#define BSD_SA_SIGINFO 0x0040
#include <emulation/conversion/signal.h>
#include <emulation/xnu_syscall/bsd/impl/signal/sigaltstack.h>
#define LINUX_SA_NOCLDSTOP 0x00000001u
#define LINUX_SA_NOCLDWAIT 0x00000002u
#define LINUX_SA_SIGINFO 0x00000004u
#define LINUX_SA_ONSTACK 0x08000000u
#define LINUX_SA_RESTART 0x10000000u
#define LINUX_SA_NODEFER 0x40000000u
#define LINUX_SA_RESETHAND 0x80000000u
struct bsd_siginfo
{
int si_signo;
int si_errno;
int si_code;
unsigned int si_pid;
unsigned int si_uid;
int si_status;
void* si_addr;
void* si_val_ptr;
long si_band;
unsigned long __pad[7];
};
# define __SI_MAX_SIZE 128
# if defined (__x86_64__)
# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4)
# else
# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3)
# endif
struct linux_siginfo
{
int si_signo;
int si_errno;
int si_code;
union
{
struct
{
int si_pid;
int si_uid;
};
void* si_addr;
};
union
{
int _pad[__SI_PAD_SIZE];
unsigned long si_value;
};
};
typedef void (bsd_sig_handler)(int, struct bsd_siginfo*, void*);
typedef void (linux_sig_handler)(int, struct linux_siginfo*, void*);
#ifndef SIG_DFL
#define SIG_DFL (bsd_sig_handler*)0
#endif
#ifndef SIG_IGN
#define SIG_IGN (bsd_sig_handler*)1
#endif
#ifndef SIG_ERR
#define SIG_ERR ((bsd_sig_handler*)-1l)
#endif
struct bsd_sigaction
{
bsd_sig_handler* sa_sigaction;
unsigned int sa_mask;
int sa_flags;
};
struct bsd___sigaction
{
bsd_sig_handler* sa_sigaction;
void (*sa_tramp)(void*, int, int, struct bsd_siginfo*, void*);
unsigned int sa_mask;
int sa_flags;
};
struct linux_sigaction
{
linux_sig_handler* sa_sigaction;
int sa_flags;
void (*sa_restorer)(void);
linux_sigset_t sa_mask;
};
long sys_sigaction(int signum, const struct bsd___sigaction* nsa, struct bsd_sigaction* osa);
//
// Linux Context
//
#ifdef __x86_64__
typedef struct _fpstate {
@ -124,8 +32,7 @@ struct linux_gregset
long long err, trapno, oldmask, cr2;
};
#else // now the i386 version
#elif defined(__i386__) // now the i386 version
typedef struct _fpstate {
unsigned long cw, sw, tag, ipoff, cssel, dataoff, datasel;
struct {
@ -151,6 +58,9 @@ struct linux_gregset
int trapno, err, eip, cs, efl, uesp;
int ss;
};
#else
#error "Missing Register Set for Arch"
#endif
struct linux_mcontext
@ -175,6 +85,10 @@ struct linux_ucontext
// linux_libc_fpstate fpregs_mem;
};
//
// BSD States
//
struct bsd_exception_state
{
unsigned short trapno;
@ -188,9 +102,11 @@ struct bsd_thread_state
#ifdef __x86_64__
long long rax, rbx, rcx, rdx, rdi, rsi, rbp, rsp, r8, r9, r10;
long long r11, r12, r13, r14, r15, rip, rflags, cs, fs, gs;
#else
#elif defined(__i386__)
int eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags;
int eip, cs, ds, es, fs, gs;
#else
#error "Missing BSD Thread State for Arch"
#endif
};
@ -216,10 +132,19 @@ struct bsd_ucontext
struct bsd_mcontext* uc_mcontext;
};
void handler_linux_to_bsd(int linux_signum, struct linux_siginfo* info, void* ctxt);
extern bsd_sig_handler* sig_handlers[32];
extern int sig_flags[32];
extern unsigned int sig_masks[32];
void ucontext_linux_to_bsd(const struct linux_ucontext* lc, struct bsd_ucontext* bc, struct bsd_mcontext* bm);
void mcontext_bsd_to_linux(const struct bsd_mcontext* bm, struct linux_mcontext* lm);
#if defined(__x86_64__)
void mcontext_to_thread_state(const struct linux_gregset* regs, x86_thread_state64_t* s);
void mcontext_to_float_state(const linux_fpregset_t fx, x86_float_state64_t* s);
void thread_state_to_mcontext(const x86_thread_state64_t* s, struct linux_gregset* regs);
void float_state_to_mcontext(const x86_float_state64_t* s, linux_fpregset_t fx);
#elif defined(__i386__)
void mcontext_to_thread_state(const struct linux_gregset* regs, x86_thread_state32_t* s);
void mcontext_to_float_state(const linux_fpregset_t fx, x86_float_state32_t* s);
void thread_state_to_mcontext(const x86_thread_state32_t* s, struct linux_gregset* regs);
void float_state_to_mcontext(const x86_float_state32_t* s, linux_fpregset_t fx);
#endif
#endif // DARLING_EMULATION_CONVERSION_CONTEXT_H

View File

@ -0,0 +1,125 @@
#include "sigaction.h"
#include <stddef.h>
#include <sys/errno.h>
#include <emulation/common/simple.h>
#include <emulation/conversion/errno.h>
#include <emulation/conversion/signal/context.h>
#include <emulation/conversion/signal/sigexc.h>
#include <emulation/xnu_syscall/bsd/impl/signal/sigaction.h>
#undef memset
// extern void* memcpy(void* dest, const void* src, __SIZE_TYPE__ len);
extern void* memset(void* dest, int v, __SIZE_TYPE__ len);
int sig_flags[32];
unsigned int sig_masks[32];
void handler_linux_to_bsd(int linux_signum, struct linux_siginfo* info, void* ctxt)
{
int bsd_signum;
struct bsd_siginfo binfo;
struct linux_ucontext* lc = (struct linux_ucontext*) ctxt;
struct bsd_ucontext bc;
bsd_signum = signum_linux_to_bsd(linux_signum);
if (info)
{
memset(&binfo, 0, sizeof(binfo));
binfo.si_signo = signum_linux_to_bsd(info->si_signo);
binfo.si_errno = errno_linux_to_bsd(info->si_errno);
binfo.si_code = info->si_code;
binfo.si_pid = info->si_pid;
binfo.si_uid = info->si_uid;
binfo.si_addr = info->si_addr;
binfo.si_val_ptr = (void*) info->si_value;
// TODO: The following exist on Linux, but it's a mess to extract them
binfo.si_status = 0;
binfo.si_band = 0;
}
if (lc != NULL)
{
ucontext_linux_to_bsd(lc, &bc, (struct bsd_mcontext*) __builtin_alloca(sizeof(struct bsd_mcontext)));
if (lc->uc_link != NULL)
{
struct bsd_ucontext* bc_link = (struct bsd_ucontext*) __builtin_alloca(sizeof(struct bsd_ucontext));
ucontext_linux_to_bsd(lc->uc_link, bc_link, (struct bsd_mcontext*) __builtin_alloca(sizeof(struct bsd_mcontext)));
bc.uc_link = bc_link;
bc_link->uc_link = NULL;
}
}
// __simple_printf("Handling signal %d\n", linux_signum);
bsd_sig_handler* handler = sig_handlers[linux_signum];
if (sig_flags[linux_signum] & LINUX_SA_RESETHAND)
{
switch (linux_signum)
{
case LINUX_SIGWINCH:
case LINUX_SIGCHLD:
case LINUX_SIGURG:
sig_handlers[linux_signum] = (bsd_sig_handler*)BSD_SIG_IGN;
break;
default:
sig_handlers[linux_signum] = NULL; // BSD_SIG_DFL
}
}
handler(bsd_signum, info ? &binfo : NULL, (lc != NULL) ? &bc : NULL);
if (lc != NULL)
{
mcontext_bsd_to_linux(bc.uc_mcontext, &lc->uc_mcontext);
}
// __simple_printf("Signal handled\n");
}
int sigflags_bsd_to_linux(int flags)
{
int linux_flags = LINUX_SA_SIGINFO;
if (flags & BSD_SA_NOCLDSTOP)
linux_flags |= LINUX_SA_NOCLDSTOP;
if (flags & BSD_SA_NOCLDWAIT)
linux_flags |= LINUX_SA_NOCLDWAIT;
if (flags & BSD_SA_ONSTACK)
linux_flags |= LINUX_SA_ONSTACK;
if (flags & BSD_SA_NODEFER)
linux_flags |= LINUX_SA_NODEFER;
if (flags & BSD_SA_RESETHAND)
linux_flags |= LINUX_SA_RESETHAND;
if (flags & BSD_SA_RESTART)
linux_flags |= LINUX_SA_RESTART;
return linux_flags;
}
int sigflags_linux_to_bsd(int flags)
{
int bsd_flags = 0;
if (flags & LINUX_SA_NOCLDSTOP)
bsd_flags |= BSD_SA_NOCLDSTOP;
if (flags & LINUX_SA_NOCLDWAIT)
bsd_flags |= BSD_SA_NOCLDWAIT;
if (flags & LINUX_SA_ONSTACK)
bsd_flags |= BSD_SA_ONSTACK;
if (flags & LINUX_SA_NODEFER)
bsd_flags |= BSD_SA_NODEFER;
if (flags & LINUX_SA_RESETHAND)
bsd_flags |= BSD_SA_RESETHAND;
if (flags & LINUX_SA_RESTART)
bsd_flags |= BSD_SA_RESTART;
return bsd_flags;
}

View File

@ -0,0 +1,72 @@
#ifndef DARLING_EMULATION_CONVERSION_SIGACTION_H
#define DARLING_EMULATION_CONVERSION_SIGACTION_H
#include <emulation/conversion/signal.h>
#include <emulation/xnu_syscall/bsd/impl/signal/sigaltstack.h>
#undef sa_sigaction
#define BSD_SA_ONSTACK 0x0001
#define BSD_SA_RESTART 0x0002
#define BSD_SA_RESETHAND 0x0004
#define BSD_SA_NOCLDSTOP 0x0008
#define BSD_SA_NODEFER 0x0010
#define BSD_SA_NOCLDWAIT 0x0020
#define BSD_SA_SIGINFO 0x0040
#define LINUX_SA_NOCLDSTOP 0x00000001u
#define LINUX_SA_NOCLDWAIT 0x00000002u
#define LINUX_SA_SIGINFO 0x00000004u
#define LINUX_SA_ONSTACK 0x08000000u
#define LINUX_SA_RESTART 0x10000000u
#define LINUX_SA_NODEFER 0x40000000u
#define LINUX_SA_RESETHAND 0x80000000u
# define __SI_MAX_SIZE 128
# if defined (__x86_64__)
# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4)
# else
# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3)
# endif
struct linux_siginfo
{
int si_signo;
int si_errno;
int si_code;
union
{
struct
{
int si_pid;
int si_uid;
};
void* si_addr;
};
union
{
int _pad[__SI_PAD_SIZE];
unsigned long si_value;
};
};
typedef void (linux_sig_handler)(int, struct linux_siginfo*, void*);
struct linux_sigaction
{
linux_sig_handler* sa_sigaction;
int sa_flags;
void (*sa_restorer)(void);
linux_sigset_t sa_mask;
};
void handler_linux_to_bsd(int linux_signum, struct linux_siginfo* info, void* ctxt);
extern int sig_flags[32];
extern unsigned int sig_masks[32];
extern int sigflags_bsd_to_linux(int flags);
extern int sigflags_linux_to_bsd(int flags);
#endif // DARLING_EMULATION_CONVERSION_SIGACTION_H

View File

@ -0,0 +1,305 @@
#include "sigexc.h"
#include <stddef.h>
#include <sys/mman.h>
#include <sys/signal.h>
// #include "../mach/lkm.h"
#include <_libkernel_init.h>
#include <darlingserver/rpc.h>
#include <emulation/conversion/signal/sigaction.h>
#include <emulation/common/simple.h>
#include <emulation/linux_api/linux_syscall.h>
#include <emulation/xnu_syscall/bsd/impl/mman/mman.h>
#include <emulation/xnu_syscall/bsd/impl/signal/sigaction.h>
#include <emulation/xnu_syscall/bsd/impl/signal/sigaltstack.h>
#include <emulation/xnu_syscall/bsd/impl/unistd/exit.h>
// Support for Darwin debugging.
// Unlike other Unix-like systems, macOS doesn't use wait() to handle events in the debugged process.
// wait() only receives termination events.
static void sigexc_fake_suspend(struct linux_ucontext* ctxt);
extern void linux_sig_restorer(void);
extern int getpid(void);
extern _libkernel_functions_t _libkernel_functions;
void darling_sigexc_uninstall(void);
void sigrt_handler(int signum, struct linux_siginfo* info, struct linux_ucontext* ctxt);
#ifndef SIGALTSTACK_GUARD
#define SIGALTSTACK_GUARD 1
#endif
#if SIGALTSTACK_GUARD
// align it on a page boundary so mprotect works properly
char sigexc_altstack[SIGEXC_STACK_SIZE + 4096ULL] __attribute__((aligned(4096)));
#else
char sigexc_altstack[SIGEXC_STACK_SIZE];
#endif
size_t default_sigaltstack_size = SIGEXC_STACK_SIZE;
static void state_from_kernel(struct linux_ucontext* ctxt, const void* tstate, const void* fstate);
static void state_to_kernel(struct linux_ucontext* ctxt, void* tstate, void* fstate);
#define DEBUG_SIGEXC
#ifdef DEBUG_SIGEXC
#define kern_printf(...) __simple_kprintf(__VA_ARGS__)
#else
#define kern_printf(...)
#endif
#define DUMPREG(regname) kern_printf("sigexc: " #regname ": 0x%llx\n", regs->regname);
static void dump_gregs(const struct linux_gregset* regs)
{
unsigned long long* p = (unsigned long long*) regs;
for (int i = 0; i < 23; i++)
{
kern_printf("sigexc: gregs 0x%llx\n", p[i]);
}
}
void handle_rt_signal(int signum)
{
int rv;
struct linux_sigaction sa;
sa.sa_sigaction = (linux_sig_handler*)sigrt_handler;
sa.sa_mask = (1ull << (SIGNAL_SIGEXC_SUSPEND-1)) | (1ull << (signum-1));
sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK;
sa.sa_restorer = linux_sig_restorer;
rv = LINUX_SYSCALL(__NR_rt_sigaction, signum,
&sa, NULL,
sizeof(sa.sa_mask));
//char buf[128];
//__simple_sprintf(xyzbuf, "Setting handler for RT signal %d: %d", signum, rv);
//external/lkm_call(0x1028, buf);
}
void sigrt_handler(int signum, struct linux_siginfo* info, struct linux_ucontext* ctxt)
{
int status = dserver_rpc_interrupt_enter();
if (status != 0) {
__simple_printf("*** dserver_rpc_interrupt_enter failed with code %d ***\n", status);
__simple_abort();
}
if (signum == SIGNAL_SIGEXC_SUSPEND) {
#if defined(__x86_64__)
x86_thread_state64_t tstate;
x86_float_state64_t fstate;
#elif defined(__i386__)
x86_thread_state32_t tstate;
x86_float_state32_t fstate;
#endif
kern_printf("sigexc: sigrt_handler SUSPEND\n");
thread_t thread = mach_thread_self();
state_to_kernel(ctxt, &tstate, &fstate);
int ret = dserver_rpc_thread_suspended(&tstate, &fstate);
if (ret < 0) {
__simple_printf("dserver_rpc_thread_suspended failed internally: %d", ret);
__simple_abort();
}
state_from_kernel(ctxt, &tstate, &fstate);
} else if (signum == SIGNAL_S2C) {
__simple_kprintf("sigexc: sigrt_handler S2C");
int ret = dserver_rpc_s2c_perform();
if (ret < 0) {
__simple_printf("dserver_rpc_s2c_perform failed internally: %d", ret);
__simple_abort();
}
} else {
__simple_printf("Unknown/unrecognized real-time signal: %d", signum);
}
status = dserver_rpc_interrupt_exit();
if (status != 0) {
__simple_printf("*** dserver_rpc_interrupt_exit failed with code %d ***\n", status);
__simple_abort();
}
}
static void state_to_kernel(struct linux_ucontext* ctxt, void* tstate, void* fstate)
{
#if defined(__x86_64__)
dump_gregs(&ctxt->uc_mcontext.gregs);
mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, (x86_thread_state64_t*) tstate);
mcontext_to_float_state(ctxt->uc_mcontext.fpregs, (x86_float_state64_t*) fstate);
#elif defined(__i386__)
mcontext_to_thread_state(&ctxt->uc_mcontext.gregs, (x86_thread_state32_t*) tstate);
mcontext_to_float_state(ctxt->uc_mcontext.fpregs, (x86_float_state32_t*) fstate);
#endif
}
static void state_from_kernel(struct linux_ucontext* ctxt, const void* tstate, const void* fstate)
{
#if defined(__x86_64__)
thread_state_to_mcontext((const x86_thread_state64_t*) tstate, &ctxt->uc_mcontext.gregs);
float_state_to_mcontext((const x86_float_state64_t*) fstate, ctxt->uc_mcontext.fpregs);
dump_gregs(&ctxt->uc_mcontext.gregs);
#elif defined(__i386__)
thread_state_to_mcontext((const x86_thread_state32_t*) tstate, &ctxt->uc_mcontext.gregs);
float_state_to_mcontext((const x86_float_state32_t*) fstate, ctxt->uc_mcontext.fpregs);
#endif
}
void sigexc_handler(int linux_signum, struct linux_siginfo* info, struct linux_ucontext* ctxt)
{
int status = dserver_rpc_interrupt_enter();
if (status != 0) {
__simple_printf("*** dserver_rpc_interrupt_enter failed with code %d ***\n", status);
__simple_abort();
}
kern_printf("sigexc_handler(%d, %p, %p)\n", linux_signum, info, ctxt);
if (linux_signum == LINUX_SIGCONT)
goto out;
int bsd_signum = signum_linux_to_bsd(linux_signum);
if (bsd_signum <= 0)
{
kern_printf("sigexc: Unmapped signal!\n");
goto out;
}
#ifdef __x86_64__
kern_printf("sigexc: have RIP 0x%llx\n", ctxt->uc_mcontext.gregs.rip);
#endif
thread_t thread = mach_thread_self();
#if defined(__x86_64__)
x86_thread_state64_t tstate;
x86_float_state64_t fstate;
#elif defined(__i386__)
x86_thread_state32_t tstate;
x86_float_state32_t fstate;
#endif
state_to_kernel(ctxt, &tstate, &fstate);
int ret = dserver_rpc_sigprocess(bsd_signum, linux_signum, info->si_pid, info->si_code, info->si_addr, &tstate, &fstate, &bsd_signum);
if (ret < 0) {
__simple_printf("sigprocess failed internally while processing Linux signal %d: %d", linux_signum, ret);
__simple_abort();
}
state_from_kernel(ctxt, &tstate, &fstate);
if (!bsd_signum)
{
kern_printf("sigexc: drop signal\n");
goto out;
}
linux_signum = signum_bsd_to_linux(bsd_signum);
if (sig_handlers[linux_signum] != BSD_SIG_IGN)
{
if (sig_handlers[linux_signum])
{
kern_printf("sigexc: will forward signal to app handler (%p)\n", sig_handlers[linux_signum]);
// Update the signal mask to what the application actually wanted
linux_sigset_t set = sig_masks[linux_signum];
// Keep the current signal blocked, which is the default behavior
if (!(sig_flags[linux_signum] & LINUX_SA_NODEFER))
set |= (1ull << (linux_signum-1));
LINUX_SYSCALL(__NR_rt_sigprocmask, 2 /* LINUX_SIG_SETMASK */,
&set, NULL, sizeof(linux_sigset_t));
handler_linux_to_bsd(linux_signum, info, ctxt);
}
else
{
if (bsd_signum == SIGTSTP || bsd_signum == SIGSTOP)
{
kern_printf("sigexc: emulating SIGTSTP/SIGSTOP\n");
LINUX_SYSCALL(__NR_kill, 0, LINUX_SIGSTOP);
}
else
{
kern_printf("sigexc: emulating default signal effects\n");
// Set handler to BSD_SIG_DFL
struct linux_sigaction sa;
sa.sa_sigaction = (linux_sig_handler*) NULL; // BSD_SIG_DFL
sa.sa_mask = 0x7fffffff; // all other standard Unix signals should be blocked while the handler is run
sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK;
sa.sa_restorer = linux_sig_restorer;
LINUX_SYSCALL(__NR_rt_sigaction, linux_signum,
&sa, NULL,
sizeof(sa.sa_mask));
// Resend signal to self
LINUX_SYSCALL(__NR_kill, 0, linux_signum);
}
}
}
kern_printf("sigexc: handler (%d) returning\n", linux_signum);
out:
status = dserver_rpc_interrupt_exit();
if (status != 0) {
__simple_printf("*** dserver_rpc_interrupt_exit failed with code %d ***\n", status);
__simple_abort();
}
}
void sigexc_thread_setup(void)
{
struct bsd_stack newstack = {
.ss_size = default_sigaltstack_size,
.ss_flags = 0
};
#if SIGALTSTACK_GUARD
newstack.ss_sp = (void*) sys_mmap(NULL, newstack.ss_size + 4096, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
sys_mprotect(newstack.ss_sp, 4096, PROT_NONE);
newstack.ss_sp = (char*)newstack.ss_sp + 4096;
#else
newstack.ss_sp = (void*) sys_mmap(NULL, newstack.ss_size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0);
#endif
sys_sigaltstack(&newstack, NULL);
}
void sigexc_thread_exit(void)
{
struct bsd_stack oldstack;
sys_sigaltstack(NULL, &oldstack);
#if SIGALTSTACK_GUARD
sys_munmap((char*)oldstack.ss_sp - 4096, oldstack.ss_size + 4096);
#else
sys_munmap(oldstack.ss_sp, oldstack.ss_size);
#endif
}

View File

@ -1,22 +1,25 @@
#ifndef _SIGEXC_H
#define _SIGEXC_H
#ifndef DARLING_EMULATION_CONVERSION_SIGEXC_H
#define DARLING_EMULATION_CONVERSION_SIGEXC_H
#include <stdbool.h>
#include "rtsig.h"
#include "sigaction.h"
#include <emulation/conversion/signal/context.h>
#include <emulation/conversion/signal/sigaction.h>
#define SIGEXC_STACK_SIZE (48ULL * 1024ULL)
// NOTE: Keep these definitions up to date with lkm/darling/binfmt.c!
// Uses one of the below magic values to toggle the debugging state
#define SIGNAL_SIGEXC_SUSPEND LINUX_SIGRTMIN
#define SIGNAL_S2C (LINUX_SIGRTMIN + 1)
void sigexc_setup(void);
void handle_rt_signal(int signum);
extern char sigexc_altstack[];
// for PT_SIGEXC to handle this operation synchronously
void darling_sigexc_self(void);
void sigexc_handler(int linux_signum, struct linux_siginfo* info, struct linux_ucontext* ctxt);
void sigexc_thread_setup(void);
void sigexc_thread_exit(void);
#endif
#endif // DARLING_EMULATION_CONVERSION_SIGEXC_H

View File

@ -1,11 +1,13 @@
// This needs be included first, so that "stat.h" can `#undef st_atime` (and more)
#include <sys/stat.h>
#include "stat.h"
// This is needed so stat is not stat64
#define _DARWIN_NO_64_BIT_INODE
// NOTE: in this case, platform-include/sys/stat.h is used
#include <sys/stat.h>
#include "common.h"
#include "../unistd/getuid.h"
#include "../unistd/getgid.h"
#include <emulation/xnu_syscall/bsd/impl/unistd/getgid.h>
#include <emulation/xnu_syscall/bsd/impl/unistd/getuid.h>
void stat_linux_to_bsd(const struct linux_stat* lstat, struct stat* stat)
{

View File

@ -1,5 +1,5 @@
#ifndef LINUX_STAT_COMMON_H
#define LINUX_STAT_COMMON_H
#ifndef DARLING_EMULATION_CONVERSION_STAT_H
#define DARLING_EMULATION_CONVERSION_STAT_H
#ifdef __i386__
@ -149,5 +149,4 @@ void stat_linux_to_bsd64(const struct linux_stat* lstat, struct stat64* stat);
void statfs_linux_to_bsd(const struct linux_statfs64* lstat, struct bsd_statfs* stat);
void statfs_linux_to_bsd64(const struct linux_statfs64* lstat, struct bsd_statfs64* stat);
#endif
#endif // DARLING_EMULATION_CONVERSION_STAT_H

View File

@ -1,5 +1,5 @@
#ifndef EXT_UNAME_H
#define EXT_UNAME_H
#ifndef DARLING_EMULATION_CONVERSION_UTSNAME_H
#define DARLING_EMULATION_CONVERSION_UTSNAME_H
#define LINUX_UTSNAME_LENGTH 65
@ -15,5 +15,4 @@ struct linux_utsname
int __linux_uname(struct linux_utsname* p);
#endif
#endif // DARLING_EMULATION_CONVERSION_UTSNAME_H

View File

@ -0,0 +1,29 @@
project(emulation_darling)
set(darling_sources
legacy_lkm.c
weak_stubs.c
c_api/elfcalls_wrapper.c
c_api/for_libkqueue.c
init/mach_driver.c
init/sigexc.c
server/dserver-rpc-defs.c
server/vchroot_userspace.c
${CMAKE_BINARY_DIR}/src/external/darlingserver/src/rpc.c
)
set_source_files_properties(${CMAKE_BINARY_DIR}/src/external/darlingserver/src/rpc.c PROPERTIES
GENERATED TRUE
COMPILE_FLAGS "-include ${CMAKE_CURRENT_SOURCE_DIR}/server/dserver-rpc-defs.h"
)
add_darling_object_library(emulation_darling ${darling_sources})
make_fat(emulation_darling)
add_darling_object_library(emulation_darling_dyld ${darling_sources})
set_target_properties(emulation_darling_dyld PROPERTIES COMPILE_FLAGS "-ffunction-sections -DVARIANT_DYLD")
make_fat(emulation_darling_dyld)

View File

@ -1,7 +1,9 @@
#include "elfcalls_wrapper.h"
// #include <dlfcn.h>
#include <elfcalls.h>
#include <dlfcn.h>
#include "simple.h"
#include <emulation/common/simple.h>
extern struct elf_calls* _elfcalls;

View File

@ -1,11 +1,11 @@
#ifndef _ELFCALLS_WRAPPER_H
#define _ELFCALLS_WRAPPER_H
#ifndef DARLING_EMULATION_DARLING_ELFCALLS_WRAPPER_H
#define DARLING_EMULATION_DARLING_ELFCALLS_WRAPPER_H
#include <darling/emulation/common/base.h>
#include <elfcalls.h>
#ifdef __cplusplus
extern "C" {
#endif
CPP_EXTERN_C_BEGIN
// Native library loading
void* native_dlopen(const char* path);
@ -37,9 +37,6 @@ int __dserver_get_process_lifetime_pipe(void);
int __dserver_process_lifetime_pipe_refresh(void);
void __dserver_close_process_lifetime_pipe(int fd);
#ifdef __cplusplus
}
#endif
#endif
CPP_EXTERN_C_END
#endif // DARLING_EMULATION_DARLING_ELFCALLS_WRAPPER_H

View File

@ -1,7 +1,8 @@
#include "for-libkqueue.h"
#include "for_libkqueue.h"
#include <darlingserver/rpc.h>
#include <linux-syscalls/linux.h>
#include "../errno.h"
#include <emulation/linux_api/linux_syscall.h>
#include <emulation/xnu_syscall/bsd/impl/unistd/close.h>
int _dserver_rpc_kqchan_mach_port_open_4libkqueue(uint32_t port_name, void* receive_buffer, uint64_t receive_buffer_size, uint64_t saved_filter_flags, int* out_socket) {
return dserver_rpc_kqchan_mach_port_open(port_name, receive_buffer, receive_buffer_size, saved_filter_flags, out_socket);
@ -20,3 +21,10 @@ int _dup_4libkqueue(int fd) {
return ret;
};
// Special variant for libkqueue to avoid recursion into kqueue_close()/kqueue_closed_fd()
__attribute__((visibility("default")))
long __close_for_kqueue(int fd)
{
return close_internal(fd);
}

View File

@ -1,9 +1,9 @@
#ifndef _DARLING_EMULATION_FOR_LIBKQUEUE_H_
#define _DARLING_EMULATION_FOR_LIBKQUEUE_H_
#ifndef DARLING_EMULATION_DARLING_FOR_LIBKQUEUE_H
#define DARLING_EMULATION_DARLING_FOR_LIBKQUEUE_H
#include <stdint.h>
#include <darling/emulation/base.h>
#include <darling/emulation/common/base.h>
VISIBLE
int _dserver_rpc_kqchan_mach_port_open_4libkqueue(uint32_t port_name, void* receive_buffer, uint64_t receive_buffer_size, uint64_t saved_filter_flags, int* out_socket);
@ -14,4 +14,4 @@ int _dserver_rpc_kqchan_proc_open_4libkqueue(int32_t pid, uint32_t flags, int* o
VISIBLE
int _dup_4libkqueue(int fd);
#endif // _DARLING_EMULATION_FOR_LIBKQUEUE_H_
#endif // DARLING_EMULATION_DARLING_FOR_LIBKQUEUE_H

View File

@ -1,16 +1,18 @@
#include "lkm.h"
#include "../signal/sigexc.h"
#include "../base.h"
#include "../linux-syscalls/linux.h"
#include "mach_driver.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/resource.h>
#include "../../../libsyscall/wrappers/_libkernel_init.h"
#include "../simple.h"
#include "../misc/ioctl.h"
#include <elfcalls.h>
#include "../guarded/table.h"
#include "../elfcalls_wrapper.h"
#include <_libkernel_init.h>
// #include "../misc/ioctl.h"
#include <emulation/common/simple.h>
#include <emulation/conversion/signal/sigexc.h>
#include <emulation/darling/c_api/elfcalls_wrapper.h>
#include <emulation/linux_api/linux_syscall.h>
#include <emulation/xnu_syscall/shared/guarded/table.h>
extern int sys_open(const char*, int, int);
extern int close_internal(int);
@ -95,20 +97,6 @@ void mach_driver_init(const char** applep)
}
}
__attribute__((visibility("default")))
int lkm_call(int call_nr, void* arg)
{
__simple_printf("Something called the old LKM API (nr = %d)\n", call_nr);
__builtin_unreachable();
}
__attribute__((visibility("default")))
int lkm_call_raw(int call_nr, void* arg)
{
__simple_printf("Something called the old LKM API (nr = %d)\n", call_nr);
__builtin_unreachable();
}
VISIBLE
int mach_driver_get_fd(void) {
return __dserver_per_thread_socket();

View File

@ -0,0 +1,8 @@
#ifndef DARLING_EMULATION_DARLING_MACH_DRIVER_INIT_H
#define DARLING_EMULATION_DARLING_MACH_DRIVER_INIT_H
void mach_driver_init(const char** applep);
int mach_driver_get_fd(void);
#endif // DARLING_EMULATION_DARLING_MACH_DRIVER_INIT_H

View File

@ -0,0 +1,115 @@
#include "sigexc.h"
#include <stdbool.h>
#include <darlingserver/rpc.h>
#include <emulation/common/simple.h>
#include <emulation/conversion/signal.h>
#include <emulation/conversion/signal/sigaction.h>
#include <emulation/conversion/signal/sigexc.h>
#include <emulation/linux_api/linux_syscall.h>
#include <emulation/xnu_syscall/bsd/impl/signal/kill.h>
#define DEBUG_SIGEXC
#ifdef DEBUG_SIGEXC
#define kern_printf(...) __simple_kprintf(__VA_ARGS__)
#else
#define kern_printf(...)
#endif
extern void linux_sig_restorer(void);
void sigexc_setup1(void);
void sigexc_setup2(void);
void sigexc_setup(void)
{
darling_sigexc_self();
sigexc_setup1();
sigexc_setup2();
#ifdef VARIANT_DYLD
bool started_suspended;
int code = dserver_rpc_started_suspended(&started_suspended);
if (code < 0) {
__simple_printf("Failed to get started_suspended status: %d\n", code);
__simple_abort();
}
if (started_suspended) {
kern_printf("sigexc: start_suspended -> suspending (ret to %p)\n", __builtin_return_address(0));
task_suspend(mach_task_self());
kern_printf("sigexc: start_suspended -> wokenup (ret to %p)\n", __builtin_return_address(0));
} else {
int32_t tracer;
code = dserver_rpc_get_tracer(&tracer);
if (code < 0) {
__simple_printf("Failed to get tracer status: %d\n", code);
__simple_abort();
}
if (tracer != 0) {
kern_printf("sigexc: already traced -> SIGTRAP\n");
sys_kill(0, SIGTRAP, 0);
}
}
#else
#endif
}
static volatile bool am_i_ptraced = false;
void darling_sigexc_self(void)
{
am_i_ptraced = true;
__simple_kprintf("darling_sigexc_self()\n");
// Make sigexc_handler the handler for all signals in the process
for (int i = 1; i <= 31; i++)
{
if (i == LINUX_SIGSTOP || i == LINUX_SIGKILL || i == LINUX_SIGCHLD)
continue;
struct linux_sigaction sa;
sa.sa_sigaction = (linux_sig_handler*) sigexc_handler;
sa.sa_mask = 0x7fffffff; // all other standard Unix signals should be blocked while the handler is run
sa.sa_mask |= (1ull << (SIGNAL_SIGEXC_SUSPEND-1));
sa.sa_flags = LINUX_SA_RESTORER | LINUX_SA_SIGINFO | LINUX_SA_RESTART | LINUX_SA_ONSTACK;
sa.sa_restorer = linux_sig_restorer;
LINUX_SYSCALL(__NR_rt_sigaction, i,
&sa, NULL,
sizeof(sa.sa_mask));
}
#if SIGALTSTACK_GUARD
sys_mprotect(sigexc_altstack, 4096, PROT_NONE);
#endif
struct bsd_stack newstack = {
#if SIGALTSTACK_GUARD
.ss_sp = sigexc_altstack + 4096,
#else
.ss_sp = sigexc_altstack,
#endif
.ss_size = SIGEXC_STACK_SIZE,
.ss_flags = 0
};
sys_sigaltstack(&newstack, NULL);
}
void sigexc_setup1(void)
{
handle_rt_signal(SIGNAL_SIGEXC_SUSPEND);
handle_rt_signal(SIGNAL_S2C);
}
void sigexc_setup2(void)
{
linux_sigset_t set;
set = (1ull << (SIGNAL_SIGEXC_SUSPEND-1));
set |= (1ull << (SIGNAL_S2C-1));
LINUX_SYSCALL(__NR_rt_sigprocmask, 1 /* LINUX_SIG_UNBLOCK */,
&set, NULL, sizeof(linux_sigset_t));
}

View File

@ -0,0 +1,7 @@
#ifndef DARLING_EMULATION_DARLING_SIGEXC_H
#define DARLING_EMULATION_DARLING_SIGEXC_H
void sigexc_setup(void);
void darling_sigexc_self(void);
#endif // DARLING_EMULATION_DARLING_SIGEXC_H

View File

@ -0,0 +1,17 @@
#include "legacy_lkm.h"
#include <emulation/common/simple.h>
__attribute__((visibility("default")))
int lkm_call(int call_nr, void* arg)
{
__simple_printf("Something called the old LKM API (nr = %d)\n", call_nr);
__builtin_unreachable();
}
__attribute__((visibility("default")))
int lkm_call_raw(int call_nr, void* arg)
{
__simple_printf("Something called the old LKM API (nr = %d)\n", call_nr);
__builtin_unreachable();
}

View File

@ -1,7 +1,5 @@
#ifndef _LKM_H
#define _LKM_H
#include <os/tsd.h>
#ifndef DARLING_EMULATION_DARLING_LEGACY_LKM_H
#define DARLING_EMULATION_DARLING_LEGACY_LKM_H
#define DARLING_MACH_API_BASE 0x1000
enum { NR_get_api_version = DARLING_MACH_API_BASE,
@ -90,10 +88,7 @@ enum { NR_get_api_version = DARLING_MACH_API_BASE,
};
#define DARLING_MACH_API_COUNT (DARLING_MACH_API_ALMOST_COUNT - DARLING_MACH_API_BASE)
void mach_driver_init(const char** applep);
int lkm_call(int call_nr, void* arg);
int lkm_call_raw(int call_nr, void* arg); // w/o errno translation
int mach_driver_get_fd(void);
#endif
int lkm_call_raw(int call_nr, void* arg);
#endif // DARLING_EMULATION_DARLING_LEGACY_LKM_H

View File

@ -1,11 +1,12 @@
#include "dserver-rpc-defs.h"
#include <darlingserver/rpc.h>
#include <libsimple/lock.h>
#include "../fcntl/open.h"
#include "../unistd/pipe.h"
#include "../unistd/read.h"
#include <darlingserver/rpc.h>
#include <emulation/xnu_syscall/bsd/impl/fcntl/open.h>
#include <emulation/xnu_syscall/bsd/impl/unistd/pipe.h>
#include <emulation/xnu_syscall/bsd/impl/unistd/read.h>
#ifndef DSERVER_RPC_USE_LOG_FILE
// CHANGE TO 0 BEFORE COMMITTING

View File

@ -1,21 +1,23 @@
#include "../network/recvmsg.h"
#include "../network/sendmsg.h"
#include "../network/getsockopt.h"
#include "../network/sendto.h"
#ifndef DARLING_EMULATION_DARLING_DSERVER_RPC_DEFS_H
#define DARLING_EMULATION_DARLING_DSERVER_RPC_DEFS_H
#include <rtsig.h>
#include <stddef.h>
#include <sys/_types/_iovec_t.h>
#include <linux-syscalls/linux.h>
#include "../base.h"
#include "../duct_errno.h"
#include "../mach/lkm.h"
#include "../elfcalls_wrapper.h"
#include "../simple.h"
#include "../signal/sigprocmask.h"
#include "../unistd/close.h"
#include <darlingserver/rpc-supplement.h>
#include <rtsig.h>
#include <emulation/common/simple.h>
#include <emulation/darling/c_api/elfcalls_wrapper.h>
#include <emulation/darling/init/mach_driver.h>
#include <emulation/linux_api/linux_syscall.h>
#include <emulation/xnu_syscall/bsd/impl/network/getsockopt.h>
#include <emulation/xnu_syscall/bsd/impl/network/recvmsg.h>
#include <emulation/xnu_syscall/bsd/impl/network/sendmsg.h>
#include <emulation/xnu_syscall/bsd/impl/network/sendto.h>
#include <emulation/xnu_syscall/bsd/impl/signal/sigprocmask.h>
#include <emulation/xnu_syscall/bsd/impl/unistd/close.h>
#ifndef DSERVER_RPC_HOOKS_ARCHITECTURE
#define DSERVER_RPC_HOOKS_ARCHITECTURE 1
@ -294,3 +296,5 @@ static void dserver_rpc_hooks_atomic_end(dserver_rpc_hooks_atomic_save_t* atomic
extern void __dserver_rpc_hooks_push_reply(int socket, const dserver_rpc_hooks_msghdr_t* reply, size_t size);
#define dserver_rpc_hooks_push_reply __dserver_rpc_hooks_push_reply
#endif // DARLING_EMULATION_DARLING_DSERVER_RPC_DEFS_H

View File

@ -1,5 +1,5 @@
#include "vchroot_expand.h"
#include "vchroot_userspace.h"
#ifdef TEST
# include <unistd.h>
# include <sys/stat.h>
@ -26,17 +26,15 @@
# define linux_dirent64 dirent
typedef struct stat stat_t;
#else
# include "base.h"
# include <mach/lkm.h>
# include <linux-syscalls/linux.h>
# include <fcntl/open.h>
# include "simple.h"
# include <stdbool.h>
# include "errno.h"
# include "duct_errno.h"
# include "stat/common.h"
# include "dirent/getdirentries.h"
# include "common_at.h"
// # include <mach/lkm.h>
# include <emulation/common/simple.h>
# include <emulation/conversion/at.h>
# include <emulation/conversion/errno.h>
# include <emulation/conversion/stat.h>
# include <emulation/linux_api/linux_syscall.h>
# include <emulation/xnu_syscall/bsd/impl/dirent/getdirentries.h>
# include <emulation/xnu_syscall/bsd/impl/fcntl/open.h>
#include <stddef.h>
#include <darlingserver/rpc.h>

View File

@ -1,5 +1,5 @@
#ifndef _VCHROOT_EXPAND_H
#define _VCHROOT_EXPAND_H
#ifndef DARLING_EMULATION_DARLING_VCHROOT_USERSPACE_H
#define DARLING_EMULATION_DARLING_VCHROOT_USERSPACE_H
#define VCHROOT_FOLLOW 1
struct vchroot_expand_args
@ -25,5 +25,4 @@ int vchroot_expand(struct vchroot_expand_args* args);
int vchroot_unexpand(struct vchroot_unexpand_args* args);
int vchroot_fdpath(struct vchroot_fdpath_args* args);
#endif
#endif // DARLING_EMULATION_DARLING_VCHROOT_USERSPACE_H

View File

@ -1,9 +1,11 @@
#ifndef _PER_THREAD_WD_H
#define _PER_THREAD_WD_H
#include "../common_at.h"
#include "../tsd.h"
#ifndef DARLING_EMULATION_DARLING_PERTHREAD_WD_H
#define DARLING_EMULATION_DARLING_PERTHREAD_WD_H
// We use the following static TSD keys (see `../tsd.h` and `pthread/tsd_private.h`):
#include <darling/emulation/darling/tsd/tsd.h>
#include <darling/emulation/conversion/at.h>
// We use the following static TSD keys (see `tsd.h` and `pthread/tsd_private.h`):
// __PTK_DARLING_PERTHREAD_WD_IS_SET = is __PTK_DARLING_PERTHREAD_WD_FD set? (Because 0 could be a valid FD, theoretically.)
// __PTK_DARLING_PERTHREAD_WD_FD = per thread wd file descriptor
//
@ -26,5 +28,4 @@ static inline void set_perthread_wd(int fd)
_pthread_setspecific_direct(__PTK_DARLING_PERTHREAD_WD_FD, fd);
}
#endif
#endif // DARLING_EMULATION_DARLING_PERTHREAD_WD_H

View File

@ -1,5 +1,5 @@
#ifndef _DARLING_EMULATION_TSD_H_
#define _DARLING_EMULATION_TSD_H_
#ifndef DARLING_EMULATION_DARLING_TSD_H
#define DARLING_EMULATION_DARLING_TSD_H
#include <pthread/tsd_private.h>
@ -8,4 +8,4 @@
#define __PTK_DARLING_PERTHREAD_WD_FD __PTK_DARLING_KEY2
// other __PTK_DARLING_KEYs are currently unused
#endif // _DARLING_EMULATION_TSD_H_
#endif // DARLING_EMULATION_DARLING_TSD_H

View File

@ -0,0 +1,21 @@
#include <emulation/common/base.h>
#include <os/lock.h>
WEAK
VISIBLE
int kqueue_close(int kq) { return 0; }
WEAK
VISIBLE
void kqueue_closed_fd(int fd) {}
WEAK
VISIBLE
void kqueue_dup(int oldfd, int newfd) { }
WEAK
void os_unfair_lock_unlock(os_unfair_lock_t lock) {}
WEAK
void os_unfair_lock_lock(os_unfair_lock_t lock) {}

View File

@ -0,0 +1 @@
../../../common/base.h

View File

@ -0,0 +1 @@
../../../common/simple.h

View File

@ -0,0 +1 @@
../../../conversion/at.h

View File

@ -0,0 +1 @@
../../../conversion/errno.h

View File

@ -0,0 +1 @@
../../../../conversion/mman/mman.h

View File

@ -0,0 +1 @@
../../../conversion/network.h

View File

@ -0,0 +1 @@
../../../conversion/signal.h

View File

@ -0,0 +1 @@
../../../../conversion/signal/sigaction.h

View File

@ -0,0 +1 @@
../../../../conversion/signal/sigexc.h

View File

@ -0,0 +1 @@
../../../conversion/stat.h

View File

@ -0,0 +1 @@
../../../../darling/c_api/elfcalls_wrapper.h

View File

@ -0,0 +1 @@
../../../../darling/c_api/for_libkqueue.h

View File

@ -0,0 +1 @@
../../../../darling/init/mach_driver.h

View File

@ -0,0 +1 @@
../../../../darling/init/sigexc.h

View File

@ -0,0 +1 @@
../../../darling/legacy_lkm.h

View File

@ -0,0 +1 @@
../../../../darling/server/dserver-rpc-defs.h

View File

@ -0,0 +1 @@
../../../../darling/server/vchroot_userspace.h

View File

@ -0,0 +1 @@
../../../../darling/tsd/perthread_wd.h

View File

@ -0,0 +1 @@
../../../../darling/tsd/tsd.h

View File

@ -0,0 +1 @@
../../../../linux_api/c_api/clock.h

View File

@ -0,0 +1 @@
../../../../linux_api/c_api/fanotify.h

View File

@ -0,0 +1 @@
../../../../linux_api/c_api/file_handle.h

View File

@ -0,0 +1 @@
../../../../linux_api/c_api/futex.h

View File

@ -0,0 +1 @@
../../../../linux_api/c_api/ioctl.h

View File

@ -0,0 +1 @@
../../../../linux_api/c_api/mremap.h

View File

@ -0,0 +1 @@
../../../../linux_api/c_api/nanosleep.h

View File

@ -0,0 +1 @@
../../../../linux_api/c_api/sched_yield.h

View File

@ -0,0 +1 @@
../../../../../linux_api/c_api/sys/epoll.h

View File

@ -0,0 +1 @@
../../../../../linux_api/c_api/sys/eventfd.h

View File

@ -0,0 +1 @@
../../../../../linux_api/c_api/sys/inotify.h

View File

@ -0,0 +1 @@
../../../../../linux_api/c_api/sys/signalfd.h

View File

@ -0,0 +1 @@
../../../../../linux_api/c_api/sys/timerfd.h

View File

@ -0,0 +1 @@
../../../linux_api/linux_syscall.h

View File

@ -0,0 +1 @@
../../../../linux_api/sysnum/linux_sysnum.h

View File

@ -0,0 +1 @@
../../../../linux_api/sysnum/linux_sysnum_arm64.h

View File

@ -0,0 +1 @@
../../../../linux_api/sysnum/linux_sysnum_x86.h

View File

@ -0,0 +1 @@
../../../../linux_api/sysnum/linux_sysnum_x86_64.h

View File

@ -0,0 +1 @@
../../../../xnu_syscall/bsd/bsd_syscall.h

View File

@ -0,0 +1 @@
../../../../xnu_syscall/bsd/bsd_syscall_table.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/bsdthread/bsdthread_create.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/bsdthread/bsdthread_register.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/bsdthread/pthread_canceled.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/dirent/getdirentries.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/fcntl/fcntl.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/fcntl/open.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/fcntl/openat.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/misc/abort_with_payload.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/misc/syscall.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/misc/thread_selfid.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/mman/mman.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/network/getsockopt.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/network/recvmsg.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/network/sendmsg.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/network/sendto.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/signal/kill.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/signal/sigaltstack.h

View File

@ -0,0 +1 @@
../../../../../../xnu_syscall/bsd/impl/signal/sigprocmask.h

Some files were not shown because too many files have changed in this diff Show More