ia64/xen-unstable

changeset 4719:70c0c5349780

bitkeeper revision 1.1389.1.16 (4273458eyxEjHSppjkQyDsXHHxOY9Q)

coredump.patch
Extend libxc and gdb server to coredump a domain.
Signed-off-by: Kip Macy <kmacy@fsmware.com>
author kaf24@firebug.cl.cam.ac.uk[kaf24]
date Sat Apr 30 08:45:02 2005 +0000 (2005-04-30)
parents c36d6a98229a
children 43be76d016ea
files .rootkeys tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/Makefile.in tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c tools/libxc/Makefile tools/libxc/xc.h tools/libxc/xc_core.c tools/libxc/xc_ptrace.c tools/libxc/xc_ptrace_core.c tools/python/xen/lowlevel/xc/xc.c
line diff
     1.1 --- a/.rootkeys	Sat Apr 30 08:35:58 2005 +0000
     1.2 +++ b/.rootkeys	Sat Apr 30 08:45:02 2005 +0000
     1.3 @@ -550,6 +550,7 @@ 423d3a7b_HtKYGocoTS1adeOpqDFnw tools/gdb
     1.4  423d3a7b2vJq86I8FbYm6up5BsCwfA tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/configure.in
     1.5  423d3a7bQPownmVb63qOoyq89ebBVA tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/configure.srv
     1.6  423d3a7bHtqhyOgiRWhjWt-S-6wbYg tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
     1.7 +4273458dYPghQKVnj_xu5-fC38CcOg tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c
     1.8  423d3a7b2ENk2IskDZYZ98pe5NsvIA tools/gdb/gdb-6.2.1-xen-sparse/mkbuildtree
     1.9  423d3a7buANO_q-kgxIRffUu7lMnUw tools/gdb/gdbbuild
    1.10  41e2ff6dNPgvIrdIF6dC1azdex1U3A tools/ioemu/Makefile
    1.11 @@ -720,6 +721,7 @@ 41cc934abX-QLXJXW_clV_wRjM0zYg tools/lib
    1.12  3fbba6dc1uU7U3IFeF6A-XEOYF2MkQ tools/libxc/rpm.spec
    1.13  3fbba6dcrNxtygEcgJYAJJ1gCQqfsA tools/libxc/xc.h
    1.14  3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/libxc/xc_bvtsched.c
    1.15 +4273458dyF2_sKA6CFkNJQYb8eY2dA tools/libxc/xc_core.c
    1.16  3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/libxc/xc_domain.c
    1.17  40278d99BLsfUv3qxv0I8C1sClZ0ow tools/libxc/xc_elf.h
    1.18  403e0977Bjsm_e82pwvl9VvaJxh8Gg tools/libxc/xc_evtchn.c
    1.19 @@ -735,6 +737,7 @@ 41cc934aO1m6NxEh_8eDr9bJIMoLFA tools/lib
    1.20  3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/libxc/xc_private.c
    1.21  3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/libxc/xc_private.h
    1.22  42337174PxyzzPk62raDiYCIsfStDg tools/libxc/xc_ptrace.c
    1.23 +4273458duzL--nsTfT6e_q6Kfij48g tools/libxc/xc_ptrace_core.c
    1.24  41dde8b0pLfAKMs_L9Uri2hnzHiCRQ tools/libxc/xc_vmx_build.c
    1.25  40e1b09dMYB4ItGCqcMIzirdMd9I-w tools/libxutil/Makefile
    1.26  40e033325Sjqs-_4TuzeUEprP_gYFg tools/libxutil/allocate.c
     2.1 --- a/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/Makefile.in	Sat Apr 30 08:35:58 2005 +0000
     2.2 +++ b/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/Makefile.in	Sat Apr 30 08:45:02 2005 +0000
     2.3 @@ -83,7 +83,7 @@ READLINE_DEP = $$(READLINE_DIR)
     2.4  # -I. for config files.
     2.5  # -I${srcdir} for our headers.
     2.6  # -I$(srcdir)/../regformats for regdef.h.
     2.7 -INCLUDE_CFLAGS = -I. -I${srcdir} -I$(srcdir)/../regformats -I$(INCLUDE_DIR)
     2.8 +INCLUDE_CFLAGS = -I. -I${srcdir} -I$(srcdir)/../regformats -I$(INCLUDE_DIR)  -I../../../../libxc/ -I../../../../libxutil/
     2.9  
    2.10  # M{H,T}_CFLAGS, if defined, has host- and target-dependent CFLAGS
    2.11  # from the config/ directory.
     3.1 --- a/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Sat Apr 30 08:35:58 2005 +0000
     3.2 +++ b/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c	Sat Apr 30 08:45:02 2005 +0000
     3.3 @@ -35,12 +35,11 @@
     3.4  #include <stdlib.h>
     3.5  #include <unistd.h>
     3.6  #include <errno.h>
     3.7 -
     3.8 +#include <xc.h>
     3.9  #define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */
    3.10 -#define ptrace xc_ptrace
    3.11 -long xc_ptrace(enum __ptrace_request request, ...);
    3.12 +long (*myptrace)(enum __ptrace_request, pid_t, long, long);
    3.13 +int (*myxcwait)(int domain, int *status, int options) ;
    3.14  
    3.15 -int waitdomain(int domain, int *status, int options);
    3.16  
    3.17  #define DOMFLAGS_DYING     (1<<0) /* Domain is scheduled to die.             */
    3.18  #define DOMFLAGS_CRASHED   (1<<1) /* Crashed domain; frozen for postmortem.  */
    3.19 @@ -61,6 +60,8 @@ static void linux_resume (struct thread_
    3.20  
    3.21  int debug_threads;
    3.22  int using_threads;
    3.23 +extern int isfile;
    3.24 +
    3.25  struct pending_signals
    3.26  {
    3.27    int signal;
    3.28 @@ -150,7 +151,7 @@ linux_attach (int domain)
    3.29  {
    3.30      struct process_info *new_process;
    3.31      current_domain = domain;
    3.32 -    if (ptrace (PTRACE_ATTACH, domain, 0, 0) != 0) {
    3.33 +    if (myptrace (PTRACE_ATTACH, domain, 0, 0) != 0) {
    3.34  	fprintf (stderr, "Cannot attach to domain %d: %s (%d)\n", domain,
    3.35  		 strerror (errno), errno);
    3.36  	fflush (stderr);
    3.37 @@ -173,7 +174,7 @@ linux_kill_one_process (struct inferior_
    3.38  {
    3.39    struct thread_info *thread = (struct thread_info *) entry;
    3.40    struct process_info *process = get_thread_process (thread);
    3.41 -  ptrace (PTRACE_KILL, pid_of (process), 0, 0);
    3.42 +  myptrace (PTRACE_KILL, pid_of (process), 0, 0);
    3.43  
    3.44  }
    3.45  
    3.46 @@ -190,7 +191,7 @@ linux_detach_one_process (struct inferio
    3.47    struct thread_info *thread = (struct thread_info *) entry;
    3.48    struct process_info *process = get_thread_process (thread);
    3.49  
    3.50 -  ptrace (PTRACE_DETACH, pid_of (process), 0, 0);
    3.51 +  myptrace (PTRACE_DETACH, pid_of (process), 0, 0);
    3.52  }
    3.53  
    3.54  
    3.55 @@ -216,8 +217,7 @@ static unsigned char
    3.56  linux_wait (char *status)
    3.57  {
    3.58    int w;
    3.59 -  TRACE_ENTER;
    3.60 -  if (waitdomain(current_domain, &w, 0))
    3.61 +  if (myxcwait(current_domain, &w, 0))
    3.62        return -1;
    3.63    
    3.64    if (w & (DOMFLAGS_CRASHED|DOMFLAGS_DYING)) {
    3.65 @@ -242,7 +242,7 @@ linux_resume (struct thread_resume *resu
    3.66    expect_signal = resume_info->sig;
    3.67    for_each_inferior(&all_threads, regcache_invalidate_one);
    3.68  
    3.69 -  ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, current_domain, 0, 0);
    3.70 +  myptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, current_domain, 0, 0);
    3.71  
    3.72  }
    3.73  
    3.74 @@ -266,7 +266,7 @@ regsets_fetch_inferior_registers ()
    3.75  	}
    3.76  
    3.77        buf = malloc (regset->size);
    3.78 -      res = ptrace (regset->get_request, inferior_pid, 0, buf);
    3.79 +      res = myptrace (regset->get_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf);
    3.80        if (res < 0)
    3.81  	{
    3.82  	  if (errno == EIO)
    3.83 @@ -318,7 +318,7 @@ regsets_store_inferior_registers ()
    3.84  
    3.85        buf = malloc (regset->size);
    3.86        regset->fill_function (buf);
    3.87 -      res = ptrace (regset->set_request, inferior_pid, 0, buf);
    3.88 +      res = myptrace (regset->set_request, inferior_pid, 0, (PTRACE_XFER_TYPE)buf);
    3.89        if (res < 0)
    3.90  	{
    3.91  	  if (errno == EIO)
    3.92 @@ -395,7 +395,7 @@ linux_read_memory (CORE_ADDR memaddr, ch
    3.93    for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
    3.94      {
    3.95        errno = 0;
    3.96 -      buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
    3.97 +      buffer[i] = myptrace (PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
    3.98        if (errno)
    3.99  	return errno;
   3.100      }
   3.101 @@ -428,13 +428,13 @@ linux_write_memory (CORE_ADDR memaddr, c
   3.102  
   3.103    /* Fill start and end extra bytes of buffer with existing memory data.  */
   3.104  
   3.105 -  buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
   3.106 +  buffer[0] = myptrace (PTRACE_PEEKTEXT, inferior_pid,
   3.107  		      (PTRACE_ARG3_TYPE) addr, 0);
   3.108  
   3.109    if (count > 1)
   3.110      {
   3.111        buffer[count - 1]
   3.112 -	= ptrace (PTRACE_PEEKTEXT, inferior_pid,
   3.113 +	= myptrace (PTRACE_PEEKTEXT, inferior_pid,
   3.114  		  (PTRACE_ARG3_TYPE) (addr + (count - 1)
   3.115  				      * sizeof (PTRACE_XFER_TYPE)),
   3.116  		  0);
   3.117 @@ -448,7 +448,7 @@ linux_write_memory (CORE_ADDR memaddr, c
   3.118    for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
   3.119      {
   3.120        errno = 0;
   3.121 -      ptrace (PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
   3.122 +      myptrace (PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
   3.123        if (errno)
   3.124  	return errno;
   3.125      }
   3.126 @@ -545,4 +545,12 @@ initialize_low (void)
   3.127  		       the_low_target.breakpoint_len);
   3.128    init_registers ();
   3.129    linux_init_signals ();
   3.130 +  if (isfile) {
   3.131 +      myptrace = xc_ptrace_core;
   3.132 +      myxcwait = xc_waitdomain_core;
   3.133 +  } else {
   3.134 +      myptrace = xc_ptrace;
   3.135 +      myxcwait = xc_waitdomain;
   3.136 +  }
   3.137 +
   3.138  }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c	Sat Apr 30 08:45:02 2005 +0000
     4.3 @@ -0,0 +1,639 @@
     4.4 +/* Main code for remote server for GDB.
     4.5 +   Copyright 1989, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2002, 2003, 2004
     4.6 +   Free Software Foundation, Inc.
     4.7 +
     4.8 +   This file is part of GDB.
     4.9 +
    4.10 +   This program is free software; you can redistribute it and/or modify
    4.11 +   it under the terms of the GNU General Public License as published by
    4.12 +   the Free Software Foundation; either version 2 of the License, or
    4.13 +   (at your option) any later version.
    4.14 +
    4.15 +   This program is distributed in the hope that it will be useful,
    4.16 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.17 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.18 +   GNU General Public License for more details.
    4.19 +
    4.20 +   You should have received a copy of the GNU General Public License
    4.21 +   along with this program; if not, write to the Free Software
    4.22 +   Foundation, Inc., 59 Temple Place - Suite 330,
    4.23 +   Boston, MA 02111-1307, USA.  */
    4.24 +
    4.25 +#include "server.h"
    4.26 +
    4.27 +#include <unistd.h>
    4.28 +#include <signal.h>
    4.29 +#include <sys/wait.h>
    4.30 +#include <sys/types.h>
    4.31 +#include <sys/stat.h>
    4.32 +#include <fcntl.h>
    4.33 +
    4.34 +int cont_thread;
    4.35 +int general_thread;
    4.36 +int step_thread;
    4.37 +int thread_from_wait;
    4.38 +int old_thread_from_wait;
    4.39 +int extended_protocol;
    4.40 +int server_waiting;
    4.41 +int isfile = 0;
    4.42 +
    4.43 +jmp_buf toplevel;
    4.44 +
    4.45 +/* The PID of the originally created or attached inferior.  Used to
    4.46 +   send signals to the process when GDB sends us an asynchronous interrupt
    4.47 +   (user hitting Control-C in the client), and to wait for the child to exit
    4.48 +   when no longer debugging it.  */
    4.49 +
    4.50 +int signal_pid;
    4.51 +
    4.52 +static unsigned char
    4.53 +start_inferior (char *argv[], char *statusptr)
    4.54 +{
    4.55 +  signal (SIGTTOU, SIG_DFL);
    4.56 +  signal (SIGTTIN, SIG_DFL);
    4.57 +
    4.58 +  signal_pid = create_inferior (argv[0], argv);
    4.59 +
    4.60 +  fprintf (stderr, "Process %s created; pid = %d\n", argv[0],
    4.61 +	   signal_pid);
    4.62 +
    4.63 +  signal (SIGTTOU, SIG_IGN);
    4.64 +  signal (SIGTTIN, SIG_IGN);
    4.65 +  tcsetpgrp (fileno (stderr), signal_pid);
    4.66 +
    4.67 +  /* Wait till we are at 1st instruction in program, return signal number.  */
    4.68 +  return mywait (statusptr, 0);
    4.69 +}
    4.70 +
    4.71 +static int
    4.72 +attach_inferior (int pid, char *statusptr, unsigned char *sigptr)
    4.73 +{
    4.74 +  /* myattach should return -1 if attaching is unsupported,
    4.75 +     0 if it succeeded, and call error() otherwise.  */
    4.76 +
    4.77 +  if (myattach (pid) != 0)
    4.78 +    return -1;
    4.79 +
    4.80 +  fprintf (stderr, "Attached; pid = %d\n", pid);
    4.81 +
    4.82 +  /* FIXME - It may be that we should get the SIGNAL_PID from the
    4.83 +     attach function, so that it can be the main thread instead of
    4.84 +     whichever we were told to attach to.  */
    4.85 +  signal_pid = pid;
    4.86 +
    4.87 +  *sigptr = mywait (statusptr, 0);
    4.88 +
    4.89 +  return 0;
    4.90 +}
    4.91 +
    4.92 +extern int remote_debug;
    4.93 +
    4.94 +/* Handle all of the extended 'q' packets.  */
    4.95 +void
    4.96 +handle_query (char *own_buf)
    4.97 +{
    4.98 +  static struct inferior_list_entry *thread_ptr;
    4.99 +
   4.100 +  if (strcmp ("qSymbol::", own_buf) == 0)
   4.101 +    {
   4.102 +      if (the_target->look_up_symbols != NULL)
   4.103 +	(*the_target->look_up_symbols) ();
   4.104 +
   4.105 +      strcpy (own_buf, "OK");
   4.106 +      return;
   4.107 +    }
   4.108 +
   4.109 +  if (strcmp ("qfThreadInfo", own_buf) == 0)
   4.110 +    {
   4.111 +      thread_ptr = all_threads.head;
   4.112 +      sprintf (own_buf, "m%x", thread_ptr->id);
   4.113 +      thread_ptr = thread_ptr->next;
   4.114 +      return;
   4.115 +    }
   4.116 +
   4.117 +  if (strcmp ("qsThreadInfo", own_buf) == 0)
   4.118 +    {
   4.119 +      if (thread_ptr != NULL)
   4.120 +	{
   4.121 +	  sprintf (own_buf, "m%x", thread_ptr->id);
   4.122 +	  thread_ptr = thread_ptr->next;
   4.123 +	  return;
   4.124 +	}
   4.125 +      else
   4.126 +	{
   4.127 +	  sprintf (own_buf, "l");
   4.128 +	  return;
   4.129 +	}
   4.130 +    }
   4.131 +
   4.132 +  if (the_target->read_auxv != NULL
   4.133 +      && strncmp ("qPart:auxv:read::", own_buf, 17) == 0)
   4.134 +    {
   4.135 +      char data[(PBUFSIZ - 1) / 2];
   4.136 +      CORE_ADDR ofs;
   4.137 +      unsigned int len;
   4.138 +      int n;
   4.139 +      decode_m_packet (&own_buf[17], &ofs, &len); /* "OFS,LEN" */
   4.140 +      if (len > sizeof data)
   4.141 +	len = sizeof data;
   4.142 +      n = (*the_target->read_auxv) (ofs, data, len);
   4.143 +      if (n == 0)
   4.144 +	write_ok (own_buf);
   4.145 +      else if (n < 0)
   4.146 +	write_enn (own_buf);
   4.147 +      else
   4.148 +	convert_int_to_ascii (data, own_buf, n);
   4.149 +      return;
   4.150 +    }
   4.151 +
   4.152 +  /* Otherwise we didn't know what packet it was.  Say we didn't
   4.153 +     understand it.  */
   4.154 +  own_buf[0] = 0;
   4.155 +}
   4.156 +
   4.157 +/* Parse vCont packets.  */
   4.158 +void
   4.159 +handle_v_cont (char *own_buf, char *status, unsigned char *signal)
   4.160 +{
   4.161 +  char *p, *q;
   4.162 +  int n = 0, i = 0;
   4.163 +  struct thread_resume *resume_info, default_action;
   4.164 +
   4.165 +  /* Count the number of semicolons in the packet.  There should be one
   4.166 +     for every action.  */
   4.167 +  p = &own_buf[5];
   4.168 +  while (p)
   4.169 +    {
   4.170 +      n++;
   4.171 +      p++;
   4.172 +      p = strchr (p, ';');
   4.173 +    }
   4.174 +  /* Allocate room for one extra action, for the default remain-stopped
   4.175 +     behavior; if no default action is in the list, we'll need the extra
   4.176 +     slot.  */
   4.177 +  resume_info = malloc ((n + 1) * sizeof (resume_info[0]));
   4.178 +
   4.179 +  default_action.thread = -1;
   4.180 +  default_action.leave_stopped = 1;
   4.181 +  default_action.step = 0;
   4.182 +  default_action.sig = 0;
   4.183 +
   4.184 +  p = &own_buf[5];
   4.185 +  i = 0;
   4.186 +  while (*p)
   4.187 +    {
   4.188 +      p++;
   4.189 +
   4.190 +      resume_info[i].leave_stopped = 0;
   4.191 +
   4.192 +      if (p[0] == 's' || p[0] == 'S')
   4.193 +	resume_info[i].step = 1;
   4.194 +      else if (p[0] == 'c' || p[0] == 'C')
   4.195 +	resume_info[i].step = 0;
   4.196 +      else
   4.197 +	goto err;
   4.198 +
   4.199 +      if (p[0] == 'S' || p[0] == 'C')
   4.200 +	{
   4.201 +	  int sig;
   4.202 +	  sig = strtol (p + 1, &q, 16);
   4.203 +	  if (p == q)
   4.204 +	    goto err;
   4.205 +	  p = q;
   4.206 +
   4.207 +	  if (!target_signal_to_host_p (sig))
   4.208 +	    goto err;
   4.209 +	  resume_info[i].sig = target_signal_to_host (sig);
   4.210 +	}
   4.211 +      else
   4.212 +	{
   4.213 +	  resume_info[i].sig = 0;
   4.214 +	  p = p + 1;
   4.215 +	}
   4.216 +
   4.217 +      if (p[0] == 0)
   4.218 +	{
   4.219 +	  resume_info[i].thread = -1;
   4.220 +	  default_action = resume_info[i];
   4.221 +
   4.222 +	  /* Note: we don't increment i here, we'll overwrite this entry
   4.223 +	     the next time through.  */
   4.224 +	}
   4.225 +      else if (p[0] == ':')
   4.226 +	{
   4.227 +	  resume_info[i].thread = strtol (p + 1, &q, 16);
   4.228 +	  if (p == q)
   4.229 +	    goto err;
   4.230 +	  p = q;
   4.231 +	  if (p[0] != ';' && p[0] != 0)
   4.232 +	    goto err;
   4.233 +
   4.234 +	  i++;
   4.235 +	}
   4.236 +    }
   4.237 +
   4.238 +  resume_info[i] = default_action;
   4.239 +
   4.240 +  /* Still used in occasional places in the backend.  */
   4.241 +  if (n == 1 && resume_info[0].thread != -1)
   4.242 +    cont_thread = resume_info[0].thread;
   4.243 +  else
   4.244 +    cont_thread = -1;
   4.245 +  set_desired_inferior (0);
   4.246 +
   4.247 +  (*the_target->resume) (resume_info);
   4.248 +
   4.249 +  free (resume_info);
   4.250 +
   4.251 +  *signal = mywait (status, 1);
   4.252 +  prepare_resume_reply (own_buf, *status, *signal);
   4.253 +  return;
   4.254 +
   4.255 +err:
   4.256 +  /* No other way to report an error... */
   4.257 +  strcpy (own_buf, "");
   4.258 +  free (resume_info);
   4.259 +  return;
   4.260 +}
   4.261 +
   4.262 +/* Handle all of the extended 'v' packets.  */
   4.263 +void
   4.264 +handle_v_requests (char *own_buf, char *status, unsigned char *signal)
   4.265 +{
   4.266 +  if (strncmp (own_buf, "vCont;", 6) == 0)
   4.267 +    {
   4.268 +      handle_v_cont (own_buf, status, signal);
   4.269 +      return;
   4.270 +    }
   4.271 +
   4.272 +  if (strncmp (own_buf, "vCont?", 6) == 0)
   4.273 +    {
   4.274 +      strcpy (own_buf, "vCont;c;C;s;S");
   4.275 +      return;
   4.276 +    }
   4.277 +
   4.278 +  /* Otherwise we didn't know what packet it was.  Say we didn't
   4.279 +     understand it.  */
   4.280 +  own_buf[0] = 0;
   4.281 +  return;
   4.282 +}
   4.283 +
   4.284 +void
   4.285 +myresume (int step, int sig)
   4.286 +{
   4.287 +  struct thread_resume resume_info[2];
   4.288 +  int n = 0;
   4.289 +
   4.290 +  if (step || sig || cont_thread > 0)
   4.291 +    {
   4.292 +      resume_info[0].thread
   4.293 +	= ((struct inferior_list_entry *) current_inferior)->id;
   4.294 +      resume_info[0].step = step;
   4.295 +      resume_info[0].sig = sig;
   4.296 +      resume_info[0].leave_stopped = 0;
   4.297 +      n++;
   4.298 +    }
   4.299 +  resume_info[n].thread = -1;
   4.300 +  resume_info[n].step = 0;
   4.301 +  resume_info[n].sig = 0;
   4.302 +  resume_info[n].leave_stopped = (cont_thread > 0);
   4.303 +
   4.304 +  (*the_target->resume) (resume_info);
   4.305 +}
   4.306 +
   4.307 +static int attached;
   4.308 +
   4.309 +static void
   4.310 +gdbserver_usage (void)
   4.311 +{
   4.312 +  error ("Usage:\tgdbserver COMM PROG [ARGS ...]\n"
   4.313 +	 "\tgdbserver COMM --attach PID\n"
   4.314 +	 "\tgdbserver COMM --file COREFILE\n"
   4.315 +	 "\n"
   4.316 +	 "COMM may either be a tty device (for serial debugging), or \n"
   4.317 +	 "HOST:PORT to listen for a TCP connection.\n");
   4.318 +}
   4.319 +
   4.320 +int
   4.321 +main (int argc, char *argv[])
   4.322 +{
   4.323 +  char ch, status, *own_buf, mem_buf[2000];
   4.324 +  int i = 0;
   4.325 +  unsigned char signal;
   4.326 +  unsigned int len;
   4.327 +  CORE_ADDR mem_addr;
   4.328 +  int bad_attach;
   4.329 +  int pid;
   4.330 +  char *arg_end;
   4.331 +
   4.332 +  if (setjmp (toplevel))
   4.333 +    {
   4.334 +      fprintf (stderr, "Exiting\n");
   4.335 +      exit (1);
   4.336 +    }
   4.337 +
   4.338 +  bad_attach = 0;
   4.339 +  pid = 0;
   4.340 +  attached = 0;
   4.341 +  if (argc >= 3 && strcmp (argv[2], "--attach") == 0)
   4.342 +    {
   4.343 +      if (argc == 4
   4.344 +	  && argv[3] != '\0'
   4.345 +	  && (pid = strtoul (argv[3], &arg_end, 10)) != 0
   4.346 +	  && *arg_end == '\0')
   4.347 +	{
   4.348 +	  ;
   4.349 +	}
   4.350 +      else
   4.351 +	bad_attach = 1;
   4.352 +    }
   4.353 +  else if (argc >= 3 && strcmp (argv[2], "--file") == 0)
   4.354 +    {
   4.355 +      if (argc == 4
   4.356 +	  && argv[3] != '\0')
   4.357 +	{
   4.358 +	  if ((pid = open(argv[3], O_RDONLY)) <= 0) 
   4.359 +	    bad_attach = 1;
   4.360 +	  else 
   4.361 +	    isfile = 1;
   4.362 +	}
   4.363 +      else
   4.364 +	bad_attach = 1;
   4.365 +    }
   4.366 +
   4.367 +  if (argc < 3 || bad_attach)
   4.368 +    gdbserver_usage();
   4.369 +
   4.370 +  initialize_low ();
   4.371 +
   4.372 +  own_buf = malloc (PBUFSIZ);
   4.373 +
   4.374 +  if (pid == 0)
   4.375 +    {
   4.376 +      /* Wait till we are at first instruction in program.  */
   4.377 +      signal = start_inferior (&argv[2], &status);
   4.378 +
   4.379 +      /* We are now stopped at the first instruction of the target process */
   4.380 +    }
   4.381 +  else
   4.382 +    {
   4.383 +      switch (attach_inferior (pid, &status, &signal))
   4.384 +	{
   4.385 +	case -1:
   4.386 +	  error ("Attaching not supported on this target");
   4.387 +	  break;
   4.388 +	default:
   4.389 +	  attached = 1;
   4.390 +	  break;
   4.391 +	}
   4.392 +    }
   4.393 +
   4.394 +  while (1)
   4.395 +    {
   4.396 +      remote_open (argv[1]);
   4.397 +
   4.398 +    restart:
   4.399 +      setjmp (toplevel);
   4.400 +      while (getpkt (own_buf) > 0)
   4.401 +	{
   4.402 +	  unsigned char sig;
   4.403 +	  i = 0;
   4.404 +	  ch = own_buf[i++];
   4.405 +	  switch (ch)
   4.406 +	    {
   4.407 +	    case 'q':
   4.408 +	      handle_query (own_buf);
   4.409 +	      break;
   4.410 +	    case 'd':
   4.411 +	      remote_debug = !remote_debug;
   4.412 +	      break;
   4.413 +	    case 'D':
   4.414 +	      fprintf (stderr, "Detaching from inferior\n");
   4.415 +	      detach_inferior ();
   4.416 +	      write_ok (own_buf);
   4.417 +	      putpkt (own_buf);
   4.418 +	      remote_close ();
   4.419 +
   4.420 +	      /* If we are attached, then we can exit.  Otherwise, we need to
   4.421 +		 hang around doing nothing, until the child is gone.  */
   4.422 +	      if (!attached)
   4.423 +		{
   4.424 +		  int status, ret;
   4.425 +
   4.426 +		  do {
   4.427 +		    ret = waitpid (signal_pid, &status, 0);
   4.428 +		    if (WIFEXITED (status) || WIFSIGNALED (status))
   4.429 +		      break;
   4.430 +		  } while (ret != -1 || errno != ECHILD);
   4.431 +		}
   4.432 +
   4.433 +	      exit (0);
   4.434 +
   4.435 +	    case '!':
   4.436 +	      if (attached == 0)
   4.437 +		{
   4.438 +		  extended_protocol = 1;
   4.439 +		  prepare_resume_reply (own_buf, status, signal);
   4.440 +		}
   4.441 +	      else
   4.442 +		{
   4.443 +		  /* We can not use the extended protocol if we are
   4.444 +		     attached, because we can not restart the running
   4.445 +		     program.  So return unrecognized.  */
   4.446 +		  own_buf[0] = '\0';
   4.447 +		}
   4.448 +	      break;
   4.449 +	    case '?':
   4.450 +	      prepare_resume_reply (own_buf, status, signal);
   4.451 +	      break;
   4.452 +	    case 'H':
   4.453 +	      switch (own_buf[1])
   4.454 +		{
   4.455 +		case 'g':
   4.456 +		  general_thread = strtol (&own_buf[2], NULL, 16);
   4.457 +		  write_ok (own_buf);
   4.458 +		  set_desired_inferior (1);
   4.459 +		  break;
   4.460 +		case 'c':
   4.461 +		  cont_thread = strtol (&own_buf[2], NULL, 16);
   4.462 +		  write_ok (own_buf);
   4.463 +		  break;
   4.464 +		case 's':
   4.465 +		  step_thread = strtol (&own_buf[2], NULL, 16);
   4.466 +		  write_ok (own_buf);
   4.467 +		  break;
   4.468 +		default:
   4.469 +		  /* Silently ignore it so that gdb can extend the protocol
   4.470 +		     without compatibility headaches.  */
   4.471 +		  own_buf[0] = '\0';
   4.472 +		  break;
   4.473 +		}
   4.474 +	      break;
   4.475 +	    case 'g':
   4.476 +	      set_desired_inferior (1);
   4.477 +	      registers_to_string (own_buf);
   4.478 +	      break;
   4.479 +	    case 'G':
   4.480 +	      set_desired_inferior (1);
   4.481 +	      registers_from_string (&own_buf[1]);
   4.482 +	      write_ok (own_buf);
   4.483 +	      break;
   4.484 +	    case 'm':
   4.485 +	      decode_m_packet (&own_buf[1], &mem_addr, &len);
   4.486 +	      if (read_inferior_memory (mem_addr, mem_buf, len) == 0)
   4.487 +		convert_int_to_ascii (mem_buf, own_buf, len);
   4.488 +	      else
   4.489 +		write_enn (own_buf);
   4.490 +	      break;
   4.491 +	    case 'M':
   4.492 +	      decode_M_packet (&own_buf[1], &mem_addr, &len, mem_buf);
   4.493 +	      if (write_inferior_memory (mem_addr, mem_buf, len) == 0)
   4.494 +		write_ok (own_buf);
   4.495 +	      else
   4.496 +		write_enn (own_buf);
   4.497 +	      break;
   4.498 +	    case 'C':
   4.499 +	      convert_ascii_to_int (own_buf + 1, &sig, 1);
   4.500 +	      if (target_signal_to_host_p (sig))
   4.501 +		signal = target_signal_to_host (sig);
   4.502 +	      else
   4.503 +		signal = 0;
   4.504 +	      set_desired_inferior (0);
   4.505 +	      myresume (0, signal);
   4.506 +	      signal = mywait (&status, 1);
   4.507 +	      prepare_resume_reply (own_buf, status, signal);
   4.508 +	      break;
   4.509 +	    case 'S':
   4.510 +	      convert_ascii_to_int (own_buf + 1, &sig, 1);
   4.511 +	      if (target_signal_to_host_p (sig))
   4.512 +		signal = target_signal_to_host (sig);
   4.513 +	      else
   4.514 +		signal = 0;
   4.515 +	      set_desired_inferior (0);
   4.516 +	      myresume (1, signal);
   4.517 +	      signal = mywait (&status, 1);
   4.518 +	      prepare_resume_reply (own_buf, status, signal);
   4.519 +	      break;
   4.520 +	    case 'c':
   4.521 +	      set_desired_inferior (0);
   4.522 +	      myresume (0, 0);
   4.523 +	      signal = mywait (&status, 1);
   4.524 +	      prepare_resume_reply (own_buf, status, signal);
   4.525 +	      break;
   4.526 +	    case 's':
   4.527 +	      set_desired_inferior (0);
   4.528 +	      myresume (1, 0);
   4.529 +	      signal = mywait (&status, 1);
   4.530 +	      prepare_resume_reply (own_buf, status, signal);
   4.531 +	      break;
   4.532 +	    case 'k':
   4.533 +	      fprintf (stderr, "Killing inferior\n");
   4.534 +	      kill_inferior ();
   4.535 +	      /* When using the extended protocol, we start up a new
   4.536 +	         debugging session.   The traditional protocol will
   4.537 +	         exit instead.  */
   4.538 +	      if (extended_protocol)
   4.539 +		{
   4.540 +		  write_ok (own_buf);
   4.541 +		  fprintf (stderr, "GDBserver restarting\n");
   4.542 +
   4.543 +		  /* Wait till we are at 1st instruction in prog.  */
   4.544 +		  signal = start_inferior (&argv[2], &status);
   4.545 +		  goto restart;
   4.546 +		  break;
   4.547 +		}
   4.548 +	      else
   4.549 +		{
   4.550 +		  exit (0);
   4.551 +		  break;
   4.552 +		}
   4.553 +	    case 'T':
   4.554 +	      if (mythread_alive (strtol (&own_buf[1], NULL, 16)))
   4.555 +		write_ok (own_buf);
   4.556 +	      else
   4.557 +		write_enn (own_buf);
   4.558 +	      break;
   4.559 +	    case 'R':
   4.560 +	      /* Restarting the inferior is only supported in the
   4.561 +	         extended protocol.  */
   4.562 +	      if (extended_protocol)
   4.563 +		{
   4.564 +		  kill_inferior ();
   4.565 +		  write_ok (own_buf);
   4.566 +		  fprintf (stderr, "GDBserver restarting\n");
   4.567 +
   4.568 +		  /* Wait till we are at 1st instruction in prog.  */
   4.569 +		  signal = start_inferior (&argv[2], &status);
   4.570 +		  goto restart;
   4.571 +		  break;
   4.572 +		}
   4.573 +	      else
   4.574 +		{
   4.575 +		  /* It is a request we don't understand.  Respond with an
   4.576 +		     empty packet so that gdb knows that we don't support this
   4.577 +		     request.  */
   4.578 +		  own_buf[0] = '\0';
   4.579 +		  break;
   4.580 +		}
   4.581 +	    case 'v':
   4.582 +	      /* Extended (long) request.  */
   4.583 +	      handle_v_requests (own_buf, &status, &signal);
   4.584 +	      break;
   4.585 +	    default:
   4.586 +	      /* It is a request we don't understand.  Respond with an
   4.587 +	         empty packet so that gdb knows that we don't support this
   4.588 +	         request.  */
   4.589 +	      own_buf[0] = '\0';
   4.590 +	      break;
   4.591 +	    }
   4.592 +
   4.593 +	  putpkt (own_buf);
   4.594 +
   4.595 +	  if (status == 'W')
   4.596 +	    fprintf (stderr,
   4.597 +		     "\nChild exited with status %d\n", signal);
   4.598 +	  if (status == 'X')
   4.599 +	    fprintf (stderr, "\nChild terminated with signal = 0x%x\n",
   4.600 +		     signal);
   4.601 +	  if (status == 'W' || status == 'X')
   4.602 +	    {
   4.603 +	      if (extended_protocol)
   4.604 +		{
   4.605 +		  fprintf (stderr, "Killing inferior\n");
   4.606 +		  kill_inferior ();
   4.607 +		  write_ok (own_buf);
   4.608 +		  fprintf (stderr, "GDBserver restarting\n");
   4.609 +
   4.610 +		  /* Wait till we are at 1st instruction in prog.  */
   4.611 +		  signal = start_inferior (&argv[2], &status);
   4.612 +		  goto restart;
   4.613 +		  break;
   4.614 +		}
   4.615 +	      else
   4.616 +		{
   4.617 +		  fprintf (stderr, "GDBserver exiting\n");
   4.618 +		  exit (0);
   4.619 +		}
   4.620 +	    }
   4.621 +	}
   4.622 +
   4.623 +      /* We come here when getpkt fails.
   4.624 +
   4.625 +         For the extended remote protocol we exit (and this is the only
   4.626 +         way we gracefully exit!).
   4.627 +
   4.628 +         For the traditional remote protocol close the connection,
   4.629 +         and re-open it at the top of the loop.  */
   4.630 +      if (extended_protocol)
   4.631 +	{
   4.632 +	  remote_close ();
   4.633 +	  exit (0);
   4.634 +	}
   4.635 +      else
   4.636 +	{
   4.637 +	  fprintf (stderr, "Remote side has terminated connection.  "
   4.638 +			   "GDBserver will reopen the connection.\n");
   4.639 +	  remote_close ();
   4.640 +	}
   4.641 +    }
   4.642 +}
     5.1 --- a/tools/libxc/Makefile	Sat Apr 30 08:35:58 2005 +0000
     5.2 +++ b/tools/libxc/Makefile	Sat Apr 30 08:45:02 2005 +0000
     5.3 @@ -17,6 +17,7 @@ INCLUDES += -I $(XEN_LIBXUTIL)
     5.4  
     5.5  SRCS     :=
     5.6  SRCS     += xc_bvtsched.c
     5.7 +SRCS     += xc_core.c
     5.8  SRCS     += xc_domain.c
     5.9  SRCS     += xc_evtchn.c
    5.10  SRCS     += xc_gnttab.c
    5.11 @@ -29,6 +30,7 @@ SRCS     += xc_misc.c
    5.12  SRCS     += xc_physdev.c
    5.13  SRCS     += xc_private.c
    5.14  SRCS     += xc_ptrace.c
    5.15 +SRCS     += xc_ptrace_core.c
    5.16  SRCS     += xc_vmx_build.c
    5.17  
    5.18  CFLAGS   += -Wall
     6.1 --- a/tools/libxc/xc.h	Sat Apr 30 08:35:58 2005 +0000
     6.2 +++ b/tools/libxc/xc.h	Sat Apr 30 08:45:02 2005 +0000
     6.3 @@ -20,6 +20,7 @@ typedef int16_t            s16;
     6.4  typedef int32_t            s32;
     6.5  typedef int64_t            s64;
     6.6  
     6.7 +#include <sys/ptrace.h>
     6.8  #include <xen/xen.h>
     6.9  #include <xen/dom0_ops.h>
    6.10  #include <xen/event_channel.h>
    6.11 @@ -72,6 +73,38 @@ int xc_interface_open(void);
    6.12  int xc_interface_close(int xc_handle);
    6.13  
    6.14  /*
    6.15 + * DOMAIN DEBUGGING FUNCTIONS
    6.16 + */
    6.17 +
    6.18 +typedef struct xc_core_header {
    6.19 +    unsigned int xch_magic;
    6.20 +    unsigned int xch_nr_vcpus;
    6.21 +    unsigned int xch_nr_pages;
    6.22 +    unsigned int xch_ctxt_offset;
    6.23 +    unsigned int xch_index_offset;
    6.24 +    unsigned int xch_pages_offset;
    6.25 +} xc_core_header_t;
    6.26 +
    6.27 +
    6.28 +long xc_ptrace(enum __ptrace_request request, 
    6.29 +	       pid_t pid, 
    6.30 +	       long addr, 
    6.31 +	       long data);
    6.32 +
    6.33 +long xc_ptrace_core(enum __ptrace_request request, 
    6.34 +		    pid_t pid, 
    6.35 +		    long addr, 
    6.36 +		    long data);
    6.37 +
    6.38 +int xc_waitdomain(int domain, 
    6.39 +		  int *status, 
    6.40 +		  int options);
    6.41 +
    6.42 +int xc_waitdomain_core(int domain, 
    6.43 +		       int *status, 
    6.44 +		       int options);
    6.45 +
    6.46 +/*
    6.47   * DOMAIN MANAGEMENT FUNCTIONS
    6.48   */
    6.49  
    6.50 @@ -94,6 +127,12 @@ int xc_domain_create(int xc_handle,
    6.51                       float cpu_weight,
    6.52                       u32 *pdomid);
    6.53  
    6.54 +
    6.55 +int xc_domain_dumpcore(int xc_handle, 
    6.56 +		       u32 domid,
    6.57 +		       const char *corename);
    6.58 +
    6.59 +
    6.60  /**
    6.61   * This function pauses a domain. A paused domain still exists in memory
    6.62   * however it does not receive any timeslices from the hypervisor.
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/libxc/xc_core.c	Sat Apr 30 08:45:02 2005 +0000
     7.3 @@ -0,0 +1,99 @@
     7.4 +#include "xc_private.h"
     7.5 +#define ELFSIZE 32
     7.6 +#include "xc_elf.h"
     7.7 +#include <stdlib.h>
     7.8 +#include <zlib.h>
     7.9 +
    7.10 +/* number of pages to write at a time */
    7.11 +#define DUMP_INCREMENT 4 * 1024
    7.12 +#define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
    7.13 +static int
    7.14 +copy_from_domain_page(int xc_handle,
    7.15 +		      u32 domid,
    7.16 +		      unsigned long *page_array,
    7.17 +		      unsigned long src_pfn,
    7.18 +		      void *dst_page)
    7.19 +{
    7.20 +    void *vaddr = xc_map_foreign_range(
    7.21 +        xc_handle, domid, PAGE_SIZE, PROT_READ, page_array[src_pfn]);
    7.22 +    if ( vaddr == NULL )
    7.23 +        return -1;
    7.24 +    memcpy(dst_page, vaddr, PAGE_SIZE);
    7.25 +    munmap(vaddr, PAGE_SIZE);
    7.26 +    return 0;
    7.27 +}
    7.28 +
    7.29 +int 
    7.30 +xc_domain_dumpcore(int xc_handle,
    7.31 +		   u32 domid,
    7.32 +		   const char *corename)
    7.33 +{
    7.34 +	vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
    7.35 +	unsigned long nr_pages;
    7.36 +	unsigned long *page_array;
    7.37 +	xc_domaininfo_t st_info, *info = &st_info;
    7.38 +	int i, dump_fd;
    7.39 +	char *dump_mem, *dump_mem_start = NULL;
    7.40 +	struct xc_core_header header;
    7.41 +	
    7.42 +	if ((dump_fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0) {
    7.43 +		PERROR("Could not open corefile %s: %s", corename, strerror(errno));
    7.44 +		goto error_out;
    7.45 +	}
    7.46 +	
    7.47 +	if ((dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == 0) {
    7.48 +		PERROR("Could not allocate dump_mem");
    7.49 +		goto error_out;
    7.50 +	}
    7.51 +	
    7.52 +	if (xc_domain_getfullinfo(xc_handle, domid, 0/* XXX hardcode */, info, ctxt)) {
    7.53 +		PERROR("Could not get full info for domain");
    7.54 +		goto error_out;
    7.55 +	}
    7.56 +
    7.57 +	nr_pages = info->tot_pages;
    7.58 +	header.xch_magic = 0xF00FEBED; 
    7.59 +	header.xch_nr_vcpus = 1; /* no interface to query at the moment */
    7.60 +	header.xch_nr_pages = nr_pages;
    7.61 +	header.xch_ctxt_offset = sizeof(struct xc_core_header);
    7.62 +	header.xch_index_offset = sizeof(struct xc_core_header) +
    7.63 +	    sizeof(vcpu_guest_context_t);
    7.64 +	header.xch_pages_offset = round_pgup(sizeof(struct xc_core_header) +
    7.65 +	    sizeof(vcpu_guest_context_t) + nr_pages * sizeof(unsigned long));
    7.66 +
    7.67 +	write(dump_fd, &header, sizeof(struct xc_core_header));
    7.68 +	write(dump_fd, ctxt, sizeof(st_ctxt));
    7.69 +
    7.70 +	if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
    7.71 +	    printf("Could not allocate memory\n");
    7.72 +	    goto error_out;
    7.73 +	}
    7.74 +	if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) {
    7.75 +	    printf("Could not get the page frame list\n");
    7.76 +	    goto error_out;
    7.77 +	}
    7.78 +	write(dump_fd, page_array, nr_pages * sizeof(unsigned long));
    7.79 +	lseek(dump_fd, header.xch_pages_offset, SEEK_SET);
    7.80 +	for (dump_mem = dump_mem_start, i = 0; i < nr_pages; i++) {
    7.81 +		copy_from_domain_page(xc_handle, domid, page_array, i, dump_mem);
    7.82 +		dump_mem += PAGE_SIZE;
    7.83 +		if (((i + 1) % DUMP_INCREMENT == 0) || (i + 1) == nr_pages) {
    7.84 +			if (write(dump_fd, dump_mem_start, dump_mem - dump_mem_start) < 
    7.85 +			    dump_mem - dump_mem_start) {
    7.86 +				PERROR("Partial write, file system full?");
    7.87 +				goto error_out;
    7.88 +			}
    7.89 +			dump_mem = dump_mem_start;
    7.90 +		}
    7.91 +	}
    7.92 +
    7.93 +	close(dump_fd);
    7.94 +	free(dump_mem_start);
    7.95 +	return 0;
    7.96 + error_out:
    7.97 +	if (dump_fd)
    7.98 +		close(dump_fd);
    7.99 +	if (dump_mem_start)
   7.100 +		free(dump_mem_start);
   7.101 +	return -1;
   7.102 +}
     8.1 --- a/tools/libxc/xc_ptrace.c	Sat Apr 30 08:35:58 2005 +0000
     8.2 +++ b/tools/libxc/xc_ptrace.c	Sat Apr 30 08:45:02 2005 +0000
     8.3 @@ -17,8 +17,7 @@
     8.4   * ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
     8.5   */
     8.6  
     8.7 -long xc_ptrace(enum __ptrace_request request, 
     8.8 -	       pid_t pid, void *addr, void *data);
     8.9 +
    8.10  int waitdomain(int domain, int *status, int options);
    8.11  
    8.12  char * ptrace_names[] = {
    8.13 @@ -218,7 +217,7 @@ map_domain_va(unsigned long domid, int c
    8.14  }
    8.15  
    8.16  int 
    8.17 -waitdomain(int domain, int *status, int options)
    8.18 +xc_waitdomain(int domain, int *status, int options)
    8.19  {
    8.20      dom0_op_t op;
    8.21      int retval;
    8.22 @@ -260,7 +259,7 @@ waitdomain(int domain, int *status, int 
    8.23  }
    8.24  
    8.25  long
    8.26 -xc_ptrace(enum __ptrace_request request, pid_t domid, void *addr, void *data)
    8.27 +xc_ptrace(enum __ptrace_request request, pid_t domid, long eaddr, long edata)
    8.28  {
    8.29      dom0_op_t       op;
    8.30      int             status = 0;
    8.31 @@ -268,6 +267,8 @@ xc_ptrace(enum __ptrace_request request,
    8.32      long            retval = 0;
    8.33      unsigned long  *guest_va;
    8.34      int             cpu = VCPU;
    8.35 +    void           *addr = (char *)eaddr;
    8.36 +    void           *data = (char *)edata;
    8.37  
    8.38      op.interface_version = DOM0_INTERFACE_VERSION;
    8.39      
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/libxc/xc_ptrace_core.c	Sat Apr 30 08:45:02 2005 +0000
     9.3 @@ -0,0 +1,287 @@
     9.4 +#include <sys/ptrace.h>
     9.5 +#include <sys/wait.h>
     9.6 +#include "xc_private.h"
     9.7 +#include <asm/elf.h>
     9.8 +#include <time.h>
     9.9 +
    9.10 +
    9.11 +#define BSD_PAGE_MASK	(PAGE_SIZE-1)
    9.12 +#define	PG_FRAME	(~((unsigned long)BSD_PAGE_MASK)
    9.13 +#define PDRSHIFT        22
    9.14 +#define	PSL_T		0x00000100	/* trace enable bit */
    9.15 +
    9.16 +#define VCPU            0               /* XXX */
    9.17 +
    9.18 +/*
    9.19 + * long  
    9.20 + * ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
    9.21 + */
    9.22 +
    9.23 +
    9.24 +struct gdb_regs {
    9.25 +    long ebx; /* 0 */
    9.26 +    long ecx; /* 4 */
    9.27 +    long edx; /* 8 */
    9.28 +    long esi; /* 12 */
    9.29 +    long edi; /* 16 */
    9.30 +    long ebp; /* 20 */
    9.31 +    long eax; /* 24 */ 
    9.32 +    int  xds; /* 28 */
    9.33 +    int  xes; /* 32 */
    9.34 +    int  xfs; /* 36 */
    9.35 +    int  xgs; /* 40 */
    9.36 +    long orig_eax; /* 44 */
    9.37 +    long eip;    /* 48 */
    9.38 +    int  xcs;    /* 52 */
    9.39 +    long eflags; /* 56 */
    9.40 +    long esp;    /* 60 */     
    9.41 +    int  xss;    /* 64 */
    9.42 +};
    9.43 +
    9.44 +#define printval(x) printf("%s = %lx\n", #x, (long)x);
    9.45 +#define SET_PT_REGS(pt, xc) \
    9.46 +{ \
    9.47 +    pt.ebx = xc.ebx; \
    9.48 +    pt.ecx = xc.ecx; \
    9.49 +    pt.edx = xc.edx; \
    9.50 +    pt.esi = xc.esi; \
    9.51 +    pt.edi = xc.edi; \
    9.52 +    pt.ebp = xc.ebp; \
    9.53 +    pt.eax = xc.eax; \
    9.54 +    pt.eip = xc.eip; \
    9.55 +    pt.xcs = xc.cs; \
    9.56 +    pt.eflags = xc.eflags; \
    9.57 +    pt.esp = xc.esp; \
    9.58 +    pt.xss = xc.ss; \
    9.59 +    pt.xes = xc.es; \
    9.60 +    pt.xds = xc.ds; \
    9.61 +    pt.xfs = xc.fs; \
    9.62 +    pt.xgs = xc.gs; \
    9.63 +}
    9.64 +
    9.65 +#define SET_XC_REGS(pt, xc) \
    9.66 +{ \
    9.67 +    xc.ebx = pt->ebx; \
    9.68 +    xc.ecx = pt->ecx; \
    9.69 +    xc.edx = pt->edx; \
    9.70 +    xc.esi = pt->esi; \
    9.71 +    xc.edi = pt->edi; \
    9.72 +    xc.ebp = pt->ebp; \
    9.73 +    xc.eax = pt->eax; \
    9.74 +    xc.eip = pt->eip; \
    9.75 +    xc.cs = pt->xcs; \
    9.76 +    xc.eflags = pt->eflags; \
    9.77 +    xc.esp = pt->esp; \
    9.78 +    xc.ss = pt->xss; \
    9.79 +    xc.es = pt->xes; \
    9.80 +    xc.ds = pt->xds; \
    9.81 +    xc.fs = pt->xfs; \
    9.82 +    xc.gs = pt->xgs; \
    9.83 +}
    9.84 +
    9.85 +
    9.86 +#define vtopdi(va) ((va) >> PDRSHIFT)
    9.87 +#define vtopti(va) (((va) >> PAGE_SHIFT) & 0x3ff)
    9.88 +
    9.89 +/* XXX application state */
    9.90 +
    9.91 +
    9.92 +static long			nr_pages = 0;
    9.93 +static unsigned long		*p2m_array = NULL;
    9.94 +static unsigned long		*m2p_array = NULL;
    9.95 +static unsigned long            pages_offset;
    9.96 +static unsigned long            cr3[MAX_VIRT_CPUS];
    9.97 +static vcpu_guest_context_t     ctxt[MAX_VIRT_CPUS];
    9.98 +
    9.99 +/* --------------------- */
   9.100 +
   9.101 +static unsigned long
   9.102 +map_mtop_offset(unsigned long ma)
   9.103 +{
   9.104 +    return pages_offset + (m2p_array[ma >> PAGE_SHIFT] << PAGE_SHIFT);
   9.105 +}
   9.106 +
   9.107 +
   9.108 +static void *
   9.109 +map_domain_va(unsigned long domfd, int cpu, void * guest_va)
   9.110 +{
   9.111 +    unsigned long pde, page;
   9.112 +    unsigned long va = (unsigned long)guest_va;
   9.113 +
   9.114 +    static unsigned long  cr3_phys[MAX_VIRT_CPUS];
   9.115 +    static unsigned long *cr3_virt[MAX_VIRT_CPUS];
   9.116 +    static unsigned long  pde_phys[MAX_VIRT_CPUS];
   9.117 +    static unsigned long *pde_virt[MAX_VIRT_CPUS];
   9.118 +    static unsigned long  page_phys[MAX_VIRT_CPUS];
   9.119 +    static unsigned long *page_virt[MAX_VIRT_CPUS];
   9.120 +
   9.121 +    if (cr3[cpu] != cr3_phys[cpu]) 
   9.122 +    {
   9.123 +	cr3_phys[cpu] = cr3[cpu];
   9.124 +	if (cr3_virt[cpu])
   9.125 +	    munmap(cr3_virt[cpu], PAGE_SIZE);
   9.126 +	if ((cr3_virt[cpu] = mmap(NULL, PAGE_SIZE, PROT_READ, 
   9.127 +				  MAP_PRIVATE, domfd, map_mtop_offset(cr3_phys[cpu]))) == 
   9.128 +	    (unsigned long*)0xffffffff)
   9.129 +	{
   9.130 +	    perror("mmap failed");
   9.131 +	    goto error_out;
   9.132 +	}
   9.133 +    } 
   9.134 +    if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */
   9.135 +	goto error_out;
   9.136 +    if (ctxt[cpu].flags & VGCF_VMX_GUEST)
   9.137 +	pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
   9.138 +    if (pde != pde_phys[cpu]) 
   9.139 +    {
   9.140 +	pde_phys[cpu] = pde;
   9.141 +	if (pde_virt[cpu])
   9.142 +	    munmap(pde_virt[cpu], PAGE_SIZE);
   9.143 +	if ((pde_virt[cpu] =  mmap(NULL, PAGE_SIZE, PROT_READ, 
   9.144 +				  MAP_PRIVATE, domfd, map_mtop_offset(pde_phys[cpu]))) == NULL)
   9.145 +	    goto error_out;
   9.146 +    }
   9.147 +    if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */
   9.148 +	goto error_out;
   9.149 +    if (ctxt[cpu].flags & VGCF_VMX_GUEST)
   9.150 +	page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
   9.151 +    if (page != page_phys[cpu]) 
   9.152 +    {
   9.153 +	page_phys[cpu] = page;
   9.154 +	if (page_virt[cpu])
   9.155 +	    munmap(page_virt[cpu], PAGE_SIZE);
   9.156 +	if ((page_virt[cpu] = mmap(NULL, PAGE_SIZE, PROT_READ, 
   9.157 +				  MAP_PRIVATE, domfd, map_mtop_offset(page_phys[cpu]))) == NULL) {
   9.158 +	    printf("cr3 %lx pde %lx page %lx pti %lx\n", cr3[cpu], pde, page, vtopti(va));
   9.159 +	    page_phys[cpu] = 0;
   9.160 +	    goto error_out;
   9.161 +	}
   9.162 +    }	
   9.163 +    return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
   9.164 +
   9.165 + error_out:
   9.166 +    return 0;
   9.167 +}
   9.168 +
   9.169 +int 
   9.170 +xc_waitdomain_core(int domfd, int *status, int options)
   9.171 +{
   9.172 +    int retval = -1;
   9.173 +    int nr_vcpus;
   9.174 +    int i;
   9.175 +    xc_core_header_t header;
   9.176 +
   9.177 +    if (nr_pages == 0) {
   9.178 +
   9.179 +	if (read(domfd, &header, sizeof(header)) != sizeof(header))
   9.180 +	    return -1;
   9.181 +
   9.182 +	nr_pages = header.xch_nr_pages;
   9.183 +	nr_vcpus = header.xch_nr_vcpus;
   9.184 +	pages_offset = header.xch_pages_offset;
   9.185 +
   9.186 +	if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) != 
   9.187 +	    sizeof(vcpu_guest_context_t)*nr_vcpus)
   9.188 +	    return -1;
   9.189 +
   9.190 +	for (i = 0; i < nr_vcpus; i++) {
   9.191 +	    cr3[i] = ctxt[i].pt_base;
   9.192 +	}
   9.193 +	if ((p2m_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
   9.194 +	    printf("Could not allocate p2m_array\n");
   9.195 +	    goto error_out;
   9.196 +	}
   9.197 +	if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) != 
   9.198 +	    sizeof(unsigned long)*nr_pages)
   9.199 +	    return -1;
   9.200 +
   9.201 +	if ((m2p_array = malloc((1<<20) * sizeof(unsigned long))) == NULL) {
   9.202 +	    printf("Could not allocate m2p array\n");
   9.203 +	    goto error_out;
   9.204 +	}
   9.205 +	bzero(m2p_array, sizeof(unsigned long)* 1 << 20);
   9.206 +
   9.207 +	for (i = 0; i < nr_pages; i++) {
   9.208 +	    m2p_array[p2m_array[i]] = i;
   9.209 +	}
   9.210 +
   9.211 +    }
   9.212 +    retval = 0;
   9.213 + error_out:
   9.214 +    return retval;
   9.215 +
   9.216 +}
   9.217 +
   9.218 +long
   9.219 +xc_ptrace_core(enum __ptrace_request request, int domfd, long eaddr, long edata)
   9.220 +{
   9.221 +    int             status = 0;
   9.222 +    struct gdb_regs pt;
   9.223 +    long            retval = 0;
   9.224 +    unsigned long  *guest_va;
   9.225 +    int             cpu = VCPU;
   9.226 +    void           *addr = (char *)eaddr;
   9.227 +    void           *data = (char *)edata;
   9.228 +
   9.229 +#if 0
   9.230 +    printf("%20s %d, %p, %p \n", ptrace_names[request], domid, addr, data);
   9.231 +#endif
   9.232 +    switch (request) {	
   9.233 +    case PTRACE_PEEKTEXT:
   9.234 +    case PTRACE_PEEKDATA:
   9.235 +	if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) {
   9.236 +	    status = EFAULT;
   9.237 +	    goto error_out;
   9.238 +	}
   9.239 +
   9.240 +	retval = *guest_va;
   9.241 +	break;
   9.242 +    case PTRACE_POKETEXT:
   9.243 +    case PTRACE_POKEDATA:
   9.244 +	if ((guest_va = (unsigned long *)map_domain_va(domfd, cpu, addr)) == NULL) {
   9.245 +	    status = EFAULT;
   9.246 +	    goto error_out;
   9.247 +	}
   9.248 +	*guest_va = (unsigned long)data;
   9.249 +	break;
   9.250 +    case PTRACE_GETREGS:
   9.251 +    case PTRACE_GETFPREGS:
   9.252 +    case PTRACE_GETFPXREGS:
   9.253 +	if (request == PTRACE_GETREGS) {
   9.254 +		SET_PT_REGS(pt, ctxt[cpu].user_regs); 
   9.255 +		memcpy(data, &pt, sizeof(elf_gregset_t));
   9.256 +	} else if (request == PTRACE_GETFPREGS)
   9.257 +	    memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
   9.258 +	else /*if (request == PTRACE_GETFPXREGS)*/
   9.259 +	    memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
   9.260 +	break;
   9.261 +    case PTRACE_ATTACH:
   9.262 +	retval = 0;
   9.263 +	break;
   9.264 +    case PTRACE_SETREGS:
   9.265 +    case PTRACE_SINGLESTEP:
   9.266 +    case PTRACE_CONT:
   9.267 +    case PTRACE_DETACH:
   9.268 +    case PTRACE_SETFPREGS:
   9.269 +    case PTRACE_SETFPXREGS:
   9.270 +    case PTRACE_PEEKUSER:
   9.271 +    case PTRACE_POKEUSER:
   9.272 +    case PTRACE_SYSCALL:
   9.273 +    case PTRACE_KILL:
   9.274 +#ifdef DEBUG
   9.275 +	printf("unsupported xc_ptrace request %s\n", ptrace_names[request]);
   9.276 +#endif
   9.277 +	status = ENOSYS;
   9.278 +	break;
   9.279 +    case PTRACE_TRACEME:
   9.280 +	printf("PTRACE_TRACEME is an invalid request under Xen\n");
   9.281 +	status = EINVAL;
   9.282 +    }
   9.283 +    
   9.284 +    if (status) {
   9.285 +	errno = status;
   9.286 +	retval = -1;
   9.287 +    }
   9.288 + error_out:
   9.289 +    return retval;
   9.290 +}
    10.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Sat Apr 30 08:35:58 2005 +0000
    10.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Sat Apr 30 08:45:02 2005 +0000
    10.3 @@ -36,6 +36,33 @@ typedef struct {
    10.4   * Definitions for the 'xc' object type.
    10.5   */
    10.6  
    10.7 +static PyObject *pyxc_domain_dumpcore(PyObject *self,
    10.8 +				      PyObject *args,
    10.9 +				      PyObject *kwds)
   10.10 +{
   10.11 +    XcObject *xc = (XcObject *)self;
   10.12 +
   10.13 +    u32 dom;
   10.14 +    char *corefile;
   10.15 +
   10.16 +    static char *kwd_list[] = { "dom", "corefile", NULL };
   10.17 +
   10.18 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is", kwd_list, &dom, &corefile) )
   10.19 +        goto exit;
   10.20 +
   10.21 +    if ( (corefile == NULL) || (corefile[0] == '\0') )
   10.22 +        goto exit;
   10.23 +
   10.24 +    if ( xc_domain_dumpcore(xc->xc_handle, dom, corefile) != 0 )
   10.25 +        return PyErr_SetFromErrno(xc_error);
   10.26 +    
   10.27 +    Py_INCREF(zero);
   10.28 +    return zero;
   10.29 +
   10.30 + exit:
   10.31 +    return NULL;
   10.32 +}
   10.33 +
   10.34  static PyObject *pyxc_domain_create(PyObject *self,
   10.35                                      PyObject *args,
   10.36                                      PyObject *kwds)
   10.37 @@ -854,6 +881,14 @@ static PyMethodDef pyxc_methods[] = {
   10.38        " mem_kb [int, 0]:        Memory allocation, in kilobytes.\n"
   10.39        "Returns: [int] new domain identifier; -1 on error.\n" },
   10.40  
   10.41 +    { "domain_dumpcore", 
   10.42 +      (PyCFunction)pyxc_domain_dumpcore, 
   10.43 +      METH_VARARGS | METH_KEYWORDS, "\n"
   10.44 +      "dump core of a domain.\n"
   10.45 +      " dom [int]: Identifier of domain to be paused.\n\n"
   10.46 +      " corefile [string]: Name of corefile to be created.\n\n"
   10.47 +      "Returns: [int] 0 on success; -1 on error.\n" },
   10.48 +
   10.49      { "domain_pause", 
   10.50        (PyCFunction)pyxc_domain_pause, 
   10.51        METH_VARARGS | METH_KEYWORDS, "\n"