blob: b0c85e3d6ac207b38309406248a19bf3b91f2cf1 [file] [log] [blame]
njn75b65aa2005-06-19 19:25:44 +00001
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
10 Copyright (C) 2000-2005 Julian Seward
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"
32#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000033#include "pub_core_clientstate.h"
njn75b65aa2005-06-19 19:25:44 +000034#include "pub_core_debugger.h"
35#include "pub_core_libcbase.h"
njn75b65aa2005-06-19 19:25:44 +000036#include "pub_core_libcprint.h"
37#include "pub_core_libcproc.h"
38#include "pub_core_libcsignal.h"
tom01093222005-11-09 08:52:56 +000039#include "pub_core_libcassert.h" // I_die_here
njn75b65aa2005-06-19 19:25:44 +000040#include "pub_core_options.h"
41
sewardj45f4e7c2005-09-27 19:20:21 +000042#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
43#define WSTOPSIG(status) (((status) & 0xff00) >> 8)
njn75b65aa2005-06-19 19:25:44 +000044
45static Int ptrace_setregs(Int pid, VexGuestArchState* vex)
46{
47 struct vki_user_regs_struct regs;
48#if defined(VGA_x86)
49 regs.cs = vex->guest_CS;
50 regs.ss = vex->guest_SS;
51 regs.ds = vex->guest_DS;
52 regs.es = vex->guest_ES;
53 regs.fs = vex->guest_FS;
54 regs.gs = vex->guest_GS;
55 regs.eax = vex->guest_EAX;
56 regs.ebx = vex->guest_EBX;
57 regs.ecx = vex->guest_ECX;
58 regs.edx = vex->guest_EDX;
59 regs.esi = vex->guest_ESI;
60 regs.edi = vex->guest_EDI;
61 regs.ebp = vex->guest_EBP;
62 regs.esp = vex->guest_ESP;
63 regs.eflags = LibVEX_GuestX86_get_eflags(vex);
64 regs.eip = vex->guest_EIP;
65
sewardj45f4e7c2005-09-27 19:20:21 +000066 return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, &regs);
njn75b65aa2005-06-19 19:25:44 +000067#elif defined(VGA_amd64)
tome4fed1c2005-07-19 18:19:48 +000068 regs.rax = vex->guest_RAX;
69 regs.rbx = vex->guest_RBX;
70 regs.rcx = vex->guest_RCX;
71 regs.rdx = vex->guest_RDX;
72 regs.rsi = vex->guest_RSI;
73 regs.rdi = vex->guest_RDI;
74 regs.rbp = vex->guest_RBP;
75 regs.rsp = vex->guest_RSP;
76 regs.r8 = vex->guest_R8;
77 regs.r9 = vex->guest_R9;
78 regs.r10 = vex->guest_R10;
79 regs.r11 = vex->guest_R11;
80 regs.r12 = vex->guest_R12;
81 regs.r13 = vex->guest_R13;
82 regs.r14 = vex->guest_R14;
83 regs.r15 = vex->guest_R15;
84 regs.eflags = LibVEX_GuestAMD64_get_rflags(vex);
85 regs.rip = vex->guest_RIP;
86
sewardj45f4e7c2005-09-27 19:20:21 +000087 return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, &regs);
cerion85665ca2005-06-20 15:51:07 +000088#elif defined(VGA_ppc32)
tom01093222005-11-09 08:52:56 +000089 Int rc = 0;
sewardj0e500f12005-11-08 20:59:14 +000090
tom01093222005-11-09 08:52:56 +000091 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R0 * 4, vex->guest_GPR0);
92 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R1 * 4, vex->guest_GPR1);
93 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R2 * 4, vex->guest_GPR2);
94 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R3 * 4, vex->guest_GPR3);
95 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R4 * 4, vex->guest_GPR4);
96 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R5 * 4, vex->guest_GPR5);
97 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R6 * 4, vex->guest_GPR6);
98 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R7 * 4, vex->guest_GPR7);
99 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R8 * 4, vex->guest_GPR8);
100 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R9 * 4, vex->guest_GPR9);
101 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R10 * 4, vex->guest_GPR10);
102 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R11 * 4, vex->guest_GPR11);
103 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R12 * 4, vex->guest_GPR12);
104 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R13 * 4, vex->guest_GPR13);
105 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R14 * 4, vex->guest_GPR14);
106 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R15 * 4, vex->guest_GPR15);
107 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R16 * 4, vex->guest_GPR16);
108 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R17 * 4, vex->guest_GPR17);
109 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R18 * 4, vex->guest_GPR18);
110 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R19 * 4, vex->guest_GPR19);
111 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R20 * 4, vex->guest_GPR20);
112 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R21 * 4, vex->guest_GPR21);
113 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R22 * 4, vex->guest_GPR22);
114 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R23 * 4, vex->guest_GPR23);
115 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R24 * 4, vex->guest_GPR24);
116 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R25 * 4, vex->guest_GPR25);
117 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R26 * 4, vex->guest_GPR26);
118 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R27 * 4, vex->guest_GPR27);
119 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R28 * 4, vex->guest_GPR28);
120 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R29 * 4, vex->guest_GPR29);
121 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R30 * 4, vex->guest_GPR30);
122 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_R31 * 4, vex->guest_GPR31);
123 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_NIP * 4, vex->guest_CIA);
124 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_CCR * 4,
125 LibVEX_GuestPPC32_get_CR(vex));
126 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_LNK * 4, vex->guest_LR);
127 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_CTR * 4, vex->guest_CTR);
128 rc |= VG_(ptrace)(VKI_PTRACE_POKEUSER, pid, VKI_PT_XER * 4,
129 LibVEX_GuestPPC32_get_XER(vex));
130 return rc;
njn75b65aa2005-06-19 19:25:44 +0000131#else
132# error Unknown arch
133#endif
134}
135
136/* Start debugger and get it to attach to this process. Called if the
137 user requests this service after an error has been shown, so she can
138 poke around and look at parameters, memory, etc. You can't
139 meaningfully get the debugger to continue the program, though; to
140 continue, quit the debugger. */
141void VG_(start_debugger) ( ThreadId tid )
142{
sewardj45f4e7c2005-09-27 19:20:21 +0000143 Int pid;
njn75b65aa2005-06-19 19:25:44 +0000144
sewardj45f4e7c2005-09-27 19:20:21 +0000145 if ((pid = VG_(fork)()) == 0) {
146 VG_(ptrace)(VKI_PTRACE_TRACEME, 0, NULL, NULL);
njn75b65aa2005-06-19 19:25:44 +0000147 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
148
149 } else if (pid > 0) {
150 Int status;
151 Int res;
152
153 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
sewardj45f4e7c2005-09-27 19:20:21 +0000154 WIFSTOPPED(status) && WSTOPSIG(status) == VKI_SIGSTOP &&
njn75b65aa2005-06-19 19:25:44 +0000155 ptrace_setregs(pid, &(VG_(threads)[tid].arch.vex)) == 0 &&
sewardj45f4e7c2005-09-27 19:20:21 +0000156 VG_(kill)(pid, VKI_SIGSTOP) == 0 &&
157 VG_(ptrace)(VKI_PTRACE_DETACH, pid, NULL, 0) == 0)
njn75b65aa2005-06-19 19:25:44 +0000158 {
159 Char pidbuf[15];
160 Char file[30];
161 Char buf[100];
162 Char *bufptr;
163 Char *cmdptr;
164
165 VG_(sprintf)(pidbuf, "%d", pid);
sewardj45f4e7c2005-09-27 19:20:21 +0000166 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(cl_exec_fd));
njn75b65aa2005-06-19 19:25:44 +0000167
168 bufptr = buf;
169 cmdptr = VG_(clo_db_command);
170
171 while (*cmdptr) {
172 switch (*cmdptr) {
173 case '%':
174 switch (*++cmdptr) {
175 case 'f':
176 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
177 bufptr += VG_(strlen)(file);
178 cmdptr++;
179 break;
180 case 'p':
181 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
182 bufptr += VG_(strlen)(pidbuf);
183 cmdptr++;
184 break;
185 default:
186 *bufptr++ = *cmdptr++;
187 break;
188 }
189 break;
190 default:
191 *bufptr++ = *cmdptr++;
192 break;
193 }
194 }
195
196 *bufptr++ = '\0';
197
198 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
199 res = VG_(system)(buf);
200 if (res == 0) {
201 VG_(message)(Vg_UserMsg, "");
202 VG_(message)(Vg_UserMsg,
203 "Debugger has detached. Valgrind regains control. We continue.");
204 } else {
205 VG_(message)(Vg_UserMsg, "Apparently failed!");
206 VG_(message)(Vg_UserMsg, "");
207 }
208 }
209
210 VG_(kill)(pid, VKI_SIGKILL);
211 VG_(waitpid)(pid, &status, 0);
212 }
213}
214
215
216
217/*--------------------------------------------------------------------*/
218/*--- end ---*/
219/*--------------------------------------------------------------------*/