breakpoints.c revision cac15c3f170b5ec2cc6304c8c0763a78103e1778
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdlib.h>
6#include <assert.h>
7
8#ifdef __powerpc__
9#include <sys/ptrace.h>
10#endif
11
12#include "ltrace.h"
13#include "options.h"
14#include "debug.h"
15#include "dict.h"
16
17/*****************************************************************************/
18
19struct breakpoint *
20address2bpstruct(struct process * proc, void * addr) {
21	return dict_find_entry(proc->breakpoints, addr);
22}
23
24void
25insert_breakpoint(struct process * proc, void * addr) {
26	struct breakpoint * sbp;
27
28	if (!proc->breakpoints) {
29		proc->breakpoints = dict_init(dict_key2hash_int, dict_key_cmp_int);
30		/* atexit(brk_dict_clear); */ /* why bother to do this on exit? */
31	}
32	sbp = dict_find_entry(proc->breakpoints, addr);
33	if (!sbp) {
34		sbp = malloc(sizeof(struct breakpoint));
35		if (!sbp) {
36			return; /* TODO FIXME XXX: error_mem */
37		}
38		dict_enter(proc->breakpoints, addr, sbp);
39		sbp->addr = addr;
40		sbp->enabled = 0;
41	}
42	sbp->enabled++;
43	if (sbp->enabled==1 && proc->pid) enable_breakpoint(proc->pid, sbp);
44}
45
46void
47delete_breakpoint(struct process * proc, void * addr) {
48	struct breakpoint * sbp = dict_find_entry(proc->breakpoints, addr);
49	assert(sbp); /* FIXME: remove after debugging has been done. */
50	/* This should only happen on out-of-memory conditions. */
51	if (sbp == NULL) return;
52
53	sbp->enabled--;
54	if (sbp->enabled == 0) disable_breakpoint(proc->pid, sbp);
55	assert(sbp->enabled >= 0);
56}
57
58static void
59enable_bp_cb(void * addr, void * sbp, void * proc) {
60	if (((struct breakpoint *)sbp)->enabled) {
61		enable_breakpoint(((struct process *)proc)->pid, sbp);
62	}
63}
64
65void
66enable_all_breakpoints(struct process * proc) {
67	if (proc->breakpoints_enabled <= 0) {
68#ifdef __powerpc__
69		unsigned long a;
70
71		/*
72		 * PPC HACK! (XXX FIXME TODO)
73		 * If the dynamic linker hasn't populated the PLT then
74		 * dont enable the breakpoints
75		 */
76		if (opt_L) {
77			a = ptrace(PTRACE_PEEKTEXT, proc->pid, proc->list_of_symbols->enter_addr, 0);
78			if (a == 0x0)
79				return;
80		}
81#endif
82
83		debug(1, "Enabling breakpoints for pid %u...", proc->pid);
84		dict_apply_to_all(proc->breakpoints, enable_bp_cb, proc);
85	}
86	proc->breakpoints_enabled = 1;
87}
88
89static void
90disable_bp_cb(void * addr, void * sbp, void * proc) {
91	if (((struct breakpoint *)sbp)->enabled) {
92		disable_breakpoint(((struct process *)proc)->pid, sbp);
93	}
94}
95
96void
97disable_all_breakpoints(struct process * proc) {
98	if (proc->breakpoints_enabled) {
99		debug(1, "Disabling breakpoints for pid %u...", proc->pid);
100		dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
101	}
102	proc->breakpoints_enabled = 0;
103}
104