trace.h revision 42748aca73359c83881556c8b28f6cda4f1c143b
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	struct 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_addrs[2];
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	/* Whether we need to use ugly workaround to get around
79	 * various problems with singlestepping.  */
80	enum callback_status (*ugly_workaround_p)
81		(struct process_stopping_handler *);
82
83	enum {
84		/* We are waiting for everyone to land in t/T.  */
85		psh_stopping = 0,
86
87		/* We are doing the PTRACE_SINGLESTEP.  */
88		psh_singlestep,
89
90		/* We are waiting for all the SIGSTOPs to arrive so
91		 * that we can sink them.  */
92		psh_sinking,
93
94		/* This is for tracking the ugly workaround.  */
95		psh_ugly_workaround,
96	} state;
97
98	int exiting;
99
100	struct pid_set pids;
101};
102
103/* Allocate a process stopping handler, initialize it and install it.
104 * Return 0 on success or a negative value on failure.  Pass NULL for
105 * each callback to use a default instead.  The default for
106 * ON_ALL_STOPPED is LINUX_PTRACE_DISABLE_AND_SINGLESTEP, the default
107 * for KEEP_STEPPING_P and UGLY_WORKAROUND_P is "no".  */
108int process_install_stopping_handler
109	(struct Process *proc, struct breakpoint *sbp,
110	 void (*on_all_stopped)(struct process_stopping_handler *),
111	 enum callback_status (*keep_stepping_p)
112		 (struct process_stopping_handler *),
113	 enum callback_status (*ugly_workaround_p)
114		(struct process_stopping_handler *));
115
116void linux_ptrace_disable_and_singlestep(struct process_stopping_handler *self);
117void linux_ptrace_disable_and_continue(struct process_stopping_handler *self);
118
119#endif /* _LTRACE_LINUX_TRACE_H_ */
120