trace.h revision 36f40e7d46838ec41ea03a2b9b748536d8fd57e2
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 * 02110-1301 USA 19 */ 20 21#ifndef _LTRACE_LINUX_TRACE_H_ 22#define _LTRACE_LINUX_TRACE_H_ 23 24/* This publishes some Linux-specific data structures used for process 25 * handling. */ 26 27/** 28 * This is used for bookkeeping related to PIDs that the event 29 * handlers work with. 30 */ 31struct pid_task { 32 pid_t pid; /* This may be 0 for tasks that exited 33 * mid-handling. */ 34 int sigstopped : 1; 35 int got_event : 1; 36 int delivered : 1; 37 int vforked : 1; 38 int sysret : 1; 39}; 40 41struct pid_set { 42 struct pid_task *tasks; 43 size_t count; 44 size_t alloc; 45}; 46 47/** 48 * Breakpoint re-enablement. When we hit a breakpoint, we must 49 * disable it, single-step, and re-enable it. That single-step can be 50 * done only by one task in a task group, while others are stopped, 51 * otherwise the processes would race for who sees the breakpoint 52 * disabled and who doesn't. The following is to keep track of it 53 * all. 54 */ 55struct process_stopping_handler 56{ 57 struct event_handler super; 58 59 /* The task that is doing the re-enablement. */ 60 Process *task_enabling_breakpoint; 61 62 /* The pointer being re-enabled. */ 63 struct breakpoint *breakpoint_being_enabled; 64 65 /* Artificial atomic skip breakpoint, if any needed. */ 66 void *atomic_skip_bp_addr; 67 68 /* When all tasks are stopped, this callback gets called. */ 69 void (*on_all_stopped)(struct process_stopping_handler *); 70 71 /* When we get a singlestep event, this is called to decide 72 * whether to stop stepping, or whether to enable the 73 * brakpoint, sink remaining signals, and continue 74 * everyone. */ 75 enum callback_status (*keep_stepping_p) 76 (struct process_stopping_handler *); 77 78 enum { 79 /* We are waiting for everyone to land in t/T. */ 80 psh_stopping = 0, 81 82 /* We are doing the PTRACE_SINGLESTEP. */ 83 psh_singlestep, 84 85 /* We are waiting for all the SIGSTOPs to arrive so 86 * that we can sink them. */ 87 psh_sinking, 88 89 /* This is for tracking the ugly workaround. */ 90 psh_ugly_workaround, 91 } state; 92 93 int exiting; 94 95 struct pid_set pids; 96}; 97 98/* Allocate a process stopping handler, initialize it and install it. 99 * Return 0 on success or a negative value on failure. Pass NULL for 100 * each callback to use a default instead. The default for 101 * ON_ALL_STOPPED is disable_and_singlestep, the default for 102 * KEEP_STEPPING_P is "no". */ 103int process_install_stopping_handler 104 (struct Process *proc, struct breakpoint *sbp, 105 void (*on_all_stopped)(struct process_stopping_handler *), 106 enum callback_status (*keep_stepping_p) 107 (struct process_stopping_handler *)); 108 109#endif /* _LTRACE_LINUX_TRACE_H_ */ 110