From 7c0bc2c85cbf0824853c4ed3ff63be976b6496ed Mon Sep 17 00:00:00 2001 From: SpecterDev Date: Tue, 21 Dec 2021 05:10:18 -0500 Subject: [PATCH] Fix ptrace and sendfile for PS4 --- arch/ps4/bits/alltypes.h.in | 2 + include/signal.h | 136 +++++++++-------------- include/sys/ptrace.h | 208 ++++++++++++++++-------------------- include/sys/sendfile.h | 9 +- src/aio/aio.c | 8 ++ src/aio/lio_listio.c | 8 ++ src/linux/ptrace.c | 6 +- src/linux/sendfile.c | 2 + src/mq/mq_notify.c | 16 ++- src/time/timer_create.c | 13 ++- 10 files changed, 203 insertions(+), 205 deletions(-) diff --git a/arch/ps4/bits/alltypes.h.in b/arch/ps4/bits/alltypes.h.in index 6b8eb394e..2e4b49ccf 100644 --- a/arch/ps4/bits/alltypes.h.in +++ b/arch/ps4/bits/alltypes.h.in @@ -23,4 +23,6 @@ TYPEDEF unsigned short mode_t; TYPEDEF unsigned short nlink_t; TYPEDEF unsigned int blksize_t; +TYPEDEF struct __sigset_t { unsigned int __bits[4]; } sigset_t; + TYPEDEF struct { long long __ll; long double __ld; } max_align_t; diff --git a/include/signal.h b/include/signal.h index fbdf667b2..d0173d798 100644 --- a/include/signal.h +++ b/include/signal.h @@ -73,14 +73,10 @@ typedef struct sigaltstack stack_t; #define SEGV_MAPERR 1 #define SEGV_ACCERR 2 -#define SEGV_BNDERR 3 -#define SEGV_PKUERR 4 #define BUS_ADRALN 1 #define BUS_ADRERR 2 #define BUS_OBJERR 3 -#define BUS_MCEERR_AR 4 -#define BUS_MCEERR_AO 5 #define CLD_EXITED 1 #define CLD_KILLED 2 @@ -90,99 +86,73 @@ typedef struct sigaltstack stack_t; #define CLD_CONTINUED 6 union sigval { - int sival_int; - void *sival_ptr; + /* Members as suggested by Annex C of POSIX 1003.1b. */ + int sival_int; + void *sival_ptr; + /* 6.0 compatibility */ + int sigval_int; + void *sigval_ptr; }; -typedef struct { -#ifdef __SI_SWAP_ERRNO_CODE - int si_signo, si_code, si_errno; -#else - int si_signo, si_errno, si_code; -#endif - union { - char __pad[128 - 2*sizeof(int) - sizeof(long)]; - struct { - union { - struct { - pid_t si_pid; - uid_t si_uid; - } __piduid; - struct { - int si_timerid; - int si_overrun; - } __timer; - } __first; - union { - union sigval si_value; - struct { - int si_status; - clock_t si_utime, si_stime; - } __sigchld; - } __second; - } __si_common; - struct { - void *si_addr; - short si_addr_lsb; - union { - struct { - void *si_lower; - void *si_upper; - } __addr_bnd; - unsigned si_pkey; - } __first; - } __sigfault; - struct { - long si_band; - int si_fd; - } __sigpoll; - struct { - void *si_call_addr; - int si_syscall; - unsigned si_arch; - } __sigsys; - } __si_fields; +typedef struct __siginfo { + int si_signo; /* signal number */ + int si_errno; /* errno association */ + /* + * Cause of signal, one of the SI_ macros or signal-specific + * values, i.e. one of the FPE_... values for SIGFPE. This + * value is equivalent to the second argument to an old-style + * FreeBSD signal handler. + */ + int si_code; /* signal code */ + pid_t si_pid; /* sending process */ + uid_t si_uid; /* sender's ruid */ + int si_status; /* exit value */ + void *si_addr; /* faulting instruction */ + union sigval si_value; /* signal value */ + union { + struct { + int _trapno;/* machine specific trap code */ + } _fault; + struct { + int _timerid; + int _overrun; + } _timer; + struct { + int _mqd; + } _mesgq; + struct { + long _band; /* band event for SIGPOLL */ + } _poll; /* was this ever used ? */ + struct { + long __spare1__; + int __spare2__[7]; + } __spare__; + } _reason; } siginfo_t; -#define si_pid __si_fields.__si_common.__first.__piduid.si_pid -#define si_uid __si_fields.__si_common.__first.__piduid.si_uid -#define si_status __si_fields.__si_common.__second.__sigchld.si_status -#define si_utime __si_fields.__si_common.__second.__sigchld.si_utime -#define si_stime __si_fields.__si_common.__second.__sigchld.si_stime -#define si_value __si_fields.__si_common.__second.si_value -#define si_addr __si_fields.__sigfault.si_addr -#define si_addr_lsb __si_fields.__sigfault.si_addr_lsb -#define si_lower __si_fields.__sigfault.__first.__addr_bnd.si_lower -#define si_upper __si_fields.__sigfault.__first.__addr_bnd.si_upper -#define si_pkey __si_fields.__sigfault.__first.si_pkey -#define si_band __si_fields.__sigpoll.si_band -#define si_fd __si_fields.__sigpoll.si_fd -#define si_timerid __si_fields.__si_common.__first.__timer.si_timerid -#define si_overrun __si_fields.__si_common.__first.__timer.si_overrun -#define si_ptr si_value.sival_ptr -#define si_int si_value.sival_int -#define si_call_addr __si_fields.__sigsys.si_call_addr -#define si_syscall __si_fields.__sigsys.si_syscall -#define si_arch __si_fields.__sigsys.si_arch struct sigaction { union { void (*sa_handler)(int); - void (*sa_sigaction)(int, siginfo_t *, void *); + void (*__sa_sigaction)(int, struct __siginfo *, void *); } __sa_handler; - sigset_t sa_mask; int sa_flags; - void (*sa_restorer)(void); + sigset_t sa_mask; }; #define sa_handler __sa_handler.sa_handler #define sa_sigaction __sa_handler.sa_sigaction struct sigevent { - union sigval sigev_value; - int sigev_signo; - int sigev_notify; - void (*sigev_notify_function)(union sigval); - pthread_attr_t *sigev_notify_attributes; - char __pad[56-3*sizeof(long)]; + int sigev_notify; /* Notification type */ + int sigev_signo; /* Signal number */ + union sigval sigev_value; /* Signal value */ + union { + int _threadid; + struct { + void (*_function)(union sigval); + void *_attribute; /* pthread_attr_t * */ + } _sigev_thread; + long __spare__[8]; + } _sigev_un; }; #define SIGEV_SIGNAL 0 diff --git a/include/sys/ptrace.h b/include/sys/ptrace.h index 5d62a9859..7e80f5ebc 100644 --- a/include/sys/ptrace.h +++ b/include/sys/ptrace.h @@ -6,131 +6,107 @@ extern "C" { #include -#define PTRACE_TRACEME 0 -#define PT_TRACE_ME PTRACE_TRACEME - -#define PTRACE_PEEKTEXT 1 -#define PTRACE_PEEKDATA 2 -#define PTRACE_PEEKUSER 3 -#define PTRACE_POKETEXT 4 -#define PTRACE_POKEDATA 5 -#define PTRACE_POKEUSER 6 -#define PTRACE_CONT 7 -#define PTRACE_KILL 8 -#define PTRACE_SINGLESTEP 9 -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 -#define PTRACE_GETFPREGS 14 -#define PTRACE_SETFPREGS 15 -#define PTRACE_ATTACH 16 -#define PTRACE_DETACH 17 -#define PTRACE_GETFPXREGS 18 -#define PTRACE_SETFPXREGS 19 -#define PTRACE_SYSCALL 24 -#define PTRACE_SETOPTIONS 0x4200 -#define PTRACE_GETEVENTMSG 0x4201 -#define PTRACE_GETSIGINFO 0x4202 -#define PTRACE_SETSIGINFO 0x4203 -#define PTRACE_GETREGSET 0x4204 -#define PTRACE_SETREGSET 0x4205 -#define PTRACE_SEIZE 0x4206 -#define PTRACE_INTERRUPT 0x4207 -#define PTRACE_LISTEN 0x4208 -#define PTRACE_PEEKSIGINFO 0x4209 -#define PTRACE_GETSIGMASK 0x420a -#define PTRACE_SETSIGMASK 0x420b -#define PTRACE_SECCOMP_GET_FILTER 0x420c -#define PTRACE_SECCOMP_GET_METADATA 0x420d -#define PTRACE_GET_SYSCALL_INFO 0x420e - -#define PT_READ_I PTRACE_PEEKTEXT -#define PT_READ_D PTRACE_PEEKDATA -#define PT_READ_U PTRACE_PEEKUSER -#define PT_WRITE_I PTRACE_POKETEXT -#define PT_WRITE_D PTRACE_POKEDATA -#define PT_WRITE_U PTRACE_POKEUSER -#define PT_CONTINUE PTRACE_CONT -#define PT_KILL PTRACE_KILL -#define PT_STEP PTRACE_SINGLESTEP -#define PT_GETREGS PTRACE_GETREGS -#define PT_SETREGS PTRACE_SETREGS -#define PT_GETFPREGS PTRACE_GETFPREGS -#define PT_SETFPREGS PTRACE_SETFPREGS -#define PT_ATTACH PTRACE_ATTACH -#define PT_DETACH PTRACE_DETACH -#define PT_GETFPXREGS PTRACE_GETFPXREGS -#define PT_SETFPXREGS PTRACE_SETFPXREGS -#define PT_SYSCALL PTRACE_SYSCALL -#define PT_SETOPTIONS PTRACE_SETOPTIONS -#define PT_GETEVENTMSG PTRACE_GETEVENTMSG -#define PT_GETSIGINFO PTRACE_GETSIGINFO -#define PT_SETSIGINFO PTRACE_SETSIGINFO - -#define PTRACE_O_TRACESYSGOOD 0x00000001 -#define PTRACE_O_TRACEFORK 0x00000002 -#define PTRACE_O_TRACEVFORK 0x00000004 -#define PTRACE_O_TRACECLONE 0x00000008 -#define PTRACE_O_TRACEEXEC 0x00000010 -#define PTRACE_O_TRACEVFORKDONE 0x00000020 -#define PTRACE_O_TRACEEXIT 0x00000040 -#define PTRACE_O_TRACESECCOMP 0x00000080 -#define PTRACE_O_EXITKILL 0x00100000 -#define PTRACE_O_SUSPEND_SECCOMP 0x00200000 -#define PTRACE_O_MASK 0x003000ff - -#define PTRACE_EVENT_FORK 1 -#define PTRACE_EVENT_VFORK 2 -#define PTRACE_EVENT_CLONE 3 -#define PTRACE_EVENT_EXEC 4 -#define PTRACE_EVENT_VFORK_DONE 5 -#define PTRACE_EVENT_EXIT 6 -#define PTRACE_EVENT_SECCOMP 7 -#define PTRACE_EVENT_STOP 128 - -#define PTRACE_PEEKSIGINFO_SHARED 1 - -#define PTRACE_SYSCALL_INFO_NONE 0 -#define PTRACE_SYSCALL_INFO_ENTRY 1 -#define PTRACE_SYSCALL_INFO_EXIT 2 -#define PTRACE_SYSCALL_INFO_SECCOMP 3 +// Updated with BSD header. +#define PT_TRACE_ME 0 /* child declares it's being traced */ +#define PT_READ_I 1 /* read word in child's I space */ +#define PT_READ_D 2 /* read word in child's D space */ +/* was PT_READ_U 3 * read word in child's user structure */ +#define PT_WRITE_I 4 /* write word in child's I space */ +#define PT_WRITE_D 5 /* write word in child's D space */ +/* was PT_WRITE_U 6 * write word in child's user structure */ +#define PT_CONTINUE 7 /* continue the child */ +#define PT_KILL 8 /* kill the child process */ +#define PT_STEP 9 /* single step the child */ + +#define PT_ATTACH 10 /* trace some running process */ +#define PT_DETACH 11 /* stop tracing a process */ +#define PT_IO 12 /* do I/O to/from stopped process. */ +#define PT_LWPINFO 13 /* Info about the LWP that stopped. */ +#define PT_GETNUMLWPS 14 /* get total number of threads */ +#define PT_GETLWPLIST 15 /* get thread list */ +#define PT_CLEARSTEP 16 /* turn off single step */ +#define PT_SETSTEP 17 /* turn on single step */ +#define PT_SUSPEND 18 /* suspend a thread */ +#define PT_RESUME 19 /* resume a thread */ + +#define PT_TO_SCE 20 +#define PT_TO_SCX 21 +#define PT_SYSCALL 22 + +#define PT_FOLLOW_FORK 23 + +#define PT_GETREGS 33 /* get general-purpose registers */ +#define PT_SETREGS 34 /* set general-purpose registers */ +#define PT_GETFPREGS 35 /* get floating-point registers */ +#define PT_SETFPREGS 36 /* set floating-point registers */ +#define PT_GETDBREGS 37 /* get debugging registers */ +#define PT_SETDBREGS 38 /* set debugging registers */ + +#define PT_VM_TIMESTAMP 40 /* Get VM version (timestamp) */ +#define PT_VM_ENTRY 41 /* Get VM map (entry) */ + +#define PT_FIRSTMACH 64 /* for machine-specific requests */ #include +#include + +#define __NEED_size_t +#define __NEED_sigset_t +#include -struct __ptrace_peeksiginfo_args { - uint64_t off; - uint32_t flags; - int32_t nr; +struct ptrace_io_desc { + int piod_op; /* I/O operation */ + void *piod_offs; /* child offset */ + void *piod_addr; /* parent offset */ + size_t piod_len; /* request length */ }; -struct __ptrace_seccomp_metadata { - uint64_t filter_off; - uint64_t flags; +/* + * Operations in piod_op. + */ +#define PIOD_READ_D 1 /* Read from D space */ +#define PIOD_WRITE_D 2 /* Write to D space */ +#define PIOD_READ_I 3 /* Read from I space */ +#define PIOD_WRITE_I 4 /* Write to I space */ + +#define MAXCOMLEN 19 /* max command name remembered */ + +/* Argument structure for PT_LWPINFO. */ +struct ptrace_lwpinfo { + int pl_lwpid; /* LWP described. */ + int pl_event; /* Event that stopped the LWP. */ +#define PL_EVENT_NONE 0 +#define PL_EVENT_SIGNAL 1 + int pl_flags; /* LWP flags. */ +#define PL_FLAG_SA 0x01 /* M:N thread */ +#define PL_FLAG_BOUND 0x02 /* M:N bound thread */ +#define PL_FLAG_SCE 0x04 /* syscall enter point */ +#define PL_FLAG_SCX 0x08 /* syscall leave point */ +#define PL_FLAG_EXEC 0x10 /* exec(2) succeeded */ +#define PL_FLAG_SI 0x20 /* siginfo is valid */ +#define PL_FLAG_FORKED 0x40 /* new child */ + sigset_t pl_sigmask; /* LWP signal mask */ + sigset_t pl_siglist; /* LWP pending signal */ + struct __siginfo pl_siginfo; /* siginfo for signal */ + char pl_tdname[MAXCOMLEN + 1]; /* LWP name */ + int pl_child_pid; /* New child pid */ }; -struct __ptrace_syscall_info { - uint8_t op; - uint8_t __pad[3]; - uint32_t arch; - uint64_t instruction_pointer; - uint64_t stack_pointer; - union { - struct { - uint64_t nr; - uint64_t args[6]; - } entry; - struct { - int64_t rval; - uint8_t is_error; - } exit; - struct { - uint64_t nr; - uint64_t args[6]; - uint32_t ret_data; - } seccomp; - }; +/* Argument structure for PT_VM_ENTRY. */ +struct ptrace_vm_entry { + int pve_entry; /* Entry number used for iteration. */ + int pve_timestamp; /* Generation number of VM map. */ + unsigned long pve_start; /* Start VA of range. */ + unsigned long pve_end; /* End VA of range (incl). */ + unsigned long pve_offset; /* Offset in backing object. */ + unsigned int pve_prot; /* Protection of memory range. */ + unsigned int pve_pathlen; /* Size of path. */ + long pve_fileid; /* File ID. */ + uint32_t pve_fsid; /* File system ID. */ + char *pve_path; /* Path name of object. */ }; -long ptrace(int, ...); +int ptrace(int _request, pid_t _pid, void* _addr, int _data); #ifdef __cplusplus } diff --git a/include/sys/sendfile.h b/include/sys/sendfile.h index e7570d8e5..6c81d7220 100644 --- a/include/sys/sendfile.h +++ b/include/sys/sendfile.h @@ -8,7 +8,14 @@ extern "C" { #include #include -ssize_t sendfile(int, int, off_t *, size_t); +struct sf_hdtr { + struct iovec *headers; /* pointer to an array of header struct iovec's */ + int hdr_cnt; /* number of header iovec's */ + struct iovec *trailers; /* pointer to an array of trailer struct iovec's */ + int trl_cnt; /* number of trailer iovec's */ +}; + +int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) #define sendfile64 sendfile diff --git a/src/aio/aio.c b/src/aio/aio.c index 28076bdbf..13319f532 100644 --- a/src/aio/aio.c +++ b/src/aio/aio.c @@ -189,7 +189,11 @@ static void cleanup(void *ctx) } if (sev.sigev_notify == SIGEV_THREAD) { a_store(&__pthread_self()->cancel, 0); +#ifdef PS4 +#warning "sigev_notify_function not supported on PS4" +#else sev.sigev_notify_function(sev.sigev_value); +#endif } } @@ -295,9 +299,13 @@ static int submit(struct aiocb *cb, int op) pthread_mutex_unlock(&q->lock); if (cb->aio_sigevent.sigev_notify == SIGEV_THREAD) { +#ifdef PS4 +#warning "sigev_notify_function not supported on PS4" +#else if (cb->aio_sigevent.sigev_notify_attributes) a = *cb->aio_sigevent.sigev_notify_attributes; else +#endif pthread_attr_init(&a); } else { pthread_once(&init_stack_size_once, init_stack_size); diff --git a/src/aio/lio_listio.c b/src/aio/lio_listio.c index 3821d33f6..b3e00eaca 100644 --- a/src/aio/lio_listio.c +++ b/src/aio/lio_listio.c @@ -64,7 +64,11 @@ static void *wait_thread(void *p) notify_signal(sev); break; case SIGEV_THREAD: +#ifdef PS4 +#warning "sigev_notify_function not supported on PS4" +#else sev->sigev_notify_function(sev->sigev_value); +#endif break; } return 0; @@ -121,9 +125,13 @@ int lio_listio(int mode, struct aiocb *restrict const *restrict cbs, int cnt, st pthread_t td; if (sev->sigev_notify == SIGEV_THREAD) { +#ifdef PS4 +#warning "sigev_notify_function not supported on PS4" +#else if (sev->sigev_notify_attributes) a = *sev->sigev_notify_attributes; else +#endif pthread_attr_init(&a); } else { pthread_attr_init(&a); diff --git a/src/linux/ptrace.c b/src/linux/ptrace.c index 40803ccaa..cf899b8ba 100644 --- a/src/linux/ptrace.c +++ b/src/linux/ptrace.c @@ -5,12 +5,14 @@ #include "syscall.h" #ifndef PS4_LIBKERNEL_SYS -long ptrace(int req, ...) -{ #ifdef PS4 +int ptrace(int _request, pid_t _pid, void* _addr, int _data) +{ errno = ENOSYS; return -1; #else +long ptrace(int req, ...) +{ va_list ap; pid_t pid; void *addr, *data, *addr2 = 0; diff --git a/src/linux/sendfile.c b/src/linux/sendfile.c index 59c7c89fb..40ea10575 100644 --- a/src/linux/sendfile.c +++ b/src/linux/sendfile.c @@ -11,5 +11,7 @@ ssize_t sendfile(int out_fd, int in_fd, off_t *ofs, size_t count) weak_alias(sendfile, sendfile64); #else + #warning "TODO: sendfile" + #endif diff --git a/src/mq/mq_notify.c b/src/mq/mq_notify.c index cda1aa615..91452280d 100644 --- a/src/mq/mq_notify.c +++ b/src/mq/mq_notify.c @@ -18,14 +18,22 @@ static void *start(void *p) char buf[32]; ssize_t n; int s = args->sock; +#ifdef PS4 +#warning "sigev_notify_function not supported on PS4" +#else void (*func)(union sigval) = args->sev->sigev_notify_function; +#endif union sigval val = args->sev->sigev_value; pthread_barrier_wait(&args->barrier); n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL); close(s); +#ifdef PS4 +#warning "sigev_notify_function not supported on PS4" +#else if (n==sizeof buf && buf[sizeof buf - 1] == 1) func(val); +#endif return 0; } @@ -61,8 +69,14 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev) if (s < 0) return -1; args.sock = s; +#ifdef PS4 +#warning "sigev_notify_function not supported on PS4" +#else if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes; - else pthread_attr_init(&attr); + + else +#endif + pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_barrier_init(&args.barrier, 0, 2); diff --git a/src/time/timer_create.c b/src/time/timer_create.c index d7b19c882..a496bae5a 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -38,15 +38,22 @@ static void timer_handler(int sig, siginfo_t *si, void *ctx) static void install_handler() { +#ifdef PS4 +#warning "timer install_handler not supported on PS4" +#else struct sigaction sa = { .sa_sigaction = timer_handler, .sa_flags = SA_SIGINFO | SA_RESTART }; __libc_sigaction(SIGTIMER, &sa, 0); +#endif } static void *start(void *arg) { +#ifdef PS4 +#warning "timer start not supported on PS4" +#else pthread_t self = __pthread_self(); struct start_args *args = arg; jmp_buf jb; @@ -65,9 +72,7 @@ static void *start(void *arg) } if (self->timer_id < 0) break; } -#ifndef PS4 __syscall(SYS_timer_delete, self->timer_id & INT_MAX); -#else { int ktimer_delete(int); ktimer_delete(self->timer_id & INT_MAX); @@ -108,9 +113,13 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict break; case SIGEV_THREAD: pthread_once(&once, install_handler); +#ifdef PS4 +#warning "sigev_notify_function not supported on PS4" +#else if (evp->sigev_notify_attributes) attr = *evp->sigev_notify_attributes; else +#endif pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_barrier_init(&args.b, 0, 2);