breakpoints.c revision d09d240bbb62af2b0a15e6bdba4114b4060d11ca
1#include "config.h"
2
3#include <stdlib.h>
4#include <string.h>
5#include <assert.h>
6#include <error.h>
7#include <errno.h>
8
9#ifdef __powerpc__
10#include <sys/ptrace.h>
11#endif
12
13#include "breakpoint.h"
14#include "common.h"
15#include "proc.h"
16#include "library.h"
17
18#ifndef ARCH_HAVE_TRANSLATE_ADDRESS
19int
20arch_translate_address(struct Process *proc,
21		       target_address_t addr, target_address_t *ret)
22{
23	*ret = addr;
24	return 0;
25}
26#endif
27
28void
29breakpoint_on_hit(struct breakpoint *bp, struct Process *proc)
30{
31	assert(bp != NULL);
32	if (bp->cbs != NULL && bp->cbs->on_hit != NULL)
33		(bp->cbs->on_hit)(bp, proc);
34}
35
36void
37breakpoint_on_continue(struct breakpoint *bp, struct Process *proc)
38{
39	assert(bp != NULL);
40	if (bp->cbs != NULL && bp->cbs->on_continue != NULL)
41		(bp->cbs->on_continue)(bp, proc);
42	else
43		continue_after_breakpoint(proc, bp);
44}
45
46/*****************************************************************************/
47
48struct breakpoint *
49address2bpstruct(Process *proc, void *addr)
50{
51	assert(proc != NULL);
52	assert(proc->breakpoints != NULL);
53	assert(proc->leader == proc);
54	debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
55	return dict_find_entry(proc->breakpoints, addr);
56}
57
58#ifndef ARCH_HAVE_BREAKPOINT_DATA
59int
60arch_breakpoint_init(struct Process *proc, struct breakpoint *sbp)
61{
62	return 0;
63}
64
65void
66arch_breakpoint_destroy(struct breakpoint *sbp)
67{
68}
69#endif
70
71/* On second thought, I don't think we need PROC.  All the translation
72 * (arch_translate_address in particular) should be doable using
73 * static lookups of various sections in the ELF file.  We shouldn't
74 * need process for anything.  */
75int
76breakpoint_init(struct breakpoint *bp, struct Process *proc,
77		target_address_t addr, struct library_symbol *libsym)
78{
79	bp->cbs = NULL;
80	bp->addr = addr;
81	memset(bp->orig_value, 0, sizeof(bp->orig_value));
82	bp->enabled = 0;
83	bp->libsym = libsym;
84	return arch_breakpoint_init(proc, bp);
85}
86
87void
88breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs)
89{
90	if (bp->cbs != NULL)
91		assert(bp->cbs == NULL);
92	bp->cbs = cbs;
93}
94
95void
96breakpoint_destroy(struct breakpoint *bp)
97{
98	if (bp == NULL)
99		return;
100
101
102	arch_breakpoint_destroy(bp);
103}
104
105int
106breakpoint_turn_on(struct breakpoint *bp, struct Process *proc)
107{
108	/* Make sure it was inserted.  XXX In a clean world, we would
109	 * have breakpoint_site representing a place and breakpoint
110	 * representing inserted breakpoint.  */
111	bp->enabled++;
112	if (bp->enabled == 1) {
113		assert(proc->pid != 0);
114		enable_breakpoint(proc, bp);
115	}
116	return 0;
117}
118
119int
120breakpoint_turn_off(struct breakpoint *bp, struct Process *proc)
121{
122	bp->enabled--;
123	if (bp->enabled == 0)
124		disable_breakpoint(proc, bp);
125	assert(bp->enabled >= 0);
126	return 0;
127}
128
129struct breakpoint *
130insert_breakpoint(struct Process *proc, void *addr,
131		  struct library_symbol *libsym)
132{
133	Process *leader = proc->leader;
134
135	/* Only the group leader should be getting the breakpoints and
136	 * thus have ->breakpoint initialized.  */
137	assert(leader != NULL);
138	assert(leader->breakpoints != NULL);
139
140	debug(DEBUG_FUNCTION, "insert_breakpoint(pid=%d, addr=%p, symbol=%s)",
141	      proc->pid, addr, libsym ? libsym->name : "NULL");
142
143	if (addr == 0) {
144		/* XXX we need a better way to deal with this.  For
145		 * now, just abuse errno to carry the error
146		 * information.  */
147		errno = EINVAL;
148		return NULL;
149	}
150
151	/* XXX what we need to do instead is have a list of
152	 * breakpoints that are enabled at this address.  The
153	 * following works if every breakpoint is the same and there's
154	 * no extra data, but that doesn't hold anymore.  For now it
155	 * will suffice, about the only realistic case where we need
156	 * to have more than one breakpoint per address is return from
157	 * a recursive library call.  */
158	struct breakpoint *sbp = dict_find_entry(leader->breakpoints, addr);
159	if (sbp == NULL) {
160		sbp = malloc(sizeof(*sbp));
161		if (sbp == NULL
162		    || breakpoint_init(sbp, proc, addr, libsym) < 0) {
163			free(sbp);
164			return NULL;
165		}
166		if (proc_add_breakpoint(leader, sbp) < 0) {
167		fail:
168			breakpoint_destroy(sbp);
169			free(sbp);
170			return NULL;
171		}
172	}
173
174	if (breakpoint_turn_on(sbp, proc) < 0)
175		goto fail;
176
177	return sbp;
178}
179
180void
181delete_breakpoint(Process *proc, void *addr)
182{
183	struct breakpoint *sbp;
184
185	debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr);
186
187	Process * leader = proc->leader;
188	assert(leader != NULL);
189
190	sbp = dict_find_entry(leader->breakpoints, addr);
191	assert(sbp);		/* FIXME: remove after debugging has been done. */
192	/* This should only happen on out-of-memory conditions. */
193	if (sbp == NULL)
194		return;
195
196	if (breakpoint_turn_off(sbp, proc) < 0) {
197		fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n",
198			breakpoint_name(sbp), sbp->addr);
199		return;
200	}
201}
202
203const char *
204breakpoint_name(const struct breakpoint *bp)
205{
206	assert(bp != NULL);
207	return bp->libsym != NULL ? bp->libsym->name : NULL;
208}
209
210struct library *
211breakpoint_library(const struct breakpoint *bp)
212{
213	assert(bp != NULL);
214	return bp->libsym != NULL ? bp->libsym->lib : NULL;
215}
216
217static void
218enable_bp_cb(void *addr, void *sbp, void *proc)
219{
220	debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", ((Process *)proc)->pid);
221	if (((struct breakpoint *)sbp)->enabled)
222		enable_breakpoint(proc, sbp);
223}
224
225void
226enable_all_breakpoints(Process *proc)
227{
228	debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid);
229
230	debug(1, "Enabling breakpoints for pid %u...", proc->pid);
231	if (proc->breakpoints) {
232		dict_apply_to_all(proc->breakpoints, enable_bp_cb,
233				  proc);
234	}
235#ifdef __mips__
236	{
237		/*
238		 * I'm sure there is a nicer way to do this. We need to
239		 * insert breakpoints _after_ the child has been started.
240		 */
241		struct library_symbol *sym;
242		struct library_symbol *new_sym;
243		sym=proc->list_of_symbols;
244		while(sym){
245			void *addr= sym2addr(proc,sym);
246			if(!addr){
247				sym=sym->next;
248				continue;
249			}
250			if(dict_find_entry(proc->breakpoints,addr)){
251				sym=sym->next;
252				continue;
253			}
254			debug(2,"inserting bp %p %s",addr,sym->name);
255			new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
256			memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
257			new_sym->next=proc->list_of_symbols;
258			proc->list_of_symbols=new_sym;
259			insert_breakpoint(proc, addr, new_sym);
260			sym=sym->next;
261		}
262	}
263#endif
264}
265
266static void
267disable_bp_cb(void *addr, void *sbp, void *proc)
268{
269	debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", ((Process *)proc)->pid);
270	if (((struct breakpoint *)sbp)->enabled)
271		disable_breakpoint(proc, sbp);
272}
273
274void
275disable_all_breakpoints(Process *proc) {
276	debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
277	assert(proc->leader == proc);
278	dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
279}
280
281/* XXX This is not currently properly supported.  On clone, this is
282 * just sliced.  Hopefully at the point that clone is done, this
283 * breakpoint is not necessary anymore.  If this use case ends up
284 * being important, we need to add a clone and destroy callbacks to
285 * breakpoints, and we should also probably drop arch_breakpoint_data
286 * so that we don't end up with two different customization mechanisms
287 * for one structure.  */
288struct entry_breakpoint {
289	struct breakpoint super;
290	target_address_t dyn_addr;
291};
292
293static void
294entry_breakpoint_on_hit(struct breakpoint *a, struct Process *proc)
295{
296	fprintf(stderr, "entry_breakpoint_on_hit\n");
297	struct entry_breakpoint *bp = (void *)a;
298	if (proc == NULL || proc->leader == NULL)
299		return;
300	delete_breakpoint(proc, bp->super.addr);
301	linkmap_init(proc, bp->dyn_addr);
302}
303
304int
305entry_breakpoint_init(struct Process *proc,
306		      struct entry_breakpoint *bp, target_address_t addr,
307		      struct library *lib)
308{
309	int err;
310	if ((err = breakpoint_init(&bp->super, proc, addr, NULL)) < 0)
311		return err;
312
313	static struct bp_callbacks entry_callbacks = {
314		.on_hit = entry_breakpoint_on_hit,
315	};
316	bp->super.cbs = &entry_callbacks;
317	bp->dyn_addr = lib->dyn_addr;
318	return 0;
319}
320
321int
322breakpoints_init(Process *proc, int enable)
323{
324	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
325
326	/* XXX breakpoint dictionary should be initialized
327	 * outside.  Here we just put in breakpoints.  */
328	assert(proc->breakpoints != NULL);
329
330	/* Only the thread group leader should hold the breakpoints.  */
331	assert(proc->leader == proc);
332
333	/* N.B. the following used to be conditional on this, and
334	 * maybe it still needs to be.  */
335	assert(proc->filename != NULL);
336
337	struct library *lib = ltelf_read_main_binary(proc, proc->filename);
338	struct entry_breakpoint *entry_bp = NULL;
339	int bp_state = 0;
340	int result = -1;
341	switch (lib != NULL) {
342	fail:
343		switch (bp_state) {
344		case 2:
345			proc_remove_library(proc, lib);
346			proc_remove_breakpoint(proc, &entry_bp->super);
347		case 1:
348			breakpoint_destroy(&entry_bp->super);
349		}
350		library_destroy(lib);
351		free(entry_bp);
352	case 0:
353		return result;
354	}
355
356	entry_bp = malloc(sizeof(*entry_bp));
357	if (entry_bp == NULL
358	    || (result = entry_breakpoint_init(proc, entry_bp,
359					       lib->entry, lib)) < 0)
360		goto fail;
361	++bp_state;
362
363	if ((result = proc_add_breakpoint(proc, &entry_bp->super)) < 0)
364		goto fail;
365	++bp_state;
366
367	if ((result = breakpoint_turn_on(&entry_bp->super, proc)) < 0)
368		goto fail;
369	proc_add_library(proc, lib);
370
371	proc->callstack_depth = 0;
372	return 0;
373}
374