diff options
Diffstat (limited to 'sysdeps/mach/hurd/ptrace.c')
-rw-r--r-- | sysdeps/mach/hurd/ptrace.c | 385 |
1 files changed, 0 insertions, 385 deletions
diff --git a/sysdeps/mach/hurd/ptrace.c b/sysdeps/mach/hurd/ptrace.c deleted file mode 100644 index f8ea7375b3..0000000000 --- a/sysdeps/mach/hurd/ptrace.c +++ /dev/null @@ -1,385 +0,0 @@ -/* Process tracing interface `ptrace' for GNU Hurd. - Copyright (C) 1991-2017 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <http://www.gnu.org/licenses/>. */ - -#include <errno.h> -#include <sys/ptrace.h> -#include <sys/types.h> -#include <stdarg.h> -#include <hurd.h> -#include <hurd/signal.h> -#include <hurd/msg.h> -#include <thread_state.h> - -/* Perform process tracing functions. REQUEST is one of the values - in <sys/ptrace.h>, and determines the action to be taken. - For all requests except PTRACE_TRACEME, PID specifies the process to be - traced. - - PID and the other arguments described above for the various requests should - appear (those that are used for the particular request) as: - pid_t PID, void *ADDR, int DATA, void *ADDR2 - after PID. */ -int -ptrace (enum __ptrace_request request, ... ) -{ - pid_t pid; - void *addr, *addr2; - natural_t data; - va_list ap; - - /* Read data from PID's address space, from ADDR for DATA bytes. */ - error_t read_data (task_t task, vm_address_t *ourpage, vm_size_t *size) - { - /* Read the pages containing the addressed range. */ - error_t err; - *size = round_page (addr + data) - trunc_page (addr); - err = __vm_read (task, trunc_page (addr), *size, ourpage, size); - return err; - } - - /* Fetch the thread port for PID's user thread. */ - error_t fetch_user_thread (task_t task, thread_t *thread) - { - thread_t threadbuf[3], *threads = threadbuf; - mach_msg_type_number_t nthreads = 3, i; - error_t err = __task_threads (task, &threads, &nthreads); - if (err) - return err; - if (nthreads == 0) - return EINVAL; - *thread = threads[0]; /* Assume user thread is first. */ - for (i = 1; i < nthreads; ++i) - __mach_port_deallocate (__mach_task_self (), threads[i]); - if (threads != threadbuf) - __vm_deallocate (__mach_task_self (), - (vm_address_t) threads, nthreads * sizeof threads[0]); - return 0; - } - - /* Fetch a thread state structure from PID and store it at ADDR. */ - int get_regs (int flavor, mach_msg_type_number_t count) - { - error_t err; - task_t task = __pid2task (pid); - thread_t thread; - if (task == MACH_PORT_NULL) - return -1; - err = fetch_user_thread (task, &thread); - __mach_port_deallocate (__mach_task_self (), task); - if (!err) - err = __thread_get_state (thread, flavor, addr, &count); - __mach_port_deallocate (__mach_task_self (), thread); - return err ? __hurd_fail (err) : 0; - } - - - switch (request) - { - case PTRACE_TRACEME: - /* Make this process be traced. */ - __sigfillset (&_hurdsig_traced); - __USEPORT (PROC, __proc_mark_traced (port)); - break; - - case PTRACE_CONT: - va_start (ap, request); - pid = va_arg (ap, pid_t); - addr = va_arg (ap, void *); - data = va_arg (ap, int); - va_end (ap); - { - /* Send a DATA signal to PID, telling it to take the signal - normally even if it's traced. */ - error_t err; - task_t task = __pid2task (pid); - if (task == MACH_PORT_NULL) - return -1; - if (data == SIGKILL) - err = __task_terminate (task); - else - { - if (addr != (void *) 1) - { - /* Move the user thread's PC to ADDR. */ - thread_t thread; - err = fetch_user_thread (task, &thread); - if (!err) - { - struct machine_thread_state state; - mach_msg_type_number_t count = MACHINE_THREAD_STATE_COUNT; - err = __thread_get_state (thread, - MACHINE_THREAD_STATE_FLAVOR, - (natural_t *) &state, &count); - if (!err) - { - MACHINE_THREAD_STATE_SET_PC (&state, addr); - err = __thread_set_state (thread, - MACHINE_THREAD_STATE_FLAVOR, - (natural_t *) &state, count); - } - - } - __mach_port_deallocate (__mach_task_self (), thread); - } - else - err = 0; - - if (! err) - /* Tell the process to take the signal (or just resume if 0). */ - err = HURD_MSGPORT_RPC - (__USEPORT (PROC, __proc_getmsgport (port, pid, &msgport)), - 0, 0, __msg_sig_post_untraced (msgport, data, 0, task)); - } - __mach_port_deallocate (__mach_task_self (), task); - return err ? __hurd_fail (err) : 0; - } - - case PTRACE_KILL: - va_start (ap, request); - pid = va_arg (ap, pid_t); - va_end (ap); - /* SIGKILL always just terminates the task, - so normal kill is just the same when traced. */ - return kill (pid, SIGKILL); - - case PTRACE_SINGLESTEP: - /* This is a machine-dependent kernel RPC on - machines that support it. Punt. */ - return __hurd_fail (EOPNOTSUPP); - - case PTRACE_ATTACH: - case PTRACE_DETACH: - va_start (ap, request); - pid = va_arg (ap, pid_t); - va_end (ap); - { - /* Tell PID to set or clear its trace bit. */ - error_t err; - mach_port_t msgport; - task_t task = __pid2task (pid); - if (task == MACH_PORT_NULL) - return -1; - err = __USEPORT (PROC, __proc_getmsgport (port, pid, &msgport)); - if (! err) - { - err = __msg_set_init_int (msgport, task, INIT_TRACEMASK, - request == PTRACE_DETACH ? 0 : - ~(sigset_t) 0); - if (! err) - { - if (request == PTRACE_ATTACH) - /* Now stop the process. */ - err = __msg_sig_post (msgport, SIGSTOP, 0, task); - else - /* Resume the process from tracing stop. */ - err = __msg_sig_post_untraced (msgport, 0, 0, task); - } - __mach_port_deallocate (__mach_task_self (), msgport); - } - __mach_port_deallocate (__mach_task_self (), task); - return err ? __hurd_fail (err) : 0; - } - - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - va_start (ap, request); - pid = va_arg (ap, pid_t); - addr = va_arg (ap, void *); - va_end (ap); - { - /* Read the page (or two pages, if the word lies on a boundary) - containing the addressed word. */ - error_t err; - vm_address_t ourpage; - vm_size_t size; - natural_t word; - task_t task = __pid2task (pid); - if (task == MACH_PORT_NULL) - return -1; - data = sizeof word; - ourpage = 0; - size = 0; - err = read_data (task, &ourpage, &size); - __mach_port_deallocate (__mach_task_self (), task); - if (err) - return __hurd_fail (err); - word = *(natural_t *) ((vm_address_t) addr - trunc_page (addr) - + ourpage); - __vm_deallocate (__mach_task_self (), ourpage, size); - return word; - } - - case PTRACE_PEEKUSER: - case PTRACE_POKEUSER: - /* U area, what's that? */ - return __hurd_fail (EOPNOTSUPP); - - case PTRACE_GETREGS: - case PTRACE_SETREGS: - va_start (ap, request); - pid = va_arg (ap, pid_t); - addr = va_arg (ap, void *); - va_end (ap); - return get_regs (MACHINE_THREAD_STATE_FLAVOR, - MACHINE_THREAD_STATE_COUNT); - - case PTRACE_GETFPREGS: - case PTRACE_SETFPREGS: - va_start (ap, request); - pid = va_arg (ap, pid_t); - addr = va_arg (ap, void *); - va_end (ap); -#ifdef MACHINE_THREAD_FLOAT_STATE_FLAVOR - return get_regs (MACHINE_THREAD_FLOAT_STATE_FLAVOR, - MACHINE_THREAD_FLOAT_STATE_COUNT); -#else - return __hurd_fail (EOPNOTSUPP); -#endif - - case PTRACE_GETFPAREGS: - case PTRACE_SETFPAREGS: - va_start (ap, request); - pid = va_arg (ap, pid_t); - addr = va_arg (ap, void *); - va_end (ap); -#ifdef MACHINE_THREAD_FPA_STATE_FLAVOR - return get_regs (MACHINE_THREAD_FPA_STATE_FLAVOR, - MACHINE_THREAD_FPA_STATE_COUNT); -#else - return __hurd_fail (EOPNOTSUPP); -#endif - - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - va_start (ap, request); - pid = va_arg (ap, pid_t); - addr = va_arg (ap, void *); - data = va_arg (ap, int); - va_end (ap); - { - /* Read the page (or two pages, if the word lies on a boundary) - containing the addressed word. */ - error_t err; - vm_address_t ourpage; - vm_size_t size; - task_t task = __pid2task (pid); - if (task == MACH_PORT_NULL) - return -1; - data = sizeof (natural_t); - ourpage = 0; - size = 0; - err = read_data (task, &ourpage, &size); - - if (!err) - { - /* Now modify the specified word and write the page back. */ - *(natural_t *) ((vm_address_t) addr - trunc_page (addr) - + ourpage) = data; - err = __vm_write (task, trunc_page (addr), ourpage, size); - __vm_deallocate (__mach_task_self (), ourpage, size); - } - - __mach_port_deallocate (__mach_task_self (), task); - return err ? __hurd_fail (err) : 0; - } - - case PTRACE_READDATA: - case PTRACE_READTEXT: - va_start (ap, request); - pid = va_arg (ap, pid_t); - addr = va_arg (ap, void *); - data = va_arg (ap, int); - addr2 = va_arg (ap, void *); - va_end (ap); - { - error_t err; - vm_address_t ourpage; - vm_size_t size; - task_t task = __pid2task (pid); - if (task == MACH_PORT_NULL) - return -1; - if (((vm_address_t) addr2 + data) % __vm_page_size == 0) - { - /* Perhaps we can write directly to the user's buffer. */ - ourpage = (vm_address_t) addr2; - size = data; - } - else - { - ourpage = 0; - size = 0; - } - err = read_data (task, &ourpage, &size); - __mach_port_deallocate (__mach_task_self (), task); - if (!err && ourpage != (vm_address_t) addr2) - { - memcpy (addr2, (void *) ourpage, data); - __vm_deallocate (__mach_task_self (), ourpage, size); - } - return err ? __hurd_fail (err) : 0; - } - - case PTRACE_WRITEDATA: - case PTRACE_WRITETEXT: - va_start (ap, request); - pid = va_arg (ap, pid_t); - addr = va_arg (ap, void *); - data = va_arg (ap, int); - addr2 = va_arg (ap, void *); - va_end (ap); - { - error_t err; - vm_address_t ourpage; - vm_size_t size; - task_t task = __pid2task (pid); - if (task == MACH_PORT_NULL) - return -1; - if ((vm_address_t) addr % __vm_page_size == 0 && - (vm_address_t) data % __vm_page_size == 0) - { - /* Writing whole pages; can go directly from the user's buffer. */ - ourpage = (vm_address_t) addr2; - size = data; - err = 0; - } - else - { - /* Read the task's pages and modify our own copy. */ - ourpage = 0; - size = 0; - err = read_data (task, &ourpage, &size); - if (!err) - memcpy ((void *) ((vm_address_t) addr - trunc_page (addr) - + ourpage), - addr2, - data); - } - if (!err) - /* Write back the modified pages. */ - err = __vm_write (task, trunc_page (addr), ourpage, size); - __mach_port_deallocate (__mach_task_self (), task); - return err ? __hurd_fail (err) : 0; - } - - default: - errno = EINVAL; - return -1; - } - - return 0; -} |