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