direct-io.hg
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>
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"