drd/tests/swapcontext: Improve the portability of this test further
[valgrind.git] / coregrind / vgdb-invoker-solaris.c
blobac95bdb85c510af26775a961048ace0f827c1f5c
1 /*--------------------------------------------------------------------*/
2 /*--- Implementation of vgdb invoker subsystem on Solaris */
3 /* via /proc filesystem and control messages. ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2014-2017 Ivo Raisr <ivosh@ivosh.net>
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, see <http://www.gnu.org/licenses/>.
25 The GNU General Public License is contained in the file COPYING.
28 /* This module implements vgdb-invoker subsystem as per vgdb.h
29 on Solaris. It differs significantly from the other ptrace-based
30 implementation found in vgdb-invoker-ptrace.c. However the goal
31 is the same - to work on the following scenario:
33 - A valgrind process (referred to also as an inferior process)
34 is remotely debugged with gdb.
35 - All threads of the inferior process are stuck in blocking
36 syscalls.
37 - Therefore no thread can process packets received from gdb.
39 When module vgdb.c detects this situation then it calls
40 function invoker_invoke_gdbserver() within the context of
41 invoke_gdbserver_in_valgrind_thread thread. The steps of
42 interaction between vgdb and m_gdbserver module are as follows:
44 1. Function invoker_invoke_gdbserver() attaches to the inferior
45 process and stops all threads.
46 2. It gets registers of the first thread and modifies them
47 and the stack so that a call to "invoke_gdbserver" function
48 is arranged along with a function parameter.
49 3. Then it creates an agent thread within the inferior process
50 with these modified registers and waits until the agent thread
51 exits.
52 4. Meanwhile in the inferior process function
53 VG_(invoke_gdbserver)() is invoked within the context of the
54 agent thread; all other threads are still stopped.
55 5. The agent thread processes packets from gdb relayed by vgdb.
56 6. Eventually processing is finished and the agent thread exits
57 in function give_control_back_to_vgdb().
58 7. vgdb then detaches from the inferior process and thus resumes
59 all the stopped threads.
62 #include "vgdb.h"
64 #include <assert.h>
65 #include <errno.h>
66 #include <string.h>
68 typedef Addr CORE_ADDR;
70 typedef struct {
71 long cmd;
72 union {
73 long flags;
74 prgregset_t regs;
75 } arg;
76 } ctl_t;
78 /* Process control file /proc/<pid>/ctl.
79 Once this file is closed, PR_RLC flag takes effect and
80 inferior process resumes automatically. */
81 static int ctl_fd = -1;
83 /* Copy LEN bytes of data from vgdb memory at MYADDR
84 to valgrind memory at MEMADDR.
85 On failure (cannot write the valgrind memory)
86 returns the value of errno. */
87 static int write_memory(pid_t pid, CORE_ADDR memaddr,
88 const void *myaddr, size_t len)
90 char procname[PATH_MAX];
91 snprintf(procname, sizeof(procname), "/proc/%d/as", pid);
93 /* Open the process address-space file. */
94 int as_fd = open(procname, O_WRONLY, 0);
95 if (as_fd < 0) {
96 int error = errno;
97 ERROR(error, "Failed to open %s.\n", procname);
98 return error;
101 if (debuglevel >= 1) {
102 DEBUG(1, "Writing bytes '");
103 size_t i;
104 for (i = 0; i < len; i++)
105 PDEBUG(1, "%02x", ((const unsigned char *) myaddr)[i]);
106 PDEBUG(1, "' to address %#lx.\n", memaddr);
109 ssize_t written = pwrite(as_fd, myaddr, len, memaddr);
110 if ((written < 0) || (written != len)) {
111 int error = errno;
112 ERROR(error, "Failed to write to file %s, memory block of %zu"
113 " bytes at %#lx to %#lx.\n",
114 procname, len, (Addr) myaddr, memaddr);
115 close(as_fd);
116 return error;
119 DEBUG(1, "Written ok.\n");
120 close(as_fd);
121 return 0;
124 /* Attaches to a process identified by pid and stops all threads. */
125 static Bool attach(pid_t pid)
127 char procname[PATH_MAX];
128 snprintf(procname, sizeof(procname), "/proc/%d/ctl", pid);
130 DEBUG(1, "Attaching to pid %d.\n", pid);
132 /* Open the process control file. */
133 ctl_fd = open(procname, O_WRONLY, 0);
134 if (ctl_fd < 0) {
135 ERROR(errno, "Failed to open %s.\n", procname);
136 return False;
139 DEBUG(1, "Setting run-on-last-close-flag (PR_RLC) to pid %d.\n", pid);
141 /* Set run-on-last-close flag. */
142 ctl_t ctl;
143 ctl.cmd = PCSET;
144 ctl.arg.flags = PR_RLC;
145 size_t bytes = sizeof(ctl.cmd) + sizeof(ctl.arg.flags);
146 ssize_t written = write(ctl_fd, (void *) &ctl, bytes);
147 if ((written < 0) || (written != bytes)) {
148 ERROR(errno, "Failed to write to ctl_fd: PCSET + PR_RLC.\n");
149 return False;
152 DEBUG(1, "Stopping process %d.\n", pid);
154 /* Stop the whole process - all threads. */
155 ctl.cmd = PCSTOP;
156 bytes = sizeof(ctl.cmd);
157 written = write(ctl_fd, (void *) &ctl, bytes);
158 if ((written < 0) || (written != bytes)) {
159 ERROR(errno, "Failed to write to ctl_fd: PCSTOP.\n");
160 return False;
163 DEBUG(1, "Process %d stopped.\n", pid);
165 /* Now confirm it is actually the case. */
166 snprintf(procname, sizeof(procname), "/proc/%d/status", pid);
167 int status_fd = open(procname, O_RDONLY, 0);
168 if (status_fd < 0) {
169 ERROR(errno, "Failed to open %s.\n", procname);
170 return False;
173 pstatus_t pstatus;
174 ssize_t nread = read(status_fd, &pstatus, sizeof(pstatus));
175 if ((nread < 0) || (nread != sizeof(pstatus))) {
176 ERROR(errno, "Failed to read from %s.\n", procname);
177 close(status_fd);
178 return False;
181 if (pstatus.pr_flags & PR_RLC) {
182 DEBUG(2, "Process %d has run-on-last-close flag set. Good.\n", pid);
183 } else {
184 ERROR(0, "Process %d does not have run-on-last-close flag set!\n", pid);
185 close(status_fd);
186 return False;
189 if (pstatus.pr_lwp.pr_flags & PR_STOPPED) {
190 DEBUG(3, "Process %d seems to be stopped. Good.\n", pid);
191 } else {
192 ERROR(0, "Process %d is not stopped!\n", pid);
193 close(status_fd);
194 return False;
197 close(status_fd);
198 return True;
201 static void detach(pid_t pid)
203 if (ctl_fd != -1) {
204 close(ctl_fd);
205 ctl_fd = -1;
208 DEBUG(1, "Detached from pid %d.\n", pid);
211 /* Gets the registers of the first thread. */
212 static Bool get_regs(pid_t pid, prgregset_t *regs)
214 char procname[PATH_MAX];
215 snprintf(procname, sizeof(procname), "/proc/%d/lwp/1/lwpstatus", pid);
217 DEBUG(1, "Getting registers from the first thread of process %d.\n", pid);
219 /* Open the first thread's status file. */
220 int status_fd = open(procname, O_RDONLY, 0);
221 if (status_fd < 0) {
222 ERROR(errno, "Failed to open file %s.\n", procname);
223 return False;
226 lwpstatus_t status;
227 ssize_t bytes = read(status_fd, &status, sizeof(status));
228 if ((bytes < 0) || (bytes != sizeof(status))) {
229 ERROR(errno, "Failed to read from %s.\n", procname);
230 close(status_fd);
231 return False;
234 DEBUG(3, "Registers of thread %d from process %d: ", status.pr_lwpid, pid);
235 unsigned int i;
236 for (i = 0; i < _NGREG; i++) {
237 PDEBUG(3, "%u: %#lx, ", i, (unsigned long) status.pr_reg[i]);
239 PDEBUG(3, "\n");
241 memcpy(regs, &status.pr_reg, sizeof(prgregset_t));
242 close(status_fd);
243 return True;
246 /* Modifies the register set so that a new stack frame is created
247 for "invoke_gdbserver" function with an extra argument.
248 The argument is written to the stack of the first thread.
250 static Bool setup_stack_frame(pid_t pid, prgregset_t *regs)
252 DEBUG(1, "Setting up new stack frame of process %d.\n", pid);
254 /* A specific int value is passed to invoke_gdbserver(), to check
255 everything goes according to the plan. */
256 const int check = 0x8BADF00D; // ate bad food.
258 /* A bad return address will be pushed on the stack.
259 Function invoke_gdbserver() cannot return. If it ever returns,
260 a NULL address pushed on the stack should ensure this is
261 detected. */
262 const Addr bad_return = 0;
264 #if defined(VGA_x86)
265 Addr sp = (*regs)[UESP];
266 #elif defined(VGA_amd64)
267 Addr sp = (*regs)[REG_RSP];
268 #else
269 I_die_here : (sp) architecture missing in vgdb-invoker-solaris.c
270 #endif
272 if (shared32 != NULL) {
273 /* vgdb speaking with a 32bit executable. */
274 #if defined(VGA_x86) || defined(VGA_amd64)
275 const size_t regsize = 4;
277 /* Push check argument on the stack - according to C/ia32 ABI. */
278 sp = sp - regsize;
279 DEBUG(1, "Pushing check argument to process %d memory.\n", pid);
280 assert(regsize == sizeof(check));
281 int error = write_memory(pid, sp, &check, regsize);
282 if (error != 0) {
283 ERROR(error, "Failed to push check argument to process %d memory.\n",
284 pid);
285 detach(pid);
286 return False;
289 sp = sp - regsize;
290 DEBUG(1, "Pushing bad_return return address to process %d memory.\n",
291 pid);
292 /* Note that even for a 64 bits vgdb, only 4 bytes
293 of NULL bad_return are written. */
294 error = write_memory(pid, sp, &bad_return, regsize);
295 if (error != 0) {
296 ERROR(error, "Failed to push bad_return return address to process %d "
297 "memory.\n", pid);
298 detach(pid);
299 return False;
302 #if defined(VGA_x86)
303 /* Set EBP, ESP, EIP to invoke gdbserver.
304 vgdb is 32bits, speaking with a 32bits process. */
305 (*regs)[EBP] = sp; // bp set to sp
306 (*regs)[UESP] = sp;
307 (*regs)[EIP] = shared32->invoke_gdbserver;
308 #elif defined(VGA_amd64)
309 /* Set RBP, RSP, RIP to invoke gdbserver.
310 vgdb is 64bits, speaking with a 32bits process. */
311 (*regs)[REG_RBP] = sp; // bp set to sp
312 (*regs)[REG_RSP] = sp;
313 (*regs)[REG_RIP] = shared32->invoke_gdbserver;
314 #else
315 I_die_here : not x86 or amd64 in x86/amd64 section/
316 #endif
318 #else
319 I_die_here : architecture missing in vgdb-invoker-solaris.c
320 #endif
322 } else if (shared64 != NULL) {
323 #if defined(VGA_x86)
324 assert(0); /* 64bits process with a 32bits vgdb - no way */
325 #elif defined(VGA_amd64)
326 /* 64bits vgdb speaking with a 64 bit process. */
327 const int regsize = 8;
329 /* Give check argument in rdi - according to C/amd64 ABI. */
330 (*regs)[REG_RDI] = check;
332 /* Push return address on stack: return to breakaddr. */
333 sp = sp - regsize;
334 DEBUG(1, "Pushing bad_return return address to process %d memory.\n",
335 pid);
336 int error = write_memory(pid, sp, &bad_return,
337 sizeof(bad_return));
338 if (error != 0) {
339 ERROR(error, "Failed to push bad_return return address to process %d "
340 "memory.\n", pid);
341 detach(pid);
342 return False;
345 /* set RBP, RSP, RIP to invoke gdbserver */
346 (*regs)[REG_RBP] = sp; // bp set to sp
347 (*regs)[REG_RSP] = sp;
348 (*regs)[REG_RIP] = shared64->invoke_gdbserver;
349 #else
350 I_die_here: architecture missing in vgdb-invoker-solaris.c
351 #endif
352 } else {
353 assert(0);
356 DEBUG(1, "New stack frame set up for process %d.\n", pid);
357 return True;
360 /* Creates and starts an agent thread within the inferior process.
361 The agent thread is created stopped and with its held signal set
362 (the signal mask) having all signals except SIGKILL and SIGSTOP
363 blocked. All these signals need to remain blocked while the agent
364 thread is running because valgrind syscall/signal machinery expects
365 that (remember: all valgrind threads are blocked in VgTs_WaitSys
366 - that is the reason why we are invoking the agent, after all).
367 It is necessary to resume the agent thread afterwards.
369 static Bool invoke_agent(pid_t pid, prgregset_t *regs, id_t *agent_lwpid)
371 assert(ctl_fd != -1);
373 DEBUG(1, "Creating an agent thread within process %d.\n", pid);
375 /* Create the agent thread. */
376 ctl_t ctl;
377 ctl.cmd = PCAGENT;
378 memcpy(&ctl.arg.regs, regs, sizeof(prgregset_t));
379 size_t bytes = sizeof(ctl.cmd) + sizeof(ctl.arg.regs);
380 ssize_t written = write(ctl_fd, (void *) &ctl, bytes);
381 if ((written < 0) || (written != bytes)) {
382 ERROR(errno, "Failed to write to ctl_fd: PCAGENT.\n");
383 return False;
386 DEBUG(1, "Obtaining agent thread lwpid for process %d.\n", pid);
388 char procname[PATH_MAX];
389 snprintf(procname, sizeof(procname),
390 "/proc/%d/lwp/agent/lwpstatus", pid);
392 int status_fd = open(procname, O_RDONLY, 0);
393 if (status_fd < 0) {
394 /* Operation failed but there is no way to get rid of the agent
395 thread from outside. We are doomed... */
396 ERROR(errno, "Failed to open file %s.\n", procname);
397 return False;
400 lwpstatus_t status;
401 ssize_t nread = read(status_fd, &status, sizeof(status));
402 if ((nread < 0) || (nread != sizeof(status))) {
403 ERROR(errno, "Failed to read from %s.\n", procname);
404 close(status_fd);
405 return False;
408 close(status_fd);
409 *agent_lwpid = status.pr_lwpid;
411 snprintf(procname, sizeof(procname),
412 "/proc/%d/lwp/agent/lwpctl", pid);
414 int agent_ctl_fd = open(procname, O_WRONLY, 0);
415 if (agent_ctl_fd < 0) {
416 /* Resuming failed but there is no way to get rid of the agent
417 thread from outside. We are doomed... */
418 ERROR(errno, "Failed to open file %s.\n", procname);
419 return False;
422 DEBUG(1, "Resuming the agent thread for process %d.\n", pid);
424 /* Resume the agent thread. */
425 ctl.cmd = PCRUN;
426 ctl.arg.flags = 0;
427 bytes = sizeof(ctl.cmd) + sizeof(ctl.arg.flags);
428 written = write(agent_ctl_fd, (void *) &ctl, bytes);
429 if ((written < 0) || (written != bytes)) {
430 /* Resuming failed but there is no way to get rid of the agent
431 thread from outside. We are doomed... */
432 ERROR(errno, "Failed to write to agent_ctl_fd: PCRUN 0.\n");
433 close(agent_ctl_fd);
434 return False;
437 DEBUG(1, "Agent thread lwpid %d now running within process %d.\n",
438 *agent_lwpid, pid);
439 close(agent_ctl_fd);
440 return True;
443 /* Waits until the agent thread running inside the inferior
444 process exits. */
445 static Bool wait_for_agent_exit(pid_t pid, id_t agent_lwpid)
447 char procname[PATH_MAX];
448 snprintf(procname, sizeof(procname), "/proc/%d/lwp/agent/lwpctl", pid);
450 int agent_ctl_fd = open(procname, O_WRONLY, 0);
451 if (agent_ctl_fd < 0) {
452 if (errno == ENOENT) {
453 DEBUG(1, "Agent control file %s no longer exists. This means "
454 "agent thread %d exited meanwhile.\n",
455 procname, agent_lwpid);
456 return True;
458 ERROR(errno, "Failed to open agent control file %s.\n", procname);
459 return False;
462 DEBUG(1, "Waiting for agent thread %d to exit.\n", agent_lwpid);
464 /* Wait until the agent thread stops. This covers also the case
465 when the thread exited. */
466 ctl_t ctl;
467 ctl.cmd = PCWSTOP;
468 size_t bytes = sizeof(ctl.cmd);
469 ssize_t written = write(agent_ctl_fd, (void *) &ctl, bytes);
470 if ((written < 0) || (written != bytes)) {
471 if (errno == ENOENT) {
472 DEBUG(1, "Agent thread lwpid %d has now exited in process %d.\n",
473 agent_lwpid, pid);
474 } else {
475 ERROR(errno, "Failed to write to agent_ctl_fd: PCWSTOP.\n");
476 close(agent_ctl_fd);
477 return False;
481 close(agent_ctl_fd);
482 return True;
485 Bool invoker_invoke_gdbserver(pid_t pid)
487 if (attach(pid) != True) {
488 return False;
491 prgregset_t regs;
492 if (get_regs(pid, &regs) != True) {
493 detach(pid);
494 return False;
497 if (setup_stack_frame(pid, &regs) != True) {
498 detach(pid);
499 return False;
502 id_t agent_lwpid;
503 if (invoke_agent(pid, &regs, &agent_lwpid) != True) {
504 detach(pid);
505 return False;
508 if (wait_for_agent_exit(pid, agent_lwpid) != True) {
509 detach(pid);
510 return False;
513 detach(pid);
514 return True;
517 void invoker_cleanup_restore_and_detach(void *v_pid)
519 detach(*(int *) v_pid);
522 void invoker_restrictions_msg(void)
526 void invoker_valgrind_dying(void)