vgdb-invoker-ptrace.c revision 5f9116d2675ee30ebb894ce13bd4e7597567b363
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
8005f9116d2675ee30ebb894ce13bd4e7597567b363philippe   Addr sp __attribute__((unused)); // Not used on all platforms.
8015f9116d2675ee30ebb894ce13bd4e7597567b363philippe
8023c761f0f0344757ac243c65511392fb41d1c841aphilippe   /* A specific int value is passed to invoke_gdbserver, to check
8033c761f0f0344757ac243c65511392fb41d1c841aphilippe      everything goes according to the plan. */
8043c761f0f0344757ac243c65511392fb41d1c841aphilippe   const int check = 0x8BADF00D; // ate bad food.
8053c761f0f0344757ac243c65511392fb41d1c841aphilippe
8063c761f0f0344757ac243c65511392fb41d1c841aphilippe   const Addr bad_return = 0;
8073c761f0f0344757ac243c65511392fb41d1c841aphilippe   // A bad return address will be pushed on the stack.
8083c761f0f0344757ac243c65511392fb41d1c841aphilippe   // The function invoke_gdbserver cannot return. If ever it returns, a NULL
8093c761f0f0344757ac243c65511392fb41d1c841aphilippe   // address pushed on the stack should ensure this is detected.
8103c761f0f0344757ac243c65511392fb41d1c841aphilippe
8113c761f0f0344757ac243c65511392fb41d1c841aphilippe   /* Not yet attached. If problem, vgdb can abort,
8123c761f0f0344757ac243c65511392fb41d1c841aphilippe      no cleanup needed. */
8133c761f0f0344757ac243c65511392fb41d1c841aphilippe
8143c761f0f0344757ac243c65511392fb41d1c841aphilippe   DEBUG(1, "attach to 'main' pid %d\n", pid);
8153c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (!attach(pid, "attach main pid")) {
8163c761f0f0344757ac243c65511392fb41d1c841aphilippe      ERROR(0, "error attach main pid %d\n", pid);
8173c761f0f0344757ac243c65511392fb41d1c841aphilippe      return False;
8183c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
8193c761f0f0344757ac243c65511392fb41d1c841aphilippe
8203c761f0f0344757ac243c65511392fb41d1c841aphilippe   /* Now, we are attached. If problem, detach and return. */
8213c761f0f0344757ac243c65511392fb41d1c841aphilippe
8223c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (!acquire_and_suspend_threads(pid)) {
8233c761f0f0344757ac243c65511392fb41d1c841aphilippe      detach_from_all_threads(pid);
8243c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* if the pid does not exist anymore, we better stop */
8253c761f0f0344757ac243c65511392fb41d1c841aphilippe      if (kill(pid, 0) != 0)
8263c761f0f0344757ac243c65511392fb41d1c841aphilippe        XERROR (errno, "invoke_gdbserver: check for pid %d existence failed\n",
8273c761f0f0344757ac243c65511392fb41d1c841aphilippe                pid);
8283c761f0f0344757ac243c65511392fb41d1c841aphilippe      return False;
8293c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
8303c761f0f0344757ac243c65511392fb41d1c841aphilippe
8313c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (!getregs(pid, &user_mod.regs, sizeof(user_mod.regs))) {
8323c761f0f0344757ac243c65511392fb41d1c841aphilippe      detach_from_all_threads(pid);
8333c761f0f0344757ac243c65511392fb41d1c841aphilippe      return False;
8343c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
8353c761f0f0344757ac243c65511392fb41d1c841aphilippe   user_save = user_mod;
8363c761f0f0344757ac243c65511392fb41d1c841aphilippe
8373c761f0f0344757ac243c65511392fb41d1c841aphilippe#if defined(VGA_x86)
8383c761f0f0344757ac243c65511392fb41d1c841aphilippe   sp = user_mod.regs.esp;
8393c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_amd64)
8403c761f0f0344757ac243c65511392fb41d1c841aphilippe   sp = user_mod.regs.rsp;
8413c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (shared32 != NULL) {
8423c761f0f0344757ac243c65511392fb41d1c841aphilippe     /* 64bit vgdb speaking with a 32bit executable.
8433c761f0f0344757ac243c65511392fb41d1c841aphilippe        To have system call restart properly, we need to sign extend rax.
8443c761f0f0344757ac243c65511392fb41d1c841aphilippe        For more info:
8453c761f0f0344757ac243c65511392fb41d1c841aphilippe        web search '[patch] Fix syscall restarts for amd64->i386 biarch'
8463c761f0f0344757ac243c65511392fb41d1c841aphilippe        e.g. http://sourceware.org/ml/gdb-patches/2009-11/msg00592.html */
8473c761f0f0344757ac243c65511392fb41d1c841aphilippe     *(long *)&user_save.regs.rax = *(int*)&user_save.regs.rax;
8483c761f0f0344757ac243c65511392fb41d1c841aphilippe     DEBUG(1, "Sign extending %8.8lx to %8.8lx\n",
8493c761f0f0344757ac243c65511392fb41d1c841aphilippe           user_mod.regs.rax, user_save.regs.rax);
8503c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
8513c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_arm)
8523c761f0f0344757ac243c65511392fb41d1c841aphilippe   sp = user_mod.regs.uregs[13];
853c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#elif defined(VGA_arm64)
854c07369bc8be6f6a26adfdbe391be7fe64a211829philippe   sp = user_mod.sp;
8553c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_ppc32)
8563c761f0f0344757ac243c65511392fb41d1c841aphilippe   sp = user_mod.regs.gpr[1];
857cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#elif defined(VGA_ppc64be) || defined(VGA_ppc64le)
8583c761f0f0344757ac243c65511392fb41d1c841aphilippe   sp = user_mod.regs.gpr[1];
8593c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_s390x)
8603c761f0f0344757ac243c65511392fb41d1c841aphilippe   sp = user_mod.regs.gprs[15];
8613c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips32)
8623c761f0f0344757ac243c65511392fb41d1c841aphilippe   long long *p = (long long *)user_mod.regs;
8633c761f0f0344757ac243c65511392fb41d1c841aphilippe   sp = p[29];
8643c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips64)
8653c761f0f0344757ac243c65511392fb41d1c841aphilippe   sp = user_mod.regs[29];
8663c761f0f0344757ac243c65511392fb41d1c841aphilippe#else
8674769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe   I_die_here : (sp) architecture missing in vgdb-invoker-ptrace.c
8683c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif
8693c761f0f0344757ac243c65511392fb41d1c841aphilippe
8703c761f0f0344757ac243c65511392fb41d1c841aphilippe
8713c761f0f0344757ac243c65511392fb41d1c841aphilippe   // the magic below is derived from spying what gdb sends to
8723c761f0f0344757ac243c65511392fb41d1c841aphilippe   // the (classical) gdbserver when invoking a C function.
8733c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (shared32 != NULL) {
8743c761f0f0344757ac243c65511392fb41d1c841aphilippe      // vgdb speaking with a 32bit executable.
8753c761f0f0344757ac243c65511392fb41d1c841aphilippe#if   defined(VGA_x86) || defined(VGA_amd64)
8763c761f0f0344757ac243c65511392fb41d1c841aphilippe      const int regsize = 4;
8773c761f0f0344757ac243c65511392fb41d1c841aphilippe      int rw;
8783c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* push check arg on the stack */
8793c761f0f0344757ac243c65511392fb41d1c841aphilippe      sp = sp - regsize;
8803c761f0f0344757ac243c65511392fb41d1c841aphilippe      DEBUG(1, "push check arg ptrace_write_memory\n");
8813c761f0f0344757ac243c65511392fb41d1c841aphilippe      assert(regsize == sizeof(check));
8823c761f0f0344757ac243c65511392fb41d1c841aphilippe      rw = ptrace_write_memory(pid, sp,
8833c761f0f0344757ac243c65511392fb41d1c841aphilippe                               &check,
8843c761f0f0344757ac243c65511392fb41d1c841aphilippe                               regsize);
8853c761f0f0344757ac243c65511392fb41d1c841aphilippe      if (rw != 0) {
8863c761f0f0344757ac243c65511392fb41d1c841aphilippe         ERROR(rw, "push check arg ptrace_write_memory");
8873c761f0f0344757ac243c65511392fb41d1c841aphilippe         detach_from_all_threads(pid);
8883c761f0f0344757ac243c65511392fb41d1c841aphilippe         return False;
8893c761f0f0344757ac243c65511392fb41d1c841aphilippe      }
8903c761f0f0344757ac243c65511392fb41d1c841aphilippe
8913c761f0f0344757ac243c65511392fb41d1c841aphilippe      sp = sp - regsize;
8923c761f0f0344757ac243c65511392fb41d1c841aphilippe      DEBUG(1, "push bad_return return address ptrace_write_memory\n");
8933c761f0f0344757ac243c65511392fb41d1c841aphilippe      // Note that for a 64 bits vgdb, only 4 bytes of NULL bad_return
8943c761f0f0344757ac243c65511392fb41d1c841aphilippe      // are written.
8953c761f0f0344757ac243c65511392fb41d1c841aphilippe      rw = ptrace_write_memory(pid, sp,
8963c761f0f0344757ac243c65511392fb41d1c841aphilippe                               &bad_return,
8973c761f0f0344757ac243c65511392fb41d1c841aphilippe                               regsize);
8983c761f0f0344757ac243c65511392fb41d1c841aphilippe      if (rw != 0) {
8993c761f0f0344757ac243c65511392fb41d1c841aphilippe         ERROR(rw, "push bad_return return address ptrace_write_memory");
9003c761f0f0344757ac243c65511392fb41d1c841aphilippe         detach_from_all_threads(pid);
9013c761f0f0344757ac243c65511392fb41d1c841aphilippe         return False;
9023c761f0f0344757ac243c65511392fb41d1c841aphilippe      }
9033c761f0f0344757ac243c65511392fb41d1c841aphilippe#if   defined(VGA_x86)
9043c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* set ebp, esp, eip and orig_eax to invoke gdbserver */
9053c761f0f0344757ac243c65511392fb41d1c841aphilippe      // compiled in 32bits, speaking with a 32bits exe
9063c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.ebp = sp; // bp set to sp
9073c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.esp = sp;
9083c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.eip = shared32->invoke_gdbserver;
9093c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.orig_eax = -1L;
9103c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_amd64)
9113c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* set ebp, esp, eip and orig_eax to invoke gdbserver */
9123c761f0f0344757ac243c65511392fb41d1c841aphilippe      // compiled in 64bits, speaking with a 32bits exe
9133c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.rbp = sp; // bp set to sp
9143c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.rsp = sp;
9153c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.rip = shared32->invoke_gdbserver;
9163c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.orig_rax = -1L;
9173c761f0f0344757ac243c65511392fb41d1c841aphilippe#else
9183c761f0f0344757ac243c65511392fb41d1c841aphilippe      I_die_here : not x86 or amd64 in x86/amd64 section/
9193c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif
9203c761f0f0344757ac243c65511392fb41d1c841aphilippe
921cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
9223c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.nip = shared32->invoke_gdbserver;
9233c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.trap = -1L;
9243c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put check arg in register 3 */
9253c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.gpr[3] = check;
9263c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put NULL return address in Link Register */
9273c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.link = bad_return;
9283c761f0f0344757ac243c65511392fb41d1c841aphilippe
9293c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_arm)
9303c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put check arg in register 0 */
9313c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.uregs[0] = check;
9323c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put NULL return address in Link Register */
9333c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.uregs[14] = bad_return;
9343c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.uregs[15] = shared32->invoke_gdbserver;
9353c761f0f0344757ac243c65511392fb41d1c841aphilippe
936c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#elif defined(VGA_arm64)
937c07369bc8be6f6a26adfdbe391be7fe64a211829philippe      XERROR(0, "TBD arm64: vgdb a 32 bits executable with a 64 bits exe");
938c07369bc8be6f6a26adfdbe391be7fe64a211829philippe
9393c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_s390x)
9403c761f0f0344757ac243c65511392fb41d1c841aphilippe      XERROR(0, "(fn32) s390x has no 32bits implementation");
9413c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips32)
9423c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put check arg in register 4 */
9433c761f0f0344757ac243c65511392fb41d1c841aphilippe      p[4] = check;
9443c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put NULL return address in ra */
9453c761f0f0344757ac243c65511392fb41d1c841aphilippe      p[31] = bad_return;
9463c761f0f0344757ac243c65511392fb41d1c841aphilippe      p[34] = shared32->invoke_gdbserver;
9473c761f0f0344757ac243c65511392fb41d1c841aphilippe      p[25] = shared32->invoke_gdbserver;
9483c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* make stack space for args */
9493c761f0f0344757ac243c65511392fb41d1c841aphilippe      p[29] = sp - 32;
9503c761f0f0344757ac243c65511392fb41d1c841aphilippe
9513c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips64)
9523c761f0f0344757ac243c65511392fb41d1c841aphilippe      assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe
9533c761f0f0344757ac243c65511392fb41d1c841aphilippe#else
9544769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe      I_die_here : architecture missing in vgdb-invoker-ptrace.c
9553c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif
9563c761f0f0344757ac243c65511392fb41d1c841aphilippe      }
9573c761f0f0344757ac243c65511392fb41d1c841aphilippe
9583c761f0f0344757ac243c65511392fb41d1c841aphilippe   else if (shared64 != NULL) {
9593c761f0f0344757ac243c65511392fb41d1c841aphilippe#if defined(VGA_x86)
9603c761f0f0344757ac243c65511392fb41d1c841aphilippe      assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
9613c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_amd64)
9623c761f0f0344757ac243c65511392fb41d1c841aphilippe      // vgdb speaking with a 64 bit executable.
9633c761f0f0344757ac243c65511392fb41d1c841aphilippe      const int regsize = 8;
9643c761f0f0344757ac243c65511392fb41d1c841aphilippe      int rw;
9653c761f0f0344757ac243c65511392fb41d1c841aphilippe
9663c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* give check arg in rdi */
9673c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.rdi = check;
9683c761f0f0344757ac243c65511392fb41d1c841aphilippe
9693c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* push return address on stack : return to breakaddr */
9703c761f0f0344757ac243c65511392fb41d1c841aphilippe      sp = sp - regsize;
9713c761f0f0344757ac243c65511392fb41d1c841aphilippe      DEBUG(1, "push bad_return return address ptrace_write_memory\n");
9723c761f0f0344757ac243c65511392fb41d1c841aphilippe      rw = ptrace_write_memory(pid, sp,
9733c761f0f0344757ac243c65511392fb41d1c841aphilippe                               &bad_return,
9743c761f0f0344757ac243c65511392fb41d1c841aphilippe                               sizeof(bad_return));
9753c761f0f0344757ac243c65511392fb41d1c841aphilippe      if (rw != 0) {
9763c761f0f0344757ac243c65511392fb41d1c841aphilippe         ERROR(rw, "push bad_return return address ptrace_write_memory");
9773c761f0f0344757ac243c65511392fb41d1c841aphilippe         detach_from_all_threads(pid);
9783c761f0f0344757ac243c65511392fb41d1c841aphilippe         return False;
9793c761f0f0344757ac243c65511392fb41d1c841aphilippe      }
9803c761f0f0344757ac243c65511392fb41d1c841aphilippe
9813c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* set rbp, rsp, rip and orig_rax to invoke gdbserver */
9823c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.rbp = sp; // bp set to sp
9833c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.rsp = sp;
9843c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.rip = shared64->invoke_gdbserver;
9853c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.orig_rax = -1L;
9863c761f0f0344757ac243c65511392fb41d1c841aphilippe
9873c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_arm)
9883c761f0f0344757ac243c65511392fb41d1c841aphilippe      assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
989c07369bc8be6f6a26adfdbe391be7fe64a211829philippe#elif defined(VGA_arm64)
990c07369bc8be6f6a26adfdbe391be7fe64a211829philippe      user_mod.regs[0] = check;
991c07369bc8be6f6a26adfdbe391be7fe64a211829philippe      user_mod.sp = sp;
992c07369bc8be6f6a26adfdbe391be7fe64a211829philippe      user_mod.pc = shared64->invoke_gdbserver;
993c07369bc8be6f6a26adfdbe391be7fe64a211829philippe      /* put NULL return address in Link Register */
994c07369bc8be6f6a26adfdbe391be7fe64a211829philippe      user_mod.regs[30] = bad_return;
995c07369bc8be6f6a26adfdbe391be7fe64a211829philippe
9963c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_ppc32)
9973c761f0f0344757ac243c65511392fb41d1c841aphilippe      assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
998cae0cc22b83ffb260ee8379e92099c5a701944cbcarll#elif defined(VGA_ppc64be)
9994769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe      Addr func_addr;
10004769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe      Addr toc_addr;
10013c761f0f0344757ac243c65511392fb41d1c841aphilippe      int rw;
10023c761f0f0344757ac243c65511392fb41d1c841aphilippe      rw = ptrace_read_memory(pid, shared64->invoke_gdbserver,
10033c761f0f0344757ac243c65511392fb41d1c841aphilippe                              &func_addr,
10044769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe                              sizeof(Addr));
10053c761f0f0344757ac243c65511392fb41d1c841aphilippe      if (rw != 0) {
10063c761f0f0344757ac243c65511392fb41d1c841aphilippe         ERROR(rw, "ppc64 read func_addr\n");
10073c761f0f0344757ac243c65511392fb41d1c841aphilippe         detach_from_all_threads(pid);
10083c761f0f0344757ac243c65511392fb41d1c841aphilippe         return False;
10093c761f0f0344757ac243c65511392fb41d1c841aphilippe      }
10103c761f0f0344757ac243c65511392fb41d1c841aphilippe      rw = ptrace_read_memory(pid, shared64->invoke_gdbserver+8,
10113c761f0f0344757ac243c65511392fb41d1c841aphilippe                              &toc_addr,
10124769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe                              sizeof(Addr));
10133c761f0f0344757ac243c65511392fb41d1c841aphilippe      if (rw != 0) {
10143c761f0f0344757ac243c65511392fb41d1c841aphilippe         ERROR(rw, "ppc64 read toc_addr\n");
10153c761f0f0344757ac243c65511392fb41d1c841aphilippe         detach_from_all_threads(pid);
10163c761f0f0344757ac243c65511392fb41d1c841aphilippe         return False;
10173c761f0f0344757ac243c65511392fb41d1c841aphilippe      }
10183c761f0f0344757ac243c65511392fb41d1c841aphilippe      // We are not pushing anything on the stack, so it is not
10193c761f0f0344757ac243c65511392fb41d1c841aphilippe      // very clear why the sp has to be decreased, but it seems
10203c761f0f0344757ac243c65511392fb41d1c841aphilippe      // needed. The ppc64 ABI might give some lights on this ?
10213c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.gpr[1] = sp - 220;
10223c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.gpr[2] = toc_addr;
10233c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.nip = func_addr;
10243c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.trap = -1L;
10253c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put check arg in register 3 */
10263c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.gpr[3] = check;
10273c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put bad_return return address in Link Register */
10283c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.link = bad_return;
1029582d58245637ab05272d89fb94b12fd0f18fa0f8carll#elif defined(VGA_ppc64le)
1030582d58245637ab05272d89fb94b12fd0f18fa0f8carll      /* LE does not use the function pointer structure used in BE */
1031582d58245637ab05272d89fb94b12fd0f18fa0f8carll      user_mod.regs.nip = shared64->invoke_gdbserver;
1032582d58245637ab05272d89fb94b12fd0f18fa0f8carll      user_mod.regs.gpr[1] = sp - 512;
1033582d58245637ab05272d89fb94b12fd0f18fa0f8carll      user_mod.regs.gpr[12] = user_mod.regs.nip;
1034582d58245637ab05272d89fb94b12fd0f18fa0f8carll      user_mod.regs.trap = -1L;
1035582d58245637ab05272d89fb94b12fd0f18fa0f8carll      /* put check arg in register 3 */
1036582d58245637ab05272d89fb94b12fd0f18fa0f8carll      user_mod.regs.gpr[3] = check;
1037582d58245637ab05272d89fb94b12fd0f18fa0f8carll      /* put bad_return return address in Link Register */
1038582d58245637ab05272d89fb94b12fd0f18fa0f8carll      user_mod.regs.link = bad_return;
10393c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_s390x)
10403c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put check arg in register r2 */
10413c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.gprs[2] = check;
10423c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* bad_return Return address is in r14 */
10433c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.gprs[14] = bad_return;
10443c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* minimum stack frame */
10453c761f0f0344757ac243c65511392fb41d1c841aphilippe      sp = sp - 160;
10463c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.gprs[15] = sp;
10473c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* set program counter */
10483c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs.psw.addr = shared64->invoke_gdbserver;
10493c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips32)
10503c761f0f0344757ac243c65511392fb41d1c841aphilippe      assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
10513c761f0f0344757ac243c65511392fb41d1c841aphilippe#elif defined(VGA_mips64)
10523c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put check arg in register 4 */
10533c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs[4] = check;
10543c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* put NULL return address in ra */
10553c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs[31] = bad_return;
10563c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs[34] = shared64->invoke_gdbserver;
10573c761f0f0344757ac243c65511392fb41d1c841aphilippe      user_mod.regs[25] = shared64->invoke_gdbserver;
10583c761f0f0344757ac243c65511392fb41d1c841aphilippe#else
10594769c3c0594bb0cbfd31a953ed39dafbe108605cphilippe      I_die_here: architecture missing in vgdb-invoker-ptrace.c
10603c761f0f0344757ac243c65511392fb41d1c841aphilippe#endif
10613c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
10623c761f0f0344757ac243c65511392fb41d1c841aphilippe   else {
10633c761f0f0344757ac243c65511392fb41d1c841aphilippe      assert(0);
10643c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
10653c761f0f0344757ac243c65511392fb41d1c841aphilippe
10663c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (!setregs(pid, &user_mod.regs, sizeof(user_mod.regs))) {
10673c761f0f0344757ac243c65511392fb41d1c841aphilippe      detach_from_all_threads(pid);
10683c761f0f0344757ac243c65511392fb41d1c841aphilippe      return False;
10693c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
10703c761f0f0344757ac243c65511392fb41d1c841aphilippe   /* Now that we have modified the registers, we set
10713c761f0f0344757ac243c65511392fb41d1c841aphilippe      pid_of_save_regs to indicate that restore_and_detach
10723c761f0f0344757ac243c65511392fb41d1c841aphilippe      must restore the registers in case of cleanup. */
10733c761f0f0344757ac243c65511392fb41d1c841aphilippe   pid_of_save_regs = pid;
10743c761f0f0344757ac243c65511392fb41d1c841aphilippe   pid_of_save_regs_continued = False;
10753c761f0f0344757ac243c65511392fb41d1c841aphilippe
10763c761f0f0344757ac243c65511392fb41d1c841aphilippe
10773c761f0f0344757ac243c65511392fb41d1c841aphilippe   /* We PTRACE_CONT-inue pid.
10783c761f0f0344757ac243c65511392fb41d1c841aphilippe      Either gdbserver will be invoked directly (if all
10793c761f0f0344757ac243c65511392fb41d1c841aphilippe      threads are interruptible) or gdbserver will be
10803c761f0f0344757ac243c65511392fb41d1c841aphilippe      called soon by the scheduler. In the first case,
10813c761f0f0344757ac243c65511392fb41d1c841aphilippe      pid will stop on the break inserted above when
10823c761f0f0344757ac243c65511392fb41d1c841aphilippe      gdbserver returns. In the 2nd case, the break will
10833c761f0f0344757ac243c65511392fb41d1c841aphilippe      be encountered directly. */
10843c761f0f0344757ac243c65511392fb41d1c841aphilippe   DEBUG(1, "PTRACE_CONT to invoke\n");
10853c761f0f0344757ac243c65511392fb41d1c841aphilippe   res = ptrace (PTRACE_CONT, pid, NULL, NULL);
10863c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (res != 0) {
10873c761f0f0344757ac243c65511392fb41d1c841aphilippe      ERROR(errno, "PTRACE_CONT\n");
10883c761f0f0344757ac243c65511392fb41d1c841aphilippe      restore_and_detach(pid);
10893c761f0f0344757ac243c65511392fb41d1c841aphilippe      return False;
10903c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
10913c761f0f0344757ac243c65511392fb41d1c841aphilippe   pid_of_save_regs_continued = True;
10923c761f0f0344757ac243c65511392fb41d1c841aphilippe   /* Wait for SIGSTOP generated by m_gdbserver.c give_control_back_to_vgdb */
10933c761f0f0344757ac243c65511392fb41d1c841aphilippe   stopped = waitstopped (pid, SIGSTOP,
10943c761f0f0344757ac243c65511392fb41d1c841aphilippe                          "waitpid status after PTRACE_CONT to invoke");
10953c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (stopped) {
10963c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* Here pid has properly stopped on the break. */
10973c761f0f0344757ac243c65511392fb41d1c841aphilippe      pid_of_save_regs_continued = False;
10983c761f0f0344757ac243c65511392fb41d1c841aphilippe      restore_and_detach(pid);
10993c761f0f0344757ac243c65511392fb41d1c841aphilippe      return True;
11003c761f0f0344757ac243c65511392fb41d1c841aphilippe   } else {
11013c761f0f0344757ac243c65511392fb41d1c841aphilippe      /* Whatever kind of problem happened. We shutdown. */
11023c761f0f0344757ac243c65511392fb41d1c841aphilippe      shutting_down = True;
11033c761f0f0344757ac243c65511392fb41d1c841aphilippe      return False;
11043c761f0f0344757ac243c65511392fb41d1c841aphilippe   }
11053c761f0f0344757ac243c65511392fb41d1c841aphilippe}
11063c761f0f0344757ac243c65511392fb41d1c841aphilippe
11073c761f0f0344757ac243c65511392fb41d1c841aphilippevoid invoker_cleanup_restore_and_detach(void *v_pid)
11083c761f0f0344757ac243c65511392fb41d1c841aphilippe{
11093c761f0f0344757ac243c65511392fb41d1c841aphilippe   DEBUG(1, "invoker_cleanup_restore_and_detach dying: %d\n", dying);
11103c761f0f0344757ac243c65511392fb41d1c841aphilippe   if (!dying)
11113c761f0f0344757ac243c65511392fb41d1c841aphilippe      restore_and_detach(*(int*)v_pid);
11123c761f0f0344757ac243c65511392fb41d1c841aphilippe}
11133c761f0f0344757ac243c65511392fb41d1c841aphilippe
11143c761f0f0344757ac243c65511392fb41d1c841aphilippevoid invoker_restrictions_msg(void)
11153c761f0f0344757ac243c65511392fb41d1c841aphilippe{
11163c761f0f0344757ac243c65511392fb41d1c841aphilippe}
11173c761f0f0344757ac243c65511392fb41d1c841aphilippe
11183c761f0f0344757ac243c65511392fb41d1c841aphilippevoid invoker_valgrind_dying(void)
11193c761f0f0344757ac243c65511392fb41d1c841aphilippe{
11203c761f0f0344757ac243c65511392fb41d1c841aphilippe   /* Avoid messing up with registers of valgrind when it is dying. */
11213c761f0f0344757ac243c65511392fb41d1c841aphilippe   pid_of_save_regs_continued = False;
11223c761f0f0344757ac243c65511392fb41d1c841aphilippe   dying = True;
11233c761f0f0344757ac243c65511392fb41d1c841aphilippe}
1124