vgdb-invoker-ptrace.c revision 4769c3c0594bb0cbfd31a953ed39dafbe108605c
13c761f0f0344757ac243c65511392fb41d1c841aphilippe/*--------------------------------------------------------------------*/ 23c761f0f0344757ac243c65511392fb41d1c841aphilippe/*--- Implementation of vgdb invoker subsystem via ptrace() calls. ---*/ 33c761f0f0344757ac243c65511392fb41d1c841aphilippe/*--------------------------------------------------------------------*/ 43c761f0f0344757ac243c65511392fb41d1c841aphilippe 53c761f0f0344757ac243c65511392fb41d1c841aphilippe/* 63c761f0f0344757ac243c65511392fb41d1c841aphilippe This file is part of Valgrind, a dynamic binary instrumentation 73c761f0f0344757ac243c65511392fb41d1c841aphilippe framework. 83c761f0f0344757ac243c65511392fb41d1c841aphilippe 93c761f0f0344757ac243c65511392fb41d1c841aphilippe Copyright (C) 2011-2013 Philippe Waroquiers 103c761f0f0344757ac243c65511392fb41d1c841aphilippe 113c761f0f0344757ac243c65511392fb41d1c841aphilippe This program is free software; you can redistribute it and/or 123c761f0f0344757ac243c65511392fb41d1c841aphilippe modify it under the terms of the GNU General Public License as 133c761f0f0344757ac243c65511392fb41d1c841aphilippe published by the Free Software Foundation; either version 2 of the 143c761f0f0344757ac243c65511392fb41d1c841aphilippe License, or (at your option) any later version. 153c761f0f0344757ac243c65511392fb41d1c841aphilippe 163c761f0f0344757ac243c65511392fb41d1c841aphilippe This program is distributed in the hope that it will be useful, but 173c761f0f0344757ac243c65511392fb41d1c841aphilippe WITHOUT ANY WARRANTY; without even the implied warranty of 183c761f0f0344757ac243c65511392fb41d1c841aphilippe MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 193c761f0f0344757ac243c65511392fb41d1c841aphilippe General Public License for more details. 203c761f0f0344757ac243c65511392fb41d1c841aphilippe 213c761f0f0344757ac243c65511392fb41d1c841aphilippe You should have received a copy of the GNU General Public License 223c761f0f0344757ac243c65511392fb41d1c841aphilippe along with this program; if not, write to the Free Software 233c761f0f0344757ac243c65511392fb41d1c841aphilippe Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 243c761f0f0344757ac243c65511392fb41d1c841aphilippe 02111-1307, USA. 253c761f0f0344757ac243c65511392fb41d1c841aphilippe 263c761f0f0344757ac243c65511392fb41d1c841aphilippe The GNU General Public License is contained in the file COPYING. 273c761f0f0344757ac243c65511392fb41d1c841aphilippe*/ 283c761f0f0344757ac243c65511392fb41d1c841aphilippe 293c761f0f0344757ac243c65511392fb41d1c841aphilippe#include "config.h" 303c761f0f0344757ac243c65511392fb41d1c841aphilippe 313c761f0f0344757ac243c65511392fb41d1c841aphilippe#include "vgdb.h" 323c761f0f0344757ac243c65511392fb41d1c841aphilippe#include "pub_core_threadstate.h" 333c761f0f0344757ac243c65511392fb41d1c841aphilippe 343c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <alloca.h> 353c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <assert.h> 363c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <errno.h> 373c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <stdio.h> 383c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <stdlib.h> 393c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <string.h> 403c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <sys/ptrace.h> 413c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <sys/time.h> 423c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <sys/user.h> 433c761f0f0344757ac243c65511392fb41d1c841aphilippe#include <sys/wait.h> 443c761f0f0344757ac243c65511392fb41d1c841aphilippe 45c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#ifdef PTRACE_GETREGSET 46c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// TBD: better have a configure test instead ? 47c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#define HAVE_PTRACE_GETREGSET 48c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 49c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// A bi-arch build using PTRACE_GET/SETREGSET needs 50c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// some conversion code for register structures. 51c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// So, better do not use PTRACE_GET/SETREGSET 52c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// Rather we use PTRACE_GETREGS or PTRACE_PEEKUSER. 53c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 54c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// The only platform on which we must use PTRACE_GETREGSET is arm64. 55c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// The resulting vgdb cannot work in a bi-arch setup. 56c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// -1 means we will check that PTRACE_GETREGSET works. 57c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# if defined(VGA_arm64) 58c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#define USE_PTRACE_GETREGSET 59c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# endif 60c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#endif 61c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 62c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#include <sys/uio.h> 63c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#include <elf.h> 64c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 65c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#include <sys/procfs.h> 66c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 673629f4a3d4a0237421da38f5f5cdf6fcfa368d03florian// glibc versions prior to 2.5 do not define PTRACE_GETSIGINFO on 683629f4a3d4a0237421da38f5f5cdf6fcfa368d03florian// the platforms we support. 693629f4a3d4a0237421da38f5f5cdf6fcfa368d03florian#if !((__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 5)) 703b4ef11d87596b6d63d690caf517a3abf62d39d4florian# ifndef PTRACE_GETSIGINFO 713b4ef11d87596b6d63d690caf517a3abf62d39d4florian# define PTRACE_GETSIGINFO 0x4202 723b4ef11d87596b6d63d690caf517a3abf62d39d4florian# endif 733b4ef11d87596b6d63d690caf517a3abf62d39d4florian#endif 743b4ef11d87596b6d63d690caf517a3abf62d39d4florian 754769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe// 32-bit or 64-bit wide, depending on primary architecture. 764769c3c0594bb0cbfd31a953ed39dafbe108605cphilippetypedef Addr CORE_ADDR; 774769c3c0594bb0cbfd31a953ed39dafbe108605cphilippetypedef Addr PTRACE_XFER_TYPE; 783c761f0f0344757ac243c65511392fb41d1c841aphilippetypedef void* PTRACE_ARG3_TYPE; 793c761f0f0344757ac243c65511392fb41d1c841aphilippe 806654de8547d2e420c20e21980669b807aa80710ephilippe// if > 0, pid for which registers have to be restored. 816654de8547d2e420c20e21980669b807aa80710ephilippe// if == 0, means we have not yet called setregs (or have already 826654de8547d2e420c20e21980669b807aa80710ephilippe// restored the registers). 836654de8547d2e420c20e21980669b807aa80710ephilippestatic int pid_of_save_regs = 0; 843c761f0f0344757ac243c65511392fb41d1c841aphilippe/* True if we have continued pid_of_save_regs after PTRACE_ATTACH. */ 853c761f0f0344757ac243c65511392fb41d1c841aphilippestatic Bool pid_of_save_regs_continued = False; 866654de8547d2e420c20e21980669b807aa80710ephilippe// When setregs has been called to change the registers of pid_of_save_regs, 876654de8547d2e420c20e21980669b807aa80710ephilippe// vgdb cannot transmit the signals intercepted during ptrace. 886654de8547d2e420c20e21980669b807aa80710ephilippe// So, we queue them, and will deliver them when detaching. 896654de8547d2e420c20e21980669b807aa80710ephilippe// See function waitstopped for more info. 906654de8547d2e420c20e21980669b807aa80710ephilippestatic int signal_queue_sz = 0; 916654de8547d2e420c20e21980669b807aa80710ephilippestatic siginfo_t *signal_queue; 923c761f0f0344757ac243c65511392fb41d1c841aphilippe 933c761f0f0344757ac243c65511392fb41d1c841aphilippe/* True when loss of connection indicating that the Valgrind 943c761f0f0344757ac243c65511392fb41d1c841aphilippe process is dying. */ 953c761f0f0344757ac243c65511392fb41d1c841aphilippestatic Bool dying = False; 963c761f0f0344757ac243c65511392fb41d1c841aphilippe 973c761f0f0344757ac243c65511392fb41d1c841aphilippe/* ptrace_(read|write)_memory are modified extracts of linux-low.c 983c761f0f0344757ac243c65511392fb41d1c841aphilippe from gdb 6.6. Copyrighted FSF */ 993c761f0f0344757ac243c65511392fb41d1c841aphilippe/* Copy LEN bytes from valgrind memory starting at MEMADDR 1003c761f0f0344757ac243c65511392fb41d1c841aphilippe to vgdb memory starting at MYADDR. */ 1013c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 1023c761f0f0344757ac243c65511392fb41d1c841aphilippeint ptrace_read_memory (pid_t inferior_pid, CORE_ADDR memaddr, 1033c761f0f0344757ac243c65511392fb41d1c841aphilippe void *myaddr, size_t len) 1043c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 1053c761f0f0344757ac243c65511392fb41d1c841aphilippe register int i; 1063c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Round starting address down to longword boundary. */ 1073c761f0f0344757ac243c65511392fb41d1c841aphilippe register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE); 1083c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Round ending address up; get number of longwords that makes. */ 1093c761f0f0344757ac243c65511392fb41d1c841aphilippe register int count 1103c761f0f0344757ac243c65511392fb41d1c841aphilippe = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) 1113c761f0f0344757ac243c65511392fb41d1c841aphilippe / sizeof (PTRACE_XFER_TYPE); 1123c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Allocate buffer of that many longwords. */ 1133c761f0f0344757ac243c65511392fb41d1c841aphilippe register PTRACE_XFER_TYPE *buffer 1143c761f0f0344757ac243c65511392fb41d1c841aphilippe = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE)); 1153c761f0f0344757ac243c65511392fb41d1c841aphilippe 1163c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Read all the longwords */ 1173c761f0f0344757ac243c65511392fb41d1c841aphilippe for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) { 1183c761f0f0344757ac243c65511392fb41d1c841aphilippe errno = 0; 1193c761f0f0344757ac243c65511392fb41d1c841aphilippe buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, 1203c761f0f0344757ac243c65511392fb41d1c841aphilippe (PTRACE_ARG3_TYPE) addr, 0); 1213c761f0f0344757ac243c65511392fb41d1c841aphilippe if (errno) 1223c761f0f0344757ac243c65511392fb41d1c841aphilippe return errno; 1233c761f0f0344757ac243c65511392fb41d1c841aphilippe } 1243c761f0f0344757ac243c65511392fb41d1c841aphilippe 1253c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Copy appropriate bytes out of the buffer. */ 1263c761f0f0344757ac243c65511392fb41d1c841aphilippe memcpy (myaddr, 1273c761f0f0344757ac243c65511392fb41d1c841aphilippe (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), len); 1283c761f0f0344757ac243c65511392fb41d1c841aphilippe 1293c761f0f0344757ac243c65511392fb41d1c841aphilippe return 0; 1303c761f0f0344757ac243c65511392fb41d1c841aphilippe} 1313c761f0f0344757ac243c65511392fb41d1c841aphilippe 1323c761f0f0344757ac243c65511392fb41d1c841aphilippe/* Copy LEN bytes of data from vgdb memory at MYADDR 1333c761f0f0344757ac243c65511392fb41d1c841aphilippe to valgrind memory at MEMADDR. 1343c761f0f0344757ac243c65511392fb41d1c841aphilippe On failure (cannot write the valgrind memory) 1353c761f0f0344757ac243c65511392fb41d1c841aphilippe returns the value of errno. */ 1363c761f0f0344757ac243c65511392fb41d1c841aphilippe__attribute__((unused)) /* not used on all platforms */ 1373c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 1383c761f0f0344757ac243c65511392fb41d1c841aphilippeint ptrace_write_memory (pid_t inferior_pid, CORE_ADDR memaddr, 1393c761f0f0344757ac243c65511392fb41d1c841aphilippe const void *myaddr, size_t len) 1403c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 1413c761f0f0344757ac243c65511392fb41d1c841aphilippe register int i; 1423c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Round starting address down to longword boundary. */ 1433c761f0f0344757ac243c65511392fb41d1c841aphilippe register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE); 1443c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Round ending address up; get number of longwords that makes. */ 1453c761f0f0344757ac243c65511392fb41d1c841aphilippe register int count 1463c761f0f0344757ac243c65511392fb41d1c841aphilippe = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) 1473c761f0f0344757ac243c65511392fb41d1c841aphilippe / sizeof (PTRACE_XFER_TYPE); 1483c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Allocate buffer of that many longwords. */ 1493c761f0f0344757ac243c65511392fb41d1c841aphilippe register PTRACE_XFER_TYPE *buffer 1503c761f0f0344757ac243c65511392fb41d1c841aphilippe = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE)); 1513c761f0f0344757ac243c65511392fb41d1c841aphilippe 1523c761f0f0344757ac243c65511392fb41d1c841aphilippe if (debuglevel >= 1) { 1533c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG (1, "Writing "); 1543c761f0f0344757ac243c65511392fb41d1c841aphilippe for (i = 0; i < len; i++) 1553c761f0f0344757ac243c65511392fb41d1c841aphilippe PDEBUG (1, "%02x", ((const unsigned char*)myaddr)[i]); 1563c761f0f0344757ac243c65511392fb41d1c841aphilippe PDEBUG(1, " to %p\n", (void *) memaddr); 1573c761f0f0344757ac243c65511392fb41d1c841aphilippe } 1583c761f0f0344757ac243c65511392fb41d1c841aphilippe 1593c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Fill start and end extra bytes of buffer with existing memory data. */ 1603c761f0f0344757ac243c65511392fb41d1c841aphilippe 1613c761f0f0344757ac243c65511392fb41d1c841aphilippe buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid, 1623c761f0f0344757ac243c65511392fb41d1c841aphilippe (PTRACE_ARG3_TYPE) addr, 0); 1633c761f0f0344757ac243c65511392fb41d1c841aphilippe 1643c761f0f0344757ac243c65511392fb41d1c841aphilippe if (count > 1) { 1653c761f0f0344757ac243c65511392fb41d1c841aphilippe buffer[count - 1] 1663c761f0f0344757ac243c65511392fb41d1c841aphilippe = ptrace (PTRACE_PEEKTEXT, inferior_pid, 1673c761f0f0344757ac243c65511392fb41d1c841aphilippe (PTRACE_ARG3_TYPE) (addr + (count - 1) 1683c761f0f0344757ac243c65511392fb41d1c841aphilippe * sizeof (PTRACE_XFER_TYPE)), 1693c761f0f0344757ac243c65511392fb41d1c841aphilippe 0); 1703c761f0f0344757ac243c65511392fb41d1c841aphilippe } 1713c761f0f0344757ac243c65511392fb41d1c841aphilippe 1723c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Copy data to be written over corresponding part of buffer */ 1733c761f0f0344757ac243c65511392fb41d1c841aphilippe 1743c761f0f0344757ac243c65511392fb41d1c841aphilippe memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), 1753c761f0f0344757ac243c65511392fb41d1c841aphilippe myaddr, len); 1763c761f0f0344757ac243c65511392fb41d1c841aphilippe 1773c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Write the entire buffer. */ 1783c761f0f0344757ac243c65511392fb41d1c841aphilippe 1793c761f0f0344757ac243c65511392fb41d1c841aphilippe for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) { 1803c761f0f0344757ac243c65511392fb41d1c841aphilippe errno = 0; 1813c761f0f0344757ac243c65511392fb41d1c841aphilippe ptrace (PTRACE_POKETEXT, inferior_pid, 1823c761f0f0344757ac243c65511392fb41d1c841aphilippe (PTRACE_ARG3_TYPE) addr, buffer[i]); 1833c761f0f0344757ac243c65511392fb41d1c841aphilippe if (errno) 1843c761f0f0344757ac243c65511392fb41d1c841aphilippe return errno; 1853c761f0f0344757ac243c65511392fb41d1c841aphilippe } 1863c761f0f0344757ac243c65511392fb41d1c841aphilippe 1873c761f0f0344757ac243c65511392fb41d1c841aphilippe return 0; 1883c761f0f0344757ac243c65511392fb41d1c841aphilippe} 1893c761f0f0344757ac243c65511392fb41d1c841aphilippe 1903c761f0f0344757ac243c65511392fb41d1c841aphilippe/* subset of VG_(threads) needed for vgdb ptrace. 1913c761f0f0344757ac243c65511392fb41d1c841aphilippe This is initialized when process is attached. */ 1923c761f0f0344757ac243c65511392fb41d1c841aphilippetypedef struct { 1933c761f0f0344757ac243c65511392fb41d1c841aphilippe ThreadStatus status; 1943c761f0f0344757ac243c65511392fb41d1c841aphilippe Int lwpid; 1953c761f0f0344757ac243c65511392fb41d1c841aphilippe} 1963c761f0f0344757ac243c65511392fb41d1c841aphilippeVgdbThreadState; 1973c761f0f0344757ac243c65511392fb41d1c841aphilippestatic VgdbThreadState vgdb_threads[VG_N_THREADS]; 1983c761f0f0344757ac243c65511392fb41d1c841aphilippe 1993c761f0f0344757ac243c65511392fb41d1c841aphilippestatic const 2003c761f0f0344757ac243c65511392fb41d1c841aphilippeHChar* name_of_ThreadStatus ( ThreadStatus status ) 2013c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 2023c761f0f0344757ac243c65511392fb41d1c841aphilippe switch (status) { 2033c761f0f0344757ac243c65511392fb41d1c841aphilippe case VgTs_Empty: return "VgTs_Empty"; 2043c761f0f0344757ac243c65511392fb41d1c841aphilippe case VgTs_Init: return "VgTs_Init"; 2053c761f0f0344757ac243c65511392fb41d1c841aphilippe case VgTs_Runnable: return "VgTs_Runnable"; 2063c761f0f0344757ac243c65511392fb41d1c841aphilippe case VgTs_WaitSys: return "VgTs_WaitSys"; 2073c761f0f0344757ac243c65511392fb41d1c841aphilippe case VgTs_Yielding: return "VgTs_Yielding"; 2083c761f0f0344757ac243c65511392fb41d1c841aphilippe case VgTs_Zombie: return "VgTs_Zombie"; 2093c761f0f0344757ac243c65511392fb41d1c841aphilippe default: return "VgTs_???"; 2103c761f0f0344757ac243c65511392fb41d1c841aphilippe } 2113c761f0f0344757ac243c65511392fb41d1c841aphilippe} 2123c761f0f0344757ac243c65511392fb41d1c841aphilippe 2133c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 2143c761f0f0344757ac243c65511392fb41d1c841aphilippechar *status_image (int status) 2153c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 2167b7d59405204f88cb944155d6bc5114025ebda98florian static char result[256]; // large enough 2173c761f0f0344757ac243c65511392fb41d1c841aphilippe int sz = 0; 2183c761f0f0344757ac243c65511392fb41d1c841aphilippe#define APPEND(...) sz += snprintf (result+sz, 256 - sz - 1, __VA_ARGS__) 2193c761f0f0344757ac243c65511392fb41d1c841aphilippe 2203c761f0f0344757ac243c65511392fb41d1c841aphilippe result[0] = 0; 2213c761f0f0344757ac243c65511392fb41d1c841aphilippe 2223c761f0f0344757ac243c65511392fb41d1c841aphilippe if (WIFEXITED(status)) 2233c761f0f0344757ac243c65511392fb41d1c841aphilippe APPEND ("WIFEXITED %d ", WEXITSTATUS(status)); 2243c761f0f0344757ac243c65511392fb41d1c841aphilippe 2253c761f0f0344757ac243c65511392fb41d1c841aphilippe if (WIFSIGNALED(status)) { 2263c761f0f0344757ac243c65511392fb41d1c841aphilippe APPEND ("WIFSIGNALED %d ", WTERMSIG(status)); 2273c761f0f0344757ac243c65511392fb41d1c841aphilippe if (WCOREDUMP(status)) APPEND ("WCOREDUMP "); 2283c761f0f0344757ac243c65511392fb41d1c841aphilippe } 2293c761f0f0344757ac243c65511392fb41d1c841aphilippe 2303c761f0f0344757ac243c65511392fb41d1c841aphilippe if (WIFSTOPPED(status)) 2313c761f0f0344757ac243c65511392fb41d1c841aphilippe APPEND ("WIFSTOPPED %d ", WSTOPSIG(status)); 2323c761f0f0344757ac243c65511392fb41d1c841aphilippe 2333c761f0f0344757ac243c65511392fb41d1c841aphilippe#ifdef WIFCONTINUED 2343c761f0f0344757ac243c65511392fb41d1c841aphilippe if (WIFCONTINUED(status)) 2353c761f0f0344757ac243c65511392fb41d1c841aphilippe APPEND ("WIFCONTINUED "); 2363c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif 2373c761f0f0344757ac243c65511392fb41d1c841aphilippe 2383c761f0f0344757ac243c65511392fb41d1c841aphilippe return result; 2393c761f0f0344757ac243c65511392fb41d1c841aphilippe#undef APPEND 2403c761f0f0344757ac243c65511392fb41d1c841aphilippe} 2413c761f0f0344757ac243c65511392fb41d1c841aphilippe 2423c761f0f0344757ac243c65511392fb41d1c841aphilippe/* Wait till the process pid is reported as stopped with signal_expected. 2433c761f0f0344757ac243c65511392fb41d1c841aphilippe If other signal(s) than signal_expected are received, waitstopped 2443c761f0f0344757ac243c65511392fb41d1c841aphilippe will pass them to pid, waiting for signal_expected to stop pid. 2453c761f0f0344757ac243c65511392fb41d1c841aphilippe Returns True when process is in stopped state with signal_expected. 2463c761f0f0344757ac243c65511392fb41d1c841aphilippe Returns False if a problem was encountered while waiting for pid 2473c761f0f0344757ac243c65511392fb41d1c841aphilippe to be stopped. 2483c761f0f0344757ac243c65511392fb41d1c841aphilippe 2493c761f0f0344757ac243c65511392fb41d1c841aphilippe If pid is reported as being dead/exited, waitstopped will return False. 2503c761f0f0344757ac243c65511392fb41d1c841aphilippe*/ 2513c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 2523c761f0f0344757ac243c65511392fb41d1c841aphilippeBool waitstopped (pid_t pid, int signal_expected, const char *msg) 2533c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 2543c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_t p; 2553c761f0f0344757ac243c65511392fb41d1c841aphilippe int status = 0; 2563c761f0f0344757ac243c65511392fb41d1c841aphilippe int signal_received; 2573c761f0f0344757ac243c65511392fb41d1c841aphilippe int res; 2583c761f0f0344757ac243c65511392fb41d1c841aphilippe 2593c761f0f0344757ac243c65511392fb41d1c841aphilippe while (1) { 2603c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "waitstopped %s before waitpid signal_expected %d\n", 2613c761f0f0344757ac243c65511392fb41d1c841aphilippe msg, signal_expected); 2623c761f0f0344757ac243c65511392fb41d1c841aphilippe p = waitpid(pid, &status, __WALL); 2633c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "after waitpid pid %d p %d status 0x%x %s\n", pid, p, 2643c761f0f0344757ac243c65511392fb41d1c841aphilippe status, status_image (status)); 2653c761f0f0344757ac243c65511392fb41d1c841aphilippe if (p != pid) { 2663c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "%s waitpid pid %d in waitstopped %d status 0x%x %s\n", 2673c761f0f0344757ac243c65511392fb41d1c841aphilippe msg, pid, p, status, status_image (status)); 2683c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 2693c761f0f0344757ac243c65511392fb41d1c841aphilippe } 2703c761f0f0344757ac243c65511392fb41d1c841aphilippe 2713c761f0f0344757ac243c65511392fb41d1c841aphilippe if (WIFEXITED(status)) { 2723c761f0f0344757ac243c65511392fb41d1c841aphilippe shutting_down = True; 2733c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 2743c761f0f0344757ac243c65511392fb41d1c841aphilippe } 2753c761f0f0344757ac243c65511392fb41d1c841aphilippe 2763c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (WIFSTOPPED(status)); 2773c761f0f0344757ac243c65511392fb41d1c841aphilippe signal_received = WSTOPSIG(status); 2783c761f0f0344757ac243c65511392fb41d1c841aphilippe if (signal_received == signal_expected) 2793c761f0f0344757ac243c65511392fb41d1c841aphilippe break; 2803c761f0f0344757ac243c65511392fb41d1c841aphilippe 2813c761f0f0344757ac243c65511392fb41d1c841aphilippe /* pid received a signal which is not the signal we are waiting for. 2826654de8547d2e420c20e21980669b807aa80710ephilippe If we have not (yet) changed the registers of the inferior 2836654de8547d2e420c20e21980669b807aa80710ephilippe or we have (already) reset them, we can transmit the signal. 2846654de8547d2e420c20e21980669b807aa80710ephilippe 2856654de8547d2e420c20e21980669b807aa80710ephilippe If we have already set the registers of the inferior, we cannot 2866654de8547d2e420c20e21980669b807aa80710ephilippe transmit the signal, as this signal would arrive when the 2876654de8547d2e420c20e21980669b807aa80710ephilippe gdbserver code runs. And valgrind only expects signals to 2886654de8547d2e420c20e21980669b807aa80710ephilippe arrive in a small code portion around 2896654de8547d2e420c20e21980669b807aa80710ephilippe client syscall logic, where signal are unmasked (see e.g. 2906654de8547d2e420c20e21980669b807aa80710ephilippe m_syswrap/syscall-x86-linux.S ML_(do_syscall_for_client_WRK). 2916654de8547d2e420c20e21980669b807aa80710ephilippe 2926654de8547d2e420c20e21980669b807aa80710ephilippe As ptrace is forcing a call to gdbserver by jumping 2936654de8547d2e420c20e21980669b807aa80710ephilippe 'out of this region', signals are not masked, but 2946654de8547d2e420c20e21980669b807aa80710ephilippe will arrive outside of the allowed/expected code region. 2956654de8547d2e420c20e21980669b807aa80710ephilippe So, if we have changed the registers of the inferior, we 2966654de8547d2e420c20e21980669b807aa80710ephilippe rather queue the signal to transmit them when detaching, 2976654de8547d2e420c20e21980669b807aa80710ephilippe after having restored the registers to the initial values. */ 2986654de8547d2e420c20e21980669b807aa80710ephilippe if (pid_of_save_regs) { 2996654de8547d2e420c20e21980669b807aa80710ephilippe siginfo_t *newsiginfo; 3006654de8547d2e420c20e21980669b807aa80710ephilippe 3016654de8547d2e420c20e21980669b807aa80710ephilippe // realloc a bigger queue, and store new signal at the end. 3026654de8547d2e420c20e21980669b807aa80710ephilippe // This is not very efficient but we assume not many sigs are queued. 3036654de8547d2e420c20e21980669b807aa80710ephilippe signal_queue_sz++; 3044769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe signal_queue = vrealloc(signal_queue, 3054769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe sizeof(siginfo_t) * signal_queue_sz); 3066654de8547d2e420c20e21980669b807aa80710ephilippe newsiginfo = signal_queue + (signal_queue_sz - 1); 3076654de8547d2e420c20e21980669b807aa80710ephilippe 3086654de8547d2e420c20e21980669b807aa80710ephilippe res = ptrace (PTRACE_GETSIGINFO, pid, NULL, newsiginfo); 3096654de8547d2e420c20e21980669b807aa80710ephilippe if (res != 0) { 3106654de8547d2e420c20e21980669b807aa80710ephilippe ERROR(errno, "PTRACE_GETSIGINFO failed: signal lost !!!!\n"); 3116654de8547d2e420c20e21980669b807aa80710ephilippe signal_queue_sz--; 3126654de8547d2e420c20e21980669b807aa80710ephilippe } else 3136654de8547d2e420c20e21980669b807aa80710ephilippe DEBUG(1, "waitstopped PTRACE_CONT, queuing signal %d" 3146654de8547d2e420c20e21980669b807aa80710ephilippe " si_signo %d si_pid %d\n", 3156654de8547d2e420c20e21980669b807aa80710ephilippe signal_received, newsiginfo->si_signo, newsiginfo->si_pid); 3166654de8547d2e420c20e21980669b807aa80710ephilippe res = ptrace (PTRACE_CONT, pid, NULL, 0); 3176654de8547d2e420c20e21980669b807aa80710ephilippe } else { 3186654de8547d2e420c20e21980669b807aa80710ephilippe DEBUG(1, "waitstopped PTRACE_CONT with signal %d\n", signal_received); 3196654de8547d2e420c20e21980669b807aa80710ephilippe res = ptrace (PTRACE_CONT, pid, NULL, signal_received); 3206654de8547d2e420c20e21980669b807aa80710ephilippe } 3213c761f0f0344757ac243c65511392fb41d1c841aphilippe if (res != 0) { 3223c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "waitstopped PTRACE_CONT\n"); 3233c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 3243c761f0f0344757ac243c65511392fb41d1c841aphilippe } 3253c761f0f0344757ac243c65511392fb41d1c841aphilippe } 3263c761f0f0344757ac243c65511392fb41d1c841aphilippe 3273c761f0f0344757ac243c65511392fb41d1c841aphilippe return True; 3283c761f0f0344757ac243c65511392fb41d1c841aphilippe} 3293c761f0f0344757ac243c65511392fb41d1c841aphilippe 3303c761f0f0344757ac243c65511392fb41d1c841aphilippe/* Stops the given pid, wait for the process to be stopped. 3313c761f0f0344757ac243c65511392fb41d1c841aphilippe Returns True if succesful, False otherwise. 3323c761f0f0344757ac243c65511392fb41d1c841aphilippe msg is used in tracing and error reporting. */ 3333c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 3343c761f0f0344757ac243c65511392fb41d1c841aphilippeBool stop (pid_t pid, const char *msg) 3353c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 3363c761f0f0344757ac243c65511392fb41d1c841aphilippe long res; 3373c761f0f0344757ac243c65511392fb41d1c841aphilippe 3383c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "%s SIGSTOP pid %d\n", msg, pid); 3393c761f0f0344757ac243c65511392fb41d1c841aphilippe res = kill (pid, SIGSTOP); 3403c761f0f0344757ac243c65511392fb41d1c841aphilippe if (res != 0) { 3413c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "%s SIGSTOP pid %d %ld\n", msg, pid, res); 3423c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 3433c761f0f0344757ac243c65511392fb41d1c841aphilippe } 3443c761f0f0344757ac243c65511392fb41d1c841aphilippe 3453c761f0f0344757ac243c65511392fb41d1c841aphilippe return waitstopped (pid, SIGSTOP, msg); 3463c761f0f0344757ac243c65511392fb41d1c841aphilippe 3473c761f0f0344757ac243c65511392fb41d1c841aphilippe} 3483c761f0f0344757ac243c65511392fb41d1c841aphilippe 3493c761f0f0344757ac243c65511392fb41d1c841aphilippe/* Attaches to given pid, wait for the process to be stopped. 3503c761f0f0344757ac243c65511392fb41d1c841aphilippe Returns True if succesful, False otherwise. 3513c761f0f0344757ac243c65511392fb41d1c841aphilippe msg is used in tracing and error reporting. */ 3523c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 3533c761f0f0344757ac243c65511392fb41d1c841aphilippeBool attach (pid_t pid, const char *msg) 3543c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 3553c761f0f0344757ac243c65511392fb41d1c841aphilippe long res; 3563c761f0f0344757ac243c65511392fb41d1c841aphilippe static Bool output_error = True; 3573c761f0f0344757ac243c65511392fb41d1c841aphilippe static Bool initial_attach = True; 3583c761f0f0344757ac243c65511392fb41d1c841aphilippe // For a ptrace_scope protected system, we do not want to output 3593c761f0f0344757ac243c65511392fb41d1c841aphilippe // repetitively attach error. We will output once an error 3603c761f0f0344757ac243c65511392fb41d1c841aphilippe // for the initial_attach. Once the 1st attach has succeeded, we 3613c761f0f0344757ac243c65511392fb41d1c841aphilippe // again show all errors. 3623c761f0f0344757ac243c65511392fb41d1c841aphilippe 3633c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "%s PTRACE_ATTACH pid %d\n", msg, pid); 3643c761f0f0344757ac243c65511392fb41d1c841aphilippe res = ptrace (PTRACE_ATTACH, pid, NULL, NULL); 3653c761f0f0344757ac243c65511392fb41d1c841aphilippe if (res != 0) { 3663c761f0f0344757ac243c65511392fb41d1c841aphilippe if (output_error || debuglevel > 0) { 3673c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "%s PTRACE_ATTACH pid %d %ld\n", msg, pid, res); 3683c761f0f0344757ac243c65511392fb41d1c841aphilippe if (initial_attach) 3693c761f0f0344757ac243c65511392fb41d1c841aphilippe output_error = False; 3703c761f0f0344757ac243c65511392fb41d1c841aphilippe } 3713c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 3723c761f0f0344757ac243c65511392fb41d1c841aphilippe } 3733c761f0f0344757ac243c65511392fb41d1c841aphilippe 3743c761f0f0344757ac243c65511392fb41d1c841aphilippe initial_attach = False; 3753c761f0f0344757ac243c65511392fb41d1c841aphilippe output_error = True; 3763c761f0f0344757ac243c65511392fb41d1c841aphilippe return waitstopped(pid, SIGSTOP, msg); 3773c761f0f0344757ac243c65511392fb41d1c841aphilippe} 3783c761f0f0344757ac243c65511392fb41d1c841aphilippe 3793c761f0f0344757ac243c65511392fb41d1c841aphilippe/* once we are attached to the pid, get the list of threads and stop 3803c761f0f0344757ac243c65511392fb41d1c841aphilippe them all. 3813c761f0f0344757ac243c65511392fb41d1c841aphilippe Returns True if all threads properly suspended, False otherwise. */ 3823c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 3833c761f0f0344757ac243c65511392fb41d1c841aphilippeBool acquire_and_suspend_threads (pid_t pid) 3843c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 3853c761f0f0344757ac243c65511392fb41d1c841aphilippe int i; 3863c761f0f0344757ac243c65511392fb41d1c841aphilippe int rw; 3873c761f0f0344757ac243c65511392fb41d1c841aphilippe Bool pid_found = False; 3883c761f0f0344757ac243c65511392fb41d1c841aphilippe Addr vgt; 3893c761f0f0344757ac243c65511392fb41d1c841aphilippe int sz_tst; 3903c761f0f0344757ac243c65511392fb41d1c841aphilippe int off_status; 3913c761f0f0344757ac243c65511392fb41d1c841aphilippe int off_lwpid; 3923c761f0f0344757ac243c65511392fb41d1c841aphilippe int nr_live_threads = 0; 3933c761f0f0344757ac243c65511392fb41d1c841aphilippe 3943c761f0f0344757ac243c65511392fb41d1c841aphilippe if (shared32 != NULL) { 3953c761f0f0344757ac243c65511392fb41d1c841aphilippe vgt = shared32->threads; 3963c761f0f0344757ac243c65511392fb41d1c841aphilippe sz_tst = shared32->sizeof_ThreadState; 3973c761f0f0344757ac243c65511392fb41d1c841aphilippe off_status = shared32->offset_status; 3983c761f0f0344757ac243c65511392fb41d1c841aphilippe off_lwpid = shared32->offset_lwpid; 3993c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4003c761f0f0344757ac243c65511392fb41d1c841aphilippe else if (shared64 != NULL) { 4013c761f0f0344757ac243c65511392fb41d1c841aphilippe vgt = shared64->threads; 4023c761f0f0344757ac243c65511392fb41d1c841aphilippe sz_tst = shared64->sizeof_ThreadState; 4033c761f0f0344757ac243c65511392fb41d1c841aphilippe off_status = shared64->offset_status; 4043c761f0f0344757ac243c65511392fb41d1c841aphilippe off_lwpid = shared64->offset_lwpid; 4053c761f0f0344757ac243c65511392fb41d1c841aphilippe } else { 4063c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (0); 4073c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4083c761f0f0344757ac243c65511392fb41d1c841aphilippe 4093c761f0f0344757ac243c65511392fb41d1c841aphilippe /* note: the entry 0 is unused */ 4103c761f0f0344757ac243c65511392fb41d1c841aphilippe for (i = 1; i < VG_N_THREADS; i++) { 4113c761f0f0344757ac243c65511392fb41d1c841aphilippe vgt += sz_tst; 4123c761f0f0344757ac243c65511392fb41d1c841aphilippe rw = ptrace_read_memory(pid, vgt+off_status, 4133c761f0f0344757ac243c65511392fb41d1c841aphilippe &(vgdb_threads[i].status), 4143c761f0f0344757ac243c65511392fb41d1c841aphilippe sizeof(ThreadStatus)); 4153c761f0f0344757ac243c65511392fb41d1c841aphilippe if (rw != 0) { 4163c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(rw, "status ptrace_read_memory\n"); 4173c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 4183c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4193c761f0f0344757ac243c65511392fb41d1c841aphilippe 4203c761f0f0344757ac243c65511392fb41d1c841aphilippe rw = ptrace_read_memory(pid, vgt+off_lwpid, 4213c761f0f0344757ac243c65511392fb41d1c841aphilippe &(vgdb_threads[i].lwpid), 4223c761f0f0344757ac243c65511392fb41d1c841aphilippe sizeof(Int)); 4233c761f0f0344757ac243c65511392fb41d1c841aphilippe if (rw != 0) { 4243c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(rw, "lwpid ptrace_read_memory\n"); 4253c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 4263c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4273c761f0f0344757ac243c65511392fb41d1c841aphilippe 4283c761f0f0344757ac243c65511392fb41d1c841aphilippe if (vgdb_threads[i].status != VgTs_Empty) { 4293c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "found tid %d status %s lwpid %d\n", 4303c761f0f0344757ac243c65511392fb41d1c841aphilippe i, name_of_ThreadStatus(vgdb_threads[i].status), 4313c761f0f0344757ac243c65511392fb41d1c841aphilippe vgdb_threads[i].lwpid); 4323c761f0f0344757ac243c65511392fb41d1c841aphilippe nr_live_threads++; 4333c761f0f0344757ac243c65511392fb41d1c841aphilippe if (vgdb_threads[i].lwpid <= 1) { 4343c761f0f0344757ac243c65511392fb41d1c841aphilippe if (vgdb_threads[i].lwpid == 0 4353c761f0f0344757ac243c65511392fb41d1c841aphilippe && vgdb_threads[i].status == VgTs_Init) { 4363c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "not set lwpid tid %d status %s lwpid %d\n", 4373c761f0f0344757ac243c65511392fb41d1c841aphilippe i, name_of_ThreadStatus(vgdb_threads[i].status), 4383c761f0f0344757ac243c65511392fb41d1c841aphilippe vgdb_threads[i].lwpid); 4393c761f0f0344757ac243c65511392fb41d1c841aphilippe } else { 4403c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(1, "unexpected lwpid tid %d status %s lwpid %d\n", 4413c761f0f0344757ac243c65511392fb41d1c841aphilippe i, name_of_ThreadStatus(vgdb_threads[i].status), 4423c761f0f0344757ac243c65511392fb41d1c841aphilippe vgdb_threads[i].lwpid); 4433c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4443c761f0f0344757ac243c65511392fb41d1c841aphilippe /* in case we have a VtTs_Init thread with lwpid not yet set, 4453c761f0f0344757ac243c65511392fb41d1c841aphilippe we try again later. */ 4463c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 4473c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4483c761f0f0344757ac243c65511392fb41d1c841aphilippe if (vgdb_threads[i].lwpid == pid) { 4493c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (!pid_found); 4503c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (i == 1); 4513c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_found = True; 4523c761f0f0344757ac243c65511392fb41d1c841aphilippe } else { 4533c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!attach(vgdb_threads[i].lwpid, "attach_thread")) { 4543c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(0, "ERROR attach pid %d tid %d\n", 4553c761f0f0344757ac243c65511392fb41d1c841aphilippe vgdb_threads[i].lwpid, i); 4563c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 4573c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4583c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4593c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4603c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4613c761f0f0344757ac243c65511392fb41d1c841aphilippe /* If we found no thread, it means the process is stopping, and 4623c761f0f0344757ac243c65511392fb41d1c841aphilippe we better do not force anything to happen during that. */ 4633c761f0f0344757ac243c65511392fb41d1c841aphilippe if (nr_live_threads > 0) 4643c761f0f0344757ac243c65511392fb41d1c841aphilippe return True; 4653c761f0f0344757ac243c65511392fb41d1c841aphilippe else 4663c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 4673c761f0f0344757ac243c65511392fb41d1c841aphilippe} 4683c761f0f0344757ac243c65511392fb41d1c841aphilippe 4693c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 4703c761f0f0344757ac243c65511392fb41d1c841aphilippevoid detach_from_all_threads (pid_t pid) 4713c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 4723c761f0f0344757ac243c65511392fb41d1c841aphilippe int i; 4733c761f0f0344757ac243c65511392fb41d1c841aphilippe long res; 4743c761f0f0344757ac243c65511392fb41d1c841aphilippe Bool pid_found = False; 4753c761f0f0344757ac243c65511392fb41d1c841aphilippe 4763c761f0f0344757ac243c65511392fb41d1c841aphilippe /* detach from all the threads */ 4773c761f0f0344757ac243c65511392fb41d1c841aphilippe for (i = 1; i < VG_N_THREADS; i++) { 4783c761f0f0344757ac243c65511392fb41d1c841aphilippe if (vgdb_threads[i].status != VgTs_Empty) { 4793c761f0f0344757ac243c65511392fb41d1c841aphilippe if (vgdb_threads[i].status == VgTs_Init 4803c761f0f0344757ac243c65511392fb41d1c841aphilippe && vgdb_threads[i].lwpid == 0) { 4813c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "skipping PTRACE_DETACH pid %d tid %d status %s\n", 4823c761f0f0344757ac243c65511392fb41d1c841aphilippe vgdb_threads[i].lwpid, i, 4833c761f0f0344757ac243c65511392fb41d1c841aphilippe name_of_ThreadStatus (vgdb_threads[i].status)); 4843c761f0f0344757ac243c65511392fb41d1c841aphilippe } else { 4853c761f0f0344757ac243c65511392fb41d1c841aphilippe if (vgdb_threads[i].lwpid == pid) { 4863c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (!pid_found); 4873c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_found = True; 4883c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4893c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "PTRACE_DETACH pid %d tid %d status %s\n", 4903c761f0f0344757ac243c65511392fb41d1c841aphilippe vgdb_threads[i].lwpid, i, 4913c761f0f0344757ac243c65511392fb41d1c841aphilippe name_of_ThreadStatus (vgdb_threads[i].status)); 4923c761f0f0344757ac243c65511392fb41d1c841aphilippe res = ptrace (PTRACE_DETACH, vgdb_threads[i].lwpid, NULL, NULL); 4933c761f0f0344757ac243c65511392fb41d1c841aphilippe if (res != 0) { 4943c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "PTRACE_DETACH pid %d tid %d status %s res %ld\n", 4953c761f0f0344757ac243c65511392fb41d1c841aphilippe vgdb_threads[i].lwpid, i, 4963c761f0f0344757ac243c65511392fb41d1c841aphilippe name_of_ThreadStatus (vgdb_threads[i].status), 4973c761f0f0344757ac243c65511392fb41d1c841aphilippe res); 4983c761f0f0344757ac243c65511392fb41d1c841aphilippe } 4993c761f0f0344757ac243c65511392fb41d1c841aphilippe } 5003c761f0f0344757ac243c65511392fb41d1c841aphilippe } 5013c761f0f0344757ac243c65511392fb41d1c841aphilippe } 5023c761f0f0344757ac243c65511392fb41d1c841aphilippe 5033c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!pid_found && pid) { 5043c761f0f0344757ac243c65511392fb41d1c841aphilippe /* No threads are live. Process is busy stopping. 5053c761f0f0344757ac243c65511392fb41d1c841aphilippe We need to detach from pid explicitely. */ 5063c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "no thread live => PTRACE_DETACH pid %d\n", pid); 5073c761f0f0344757ac243c65511392fb41d1c841aphilippe res = ptrace (PTRACE_DETACH, pid, NULL, NULL); 5083c761f0f0344757ac243c65511392fb41d1c841aphilippe if (res != 0) 5093c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "PTRACE_DETACH pid %d res %ld\n", pid, res); 5103c761f0f0344757ac243c65511392fb41d1c841aphilippe } 5113c761f0f0344757ac243c65511392fb41d1c841aphilippe} 5123c761f0f0344757ac243c65511392fb41d1c841aphilippe 513c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# if defined(VGA_arm64) 5142a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw/* arm64 is extra special, old glibc defined kernel user_pt_regs, but 5152a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw newer glibc instead define user_regs_struct. */ 5162a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw# ifdef HAVE_SYS_USER_REGS 5172a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjwstatic struct user_regs_struct user_save; 5182a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw# else 519c07369bc8be6f6a26adfdbe391be7fe64a211829philippestatic struct user_pt_regs user_save; 5202a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw# endif 521c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# else 5223c761f0f0344757ac243c65511392fb41d1c841aphilippestatic struct user user_save; 523c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# endif 5243c761f0f0344757ac243c65511392fb41d1c841aphilippe// The below indicates if ptrace_getregs (and ptrace_setregs) can be used. 5253c761f0f0344757ac243c65511392fb41d1c841aphilippe// Note that some linux versions are defining PTRACE_GETREGS but using 5263c761f0f0344757ac243c65511392fb41d1c841aphilippe// it gives back EIO. 5273c761f0f0344757ac243c65511392fb41d1c841aphilippe// has_working_ptrace_getregs can take the following values: 5283c761f0f0344757ac243c65511392fb41d1c841aphilippe// -1 : PTRACE_GETREGS is defined 5293c761f0f0344757ac243c65511392fb41d1c841aphilippe// runtime check not yet done. 5303c761f0f0344757ac243c65511392fb41d1c841aphilippe// 0 : PTRACE_GETREGS runtime check has failed. 5313c761f0f0344757ac243c65511392fb41d1c841aphilippe// 1 : PTRACE_GETREGS defined and runtime check ok. 5323c761f0f0344757ac243c65511392fb41d1c841aphilippe#ifdef HAVE_PTRACE_GETREGS 5333c761f0f0344757ac243c65511392fb41d1c841aphilippestatic int has_working_ptrace_getregs = -1; 5343c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif 535c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// Similar but for PTRACE_GETREGSET 536c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#ifdef HAVE_PTRACE_GETREGSET 537c07369bc8be6f6a26adfdbe391be7fe64a211829philippestatic int has_working_ptrace_getregset = -1; 538c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#endif 5393c761f0f0344757ac243c65511392fb41d1c841aphilippe 5403c761f0f0344757ac243c65511392fb41d1c841aphilippe/* Get the registers from pid into regs. 5413c761f0f0344757ac243c65511392fb41d1c841aphilippe regs_bsz value gives the length of *regs. 5423c761f0f0344757ac243c65511392fb41d1c841aphilippe Returns True if all ok, otherwise False. */ 5433c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 5443c761f0f0344757ac243c65511392fb41d1c841aphilippeBool getregs (pid_t pid, void *regs, long regs_bsz) 5453c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 5463c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "getregs regs_bsz %ld\n", regs_bsz); 547c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# ifdef HAVE_PTRACE_GETREGSET 548c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# ifndef USE_PTRACE_GETREGSET 549c07369bc8be6f6a26adfdbe391be7fe64a211829philippe if (has_working_ptrace_getregset) 550c07369bc8be6f6a26adfdbe391be7fe64a211829philippe DEBUG(1, "PTRACE_GETREGSET defined, not used (yet?) by vgdb\n"); 551c07369bc8be6f6a26adfdbe391be7fe64a211829philippe has_working_ptrace_getregset = 0; 552c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# endif 553c07369bc8be6f6a26adfdbe391be7fe64a211829philippe if (has_working_ptrace_getregset) { 554c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // Platforms having GETREGSET 555c07369bc8be6f6a26adfdbe391be7fe64a211829philippe long res; 556c07369bc8be6f6a26adfdbe391be7fe64a211829philippe elf_gregset_t elf_regs; 557c07369bc8be6f6a26adfdbe391be7fe64a211829philippe struct iovec iovec; 558c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 559ee0ee03c426c9712903cfa17cdca12bc6134807eflorian DEBUG(1, "getregs PTRACE_GETREGSET sizeof(elf_regs) %zu\n", 560ee0ee03c426c9712903cfa17cdca12bc6134807eflorian sizeof(elf_regs)); 561c07369bc8be6f6a26adfdbe391be7fe64a211829philippe iovec.iov_base = regs; 562c07369bc8be6f6a26adfdbe391be7fe64a211829philippe iovec.iov_len = sizeof(elf_regs); 563c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 564c07369bc8be6f6a26adfdbe391be7fe64a211829philippe res = ptrace (PTRACE_GETREGSET, pid, NT_PRSTATUS, &iovec); 565c07369bc8be6f6a26adfdbe391be7fe64a211829philippe if (res == 0) { 566c07369bc8be6f6a26adfdbe391be7fe64a211829philippe if (has_working_ptrace_getregset == -1) { 567c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // First call to PTRACE_GETREGSET succesful => 568c07369bc8be6f6a26adfdbe391be7fe64a211829philippe has_working_ptrace_getregset = 1; 569c07369bc8be6f6a26adfdbe391be7fe64a211829philippe DEBUG(1, "detected a working PTRACE_GETREGSET\n"); 570c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } 571c07369bc8be6f6a26adfdbe391be7fe64a211829philippe assert (has_working_ptrace_getregset == 1); 572c07369bc8be6f6a26adfdbe391be7fe64a211829philippe return True; 573c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } 574c07369bc8be6f6a26adfdbe391be7fe64a211829philippe else if (has_working_ptrace_getregset == 1) { 575c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // We had a working call, but now it fails. 576c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // This is unexpected. 577c07369bc8be6f6a26adfdbe391be7fe64a211829philippe ERROR(errno, "PTRACE_GETREGSET %ld\n", res); 578c07369bc8be6f6a26adfdbe391be7fe64a211829philippe return False; 579c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } else { 580c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // Check this is the first call: 581c07369bc8be6f6a26adfdbe391be7fe64a211829philippe assert (has_working_ptrace_getregset == -1); 582c07369bc8be6f6a26adfdbe391be7fe64a211829philippe if (errno == EIO) { 583c07369bc8be6f6a26adfdbe391be7fe64a211829philippe DEBUG(1, "detected a broken PTRACE_GETREGSET with EIO\n"); 584c07369bc8be6f6a26adfdbe391be7fe64a211829philippe has_working_ptrace_getregset = 0; 585c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // Fall over to the PTRACE_GETREGS or PTRACE_PEEKUSER case. 586c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } else { 587c07369bc8be6f6a26adfdbe391be7fe64a211829philippe ERROR(errno, "broken PTRACE_GETREGSET unexpected errno %ld\n", res); 588c07369bc8be6f6a26adfdbe391be7fe64a211829philippe return False; 589c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } 590c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } 591c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } 592c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# endif 593c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 5943c761f0f0344757ac243c65511392fb41d1c841aphilippe# ifdef HAVE_PTRACE_GETREGS 5953c761f0f0344757ac243c65511392fb41d1c841aphilippe if (has_working_ptrace_getregs) { 5963c761f0f0344757ac243c65511392fb41d1c841aphilippe // Platforms having GETREGS 5973c761f0f0344757ac243c65511392fb41d1c841aphilippe long res; 5983c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "getregs PTRACE_GETREGS\n"); 5993c761f0f0344757ac243c65511392fb41d1c841aphilippe res = ptrace (PTRACE_GETREGS, pid, NULL, regs); 6003c761f0f0344757ac243c65511392fb41d1c841aphilippe if (res == 0) { 6013c761f0f0344757ac243c65511392fb41d1c841aphilippe if (has_working_ptrace_getregs == -1) { 6023c761f0f0344757ac243c65511392fb41d1c841aphilippe // First call to PTRACE_GETREGS succesful => 6033c761f0f0344757ac243c65511392fb41d1c841aphilippe has_working_ptrace_getregs = 1; 6043c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "detected a working PTRACE_GETREGS\n"); 6053c761f0f0344757ac243c65511392fb41d1c841aphilippe } 6063c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (has_working_ptrace_getregs == 1); 6073c761f0f0344757ac243c65511392fb41d1c841aphilippe return True; 6083c761f0f0344757ac243c65511392fb41d1c841aphilippe } 6093c761f0f0344757ac243c65511392fb41d1c841aphilippe else if (has_working_ptrace_getregs == 1) { 6103c761f0f0344757ac243c65511392fb41d1c841aphilippe // We had a working call, but now it fails. 6113c761f0f0344757ac243c65511392fb41d1c841aphilippe // This is unexpected. 6123c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "PTRACE_GETREGS %ld\n", res); 6133c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 6143c761f0f0344757ac243c65511392fb41d1c841aphilippe } else { 6153c761f0f0344757ac243c65511392fb41d1c841aphilippe // Check this is the first call: 6163c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (has_working_ptrace_getregs == -1); 6173c761f0f0344757ac243c65511392fb41d1c841aphilippe if (errno == EIO) { 6183c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "detected a broken PTRACE_GETREGS with EIO\n"); 6193c761f0f0344757ac243c65511392fb41d1c841aphilippe has_working_ptrace_getregs = 0; 6203c761f0f0344757ac243c65511392fb41d1c841aphilippe // Fall over to the PTRACE_PEEKUSER case. 6213c761f0f0344757ac243c65511392fb41d1c841aphilippe } else { 6223c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "broken PTRACE_GETREGS unexpected errno %ld\n", res); 6233c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 6243c761f0f0344757ac243c65511392fb41d1c841aphilippe } 6253c761f0f0344757ac243c65511392fb41d1c841aphilippe } 6263c761f0f0344757ac243c65511392fb41d1c841aphilippe } 6273c761f0f0344757ac243c65511392fb41d1c841aphilippe# endif 6283c761f0f0344757ac243c65511392fb41d1c841aphilippe 6293c761f0f0344757ac243c65511392fb41d1c841aphilippe // We assume PTRACE_PEEKUSER is defined everywhere. 6303c761f0f0344757ac243c65511392fb41d1c841aphilippe { 6313c761f0f0344757ac243c65511392fb41d1c841aphilippe# ifdef PT_ENDREGS 6323c761f0f0344757ac243c65511392fb41d1c841aphilippe long peek_bsz = PT_ENDREGS; 6333c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (peek_bsz <= regs_bsz); 6343c761f0f0344757ac243c65511392fb41d1c841aphilippe# else 6353c761f0f0344757ac243c65511392fb41d1c841aphilippe long peek_bsz = regs_bsz-1; 6363c761f0f0344757ac243c65511392fb41d1c841aphilippe# endif 6373c761f0f0344757ac243c65511392fb41d1c841aphilippe char *pregs = (char *) regs; 6383c761f0f0344757ac243c65511392fb41d1c841aphilippe long offset; 6393c761f0f0344757ac243c65511392fb41d1c841aphilippe errno = 0; 6403c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "getregs PTRACE_PEEKUSER(s) peek_bsz %ld\n", peek_bsz); 6413c761f0f0344757ac243c65511392fb41d1c841aphilippe for (offset = 0; offset < peek_bsz; offset = offset + sizeof(long)) { 6423c761f0f0344757ac243c65511392fb41d1c841aphilippe *(long *)(pregs+offset) = ptrace(PTRACE_PEEKUSER, pid, offset, NULL); 6433c761f0f0344757ac243c65511392fb41d1c841aphilippe if (errno != 0) { 6443c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "PTRACE_PEEKUSER offset %ld\n", offset); 6453c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 6463c761f0f0344757ac243c65511392fb41d1c841aphilippe } 6473c761f0f0344757ac243c65511392fb41d1c841aphilippe } 6483c761f0f0344757ac243c65511392fb41d1c841aphilippe return True; 6493c761f0f0344757ac243c65511392fb41d1c841aphilippe } 6503c761f0f0344757ac243c65511392fb41d1c841aphilippe 651c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // If neither of PTRACE_GETREGSET PTRACE_GETREGS PTRACE_PEEKUSER have 652c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // returned, then we are in serious trouble. 6533c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (0); 6543c761f0f0344757ac243c65511392fb41d1c841aphilippe} 6553c761f0f0344757ac243c65511392fb41d1c841aphilippe 6563c761f0f0344757ac243c65511392fb41d1c841aphilippe/* Set the registers of pid to regs. 6573c761f0f0344757ac243c65511392fb41d1c841aphilippe regs_bsz value gives the length of *regs. 6583c761f0f0344757ac243c65511392fb41d1c841aphilippe Returns True if all ok, otherwise False. */ 6593c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 6603c761f0f0344757ac243c65511392fb41d1c841aphilippeBool setregs (pid_t pid, void *regs, long regs_bsz) 6613c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 6623c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "setregs regs_bsz %ld\n", regs_bsz); 663c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 664c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// Note : the below is checking for GETREGSET, not SETREGSET 665c07369bc8be6f6a26adfdbe391be7fe64a211829philippe// as if one is defined and working, the other one should also work. 666c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# ifdef HAVE_PTRACE_GETREGSET 667c07369bc8be6f6a26adfdbe391be7fe64a211829philippe if (has_working_ptrace_getregset) { 668c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // Platforms having SETREGSET 669c07369bc8be6f6a26adfdbe391be7fe64a211829philippe long res; 670c07369bc8be6f6a26adfdbe391be7fe64a211829philippe elf_gregset_t elf_regs; 671c07369bc8be6f6a26adfdbe391be7fe64a211829philippe struct iovec iovec; 672c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 673c07369bc8be6f6a26adfdbe391be7fe64a211829philippe // setregset can never be called before getregset has done a runtime check. 674c07369bc8be6f6a26adfdbe391be7fe64a211829philippe assert (has_working_ptrace_getregset == 1); 675ee0ee03c426c9712903cfa17cdca12bc6134807eflorian DEBUG(1, "setregs PTRACE_SETREGSET sizeof(elf_regs) %zu\n", 676ee0ee03c426c9712903cfa17cdca12bc6134807eflorian sizeof(elf_regs)); 677c07369bc8be6f6a26adfdbe391be7fe64a211829philippe iovec.iov_base = regs; 678c07369bc8be6f6a26adfdbe391be7fe64a211829philippe iovec.iov_len = sizeof(elf_regs); 679c07369bc8be6f6a26adfdbe391be7fe64a211829philippe res = ptrace (PTRACE_SETREGSET, pid, NT_PRSTATUS, &iovec); 680c07369bc8be6f6a26adfdbe391be7fe64a211829philippe if (res != 0) { 681c07369bc8be6f6a26adfdbe391be7fe64a211829philippe ERROR(errno, "PTRACE_SETREGSET %ld\n", res); 682c07369bc8be6f6a26adfdbe391be7fe64a211829philippe return False; 683c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } 684c07369bc8be6f6a26adfdbe391be7fe64a211829philippe return True; 685c07369bc8be6f6a26adfdbe391be7fe64a211829philippe } 686c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# endif 687c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 6883c761f0f0344757ac243c65511392fb41d1c841aphilippe// Note : the below is checking for GETREGS, not SETREGS 6893c761f0f0344757ac243c65511392fb41d1c841aphilippe// as if one is defined and working, the other one should also work. 6903c761f0f0344757ac243c65511392fb41d1c841aphilippe# ifdef HAVE_PTRACE_GETREGS 6913c761f0f0344757ac243c65511392fb41d1c841aphilippe if (has_working_ptrace_getregs) { 6923c761f0f0344757ac243c65511392fb41d1c841aphilippe // Platforms having SETREGS 6933c761f0f0344757ac243c65511392fb41d1c841aphilippe long res; 6943c761f0f0344757ac243c65511392fb41d1c841aphilippe // setregs can never be called before getregs has done a runtime check. 6953c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (has_working_ptrace_getregs == 1); 6963c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "setregs PTRACE_SETREGS\n"); 6973c761f0f0344757ac243c65511392fb41d1c841aphilippe res = ptrace (PTRACE_SETREGS, pid, NULL, regs); 6983c761f0f0344757ac243c65511392fb41d1c841aphilippe if (res != 0) { 6993c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "PTRACE_SETREGS %ld\n", res); 7003c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 7013c761f0f0344757ac243c65511392fb41d1c841aphilippe } 7023c761f0f0344757ac243c65511392fb41d1c841aphilippe return True; 7033c761f0f0344757ac243c65511392fb41d1c841aphilippe } 7043c761f0f0344757ac243c65511392fb41d1c841aphilippe# endif 7053c761f0f0344757ac243c65511392fb41d1c841aphilippe 7063c761f0f0344757ac243c65511392fb41d1c841aphilippe { 7073c761f0f0344757ac243c65511392fb41d1c841aphilippe char *pregs = (char *) regs; 7083c761f0f0344757ac243c65511392fb41d1c841aphilippe long offset; 7093c761f0f0344757ac243c65511392fb41d1c841aphilippe long res; 7103c761f0f0344757ac243c65511392fb41d1c841aphilippe# ifdef PT_ENDREGS 7113c761f0f0344757ac243c65511392fb41d1c841aphilippe long peek_bsz = PT_ENDREGS; 7123c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (peek_bsz <= regs_bsz); 7133c761f0f0344757ac243c65511392fb41d1c841aphilippe# else 7143c761f0f0344757ac243c65511392fb41d1c841aphilippe long peek_bsz = regs_bsz-1; 7153c761f0f0344757ac243c65511392fb41d1c841aphilippe# endif 7163c761f0f0344757ac243c65511392fb41d1c841aphilippe errno = 0; 7173c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "setregs PTRACE_POKEUSER(s) %ld\n", peek_bsz); 7183c761f0f0344757ac243c65511392fb41d1c841aphilippe for (offset = 0; offset < peek_bsz; offset = offset + sizeof(long)) { 7193c761f0f0344757ac243c65511392fb41d1c841aphilippe res = ptrace(PTRACE_POKEUSER, pid, offset, *(long*)(pregs+offset)); 7203c761f0f0344757ac243c65511392fb41d1c841aphilippe if (errno != 0) { 7213c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "PTRACE_POKEUSER offset %ld res %ld\n", offset, res); 7223c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 7233c761f0f0344757ac243c65511392fb41d1c841aphilippe } 7243c761f0f0344757ac243c65511392fb41d1c841aphilippe } 7253c761f0f0344757ac243c65511392fb41d1c841aphilippe return True; 7263c761f0f0344757ac243c65511392fb41d1c841aphilippe } 7273c761f0f0344757ac243c65511392fb41d1c841aphilippe 7283c761f0f0344757ac243c65511392fb41d1c841aphilippe // If neither PTRACE_SETREGS not PTRACE_POKEUSER have returned, 7293c761f0f0344757ac243c65511392fb41d1c841aphilippe // then we are in serious trouble. 7303c761f0f0344757ac243c65511392fb41d1c841aphilippe assert (0); 7313c761f0f0344757ac243c65511392fb41d1c841aphilippe} 7323c761f0f0344757ac243c65511392fb41d1c841aphilippe 7333c761f0f0344757ac243c65511392fb41d1c841aphilippe/* Restore the registers to the saved value, then detaches from all threads */ 7343c761f0f0344757ac243c65511392fb41d1c841aphilippestatic 7353c761f0f0344757ac243c65511392fb41d1c841aphilippevoid restore_and_detach (pid_t pid) 7363c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 7376654de8547d2e420c20e21980669b807aa80710ephilippe int res; 7386654de8547d2e420c20e21980669b807aa80710ephilippe 7396654de8547d2e420c20e21980669b807aa80710ephilippe DEBUG(1, "restore_and_detach pid %d pid_of_save_regs %d\n", 7406654de8547d2e420c20e21980669b807aa80710ephilippe pid, pid_of_save_regs); 7416654de8547d2e420c20e21980669b807aa80710ephilippe 7423c761f0f0344757ac243c65511392fb41d1c841aphilippe if (pid_of_save_regs) { 7433c761f0f0344757ac243c65511392fb41d1c841aphilippe /* In case the 'main pid' has been continued, we need to stop it 7443c761f0f0344757ac243c65511392fb41d1c841aphilippe before resetting the registers. */ 7453c761f0f0344757ac243c65511392fb41d1c841aphilippe if (pid_of_save_regs_continued) { 7463c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs_continued = False; 7473c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!stop(pid_of_save_regs, "sigstop before reset regs")) 7483c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(0, "Could not sigstop before reset"); 7493c761f0f0344757ac243c65511392fb41d1c841aphilippe } 7503c761f0f0344757ac243c65511392fb41d1c841aphilippe 7513c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "setregs restore registers pid %d\n", pid_of_save_regs); 7523c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!setregs(pid_of_save_regs, &user_save.regs, sizeof(user_save.regs))) { 7533c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "setregs restore registers pid %d after cont\n", 7543c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs); 7553c761f0f0344757ac243c65511392fb41d1c841aphilippe } 7566654de8547d2e420c20e21980669b807aa80710ephilippe 7576654de8547d2e420c20e21980669b807aa80710ephilippe /* Now, we transmit all the signals we have queued. */ 7586654de8547d2e420c20e21980669b807aa80710ephilippe if (signal_queue_sz > 0) { 7596654de8547d2e420c20e21980669b807aa80710ephilippe int i; 7606654de8547d2e420c20e21980669b807aa80710ephilippe for (i = 0; i < signal_queue_sz; i++) { 7616654de8547d2e420c20e21980669b807aa80710ephilippe DEBUG(1, "PTRACE_CONT to transmit queued signal %d\n", 7626654de8547d2e420c20e21980669b807aa80710ephilippe signal_queue[i].si_signo); 7636654de8547d2e420c20e21980669b807aa80710ephilippe res = ptrace (PTRACE_CONT, pid_of_save_regs, NULL, 7646654de8547d2e420c20e21980669b807aa80710ephilippe signal_queue[i].si_signo); 7656654de8547d2e420c20e21980669b807aa80710ephilippe if (res != 0) 7666654de8547d2e420c20e21980669b807aa80710ephilippe ERROR(errno, "PTRACE_CONT with signal %d\n", 7676654de8547d2e420c20e21980669b807aa80710ephilippe signal_queue[i].si_signo); 7686654de8547d2e420c20e21980669b807aa80710ephilippe if (!stop(pid_of_save_regs, "sigstop after transmit sig")) 7696654de8547d2e420c20e21980669b807aa80710ephilippe DEBUG(0, "Could not sigstop after transmit sig"); 7706654de8547d2e420c20e21980669b807aa80710ephilippe } 7716654de8547d2e420c20e21980669b807aa80710ephilippe free (signal_queue); 7726654de8547d2e420c20e21980669b807aa80710ephilippe signal_queue = NULL; 7736654de8547d2e420c20e21980669b807aa80710ephilippe signal_queue_sz = 0; 7746654de8547d2e420c20e21980669b807aa80710ephilippe } 7753c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs = 0; 7763c761f0f0344757ac243c65511392fb41d1c841aphilippe } else { 7773c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "PTRACE_SETREGS restore registers: no pid\n"); 7783c761f0f0344757ac243c65511392fb41d1c841aphilippe } 7796654de8547d2e420c20e21980669b807aa80710ephilippe if (signal_queue) 7806654de8547d2e420c20e21980669b807aa80710ephilippe ERROR (0, "One or more signals queued were not delivered. " 7817136e5f14ebcb8117f629becf48bc8a49ab0b5afcarll "First signal: %d\n", signal_queue[0].si_signo); 7823c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 7833c761f0f0344757ac243c65511392fb41d1c841aphilippe} 7843c761f0f0344757ac243c65511392fb41d1c841aphilippe 7853c761f0f0344757ac243c65511392fb41d1c841aphilippeBool invoker_invoke_gdbserver (pid_t pid) 7863c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 7873c761f0f0344757ac243c65511392fb41d1c841aphilippe long res; 7883c761f0f0344757ac243c65511392fb41d1c841aphilippe Bool stopped; 789c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# if defined(VGA_arm64) 7902a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw/* arm64 is extra special, old glibc defined kernel user_pt_regs, but 7912a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw newer glibc instead define user_regs_struct. */ 7922a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw# ifdef HAVE_SYS_USER_REGS 7932a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw struct user_regs_struct user_mod; 7942a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw# else 795c07369bc8be6f6a26adfdbe391be7fe64a211829philippe struct user_pt_regs user_mod; 7962a429f5d70a41ab1673c9f2ec220e8a10d8c90d5mjw# endif 797c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# else 7983c761f0f0344757ac243c65511392fb41d1c841aphilippe struct user user_mod; 799c07369bc8be6f6a26adfdbe391be7fe64a211829philippe# endif 8003c761f0f0344757ac243c65511392fb41d1c841aphilippe Addr sp; 8013c761f0f0344757ac243c65511392fb41d1c841aphilippe /* A specific int value is passed to invoke_gdbserver, to check 8023c761f0f0344757ac243c65511392fb41d1c841aphilippe everything goes according to the plan. */ 8033c761f0f0344757ac243c65511392fb41d1c841aphilippe const int check = 0x8BADF00D; // ate bad food. 8043c761f0f0344757ac243c65511392fb41d1c841aphilippe 8053c761f0f0344757ac243c65511392fb41d1c841aphilippe const Addr bad_return = 0; 8063c761f0f0344757ac243c65511392fb41d1c841aphilippe // A bad return address will be pushed on the stack. 8073c761f0f0344757ac243c65511392fb41d1c841aphilippe // The function invoke_gdbserver cannot return. If ever it returns, a NULL 8083c761f0f0344757ac243c65511392fb41d1c841aphilippe // address pushed on the stack should ensure this is detected. 8093c761f0f0344757ac243c65511392fb41d1c841aphilippe 8103c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Not yet attached. If problem, vgdb can abort, 8113c761f0f0344757ac243c65511392fb41d1c841aphilippe no cleanup needed. */ 8123c761f0f0344757ac243c65511392fb41d1c841aphilippe 8133c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "attach to 'main' pid %d\n", pid); 8143c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!attach(pid, "attach main pid")) { 8153c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(0, "error attach main pid %d\n", pid); 8163c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 8173c761f0f0344757ac243c65511392fb41d1c841aphilippe } 8183c761f0f0344757ac243c65511392fb41d1c841aphilippe 8193c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Now, we are attached. If problem, detach and return. */ 8203c761f0f0344757ac243c65511392fb41d1c841aphilippe 8213c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!acquire_and_suspend_threads(pid)) { 8223c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 8233c761f0f0344757ac243c65511392fb41d1c841aphilippe /* if the pid does not exist anymore, we better stop */ 8243c761f0f0344757ac243c65511392fb41d1c841aphilippe if (kill(pid, 0) != 0) 8253c761f0f0344757ac243c65511392fb41d1c841aphilippe XERROR (errno, "invoke_gdbserver: check for pid %d existence failed\n", 8263c761f0f0344757ac243c65511392fb41d1c841aphilippe pid); 8273c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 8283c761f0f0344757ac243c65511392fb41d1c841aphilippe } 8293c761f0f0344757ac243c65511392fb41d1c841aphilippe 8303c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!getregs(pid, &user_mod.regs, sizeof(user_mod.regs))) { 8313c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 8323c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 8333c761f0f0344757ac243c65511392fb41d1c841aphilippe } 8343c761f0f0344757ac243c65511392fb41d1c841aphilippe user_save = user_mod; 8353c761f0f0344757ac243c65511392fb41d1c841aphilippe 8363c761f0f0344757ac243c65511392fb41d1c841aphilippe#if defined(VGA_x86) 8373c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = user_mod.regs.esp; 8383c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_amd64) 8393c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = user_mod.regs.rsp; 8403c761f0f0344757ac243c65511392fb41d1c841aphilippe if (shared32 != NULL) { 8413c761f0f0344757ac243c65511392fb41d1c841aphilippe /* 64bit vgdb speaking with a 32bit executable. 8423c761f0f0344757ac243c65511392fb41d1c841aphilippe To have system call restart properly, we need to sign extend rax. 8433c761f0f0344757ac243c65511392fb41d1c841aphilippe For more info: 8443c761f0f0344757ac243c65511392fb41d1c841aphilippe web search '[patch] Fix syscall restarts for amd64->i386 biarch' 8453c761f0f0344757ac243c65511392fb41d1c841aphilippe e.g. http://sourceware.org/ml/gdb-patches/2009-11/msg00592.html */ 8463c761f0f0344757ac243c65511392fb41d1c841aphilippe *(long *)&user_save.regs.rax = *(int*)&user_save.regs.rax; 8473c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "Sign extending %8.8lx to %8.8lx\n", 8483c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.rax, user_save.regs.rax); 8493c761f0f0344757ac243c65511392fb41d1c841aphilippe } 8503c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_arm) 8513c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = user_mod.regs.uregs[13]; 852c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#elif defined(VGA_arm64) 853c07369bc8be6f6a26adfdbe391be7fe64a211829philippe sp = user_mod.sp; 8543c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_ppc32) 8553c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = user_mod.regs.gpr[1]; 856cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#elif defined(VGA_ppc64be) || defined(VGA_ppc64le) 8573c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = user_mod.regs.gpr[1]; 8583c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_s390x) 8593c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = user_mod.regs.gprs[15]; 8603c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips32) 8613c761f0f0344757ac243c65511392fb41d1c841aphilippe long long *p = (long long *)user_mod.regs; 8623c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = p[29]; 8633c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips64) 8643c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = user_mod.regs[29]; 8653c761f0f0344757ac243c65511392fb41d1c841aphilippe#else 8664769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe I_die_here : (sp) architecture missing in vgdb-invoker-ptrace.c 8673c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif 8683c761f0f0344757ac243c65511392fb41d1c841aphilippe 8693c761f0f0344757ac243c65511392fb41d1c841aphilippe 8703c761f0f0344757ac243c65511392fb41d1c841aphilippe // the magic below is derived from spying what gdb sends to 8713c761f0f0344757ac243c65511392fb41d1c841aphilippe // the (classical) gdbserver when invoking a C function. 8723c761f0f0344757ac243c65511392fb41d1c841aphilippe if (shared32 != NULL) { 8733c761f0f0344757ac243c65511392fb41d1c841aphilippe // vgdb speaking with a 32bit executable. 8743c761f0f0344757ac243c65511392fb41d1c841aphilippe#if defined(VGA_x86) || defined(VGA_amd64) 8753c761f0f0344757ac243c65511392fb41d1c841aphilippe const int regsize = 4; 8763c761f0f0344757ac243c65511392fb41d1c841aphilippe int rw; 8773c761f0f0344757ac243c65511392fb41d1c841aphilippe /* push check arg on the stack */ 8783c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = sp - regsize; 8793c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "push check arg ptrace_write_memory\n"); 8803c761f0f0344757ac243c65511392fb41d1c841aphilippe assert(regsize == sizeof(check)); 8813c761f0f0344757ac243c65511392fb41d1c841aphilippe rw = ptrace_write_memory(pid, sp, 8823c761f0f0344757ac243c65511392fb41d1c841aphilippe &check, 8833c761f0f0344757ac243c65511392fb41d1c841aphilippe regsize); 8843c761f0f0344757ac243c65511392fb41d1c841aphilippe if (rw != 0) { 8853c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(rw, "push check arg ptrace_write_memory"); 8863c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 8873c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 8883c761f0f0344757ac243c65511392fb41d1c841aphilippe } 8893c761f0f0344757ac243c65511392fb41d1c841aphilippe 8903c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = sp - regsize; 8913c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "push bad_return return address ptrace_write_memory\n"); 8923c761f0f0344757ac243c65511392fb41d1c841aphilippe // Note that for a 64 bits vgdb, only 4 bytes of NULL bad_return 8933c761f0f0344757ac243c65511392fb41d1c841aphilippe // are written. 8943c761f0f0344757ac243c65511392fb41d1c841aphilippe rw = ptrace_write_memory(pid, sp, 8953c761f0f0344757ac243c65511392fb41d1c841aphilippe &bad_return, 8963c761f0f0344757ac243c65511392fb41d1c841aphilippe regsize); 8973c761f0f0344757ac243c65511392fb41d1c841aphilippe if (rw != 0) { 8983c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(rw, "push bad_return return address ptrace_write_memory"); 8993c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 9003c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 9013c761f0f0344757ac243c65511392fb41d1c841aphilippe } 9023c761f0f0344757ac243c65511392fb41d1c841aphilippe#if defined(VGA_x86) 9033c761f0f0344757ac243c65511392fb41d1c841aphilippe /* set ebp, esp, eip and orig_eax to invoke gdbserver */ 9043c761f0f0344757ac243c65511392fb41d1c841aphilippe // compiled in 32bits, speaking with a 32bits exe 9053c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.ebp = sp; // bp set to sp 9063c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.esp = sp; 9073c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.eip = shared32->invoke_gdbserver; 9083c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.orig_eax = -1L; 9093c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_amd64) 9103c761f0f0344757ac243c65511392fb41d1c841aphilippe /* set ebp, esp, eip and orig_eax to invoke gdbserver */ 9113c761f0f0344757ac243c65511392fb41d1c841aphilippe // compiled in 64bits, speaking with a 32bits exe 9123c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.rbp = sp; // bp set to sp 9133c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.rsp = sp; 9143c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.rip = shared32->invoke_gdbserver; 9153c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.orig_rax = -1L; 9163c761f0f0344757ac243c65511392fb41d1c841aphilippe#else 9173c761f0f0344757ac243c65511392fb41d1c841aphilippe I_die_here : not x86 or amd64 in x86/amd64 section/ 9183c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif 9193c761f0f0344757ac243c65511392fb41d1c841aphilippe 920cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) 9213c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.nip = shared32->invoke_gdbserver; 9223c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.trap = -1L; 9233c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put check arg in register 3 */ 9243c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.gpr[3] = check; 9253c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put NULL return address in Link Register */ 9263c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.link = bad_return; 9273c761f0f0344757ac243c65511392fb41d1c841aphilippe 9283c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_arm) 9293c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put check arg in register 0 */ 9303c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.uregs[0] = check; 9313c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put NULL return address in Link Register */ 9323c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.uregs[14] = bad_return; 9333c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.uregs[15] = shared32->invoke_gdbserver; 9343c761f0f0344757ac243c65511392fb41d1c841aphilippe 935c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#elif defined(VGA_arm64) 936c07369bc8be6f6a26adfdbe391be7fe64a211829philippe XERROR(0, "TBD arm64: vgdb a 32 bits executable with a 64 bits exe"); 937c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 9383c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_s390x) 9393c761f0f0344757ac243c65511392fb41d1c841aphilippe XERROR(0, "(fn32) s390x has no 32bits implementation"); 9403c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips32) 9413c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put check arg in register 4 */ 9423c761f0f0344757ac243c65511392fb41d1c841aphilippe p[4] = check; 9433c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put NULL return address in ra */ 9443c761f0f0344757ac243c65511392fb41d1c841aphilippe p[31] = bad_return; 9453c761f0f0344757ac243c65511392fb41d1c841aphilippe p[34] = shared32->invoke_gdbserver; 9463c761f0f0344757ac243c65511392fb41d1c841aphilippe p[25] = shared32->invoke_gdbserver; 9473c761f0f0344757ac243c65511392fb41d1c841aphilippe /* make stack space for args */ 9483c761f0f0344757ac243c65511392fb41d1c841aphilippe p[29] = sp - 32; 9493c761f0f0344757ac243c65511392fb41d1c841aphilippe 9503c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips64) 9513c761f0f0344757ac243c65511392fb41d1c841aphilippe assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe 9523c761f0f0344757ac243c65511392fb41d1c841aphilippe#else 9534769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe I_die_here : architecture missing in vgdb-invoker-ptrace.c 9543c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif 9553c761f0f0344757ac243c65511392fb41d1c841aphilippe } 9563c761f0f0344757ac243c65511392fb41d1c841aphilippe 9573c761f0f0344757ac243c65511392fb41d1c841aphilippe else if (shared64 != NULL) { 9583c761f0f0344757ac243c65511392fb41d1c841aphilippe#if defined(VGA_x86) 9593c761f0f0344757ac243c65511392fb41d1c841aphilippe assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe 9603c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_amd64) 9613c761f0f0344757ac243c65511392fb41d1c841aphilippe // vgdb speaking with a 64 bit executable. 9623c761f0f0344757ac243c65511392fb41d1c841aphilippe const int regsize = 8; 9633c761f0f0344757ac243c65511392fb41d1c841aphilippe int rw; 9643c761f0f0344757ac243c65511392fb41d1c841aphilippe 9653c761f0f0344757ac243c65511392fb41d1c841aphilippe /* give check arg in rdi */ 9663c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.rdi = check; 9673c761f0f0344757ac243c65511392fb41d1c841aphilippe 9683c761f0f0344757ac243c65511392fb41d1c841aphilippe /* push return address on stack : return to breakaddr */ 9693c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = sp - regsize; 9703c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "push bad_return return address ptrace_write_memory\n"); 9713c761f0f0344757ac243c65511392fb41d1c841aphilippe rw = ptrace_write_memory(pid, sp, 9723c761f0f0344757ac243c65511392fb41d1c841aphilippe &bad_return, 9733c761f0f0344757ac243c65511392fb41d1c841aphilippe sizeof(bad_return)); 9743c761f0f0344757ac243c65511392fb41d1c841aphilippe if (rw != 0) { 9753c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(rw, "push bad_return return address ptrace_write_memory"); 9763c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 9773c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 9783c761f0f0344757ac243c65511392fb41d1c841aphilippe } 9793c761f0f0344757ac243c65511392fb41d1c841aphilippe 9803c761f0f0344757ac243c65511392fb41d1c841aphilippe /* set rbp, rsp, rip and orig_rax to invoke gdbserver */ 9813c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.rbp = sp; // bp set to sp 9823c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.rsp = sp; 9833c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.rip = shared64->invoke_gdbserver; 9843c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.orig_rax = -1L; 9853c761f0f0344757ac243c65511392fb41d1c841aphilippe 9863c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_arm) 9873c761f0f0344757ac243c65511392fb41d1c841aphilippe assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe 988c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#elif defined(VGA_arm64) 989c07369bc8be6f6a26adfdbe391be7fe64a211829philippe user_mod.regs[0] = check; 990c07369bc8be6f6a26adfdbe391be7fe64a211829philippe user_mod.sp = sp; 991c07369bc8be6f6a26adfdbe391be7fe64a211829philippe user_mod.pc = shared64->invoke_gdbserver; 992c07369bc8be6f6a26adfdbe391be7fe64a211829philippe /* put NULL return address in Link Register */ 993c07369bc8be6f6a26adfdbe391be7fe64a211829philippe user_mod.regs[30] = bad_return; 994c07369bc8be6f6a26adfdbe391be7fe64a211829philippe 9953c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_ppc32) 9963c761f0f0344757ac243c65511392fb41d1c841aphilippe assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe 997cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#elif defined(VGA_ppc64be) 9984769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe Addr func_addr; 9994769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe Addr toc_addr; 10003c761f0f0344757ac243c65511392fb41d1c841aphilippe int rw; 10013c761f0f0344757ac243c65511392fb41d1c841aphilippe rw = ptrace_read_memory(pid, shared64->invoke_gdbserver, 10023c761f0f0344757ac243c65511392fb41d1c841aphilippe &func_addr, 10034769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe sizeof(Addr)); 10043c761f0f0344757ac243c65511392fb41d1c841aphilippe if (rw != 0) { 10053c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(rw, "ppc64 read func_addr\n"); 10063c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 10073c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 10083c761f0f0344757ac243c65511392fb41d1c841aphilippe } 10093c761f0f0344757ac243c65511392fb41d1c841aphilippe rw = ptrace_read_memory(pid, shared64->invoke_gdbserver+8, 10103c761f0f0344757ac243c65511392fb41d1c841aphilippe &toc_addr, 10114769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe sizeof(Addr)); 10123c761f0f0344757ac243c65511392fb41d1c841aphilippe if (rw != 0) { 10133c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(rw, "ppc64 read toc_addr\n"); 10143c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 10153c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 10163c761f0f0344757ac243c65511392fb41d1c841aphilippe } 10173c761f0f0344757ac243c65511392fb41d1c841aphilippe // We are not pushing anything on the stack, so it is not 10183c761f0f0344757ac243c65511392fb41d1c841aphilippe // very clear why the sp has to be decreased, but it seems 10193c761f0f0344757ac243c65511392fb41d1c841aphilippe // needed. The ppc64 ABI might give some lights on this ? 10203c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.gpr[1] = sp - 220; 10213c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.gpr[2] = toc_addr; 10223c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.nip = func_addr; 10233c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.trap = -1L; 10243c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put check arg in register 3 */ 10253c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.gpr[3] = check; 10263c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put bad_return return address in Link Register */ 10273c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.link = bad_return; 1028582d58245637ab05272d89fb94b12fd0f18fa0f8carll#elif defined(VGA_ppc64le) 1029582d58245637ab05272d89fb94b12fd0f18fa0f8carll /* LE does not use the function pointer structure used in BE */ 1030582d58245637ab05272d89fb94b12fd0f18fa0f8carll user_mod.regs.nip = shared64->invoke_gdbserver; 1031582d58245637ab05272d89fb94b12fd0f18fa0f8carll user_mod.regs.gpr[1] = sp - 512; 1032582d58245637ab05272d89fb94b12fd0f18fa0f8carll user_mod.regs.gpr[12] = user_mod.regs.nip; 1033582d58245637ab05272d89fb94b12fd0f18fa0f8carll user_mod.regs.trap = -1L; 1034582d58245637ab05272d89fb94b12fd0f18fa0f8carll /* put check arg in register 3 */ 1035582d58245637ab05272d89fb94b12fd0f18fa0f8carll user_mod.regs.gpr[3] = check; 1036582d58245637ab05272d89fb94b12fd0f18fa0f8carll /* put bad_return return address in Link Register */ 1037582d58245637ab05272d89fb94b12fd0f18fa0f8carll user_mod.regs.link = bad_return; 10383c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_s390x) 10393c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put check arg in register r2 */ 10403c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.gprs[2] = check; 10413c761f0f0344757ac243c65511392fb41d1c841aphilippe /* bad_return Return address is in r14 */ 10423c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.gprs[14] = bad_return; 10433c761f0f0344757ac243c65511392fb41d1c841aphilippe /* minimum stack frame */ 10443c761f0f0344757ac243c65511392fb41d1c841aphilippe sp = sp - 160; 10453c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.gprs[15] = sp; 10463c761f0f0344757ac243c65511392fb41d1c841aphilippe /* set program counter */ 10473c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs.psw.addr = shared64->invoke_gdbserver; 10483c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips32) 10493c761f0f0344757ac243c65511392fb41d1c841aphilippe assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe 10503c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips64) 10513c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put check arg in register 4 */ 10523c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs[4] = check; 10533c761f0f0344757ac243c65511392fb41d1c841aphilippe /* put NULL return address in ra */ 10543c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs[31] = bad_return; 10553c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs[34] = shared64->invoke_gdbserver; 10563c761f0f0344757ac243c65511392fb41d1c841aphilippe user_mod.regs[25] = shared64->invoke_gdbserver; 10573c761f0f0344757ac243c65511392fb41d1c841aphilippe#else 10584769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe I_die_here: architecture missing in vgdb-invoker-ptrace.c 10593c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif 10603c761f0f0344757ac243c65511392fb41d1c841aphilippe } 10613c761f0f0344757ac243c65511392fb41d1c841aphilippe else { 10623c761f0f0344757ac243c65511392fb41d1c841aphilippe assert(0); 10633c761f0f0344757ac243c65511392fb41d1c841aphilippe } 10643c761f0f0344757ac243c65511392fb41d1c841aphilippe 10653c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!setregs(pid, &user_mod.regs, sizeof(user_mod.regs))) { 10663c761f0f0344757ac243c65511392fb41d1c841aphilippe detach_from_all_threads(pid); 10673c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 10683c761f0f0344757ac243c65511392fb41d1c841aphilippe } 10693c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Now that we have modified the registers, we set 10703c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs to indicate that restore_and_detach 10713c761f0f0344757ac243c65511392fb41d1c841aphilippe must restore the registers in case of cleanup. */ 10723c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs = pid; 10733c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs_continued = False; 10743c761f0f0344757ac243c65511392fb41d1c841aphilippe 10753c761f0f0344757ac243c65511392fb41d1c841aphilippe 10763c761f0f0344757ac243c65511392fb41d1c841aphilippe /* We PTRACE_CONT-inue pid. 10773c761f0f0344757ac243c65511392fb41d1c841aphilippe Either gdbserver will be invoked directly (if all 10783c761f0f0344757ac243c65511392fb41d1c841aphilippe threads are interruptible) or gdbserver will be 10793c761f0f0344757ac243c65511392fb41d1c841aphilippe called soon by the scheduler. In the first case, 10803c761f0f0344757ac243c65511392fb41d1c841aphilippe pid will stop on the break inserted above when 10813c761f0f0344757ac243c65511392fb41d1c841aphilippe gdbserver returns. In the 2nd case, the break will 10823c761f0f0344757ac243c65511392fb41d1c841aphilippe be encountered directly. */ 10833c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "PTRACE_CONT to invoke\n"); 10843c761f0f0344757ac243c65511392fb41d1c841aphilippe res = ptrace (PTRACE_CONT, pid, NULL, NULL); 10853c761f0f0344757ac243c65511392fb41d1c841aphilippe if (res != 0) { 10863c761f0f0344757ac243c65511392fb41d1c841aphilippe ERROR(errno, "PTRACE_CONT\n"); 10873c761f0f0344757ac243c65511392fb41d1c841aphilippe restore_and_detach(pid); 10883c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 10893c761f0f0344757ac243c65511392fb41d1c841aphilippe } 10903c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs_continued = True; 10913c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Wait for SIGSTOP generated by m_gdbserver.c give_control_back_to_vgdb */ 10923c761f0f0344757ac243c65511392fb41d1c841aphilippe stopped = waitstopped (pid, SIGSTOP, 10933c761f0f0344757ac243c65511392fb41d1c841aphilippe "waitpid status after PTRACE_CONT to invoke"); 10943c761f0f0344757ac243c65511392fb41d1c841aphilippe if (stopped) { 10953c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Here pid has properly stopped on the break. */ 10963c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs_continued = False; 10973c761f0f0344757ac243c65511392fb41d1c841aphilippe restore_and_detach(pid); 10983c761f0f0344757ac243c65511392fb41d1c841aphilippe return True; 10993c761f0f0344757ac243c65511392fb41d1c841aphilippe } else { 11003c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Whatever kind of problem happened. We shutdown. */ 11013c761f0f0344757ac243c65511392fb41d1c841aphilippe shutting_down = True; 11023c761f0f0344757ac243c65511392fb41d1c841aphilippe return False; 11033c761f0f0344757ac243c65511392fb41d1c841aphilippe } 11043c761f0f0344757ac243c65511392fb41d1c841aphilippe} 11053c761f0f0344757ac243c65511392fb41d1c841aphilippe 11063c761f0f0344757ac243c65511392fb41d1c841aphilippevoid invoker_cleanup_restore_and_detach(void *v_pid) 11073c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 11083c761f0f0344757ac243c65511392fb41d1c841aphilippe DEBUG(1, "invoker_cleanup_restore_and_detach dying: %d\n", dying); 11093c761f0f0344757ac243c65511392fb41d1c841aphilippe if (!dying) 11103c761f0f0344757ac243c65511392fb41d1c841aphilippe restore_and_detach(*(int*)v_pid); 11113c761f0f0344757ac243c65511392fb41d1c841aphilippe} 11123c761f0f0344757ac243c65511392fb41d1c841aphilippe 11133c761f0f0344757ac243c65511392fb41d1c841aphilippevoid invoker_restrictions_msg(void) 11143c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 11153c761f0f0344757ac243c65511392fb41d1c841aphilippe} 11163c761f0f0344757ac243c65511392fb41d1c841aphilippe 11173c761f0f0344757ac243c65511392fb41d1c841aphilippevoid invoker_valgrind_dying(void) 11183c761f0f0344757ac243c65511392fb41d1c841aphilippe{ 11193c761f0f0344757ac243c65511392fb41d1c841aphilippe /* Avoid messing up with registers of valgrind when it is dying. */ 11203c761f0f0344757ac243c65511392fb41d1c841aphilippe pid_of_save_regs_continued = False; 11213c761f0f0344757ac243c65511392fb41d1c841aphilippe dying = True; 11223c761f0f0344757ac243c65511392fb41d1c841aphilippe} 1123