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