trace.h revision 929bd57ca202fd2f2e8485ebf65d683e664f67b5
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#include "proc.h" 25 26/* This publishes some Linux-specific data structures used for process 27 * handling. */ 28 29/** 30 * This is used for bookkeeping related to PIDs that the event 31 * handlers work with. 32 */ 33struct pid_task { 34 pid_t pid; /* This may be 0 for tasks that exited 35 * mid-handling. */ 36 int sigstopped : 1; 37 int got_event : 1; 38 int delivered : 1; 39 int vforked : 1; 40 int sysret : 1; 41}; 42 43struct pid_set { 44 struct pid_task *tasks; 45 size_t count; 46 size_t alloc; 47}; 48 49/** 50 * Breakpoint re-enablement. When we hit a breakpoint, we must 51 * disable it, single-step, and re-enable it. That single-step can be 52 * done only by one task in a task group, while others are stopped, 53 * otherwise the processes would race for who sees the breakpoint 54 * disabled and who doesn't. The following is to keep track of it 55 * all. 56 */ 57struct process_stopping_handler 58{ 59 struct event_handler super; 60 61 /* The task that is doing the re-enablement. */ 62 struct process *task_enabling_breakpoint; 63 64 /* The pointer being re-enabled. */ 65 struct breakpoint *breakpoint_being_enabled; 66 67 /* Artificial atomic skip breakpoint, if any needed. */ 68 void *atomic_skip_bp_addrs[2]; 69 70 /* When all tasks are stopped, this callback gets called. */ 71 void (*on_all_stopped)(struct process_stopping_handler *); 72 73 /* When we get a singlestep event, this is called to decide 74 * whether to stop stepping, or whether to enable the 75 * brakpoint, sink remaining signals, and continue 76 * everyone. */ 77 enum callback_status (*keep_stepping_p) 78 (struct process_stopping_handler *); 79 80 /* Whether we need to use ugly workaround to get around 81 * various problems with singlestepping. */ 82 enum callback_status (*ugly_workaround_p) 83 (struct process_stopping_handler *); 84 85 enum { 86 /* We are waiting for everyone to land in t/T. */ 87 psh_stopping = 0, 88 89 /* We are doing the PTRACE_SINGLESTEP. */ 90 psh_singlestep, 91 92 /* We are waiting for all the SIGSTOPs to arrive so 93 * that we can sink them. */ 94 psh_sinking, 95 96 /* This is for tracking the ugly workaround. */ 97 psh_ugly_workaround, 98 } state; 99 100 int exiting; 101 102 struct pid_set pids; 103}; 104 105/* Allocate a process stopping handler, initialize it and install it. 106 * Return 0 on success or a negative value on failure. Pass NULL for 107 * each callback to use a default instead. The default for 108 * ON_ALL_STOPPED is LINUX_PTRACE_DISABLE_AND_SINGLESTEP, the default 109 * for KEEP_STEPPING_P and UGLY_WORKAROUND_P is "no". */ 110int process_install_stopping_handler 111 (struct process *proc, struct breakpoint *sbp, 112 void (*on_all_stopped)(struct process_stopping_handler *), 113 enum callback_status (*keep_stepping_p) 114 (struct process_stopping_handler *), 115 enum callback_status (*ugly_workaround_p) 116 (struct process_stopping_handler *)); 117 118void linux_ptrace_disable_and_singlestep(struct process_stopping_handler *self); 119void linux_ptrace_disable_and_continue(struct process_stopping_handler *self); 120 121#endif /* _LTRACE_LINUX_TRACE_H_ */ 122