blob: 6b46355db0d29d1ba486be9c331a5fac2e007980 [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"
39#include "pub_core_options.h"
40
sewardj45f4e7c2005-09-27 19:20:21 +000041#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
42#define WSTOPSIG(status) (((status) & 0xff00) >> 8)
njn75b65aa2005-06-19 19:25:44 +000043
44static Int ptrace_setregs(Int pid, VexGuestArchState* vex)
45{
46 struct vki_user_regs_struct regs;
47#if defined(VGA_x86)
48 regs.cs = vex->guest_CS;
49 regs.ss = vex->guest_SS;
50 regs.ds = vex->guest_DS;
51 regs.es = vex->guest_ES;
52 regs.fs = vex->guest_FS;
53 regs.gs = vex->guest_GS;
54 regs.eax = vex->guest_EAX;
55 regs.ebx = vex->guest_EBX;
56 regs.ecx = vex->guest_ECX;
57 regs.edx = vex->guest_EDX;
58 regs.esi = vex->guest_ESI;
59 regs.edi = vex->guest_EDI;
60 regs.ebp = vex->guest_EBP;
61 regs.esp = vex->guest_ESP;
62 regs.eflags = LibVEX_GuestX86_get_eflags(vex);
63 regs.eip = vex->guest_EIP;
64
sewardj45f4e7c2005-09-27 19:20:21 +000065 return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, &regs);
njn75b65aa2005-06-19 19:25:44 +000066#elif defined(VGA_amd64)
tome4fed1c2005-07-19 18:19:48 +000067 regs.rax = vex->guest_RAX;
68 regs.rbx = vex->guest_RBX;
69 regs.rcx = vex->guest_RCX;
70 regs.rdx = vex->guest_RDX;
71 regs.rsi = vex->guest_RSI;
72 regs.rdi = vex->guest_RDI;
73 regs.rbp = vex->guest_RBP;
74 regs.rsp = vex->guest_RSP;
75 regs.r8 = vex->guest_R8;
76 regs.r9 = vex->guest_R9;
77 regs.r10 = vex->guest_R10;
78 regs.r11 = vex->guest_R11;
79 regs.r12 = vex->guest_R12;
80 regs.r13 = vex->guest_R13;
81 regs.r14 = vex->guest_R14;
82 regs.r15 = vex->guest_R15;
83 regs.eflags = LibVEX_GuestAMD64_get_rflags(vex);
84 regs.rip = vex->guest_RIP;
85
sewardj45f4e7c2005-09-27 19:20:21 +000086 return VG_(ptrace)(VKI_PTRACE_SETREGS, pid, NULL, &regs);
cerion85665ca2005-06-20 15:51:07 +000087#elif defined(VGA_ppc32)
88 I_die_here;
89 regs.gpr[0] = 0; // stop compiler complaints
njn75b65aa2005-06-19 19:25:44 +000090#else
91# error Unknown arch
92#endif
93}
94
95/* Start debugger and get it to attach to this process. Called if the
96 user requests this service after an error has been shown, so she can
97 poke around and look at parameters, memory, etc. You can't
98 meaningfully get the debugger to continue the program, though; to
99 continue, quit the debugger. */
100void VG_(start_debugger) ( ThreadId tid )
101{
sewardj45f4e7c2005-09-27 19:20:21 +0000102 Int pid;
njn75b65aa2005-06-19 19:25:44 +0000103
sewardj45f4e7c2005-09-27 19:20:21 +0000104 if ((pid = VG_(fork)()) == 0) {
105 VG_(ptrace)(VKI_PTRACE_TRACEME, 0, NULL, NULL);
njn75b65aa2005-06-19 19:25:44 +0000106 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
107
108 } else if (pid > 0) {
109 Int status;
110 Int res;
111
112 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
sewardj45f4e7c2005-09-27 19:20:21 +0000113 WIFSTOPPED(status) && WSTOPSIG(status) == VKI_SIGSTOP &&
njn75b65aa2005-06-19 19:25:44 +0000114 ptrace_setregs(pid, &(VG_(threads)[tid].arch.vex)) == 0 &&
sewardj45f4e7c2005-09-27 19:20:21 +0000115 VG_(kill)(pid, VKI_SIGSTOP) == 0 &&
116 VG_(ptrace)(VKI_PTRACE_DETACH, pid, NULL, 0) == 0)
njn75b65aa2005-06-19 19:25:44 +0000117 {
118 Char pidbuf[15];
119 Char file[30];
120 Char buf[100];
121 Char *bufptr;
122 Char *cmdptr;
123
124 VG_(sprintf)(pidbuf, "%d", pid);
sewardj45f4e7c2005-09-27 19:20:21 +0000125 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(cl_exec_fd));
njn75b65aa2005-06-19 19:25:44 +0000126
127 bufptr = buf;
128 cmdptr = VG_(clo_db_command);
129
130 while (*cmdptr) {
131 switch (*cmdptr) {
132 case '%':
133 switch (*++cmdptr) {
134 case 'f':
135 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
136 bufptr += VG_(strlen)(file);
137 cmdptr++;
138 break;
139 case 'p':
140 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
141 bufptr += VG_(strlen)(pidbuf);
142 cmdptr++;
143 break;
144 default:
145 *bufptr++ = *cmdptr++;
146 break;
147 }
148 break;
149 default:
150 *bufptr++ = *cmdptr++;
151 break;
152 }
153 }
154
155 *bufptr++ = '\0';
156
157 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
158 res = VG_(system)(buf);
159 if (res == 0) {
160 VG_(message)(Vg_UserMsg, "");
161 VG_(message)(Vg_UserMsg,
162 "Debugger has detached. Valgrind regains control. We continue.");
163 } else {
164 VG_(message)(Vg_UserMsg, "Apparently failed!");
165 VG_(message)(Vg_UserMsg, "");
166 }
167 }
168
169 VG_(kill)(pid, VKI_SIGKILL);
170 VG_(waitpid)(pid, &status, 0);
171 }
172}
173
174
175
176/*--------------------------------------------------------------------*/
177/*--- end ---*/
178/*--------------------------------------------------------------------*/