breakpoints.c revision 9f819d5747dc2b8e0f7ac54b38dc321115de6dda
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 OS_HAVE_BREAKPOINT_DATA
105int
106os_breakpoint_init(struct process *proc, struct breakpoint *sbp)
107{
108	return 0;
109}
110
111void
112os_breakpoint_destroy(struct breakpoint *sbp)
113{
114}
115
116int
117os_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
118{
119	return 0;
120}
121#endif
122
123#ifndef ARCH_HAVE_BREAKPOINT_DATA
124int
125arch_breakpoint_init(struct process *proc, struct breakpoint *sbp)
126{
127	return 0;
128}
129
130void
131arch_breakpoint_destroy(struct breakpoint *sbp)
132{
133}
134
135int
136arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
137{
138	return 0;
139}
140#endif
141
142static void
143breakpoint_init_base(struct breakpoint *bp,
144		     arch_addr_t addr, struct library_symbol *libsym)
145{
146	bp->cbs = NULL;
147	bp->addr = addr;
148	memset(bp->orig_value, 0, sizeof(bp->orig_value));
149	bp->enabled = 0;
150	bp->libsym = libsym;
151}
152
153/* On second thought, I don't think we need PROC.  All the translation
154 * (arch_translate_address in particular) should be doable using
155 * static lookups of various sections in the ELF file.  We shouldn't
156 * need process for anything.  */
157int
158breakpoint_init(struct breakpoint *bp, struct process *proc,
159		arch_addr_t addr, struct library_symbol *libsym)
160{
161	breakpoint_init_base(bp, addr, libsym);
162	if (os_breakpoint_init(proc, bp) < 0)
163		return -1;
164	if (arch_breakpoint_init(proc, bp) < 0) {
165		os_breakpoint_destroy(bp);
166		return -1;
167	}
168	return 0;
169}
170
171void
172breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs)
173{
174	if (bp->cbs != NULL)
175		assert(bp->cbs == NULL);
176	bp->cbs = cbs;
177}
178
179void
180breakpoint_destroy(struct breakpoint *bp)
181{
182	if (bp == NULL)
183		return;
184	arch_breakpoint_destroy(bp);
185	os_breakpoint_destroy(bp);
186}
187
188int
189breakpoint_clone(struct breakpoint *retp, struct process *new_proc,
190		 struct breakpoint *bp)
191{
192	struct library_symbol *libsym = NULL;
193	if (bp->libsym != NULL) {
194		int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym);
195		assert(rc == 0);
196	}
197
198	breakpoint_init_base(retp, bp->addr, libsym);
199	memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value));
200	retp->enabled = bp->enabled;
201	if (os_breakpoint_clone(retp, bp) < 0)
202		return -1;
203	if (arch_breakpoint_clone(retp, bp) < 0) {
204		os_breakpoint_destroy(retp);
205		return -1;
206	}
207	breakpoint_set_callbacks(retp, bp->cbs);
208	return 0;
209}
210
211int
212breakpoint_turn_on(struct breakpoint *bp, struct process *proc)
213{
214	bp->enabled++;
215	if (bp->enabled == 1) {
216		assert(proc->pid != 0);
217		enable_breakpoint(proc, bp);
218	}
219	return 0;
220}
221
222int
223breakpoint_turn_off(struct breakpoint *bp, struct process *proc)
224{
225	bp->enabled--;
226	if (bp->enabled == 0)
227		disable_breakpoint(proc, bp);
228	assert(bp->enabled >= 0);
229	return 0;
230}
231
232struct breakpoint *
233insert_breakpoint_at(struct process *proc, arch_addr_t addr,
234		     struct library_symbol *libsym)
235{
236	debug(DEBUG_FUNCTION,
237	      "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)",
238	      proc->pid, addr, libsym ? libsym->name : "NULL");
239
240	assert(addr != 0);
241
242	struct breakpoint *bp = malloc(sizeof *bp);
243	if (bp == NULL || breakpoint_init(bp, proc, addr, libsym) < 0) {
244		free(bp);
245		return NULL;
246	}
247
248	/* N.B. (and XXX): BP->addr might differ from ADDR.  On ARM
249	 * this is a real possibility.  The problem here is that to
250	 * create a return breakpoint ltrace calls get_return_addr and
251	 * then insert_breakpoint_at.  So get_return_addr needs to
252	 * encode all the information necessary for breakpoint_init
253	 * into the address itself, so ADDR is potentially
254	 * mangled.  */
255
256	struct breakpoint *tmp = insert_breakpoint(proc, bp);
257	if (tmp != bp) {
258		breakpoint_destroy(bp);
259		free(bp);
260	}
261	return tmp;
262}
263
264struct breakpoint *
265insert_breakpoint(struct process *proc, struct breakpoint *bp)
266{
267	/* Only the group leader should be getting the breakpoints and
268	 * thus have ->breakpoint initialized.  */
269	struct process *leader = proc->leader;
270	assert(leader != NULL);
271	assert(leader->breakpoints != NULL);
272
273	/* XXX what we need to do instead is have a list of
274	 * breakpoints that are enabled at this address.  The
275	 * following works if every breakpoint is the same and there's
276	 * no extra data, but that doesn't hold anymore.  For now it
277	 * will suffice, about the only realistic case where we need
278	 * to have more than one breakpoint per address is return from
279	 * a recursive library call.  */
280	struct breakpoint *ext_bp = bp;
281	if (DICT_FIND_VAL(leader->breakpoints, &bp->addr, &ext_bp) != 0) {
282		if (proc_add_breakpoint(leader, bp) < 0)
283			return NULL;
284		ext_bp = bp;
285	}
286
287	if (breakpoint_turn_on(ext_bp, proc) < 0) {
288		if (ext_bp != bp)
289			proc_remove_breakpoint(leader, bp);
290		return NULL;
291	}
292
293	return ext_bp;
294}
295
296void
297delete_breakpoint(struct process *proc, arch_addr_t addr)
298{
299	debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr);
300
301	struct process *leader = proc->leader;
302	assert(leader != NULL);
303
304	struct breakpoint *sbp = NULL;
305	DICT_FIND_VAL(leader->breakpoints, &addr, &sbp);
306	assert(sbp != NULL);
307
308	if (breakpoint_turn_off(sbp, proc) < 0) {
309		fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n",
310			breakpoint_name(sbp), sbp->addr);
311		return;
312	}
313	if (sbp->enabled == 0) {
314		proc_remove_breakpoint(leader, sbp);
315		breakpoint_destroy(sbp);
316		free(sbp);
317	}
318}
319
320const char *
321breakpoint_name(const struct breakpoint *bp)
322{
323	assert(bp != NULL);
324	return bp->libsym != NULL ? bp->libsym->name : NULL;
325}
326
327struct library *
328breakpoint_library(const struct breakpoint *bp)
329{
330	assert(bp != NULL);
331	return bp->libsym != NULL ? bp->libsym->lib : NULL;
332}
333
334static enum callback_status
335enable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
336{
337	struct process *proc = data;
338	debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", proc->pid);
339	if ((*bpp)->enabled)
340		enable_breakpoint(proc, *bpp);
341	return CBS_CONT;
342}
343
344void
345enable_all_breakpoints(struct process *proc)
346{
347	debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid);
348
349	debug(1, "Enabling breakpoints for pid %u...", proc->pid);
350	if (proc->breakpoints != NULL)
351		DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
352			  NULL, enable_bp_cb, proc);
353}
354
355static enum callback_status
356disable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
357{
358	struct process *proc = data;
359	debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", proc->pid);
360	if ((*bpp)->enabled)
361		disable_breakpoint(proc, *bpp);
362	return CBS_CONT;
363}
364
365void
366disable_all_breakpoints(struct process *proc)
367{
368	debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
369	assert(proc->leader == proc);
370	DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
371		  NULL, disable_bp_cb, proc);
372}
373
374static void
375entry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
376{
377	if (proc == NULL || proc->leader == NULL)
378		return;
379	delete_breakpoint(proc, bp->addr);
380	process_hit_start(proc);
381}
382
383int
384entry_breakpoint_init(struct process *proc,
385		      struct breakpoint *bp, arch_addr_t addr,
386		      struct library *lib)
387{
388	assert(addr != 0);
389	int err = breakpoint_init(bp, proc, addr, NULL);
390	if (err < 0)
391		return err;
392
393	static struct bp_callbacks entry_callbacks = {
394		.on_hit = entry_breakpoint_on_hit,
395	};
396	bp->cbs = &entry_callbacks;
397	return 0;
398}
399
400int
401breakpoints_init(struct process *proc)
402{
403	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
404
405	/* XXX breakpoint dictionary should be initialized
406	 * outside.  Here we just put in breakpoints.  */
407	assert(proc->breakpoints != NULL);
408
409	/* Only the thread group leader should hold the breakpoints.  */
410	assert(proc->leader == proc);
411
412	/* N.B. the following used to be conditional on this, and
413	 * maybe it still needs to be.  */
414	assert(proc->filename != NULL);
415
416	struct library *lib = ltelf_read_main_binary(proc, proc->filename);
417	struct breakpoint *entry_bp = NULL;
418	int bp_state = 0;
419	int result = -1;
420	switch ((int)(lib != NULL)) {
421	fail:
422		switch (bp_state) {
423		case 2:
424			proc_remove_library(proc, lib);
425			proc_remove_breakpoint(proc, entry_bp);
426		case 1:
427			breakpoint_destroy(entry_bp);
428		}
429		library_destroy(lib);
430		free(entry_bp);
431	case 0:
432		return result;
433	}
434
435	entry_bp = malloc(sizeof(*entry_bp));
436	if (entry_bp == NULL
437	    || (entry_breakpoint_init(proc, entry_bp,
438				      lib->entry, lib)) < 0) {
439		fprintf(stderr,
440			"Couldn't initialize entry breakpoint for PID %d.\n"
441			"Some tracing events may be missed.\n", proc->pid);
442		free(entry_bp);
443
444	} else {
445		++bp_state;
446
447		if ((result = proc_add_breakpoint(proc, entry_bp)) < 0)
448			goto fail;
449		++bp_state;
450
451		if ((result = breakpoint_turn_on(entry_bp, proc)) < 0)
452			goto fail;
453	}
454	proc_add_library(proc, lib);
455
456	proc->callstack_depth = 0;
457	return 0;
458}
459