breakpoints.c revision bc37326ace5c70e57928c000162cffbcca9afb77
1d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes#include "config.h"
2d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes
35b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes#include <stdlib.h>
47186e2af704f4458e6383e8a92482594db29b597Juan Cespedes#include <string.h>
55b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes#include <assert.h>
65b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
7f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#ifdef __powerpc__
8f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#include <sys/ptrace.h>
9f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#endif
10f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes
119294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata#include "breakpoint.h"
12f728123bd75a65a6a1536e198c3c30719e494e71Juan Cespedes#include "common.h"
135b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
14a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machatavoid
15a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machatabreakpoint_on_hit(struct breakpoint *bp, struct Process *proc)
16a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata{
17a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata	assert(bp != NULL);
18a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata	if (bp->cbs != NULL && bp->cbs->on_hit != NULL)
19a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata		(bp->cbs->on_hit) (bp, proc);
20a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata}
21a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata
22a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machatavoid
23a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machatabreakpoint_on_destroy(struct breakpoint *bp)
24a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata{
25a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata	assert(bp != NULL);
26a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata	if (bp->cbs != NULL && bp->cbs->on_destroy != NULL)
27a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata		(bp->cbs->on_destroy) (bp);
28a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata}
29a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata
305b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes/*****************************************************************************/
315b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
329294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machatastruct breakpoint *
33fed1e8d33ab050df892a88110e1a316d285ee650Petr Machataaddress2bpstruct(Process *proc, void *addr)
34fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
352662768efe599f6bb43c4310177e30f56b601bb7Petr Machata	assert(proc != NULL);
362662768efe599f6bb43c4310177e30f56b601bb7Petr Machata	assert(proc->breakpoints != NULL);
379a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(proc->leader == proc);
38cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
39cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes	return dict_find_entry(proc->breakpoints, addr);
405b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
415b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
429294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machatastruct breakpoint *
43a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesinsert_breakpoint(Process *proc, void *addr,
44fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata		  struct library_symbol *libsym, int enable)
45fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
469294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata	struct breakpoint *sbp;
47cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
489a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	Process * leader = proc->leader;
499a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
509a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	/* Only the group leader should be getting the breakpoints and
519a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	 * thus have ->breakpoint initialized.  */
529a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(leader != NULL);
539a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(leader->breakpoints != NULL);
549a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
55a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch#ifdef __arm__
56a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch	int thumb_mode = (int)addr & 1;
57a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch	if (thumb_mode)
58a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch		addr = (void *)((int)addr & ~1);
59a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch#endif
60a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch
61cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "insert_breakpoint(pid=%d, addr=%p, symbol=%s)", proc->pid, addr, libsym ? libsym->name : "NULL");
62b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata	debug(1, "symbol=%s, addr=%p", libsym?libsym->name:"(nil)", addr);
635b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
642d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (!addr)
659294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata		return NULL;
669a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
672d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (libsym)
689a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand		libsym->needs_init = 0;
699a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
709a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	sbp = dict_find_entry(leader->breakpoints, addr);
71fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata	if (sbp == NULL) {
72fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata		sbp = calloc(1, sizeof(*sbp));
73fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata		if (sbp == NULL) {
749294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata			return NULL;	/* TODO FIXME XXX: error_mem */
75cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes		}
769a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata		dict_enter(leader->breakpoints, addr, sbp);
77cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes		sbp->addr = addr;
782d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		sbp->libsym = libsym;
795b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	}
8063184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes#ifdef __arm__
81a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch	sbp->thumb_mode = thumb_mode | proc->thumb_mode;
8263184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes	proc->thumb_mode = 0;
8363184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes#endif
845b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	sbp->enabled++;
85c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata	if (sbp->enabled == 1 && enable) {
86c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata		assert(proc->pid != 0);
87f789c9c0d1f3301afad66e5f0520b9093665f242Petr Machata		enable_breakpoint(proc, sbp);
88c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata	}
899294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata
909294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata	return sbp;
915b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
925b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
93f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
94fed1e8d33ab050df892a88110e1a316d285ee650Petr Machatadelete_breakpoint(Process *proc, void *addr)
95fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
969294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata	struct breakpoint *sbp;
97cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
98cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr);
99cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
1009a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	Process * leader = proc->leader;
1019a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(leader != NULL);
1029a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
1039a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	sbp = dict_find_entry(leader->breakpoints, addr);
1042d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	assert(sbp);		/* FIXME: remove after debugging has been done. */
1055b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	/* This should only happen on out-of-memory conditions. */
1062d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (sbp == NULL)
1072d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		return;
1085b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
1095b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	sbp->enabled--;
1102d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (sbp->enabled == 0)
111f789c9c0d1f3301afad66e5f0520b9093665f242Petr Machata		disable_breakpoint(proc, sbp);
1125b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	assert(sbp->enabled >= 0);
1135b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
1145b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
115f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
116fed1e8d33ab050df892a88110e1a316d285ee650Petr Machataenable_bp_cb(void *addr, void *sbp, void *proc)
117fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
118cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", ((Process *)proc)->pid);
119bc37326ace5c70e57928c000162cffbcca9afb77Petr Machata	if (((struct breakpoint *)sbp)->enabled)
120f789c9c0d1f3301afad66e5f0520b9093665f242Petr Machata		enable_breakpoint(proc, sbp);
1215b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
1225b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
123f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
124bc37326ace5c70e57928c000162cffbcca9afb77Petr Machataenable_all_breakpoints(Process *proc)
125bc37326ace5c70e57928c000162cffbcca9afb77Petr Machata{
126cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid);
127f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#ifdef __powerpc__
12861196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	unsigned long a;
12961196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata
13061196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	/*
13161196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	 * PPC HACK! (XXX FIXME TODO)
13261196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	 * If the dynamic linker hasn't populated the PLT then
13361196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	 * dont enable the breakpoints
13461196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	 */
13561196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	if (options.libcalls) {
13661196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		a = ptrace(PTRACE_PEEKTEXT, proc->pid,
13761196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			   sym2addr(proc, proc->list_of_symbols),
13861196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			   0);
13961196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		if (a == 0x0)
14061196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			return;
14161196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	}
142f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#endif
143f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes
14461196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	debug(1, "Enabling breakpoints for pid %u...", proc->pid);
14561196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	if (proc->breakpoints) {
14661196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		dict_apply_to_all(proc->breakpoints, enable_bp_cb,
14761196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata				  proc);
14861196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	}
1491228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#ifdef __mips__
15061196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	{
15161196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		/*
15261196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		 * I'm sure there is a nicer way to do this. We need to
15361196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		 * insert breakpoints _after_ the child has been started.
15461196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		 */
15561196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		struct library_symbol *sym;
15661196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		struct library_symbol *new_sym;
15761196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		sym=proc->list_of_symbols;
15861196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		while(sym){
15961196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			void *addr= sym2addr(proc,sym);
16061196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			if(!addr){
16161196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata				sym=sym->next;
16261196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata				continue;
16361196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			}
16461196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			if(dict_find_entry(proc->breakpoints,addr)){
165a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				sym=sym->next;
16661196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata				continue;
167a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes			}
16861196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			debug(2,"inserting bp %p %s",addr,sym->name);
16961196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
17061196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
17161196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			new_sym->next=proc->list_of_symbols;
17261196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			proc->list_of_symbols=new_sym;
17361196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			insert_breakpoint(proc, addr, new_sym);
17461196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata			sym=sym->next;
175a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes		}
1765e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
17761196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata#endif
1785e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes}
1795e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
180f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
181fed1e8d33ab050df892a88110e1a316d285ee650Petr Machatadisable_bp_cb(void *addr, void *sbp, void *proc)
182fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
183cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", ((Process *)proc)->pid);
184bc37326ace5c70e57928c000162cffbcca9afb77Petr Machata	if (((struct breakpoint *)sbp)->enabled)
185f789c9c0d1f3301afad66e5f0520b9093665f242Petr Machata		disable_breakpoint(proc, sbp);
1865b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
1875b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
188f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
189a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesdisable_all_breakpoints(Process *proc) {
190cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
1919a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(proc->leader == proc);
19261196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata	dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
1935e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes}
1947186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
195f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
196f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesfree_bp_cb(void *addr, void *sbp, void *data) {
197cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "free_bp_cb(sbp=%p)", sbp);
1987186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	assert(sbp);
1997186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	free(sbp);
2007186e2af704f4458e6383e8a92482594db29b597Juan Cespedes}
2017186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
20202648a119092bb5b64918063521237f257283c72Petr Machatastatic void
20302648a119092bb5b64918063521237f257283c72Petr Machataentry_callback_hit(struct breakpoint *bp, struct Process *proc)
20402648a119092bb5b64918063521237f257283c72Petr Machata{
20502648a119092bb5b64918063521237f257283c72Petr Machata	if (proc == NULL || proc->leader == NULL)
20602648a119092bb5b64918063521237f257283c72Petr Machata		return;
20702648a119092bb5b64918063521237f257283c72Petr Machata	delete_breakpoint(proc, bp->addr); // xxx
20802648a119092bb5b64918063521237f257283c72Petr Machata	reinitialize_breakpoints(proc->leader);
20902648a119092bb5b64918063521237f257283c72Petr Machata}
21002648a119092bb5b64918063521237f257283c72Petr Machata
2111974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machataint
212c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machatabreakpoints_init(Process *proc, int enable)
213c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata{
214cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
2152d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (proc->breakpoints) {	/* let's remove that struct */
2167186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		dict_apply_to_all(proc->breakpoints, free_bp_cb, NULL);
2177186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		dict_clear(proc->breakpoints);
2187186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		proc->breakpoints = NULL;
2197186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	}
2202662768efe599f6bb43c4310177e30f56b601bb7Petr Machata
2219a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	/* Only the thread group leader should hold the breakpoints.
2229a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	 * (N.B. PID may be set to 0 temporarily when called by
2239a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	 * handle_exec).  */
2249a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(proc->leader == proc);
2259a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
2262662768efe599f6bb43c4310177e30f56b601bb7Petr Machata	proc->breakpoints = dict_init(dict_key2hash_int,
2272662768efe599f6bb43c4310177e30f56b601bb7Petr Machata				      dict_key_cmp_int);
2287186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
229534e00fcdb63af352414f5bf180ec392157b1a2bPetr Machata	destroy_library_symbol_chain(proc->list_of_symbols);
2303d7e4b8d6119c1cda159e2665b40b6dcd4052e85Petr Machata	proc->list_of_symbols = NULL;
2313d7e4b8d6119c1cda159e2665b40b6dcd4052e85Petr Machata
232e84fa00bdabf20f57d1d02d159aa3fcab4e549fePetr Machata	GElf_Addr entry;
233ce377d567ccc0b14693619b69ebe0ac6deb0ba90Juan Cespedes	if (options.libcalls && proc->filename) {
234e84fa00bdabf20f57d1d02d159aa3fcab4e549fePetr Machata		proc->list_of_symbols = read_elf(proc, &entry);
2351974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata		if (proc->list_of_symbols == NULL) {
23602648a119092bb5b64918063521237f257283c72Petr Machata		fail:
2371974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata			/* XXX leak breakpoints */
2381974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata			return -1;
2391974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata		}
2401974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata
2417186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		if (opt_e) {
2422662768efe599f6bb43c4310177e30f56b601bb7Petr Machata			struct library_symbol **tmp1 = &proc->list_of_symbols;
2432d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			while (*tmp1) {
2442d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				struct opt_e_t *tmp2 = opt_e;
2457186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				int keep = !opt_e_enable;
2467186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
2472d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				while (tmp2) {
2482662768efe599f6bb43c4310177e30f56b601bb7Petr Machata					if (!strcmp((*tmp1)->name,
2492662768efe599f6bb43c4310177e30f56b601bb7Petr Machata						    tmp2->name)) {
2507186e2af704f4458e6383e8a92482594db29b597Juan Cespedes						keep = opt_e_enable;
2517186e2af704f4458e6383e8a92482594db29b597Juan Cespedes					}
2527186e2af704f4458e6383e8a92482594db29b597Juan Cespedes					tmp2 = tmp2->next;
2537186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				}
2547186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				if (!keep) {
2557186e2af704f4458e6383e8a92482594db29b597Juan Cespedes					*tmp1 = (*tmp1)->next;
2567186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				} else {
2577186e2af704f4458e6383e8a92482594db29b597Juan Cespedes					tmp1 = &((*tmp1)->next);
2587186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				}
2597186e2af704f4458e6383e8a92482594db29b597Juan Cespedes			}
2607186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		}
2617186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	}
262c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata
26302648a119092bb5b64918063521237f257283c72Petr Machata	struct breakpoint *entry_bp
26461196a4a81e77322bf1f3dc609007f5d35a5103aPetr Machata		= insert_breakpoint(proc, (void *)(uintptr_t)entry, NULL, 1);
26502648a119092bb5b64918063521237f257283c72Petr Machata	if (entry_bp == NULL) {
26602648a119092bb5b64918063521237f257283c72Petr Machata		fprintf(stderr, "fail!\n");
26702648a119092bb5b64918063521237f257283c72Petr Machata		goto fail;
26802648a119092bb5b64918063521237f257283c72Petr Machata	}
26902648a119092bb5b64918063521237f257283c72Petr Machata
27002648a119092bb5b64918063521237f257283c72Petr Machata	static struct bp_callbacks entry_callbacks = {
27102648a119092bb5b64918063521237f257283c72Petr Machata		.on_hit = entry_callback_hit,
27202648a119092bb5b64918063521237f257283c72Petr Machata	};
27302648a119092bb5b64918063521237f257283c72Petr Machata	entry_bp->cbs = &entry_callbacks;
274c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata
2757186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	proc->callstack_depth = 0;
2761974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata	return 0;
2777186e2af704f4458e6383e8a92482594db29b597Juan Cespedes}
2789a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
279f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
280a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesreinitialize_breakpoints(Process *proc) {
281cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	struct library_symbol *sym;
282cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
283cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "reinitialize_breakpoints(pid=%d)", proc->pid);
284cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
285cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	sym = proc->list_of_symbols;
2862d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
2872d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	while (sym) {
2889a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand		if (sym->needs_init) {
289c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata			insert_breakpoint(proc, sym2addr(proc, sym), sym, 1);
2902d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			if (sym->needs_init && !sym->is_weak) {
2912d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				fprintf(stderr,
2922d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand					"could not re-initialize breakpoint for \"%s\" in file \"%s\"\n",
2932d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand					sym->name, proc->filename);
2949a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand				exit(1);
2952d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			}
2962d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		}
2979a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand		sym = sym->next;
2982d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	}
2999a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand}
300