breakpoints.c revision 02a796e5e49c147982020c78b0066930e979f3e4
1/*
2 * This file is part of ltrace.
3 * Copyright (C) 2006,2007,2011,2012,2013 Petr Machata, Red Hat Inc.
4 * Copyright (C) 2009 Juan Cespedes
5 * Copyright (C) 1998,2001,2002,2003,2007,2008,2009 Juan Cespedes
6 * Copyright (C) 2006 Ian Wienand
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 */
23
24#include "config.h"
25
26#include <assert.h>
27#include <errno.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31
32#ifdef __powerpc__
33#include <sys/ptrace.h>
34#endif
35
36#include "backend.h"
37#include "breakpoint.h"
38#include "debug.h"
39#include "library.h"
40#include "ltrace-elf.h"
41#include "proc.h"
42
43#ifndef ARCH_HAVE_TRANSLATE_ADDRESS
44int
45arch_translate_address_dyn(struct process *proc,
46		       arch_addr_t addr, arch_addr_t *ret)
47{
48	*ret = addr;
49	return 0;
50}
51
52struct ltelf;
53int
54arch_translate_address(struct ltelf *lte,
55		       arch_addr_t addr, arch_addr_t *ret)
56{
57	*ret = addr;
58	return 0;
59}
60#endif
61
62void
63breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
64{
65	assert(bp != NULL);
66	if (bp->cbs != NULL && bp->cbs->on_hit != NULL)
67		(bp->cbs->on_hit)(bp, proc);
68}
69
70void
71breakpoint_on_continue(struct breakpoint *bp, struct process *proc)
72{
73	assert(bp != NULL);
74	if (bp->cbs != NULL && bp->cbs->on_continue != NULL)
75		(bp->cbs->on_continue)(bp, proc);
76	else
77		continue_after_breakpoint(proc, bp);
78}
79
80void
81breakpoint_on_retract(struct breakpoint *bp, struct process *proc)
82{
83	assert(bp != NULL);
84	if (bp->cbs != NULL && bp->cbs->on_retract != NULL)
85		(bp->cbs->on_retract)(bp, proc);
86}
87
88/*****************************************************************************/
89
90struct breakpoint *
91address2bpstruct(struct process *proc, arch_addr_t addr)
92{
93	assert(proc != NULL);
94	assert(proc->breakpoints != NULL);
95	assert(proc->leader == proc);
96	debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
97
98	struct breakpoint *found;
99	if (DICT_FIND_VAL(proc->breakpoints, &addr, &found) < 0)
100		return NULL;
101	return found;
102}
103
104#ifndef ARCH_HAVE_BREAKPOINT_DATA
105int
106arch_breakpoint_init(struct process *proc, struct breakpoint *sbp)
107{
108	return 0;
109}
110
111void
112arch_breakpoint_destroy(struct breakpoint *sbp)
113{
114}
115
116int
117arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
118{
119	return 0;
120}
121#endif
122
123static void
124breakpoint_init_base(struct breakpoint *bp,
125		     arch_addr_t addr, struct library_symbol *libsym)
126{
127	bp->cbs = NULL;
128	bp->addr = addr;
129	memset(bp->orig_value, 0, sizeof(bp->orig_value));
130	bp->enabled = 0;
131	bp->libsym = libsym;
132}
133
134/* On second thought, I don't think we need PROC.  All the translation
135 * (arch_translate_address in particular) should be doable using
136 * static lookups of various sections in the ELF file.  We shouldn't
137 * need process for anything.  */
138int
139breakpoint_init(struct breakpoint *bp, struct process *proc,
140		arch_addr_t addr, struct library_symbol *libsym)
141{
142	breakpoint_init_base(bp, addr, libsym);
143	return arch_breakpoint_init(proc, bp);
144}
145
146void
147breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs)
148{
149	if (bp->cbs != NULL)
150		assert(bp->cbs == NULL);
151	bp->cbs = cbs;
152}
153
154void
155breakpoint_destroy(struct breakpoint *bp)
156{
157	if (bp == NULL)
158		return;
159	arch_breakpoint_destroy(bp);
160}
161
162int
163breakpoint_clone(struct breakpoint *retp, struct process *new_proc,
164		 struct breakpoint *bp)
165{
166	struct library_symbol *libsym = NULL;
167	if (bp->libsym != NULL) {
168		int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym);
169		assert(rc == 0);
170	}
171
172	breakpoint_init_base(retp, bp->addr, libsym);
173	memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value));
174	retp->enabled = bp->enabled;
175	if (arch_breakpoint_clone(retp, bp) < 0)
176		return -1;
177	breakpoint_set_callbacks(retp, bp->cbs);
178	return 0;
179}
180
181int
182breakpoint_turn_on(struct breakpoint *bp, struct process *proc)
183{
184	bp->enabled++;
185	if (bp->enabled == 1) {
186		assert(proc->pid != 0);
187		enable_breakpoint(proc, bp);
188	}
189	return 0;
190}
191
192int
193breakpoint_turn_off(struct breakpoint *bp, struct process *proc)
194{
195	bp->enabled--;
196	if (bp->enabled == 0)
197		disable_breakpoint(proc, bp);
198	assert(bp->enabled >= 0);
199	return 0;
200}
201
202struct breakpoint *
203insert_breakpoint_at(struct process *proc, arch_addr_t addr,
204		     struct library_symbol *libsym)
205{
206	struct process *leader = proc->leader;
207
208	/* Only the group leader should be getting the breakpoints and
209	 * thus have ->breakpoint initialized.  */
210	assert(leader != NULL);
211	assert(leader->breakpoints != NULL);
212
213	debug(DEBUG_FUNCTION,
214	      "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)",
215	      proc->pid, addr, libsym ? libsym->name : "NULL");
216
217	assert(addr != 0);
218
219	/* We first create the breakpoint to find out what it's real
220	 * address is.  This makes a difference on ARM.
221	 *
222	 * XXX The real problem here is that to create a return
223	 * breakpoint ltrace calls get_return_addr and then
224	 * insert_breakpoint_at.  So get_return_addr needs to encode
225	 * all the information necessary for breakpoint_init into the
226	 * address itself, so ADDR is potentially mangled.  We filter
227	 * the noise out by first creating the breakpoint on stack,
228	 * and then looking at the address of the created breakpoint.
229	 * Replacing get_return_addr with get_return_breakpoint might
230	 * be a better solution.  */
231	struct breakpoint bp;
232	if (breakpoint_init(&bp, proc, addr, libsym) < 0)
233		return NULL;
234
235	/* XXX what we need to do instead is have a list of
236	 * breakpoints that are enabled at this address.  The
237	 * following works if every breakpoint is the same and there's
238	 * no extra data, but that doesn't hold anymore.  For now it
239	 * will suffice, about the only realistic case where we need
240	 * to have more than one breakpoint per address is return from
241	 * a recursive library call.  */
242	struct breakpoint *sbp;
243	if (DICT_FIND_VAL(leader->breakpoints, &bp.addr, &sbp) >= 0) {
244		breakpoint_destroy(&bp);
245	} else {
246		sbp = malloc(sizeof(*sbp));
247		if (sbp == NULL
248		    || breakpoint_init(sbp, proc, addr, libsym) < 0) {
249			free(sbp);
250			return NULL;
251		}
252		if (proc_add_breakpoint(leader, sbp) < 0) {
253		fail:
254			free(sbp);
255			breakpoint_destroy(&bp);
256			return NULL;
257		}
258		memcpy(sbp, &bp, sizeof(*sbp));
259	}
260
261	if (breakpoint_turn_on(sbp, proc) < 0) {
262		proc_remove_breakpoint(leader, sbp);
263		goto fail;
264	}
265
266	return sbp;
267}
268
269void
270delete_breakpoint(struct process *proc, arch_addr_t addr)
271{
272	debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr);
273
274	struct process *leader = proc->leader;
275	assert(leader != NULL);
276
277	struct breakpoint *sbp = NULL;
278	DICT_FIND_VAL(leader->breakpoints, &addr, &sbp);
279	assert(sbp != NULL);
280
281	if (breakpoint_turn_off(sbp, proc) < 0) {
282		fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n",
283			breakpoint_name(sbp), sbp->addr);
284		return;
285	}
286	if (sbp->enabled == 0) {
287		proc_remove_breakpoint(leader, sbp);
288		breakpoint_destroy(sbp);
289		free(sbp);
290	}
291}
292
293const char *
294breakpoint_name(const struct breakpoint *bp)
295{
296	assert(bp != NULL);
297	return bp->libsym != NULL ? bp->libsym->name : NULL;
298}
299
300struct library *
301breakpoint_library(const struct breakpoint *bp)
302{
303	assert(bp != NULL);
304	return bp->libsym != NULL ? bp->libsym->lib : NULL;
305}
306
307static enum callback_status
308enable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
309{
310	struct process *proc = data;
311	debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", proc->pid);
312	if ((*bpp)->enabled)
313		enable_breakpoint(proc, *bpp);
314	return CBS_CONT;
315}
316
317void
318enable_all_breakpoints(struct process *proc)
319{
320	debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid);
321
322	debug(1, "Enabling breakpoints for pid %u...", proc->pid);
323	if (proc->breakpoints != NULL)
324		DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
325			  NULL, enable_bp_cb, proc);
326}
327
328static enum callback_status
329disable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
330{
331	struct process *proc = data;
332	debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", proc->pid);
333	if ((*bpp)->enabled)
334		disable_breakpoint(proc, *bpp);
335	return CBS_CONT;
336}
337
338void
339disable_all_breakpoints(struct process *proc)
340{
341	debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
342	assert(proc->leader == proc);
343	DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
344		  NULL, disable_bp_cb, proc);
345}
346
347static void
348entry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
349{
350	if (proc == NULL || proc->leader == NULL)
351		return;
352	delete_breakpoint(proc, bp->addr);
353	process_hit_start(proc);
354}
355
356int
357entry_breakpoint_init(struct process *proc,
358		      struct breakpoint *bp, arch_addr_t addr,
359		      struct library *lib)
360{
361	assert(addr != 0);
362	int err = breakpoint_init(bp, proc, addr, NULL);
363	if (err < 0)
364		return err;
365
366	static struct bp_callbacks entry_callbacks = {
367		.on_hit = entry_breakpoint_on_hit,
368	};
369	bp->cbs = &entry_callbacks;
370	return 0;
371}
372
373int
374breakpoints_init(struct process *proc)
375{
376	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
377
378	/* XXX breakpoint dictionary should be initialized
379	 * outside.  Here we just put in breakpoints.  */
380	assert(proc->breakpoints != NULL);
381
382	/* Only the thread group leader should hold the breakpoints.  */
383	assert(proc->leader == proc);
384
385	/* N.B. the following used to be conditional on this, and
386	 * maybe it still needs to be.  */
387	assert(proc->filename != NULL);
388
389	struct library *lib = ltelf_read_main_binary(proc, proc->filename);
390	struct breakpoint *entry_bp = NULL;
391	int bp_state = 0;
392	int result = -1;
393	switch ((int)(lib != NULL)) {
394	fail:
395		switch (bp_state) {
396		case 2:
397			proc_remove_library(proc, lib);
398			proc_remove_breakpoint(proc, entry_bp);
399		case 1:
400			breakpoint_destroy(entry_bp);
401		}
402		library_destroy(lib);
403		free(entry_bp);
404	case 0:
405		return result;
406	}
407
408	entry_bp = malloc(sizeof(*entry_bp));
409	if (entry_bp == NULL
410	    || (entry_breakpoint_init(proc, entry_bp,
411				      lib->entry, lib)) < 0) {
412		fprintf(stderr,
413			"Couldn't initialize entry breakpoint for PID %d.\n"
414			"Some tracing events may be missed.\n", proc->pid);
415		free(entry_bp);
416
417	} else {
418		++bp_state;
419
420		if ((result = proc_add_breakpoint(proc, entry_bp)) < 0)
421			goto fail;
422		++bp_state;
423
424		if ((result = breakpoint_turn_on(entry_bp, proc)) < 0)
425			goto fail;
426	}
427	proc_add_library(proc, lib);
428
429	proc->callstack_depth = 0;
430	return 0;
431}
432