njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
| 3 | /*--- Attaching a debugger. m_debugger.c ---*/ |
| 4 | /*--------------------------------------------------------------------*/ |
| 5 | |
| 6 | /* |
| 7 | This file is part of Valgrind, a dynamic binary instrumentation |
| 8 | framework. |
| 9 | |
sewardj | 4d474d0 | 2008-02-11 11:34:59 +0000 | [diff] [blame] | 10 | Copyright (C) 2000-2008 Julian Seward |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 11 | jseward@acm.org |
| 12 | |
| 13 | This program is free software; you can redistribute it and/or |
| 14 | modify it under the terms of the GNU General Public License as |
| 15 | published by the Free Software Foundation; either version 2 of the |
| 16 | License, or (at your option) any later version. |
| 17 | |
| 18 | This program is distributed in the hope that it will be useful, but |
| 19 | WITHOUT ANY WARRANTY; without even the implied warranty of |
| 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 21 | General Public License for more details. |
| 22 | |
| 23 | You should have received a copy of the GNU General Public License |
| 24 | along with this program; if not, write to the Free Software |
| 25 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 26 | 02111-1307, USA. |
| 27 | |
| 28 | The GNU General Public License is contained in the file COPYING. |
| 29 | */ |
| 30 | |
| 31 | #include "pub_core_basics.h" |
sewardj | 4cfea4f | 2006-10-14 19:26:10 +0000 | [diff] [blame] | 32 | #include "pub_core_vki.h" |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 33 | #include "pub_core_threadstate.h" |
sewardj | 14c7cc5 | 2007-02-25 15:08:24 +0000 | [diff] [blame] | 34 | #include "pub_core_xarray.h" |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 35 | #include "pub_core_clientstate.h" |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 36 | #include "pub_core_debugger.h" |
| 37 | #include "pub_core_libcbase.h" |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 38 | #include "pub_core_libcprint.h" |
| 39 | #include "pub_core_libcproc.h" |
| 40 | #include "pub_core_libcsignal.h" |
sewardj | 2c48c7b | 2005-11-29 13:05:56 +0000 | [diff] [blame] | 41 | #include "pub_core_libcassert.h" |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 42 | #include "pub_core_options.h" |
| 43 | |
sewardj | ccc89d9 | 2005-11-09 14:43:03 +0000 | [diff] [blame] | 44 | |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 45 | #define WIFSTOPPED(status) (((status) & 0xff) == 0x7f) |
| 46 | #define WSTOPSIG(status) (((status) & 0xff00) >> 8) |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 47 | |
| 48 | static Int ptrace_setregs(Int pid, VexGuestArchState* vex) |
| 49 | { |
sewardj | 957ee5d | 2006-10-17 01:54:20 +0000 | [diff] [blame] | 50 | #if defined(VGP_x86_linux) |
sewardj | c9e73dc | 2005-11-09 15:14:16 +0000 | [diff] [blame] | 51 | struct vki_user_regs_struct regs; |
sewardj | 0313b1e | 2007-11-19 14:54:09 +0000 | [diff] [blame] | 52 | VG_(memset)(®s, 0, sizeof(regs)); |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 53 | regs.cs = vex->guest_CS; |
| 54 | regs.ss = vex->guest_SS; |
| 55 | regs.ds = vex->guest_DS; |
| 56 | regs.es = vex->guest_ES; |
| 57 | regs.fs = vex->guest_FS; |
| 58 | regs.gs = vex->guest_GS; |
| 59 | regs.eax = vex->guest_EAX; |
| 60 | regs.ebx = vex->guest_EBX; |
| 61 | regs.ecx = vex->guest_ECX; |
| 62 | regs.edx = vex->guest_EDX; |
| 63 | regs.esi = vex->guest_ESI; |
| 64 | regs.edi = vex->guest_EDI; |
| 65 | regs.ebp = vex->guest_EBP; |
| 66 | regs.esp = vex->guest_ESP; |
| 67 | regs.eflags = LibVEX_GuestX86_get_eflags(vex); |
| 68 | regs.eip = vex->guest_EIP; |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 69 | return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, ®s); |
sewardj | c9e73dc | 2005-11-09 15:14:16 +0000 | [diff] [blame] | 70 | |
sewardj | 957ee5d | 2006-10-17 01:54:20 +0000 | [diff] [blame] | 71 | #elif defined(VGP_amd64_linux) |
sewardj | c9e73dc | 2005-11-09 15:14:16 +0000 | [diff] [blame] | 72 | struct vki_user_regs_struct regs; |
sewardj | 0313b1e | 2007-11-19 14:54:09 +0000 | [diff] [blame] | 73 | VG_(memset)(®s, 0, sizeof(regs)); |
tom | e4fed1c | 2005-07-19 18:19:48 +0000 | [diff] [blame] | 74 | regs.rax = vex->guest_RAX; |
| 75 | regs.rbx = vex->guest_RBX; |
| 76 | regs.rcx = vex->guest_RCX; |
| 77 | regs.rdx = vex->guest_RDX; |
| 78 | regs.rsi = vex->guest_RSI; |
| 79 | regs.rdi = vex->guest_RDI; |
| 80 | regs.rbp = vex->guest_RBP; |
| 81 | regs.rsp = vex->guest_RSP; |
| 82 | regs.r8 = vex->guest_R8; |
| 83 | regs.r9 = vex->guest_R9; |
| 84 | regs.r10 = vex->guest_R10; |
| 85 | regs.r11 = vex->guest_R11; |
| 86 | regs.r12 = vex->guest_R12; |
| 87 | regs.r13 = vex->guest_R13; |
| 88 | regs.r14 = vex->guest_R14; |
| 89 | regs.r15 = vex->guest_R15; |
| 90 | regs.eflags = LibVEX_GuestAMD64_get_rflags(vex); |
| 91 | regs.rip = vex->guest_RIP; |
sewardj | fc9bf72 | 2007-11-19 00:58:18 +0000 | [diff] [blame] | 92 | /* Set %{c,d,e,f,s,g}s and %{fs,gs}_base (whatever those are) to |
| 93 | values which don't fail the kernel's sanity checks. I have no |
| 94 | idea what these should really be set to. Anyway, mostly it |
| 95 | seems that zero is an allowable value, except for %cs and %ss |
| 96 | which have to have their lowest 2 bits be 11. See putreg() in |
| 97 | linux-2.6.23/arch/x86_64/kernel/ptrace.c for the apparently |
| 98 | relevant sanity checks. This fixes #145622. */ |
| 99 | regs.cs = 3; |
| 100 | regs.ds = 0; |
| 101 | regs.es = 0; |
| 102 | regs.fs = 0; |
| 103 | regs.ss = 3; |
| 104 | regs.gs = 0; |
| 105 | regs.fs_base = 0; |
| 106 | regs.gs_base = 0; |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 107 | return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, ®s); |
sewardj | c9e73dc | 2005-11-09 15:14:16 +0000 | [diff] [blame] | 108 | |
sewardj | 957ee5d | 2006-10-17 01:54:20 +0000 | [diff] [blame] | 109 | #elif defined(VGP_ppc32_linux) |
tom | 0109322 | 2005-11-09 08:52:56 +0000 | [diff] [blame] | 110 | Int rc = 0; |
sewardj | c9e73dc | 2005-11-09 15:14:16 +0000 | [diff] [blame] | 111 | /* apparently the casting to void* is the Right Thing To Do */ |
| 112 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R0 * 4), (void*)vex->guest_GPR0); |
| 113 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R1 * 4), (void*)vex->guest_GPR1); |
| 114 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R2 * 4), (void*)vex->guest_GPR2); |
| 115 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R3 * 4), (void*)vex->guest_GPR3); |
| 116 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R4 * 4), (void*)vex->guest_GPR4); |
| 117 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R5 * 4), (void*)vex->guest_GPR5); |
| 118 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R6 * 4), (void*)vex->guest_GPR6); |
| 119 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R7 * 4), (void*)vex->guest_GPR7); |
| 120 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R8 * 4), (void*)vex->guest_GPR8); |
| 121 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R9 * 4), (void*)vex->guest_GPR9); |
| 122 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R10 * 4), (void*)vex->guest_GPR10); |
| 123 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R11 * 4), (void*)vex->guest_GPR11); |
| 124 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R12 * 4), (void*)vex->guest_GPR12); |
| 125 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R13 * 4), (void*)vex->guest_GPR13); |
| 126 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R14 * 4), (void*)vex->guest_GPR14); |
| 127 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R15 * 4), (void*)vex->guest_GPR15); |
| 128 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R16 * 4), (void*)vex->guest_GPR16); |
| 129 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R17 * 4), (void*)vex->guest_GPR17); |
| 130 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R18 * 4), (void*)vex->guest_GPR18); |
| 131 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R19 * 4), (void*)vex->guest_GPR19); |
| 132 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R20 * 4), (void*)vex->guest_GPR20); |
| 133 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R21 * 4), (void*)vex->guest_GPR21); |
| 134 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R22 * 4), (void*)vex->guest_GPR22); |
| 135 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R23 * 4), (void*)vex->guest_GPR23); |
| 136 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R24 * 4), (void*)vex->guest_GPR24); |
| 137 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R25 * 4), (void*)vex->guest_GPR25); |
| 138 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R26 * 4), (void*)vex->guest_GPR26); |
| 139 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R27 * 4), (void*)vex->guest_GPR27); |
| 140 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R28 * 4), (void*)vex->guest_GPR28); |
| 141 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R29 * 4), (void*)vex->guest_GPR29); |
| 142 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R30 * 4), (void*)vex->guest_GPR30); |
| 143 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R31 * 4), (void*)vex->guest_GPR31); |
| 144 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_NIP * 4), (void*)vex->guest_CIA); |
| 145 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_CCR * 4), |
| 146 | (void*)LibVEX_GuestPPC32_get_CR(vex)); |
| 147 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_LNK * 4), (void*)vex->guest_LR); |
| 148 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_CTR * 4), (void*)vex->guest_CTR); |
| 149 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_XER * 4), |
| 150 | (void*)LibVEX_GuestPPC32_get_XER(vex)); |
tom | 0109322 | 2005-11-09 08:52:56 +0000 | [diff] [blame] | 151 | return rc; |
sewardj | c9e73dc | 2005-11-09 15:14:16 +0000 | [diff] [blame] | 152 | |
sewardj | 957ee5d | 2006-10-17 01:54:20 +0000 | [diff] [blame] | 153 | #elif defined(VGP_ppc64_linux) |
sewardj | 62c9aa7 | 2007-11-19 02:29:07 +0000 | [diff] [blame] | 154 | Int rc = 0; |
| 155 | /* FRJ: copied nearly verbatim from the ppc32 case. I compared the |
| 156 | vki-ppc64-linux.h with its ppc32 counterpart and saw no |
| 157 | appreciable differences, other than the registers being 8 bytes |
| 158 | instead of 4. No idea why we don't set all of the entries |
| 159 | declared in vki_pt_regs, but ppc32 doesn't so there must be a |
| 160 | reason. |
| 161 | |
| 162 | Finally, note that CR and XER are 32 bits even for ppc64 (see |
| 163 | libvex_guest_ppc64.h), but the vki_pt_regs struct still gives |
| 164 | them 64 bits. |
| 165 | */ |
| 166 | /* apparently the casting to void* is the Right Thing To Do */ |
| 167 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R0 * 8), (void*)vex->guest_GPR0); |
| 168 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R1 * 8), (void*)vex->guest_GPR1); |
| 169 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R2 * 8), (void*)vex->guest_GPR2); |
| 170 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R3 * 8), (void*)vex->guest_GPR3); |
| 171 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R4 * 8), (void*)vex->guest_GPR4); |
| 172 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R5 * 8), (void*)vex->guest_GPR5); |
| 173 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R6 * 8), (void*)vex->guest_GPR6); |
| 174 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R7 * 8), (void*)vex->guest_GPR7); |
| 175 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R8 * 8), (void*)vex->guest_GPR8); |
| 176 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R9 * 8), (void*)vex->guest_GPR9); |
| 177 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R10 * 8), (void*)vex->guest_GPR10); |
| 178 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R11 * 8), (void*)vex->guest_GPR11); |
| 179 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R12 * 8), (void*)vex->guest_GPR12); |
| 180 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R13 * 8), (void*)vex->guest_GPR13); |
| 181 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R14 * 8), (void*)vex->guest_GPR14); |
| 182 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R15 * 8), (void*)vex->guest_GPR15); |
| 183 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R16 * 8), (void*)vex->guest_GPR16); |
| 184 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R17 * 8), (void*)vex->guest_GPR17); |
| 185 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R18 * 8), (void*)vex->guest_GPR18); |
| 186 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R19 * 8), (void*)vex->guest_GPR19); |
| 187 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R20 * 8), (void*)vex->guest_GPR20); |
| 188 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R21 * 8), (void*)vex->guest_GPR21); |
| 189 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R22 * 8), (void*)vex->guest_GPR22); |
| 190 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R23 * 8), (void*)vex->guest_GPR23); |
| 191 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R24 * 8), (void*)vex->guest_GPR24); |
| 192 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R25 * 8), (void*)vex->guest_GPR25); |
| 193 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R26 * 8), (void*)vex->guest_GPR26); |
| 194 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R27 * 8), (void*)vex->guest_GPR27); |
| 195 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R28 * 8), (void*)vex->guest_GPR28); |
| 196 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R29 * 8), (void*)vex->guest_GPR29); |
| 197 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R30 * 8), (void*)vex->guest_GPR30); |
| 198 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_R31 * 8), (void*)vex->guest_GPR31); |
| 199 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_NIP * 8), (void*)vex->guest_CIA); |
| 200 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_CCR * 8), |
| 201 | (void*)(long)LibVEX_GuestPPC64_get_CR(vex)); |
| 202 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_LNK * 8), (void*)vex->guest_LR); |
| 203 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_CTR * 8), (void*)vex->guest_CTR); |
| 204 | rc |= VG_(ptrace)(VKI_PTRACE_POKEUSR, pid, (void*)(VKI_PT_XER * 8), |
| 205 | (void*)(long)LibVEX_GuestPPC64_get_XER(vex)); |
| 206 | return rc; |
sewardj | 957ee5d | 2006-10-17 01:54:20 +0000 | [diff] [blame] | 207 | |
| 208 | #elif defined(VGP_ppc32_aix5) |
| 209 | I_die_here; |
| 210 | |
| 211 | #elif defined(VGP_ppc64_aix5) |
sewardj | 2c48c7b | 2005-11-29 13:05:56 +0000 | [diff] [blame] | 212 | I_die_here; |
| 213 | |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 214 | #else |
| 215 | # error Unknown arch |
| 216 | #endif |
| 217 | } |
| 218 | |
| 219 | /* Start debugger and get it to attach to this process. Called if the |
| 220 | user requests this service after an error has been shown, so she can |
| 221 | poke around and look at parameters, memory, etc. You can't |
| 222 | meaningfully get the debugger to continue the program, though; to |
| 223 | continue, quit the debugger. */ |
| 224 | void VG_(start_debugger) ( ThreadId tid ) |
| 225 | { |
sewardj | 7289274 | 2005-12-18 03:22:50 +0000 | [diff] [blame] | 226 | # define N_BUF 4096 |
sewardj | 7d7ddd2 | 2007-11-19 02:01:01 +0000 | [diff] [blame] | 227 | Int pid, rc; |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 228 | |
sewardj | 7d7ddd2 | 2007-11-19 02:01:01 +0000 | [diff] [blame] | 229 | pid = VG_(fork)(); |
| 230 | |
| 231 | if (pid == 0) { |
sewardj | 7d7ddd2 | 2007-11-19 02:01:01 +0000 | [diff] [blame] | 232 | /* child */ |
| 233 | rc = VG_(ptrace)(VKI_PTRACE_TRACEME, 0, NULL, NULL); |
| 234 | vg_assert(rc == 0); |
| 235 | rc = VG_(kill)(VG_(getpid)(), VKI_SIGSTOP); |
| 236 | vg_assert(rc == 0); |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 237 | |
| 238 | } else if (pid > 0) { |
sewardj | 7d7ddd2 | 2007-11-19 02:01:01 +0000 | [diff] [blame] | 239 | /* parent */ |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 240 | Int status; |
| 241 | Int res; |
| 242 | |
| 243 | if ((res = VG_(waitpid)(pid, &status, 0)) == pid && |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 244 | WIFSTOPPED(status) && WSTOPSIG(status) == VKI_SIGSTOP && |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 245 | ptrace_setregs(pid, &(VG_(threads)[tid].arch.vex)) == 0 && |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 246 | VG_(kill)(pid, VKI_SIGSTOP) == 0 && |
| 247 | VG_(ptrace)(VKI_PTRACE_DETACH, pid, NULL, 0) == 0) |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 248 | { |
| 249 | Char pidbuf[15]; |
sewardj | 7289274 | 2005-12-18 03:22:50 +0000 | [diff] [blame] | 250 | Char file[50]; |
| 251 | Char buf[N_BUF]; |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 252 | Char *bufptr; |
| 253 | Char *cmdptr; |
| 254 | |
| 255 | VG_(sprintf)(pidbuf, "%d", pid); |
sewardj | 45f4e7c | 2005-09-27 19:20:21 +0000 | [diff] [blame] | 256 | VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(cl_exec_fd)); |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 257 | |
| 258 | bufptr = buf; |
| 259 | cmdptr = VG_(clo_db_command); |
| 260 | |
| 261 | while (*cmdptr) { |
sewardj | 7289274 | 2005-12-18 03:22:50 +0000 | [diff] [blame] | 262 | /* each iteration can advance bufptr by at most the length |
| 263 | of file[], so the following assertion is generously |
| 264 | over-paranoid. */ |
| 265 | vg_assert(bufptr - buf < N_BUF-15-50-10/*paranoia*/); |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 266 | switch (*cmdptr) { |
| 267 | case '%': |
| 268 | switch (*++cmdptr) { |
| 269 | case 'f': |
| 270 | VG_(memcpy)(bufptr, file, VG_(strlen)(file)); |
| 271 | bufptr += VG_(strlen)(file); |
| 272 | cmdptr++; |
| 273 | break; |
sewardj | 7289274 | 2005-12-18 03:22:50 +0000 | [diff] [blame] | 274 | case 'p': |
| 275 | VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf)); |
| 276 | bufptr += VG_(strlen)(pidbuf); |
| 277 | cmdptr++; |
| 278 | break; |
| 279 | default: |
| 280 | *bufptr++ = *cmdptr++; |
| 281 | break; |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 282 | } |
| 283 | break; |
| 284 | default: |
| 285 | *bufptr++ = *cmdptr++; |
| 286 | break; |
| 287 | } |
sewardj | 7289274 | 2005-12-18 03:22:50 +0000 | [diff] [blame] | 288 | vg_assert(bufptr - buf < N_BUF-15-50-10/*paranoia*/); |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 289 | } |
| 290 | |
| 291 | *bufptr++ = '\0'; |
| 292 | |
| 293 | VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf); |
| 294 | res = VG_(system)(buf); |
| 295 | if (res == 0) { |
| 296 | VG_(message)(Vg_UserMsg, ""); |
| 297 | VG_(message)(Vg_UserMsg, |
sewardj | 5b9b441 | 2007-11-24 21:24:25 +0000 | [diff] [blame] | 298 | "Debugger has detached. Valgrind regains control." |
| 299 | " We continue."); |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 300 | } else { |
sewardj | 5b9b441 | 2007-11-24 21:24:25 +0000 | [diff] [blame] | 301 | VG_(message)(Vg_UserMsg, |
| 302 | "Warning: Debugger attach failed! (sys_system)"); |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 303 | VG_(message)(Vg_UserMsg, ""); |
| 304 | } |
sewardj | 5b9b441 | 2007-11-24 21:24:25 +0000 | [diff] [blame] | 305 | } else { |
| 306 | VG_(message)(Vg_UserMsg, |
| 307 | "Warning: Debugger attach failed! (ptrace problem?)"); |
| 308 | VG_(message)(Vg_UserMsg, ""); |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | VG_(kill)(pid, VKI_SIGKILL); |
| 312 | VG_(waitpid)(pid, &status, 0); |
| 313 | } |
sewardj | 7289274 | 2005-12-18 03:22:50 +0000 | [diff] [blame] | 314 | # undef N_BUF |
njn | 75b65aa | 2005-06-19 19:25:44 +0000 | [diff] [blame] | 315 | } |
| 316 | |
| 317 | |
| 318 | |
| 319 | /*--------------------------------------------------------------------*/ |
| 320 | /*--- end ---*/ |
| 321 | /*--------------------------------------------------------------------*/ |