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