breakpoints.c revision 534e00fcdb63af352414f5bf180ec392157b1a2b
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
11f728123bd75a65a6a1536e198c3c30719e494e71Juan Cespedes#include "common.h"
125b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
135b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes/*****************************************************************************/
145b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
151dec217e47f998c03c642561d98753c32683985cJuan CespedesBreakpoint *
16a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesaddress2bpstruct(Process *proc, void *addr) {
172662768efe599f6bb43c4310177e30f56b601bb7Petr Machata	assert(proc != NULL);
182662768efe599f6bb43c4310177e30f56b601bb7Petr Machata	assert(proc->breakpoints != NULL);
199a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(proc->leader == proc);
20cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
21cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes	return dict_find_entry(proc->breakpoints, addr);
225b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
235b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
249a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienandvoid
25a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesinsert_breakpoint(Process *proc, void *addr,
26c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata		  struct library_symbol *libsym, int enable) {
271dec217e47f998c03c642561d98753c32683985cJuan Cespedes	Breakpoint *sbp;
28cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
299a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	Process * leader = proc->leader;
309a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
319a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	/* Only the group leader should be getting the breakpoints and
329a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	 * thus have ->breakpoint initialized.  */
339a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(leader != NULL);
349a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(leader->breakpoints != NULL);
359a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
36a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch#ifdef __arm__
37a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch	int thumb_mode = (int)addr & 1;
38a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch	if (thumb_mode)
39a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch		addr = (void *)((int)addr & ~1);
40a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch#endif
41a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch
42cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "insert_breakpoint(pid=%d, addr=%p, symbol=%s)", proc->pid, addr, libsym ? libsym->name : "NULL");
43b3f8fef12fccb0914b7b28725f42192c279d31c9Petr Machata	debug(1, "symbol=%s, addr=%p", libsym?libsym->name:"(nil)", addr);
445b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
452d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (!addr)
462d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		return;
479a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
482d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (libsym)
499a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand		libsym->needs_init = 0;
509a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
519a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	sbp = dict_find_entry(leader->breakpoints, addr);
52cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes	if (!sbp) {
531dec217e47f998c03c642561d98753c32683985cJuan Cespedes		sbp = calloc(1, sizeof(Breakpoint));
54cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes		if (!sbp) {
552d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			return;	/* TODO FIXME XXX: error_mem */
56cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes		}
579a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata		dict_enter(leader->breakpoints, addr, sbp);
58cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes		sbp->addr = addr;
592d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		sbp->libsym = libsym;
605b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	}
6163184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes#ifdef __arm__
62a2ff9d6db878e564caffef8807907aa0faedb7fdZachary T Welch	sbp->thumb_mode = thumb_mode | proc->thumb_mode;
6363184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes	proc->thumb_mode = 0;
6463184be8c577f5799e44db2a4e312a8240ad7751Juan Cespedes#endif
655b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	sbp->enabled++;
66c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata	if (sbp->enabled == 1 && enable) {
67c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata		assert(proc->pid != 0);
68f789c9c0d1f3301afad66e5f0520b9093665f242Petr Machata		enable_breakpoint(proc, sbp);
69c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata	}
705b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
715b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
72f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
73a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesdelete_breakpoint(Process *proc, void *addr) {
74cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	Breakpoint *sbp;
75cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
76cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr);
77cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
789a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	Process * leader = proc->leader;
799a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(leader != NULL);
809a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
819a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	sbp = dict_find_entry(leader->breakpoints, addr);
822d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	assert(sbp);		/* FIXME: remove after debugging has been done. */
835b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	/* This should only happen on out-of-memory conditions. */
842d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (sbp == NULL)
852d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		return;
865b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
875b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	sbp->enabled--;
882d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (sbp->enabled == 0)
89f789c9c0d1f3301afad66e5f0520b9093665f242Petr Machata		disable_breakpoint(proc, sbp);
905b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	assert(sbp->enabled >= 0);
915b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
925b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
93f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
94f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesenable_bp_cb(void *addr, void *sbp, void *proc) {
95cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", ((Process *)proc)->pid);
961dec217e47f998c03c642561d98753c32683985cJuan Cespedes	if (((Breakpoint *)sbp)->enabled) {
97f789c9c0d1f3301afad66e5f0520b9093665f242Petr Machata		enable_breakpoint(proc, sbp);
98cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes	}
995b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
1005b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
101f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
102a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesenable_all_breakpoints(Process *proc) {
103cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid);
1045e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	if (proc->breakpoints_enabled <= 0) {
105f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#ifdef __powerpc__
106f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes		unsigned long a;
107f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes
108f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes		/*
109f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes		 * PPC HACK! (XXX FIXME TODO)
110f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes		 * If the dynamic linker hasn't populated the PLT then
111f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes		 * dont enable the breakpoints
112f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes		 */
113ce377d567ccc0b14693619b69ebe0ac6deb0ba90Juan Cespedes		if (options.libcalls) {
1142d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			a = ptrace(PTRACE_PEEKTEXT, proc->pid,
11576c61f15d7989bf7adffed2e46a44c34a80bd927Paul Gilliam				   sym2addr(proc, proc->list_of_symbols),
1162d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				   0);
117de5a7eb873c05a698e4267b554e25124dc92e7f4Juan Cespedes			if (a == 0x0)
118de5a7eb873c05a698e4267b554e25124dc92e7f4Juan Cespedes				return;
119de5a7eb873c05a698e4267b554e25124dc92e7f4Juan Cespedes		}
120f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#endif
121f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes
122cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes		debug(1, "Enabling breakpoints for pid %u...", proc->pid);
123a0ccf39a68c0fcdf2165bde0f9b70ed12fc61cd8Juan Cespedes		if (proc->breakpoints) {
1242d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			dict_apply_to_all(proc->breakpoints, enable_bp_cb,
1252d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand					  proc);
126a0ccf39a68c0fcdf2165bde0f9b70ed12fc61cd8Juan Cespedes		}
1271228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#ifdef __mips__
128a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes		{
1295c682047d0b03f53dc05d3bd80181e7f82121779Juan Cespedes			/*
1305c682047d0b03f53dc05d3bd80181e7f82121779Juan Cespedes			 * I'm sure there is a nicer way to do this. We need to
1315c682047d0b03f53dc05d3bd80181e7f82121779Juan Cespedes			 * insert breakpoints _after_ the child has been started.
1325c682047d0b03f53dc05d3bd80181e7f82121779Juan Cespedes			 */
133a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes			struct library_symbol *sym;
134a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes			struct library_symbol *new_sym;
135a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes			sym=proc->list_of_symbols;
136a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes			while(sym){
137a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				void *addr= sym2addr(proc,sym);
138a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				if(!addr){
139a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes					sym=sym->next;
140a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes					continue;
141a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				}
142a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				if(dict_find_entry(proc->breakpoints,addr)){
143a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes					sym=sym->next;
144a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes					continue;
145a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				}
146a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				debug(2,"inserting bp %p %s",addr,sym->name);
1474795087c406008f63de933755c87851acd6b9806Arnaud Patard				new_sym=malloc(sizeof(*new_sym) + strlen(sym->name) + 1);
1484795087c406008f63de933755c87851acd6b9806Arnaud Patard				memcpy(new_sym,sym,sizeof(*new_sym) + strlen(sym->name) + 1);
149a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				new_sym->next=proc->list_of_symbols;
150a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				proc->list_of_symbols=new_sym;
151a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				insert_breakpoint(proc, addr, new_sym);
152a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes				sym=sym->next;
153a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes			}
154a413e5b8880de643a83ad124d078091c0956fe1dJuan Cespedes		}
1551228a91e6560c5e5ac4fdd051adc9b34bf9fc047Eric Vaitl#endif
1565e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
1575e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	proc->breakpoints_enabled = 1;
1585e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes}
1595e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes
160f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
161f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesdisable_bp_cb(void *addr, void *sbp, void *proc) {
162cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", ((Process *)proc)->pid);
1631dec217e47f998c03c642561d98753c32683985cJuan Cespedes	if (((Breakpoint *)sbp)->enabled) {
164f789c9c0d1f3301afad66e5f0520b9093665f242Petr Machata		disable_breakpoint(proc, sbp);
165cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes	}
1665b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
1675b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
168f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
169a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesdisable_all_breakpoints(Process *proc) {
170cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
1719a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(proc->leader == proc);
1725e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	if (proc->breakpoints_enabled) {
173cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes		debug(1, "Disabling breakpoints for pid %u...", proc->pid);
174cac15c3f170b5ec2cc6304c8c0763a78103e1778Juan Cespedes		dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
1755e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	}
1765e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes	proc->breakpoints_enabled = 0;
1775e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes}
1787186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
179f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesstatic void
180f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesfree_bp_cb(void *addr, void *sbp, void *data) {
181cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "free_bp_cb(sbp=%p)", sbp);
1827186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	assert(sbp);
1837186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	free(sbp);
1847186e2af704f4458e6383e8a92482594db29b597Juan Cespedes}
1857186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
1861974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machataint
187c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machatabreakpoints_init(Process *proc, int enable)
188c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata{
1892d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	struct library_symbol *sym;
1907186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
191cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
1922d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	if (proc->breakpoints) {	/* let's remove that struct */
1937186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		dict_apply_to_all(proc->breakpoints, free_bp_cb, NULL);
1947186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		dict_clear(proc->breakpoints);
1957186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		proc->breakpoints = NULL;
1967186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	}
1972662768efe599f6bb43c4310177e30f56b601bb7Petr Machata
1989a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	/* Only the thread group leader should hold the breakpoints.
1999a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	 * (N.B. PID may be set to 0 temporarily when called by
2009a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	 * handle_exec).  */
2019a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(proc->leader == proc);
2029a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
2032662768efe599f6bb43c4310177e30f56b601bb7Petr Machata	proc->breakpoints = dict_init(dict_key2hash_int,
2042662768efe599f6bb43c4310177e30f56b601bb7Petr Machata				      dict_key_cmp_int);
2057186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
206534e00fcdb63af352414f5bf180ec392157b1a2bPetr Machata	destroy_library_symbol_chain(proc->list_of_symbols);
2073d7e4b8d6119c1cda159e2665b40b6dcd4052e85Petr Machata	proc->list_of_symbols = NULL;
2083d7e4b8d6119c1cda159e2665b40b6dcd4052e85Petr Machata
209ce377d567ccc0b14693619b69ebe0ac6deb0ba90Juan Cespedes	if (options.libcalls && proc->filename) {
2109a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand		proc->list_of_symbols = read_elf(proc);
2111974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata		if (proc->list_of_symbols == NULL) {
2121974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata			/* XXX leak breakpoints */
2131974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata			return -1;
2141974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata		}
2151974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata
2167186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		if (opt_e) {
2172662768efe599f6bb43c4310177e30f56b601bb7Petr Machata			struct library_symbol **tmp1 = &proc->list_of_symbols;
2182d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			while (*tmp1) {
2192d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				struct opt_e_t *tmp2 = opt_e;
2207186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				int keep = !opt_e_enable;
2217186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
2222d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				while (tmp2) {
2232662768efe599f6bb43c4310177e30f56b601bb7Petr Machata					if (!strcmp((*tmp1)->name,
2242662768efe599f6bb43c4310177e30f56b601bb7Petr Machata						    tmp2->name)) {
2257186e2af704f4458e6383e8a92482594db29b597Juan Cespedes						keep = opt_e_enable;
2267186e2af704f4458e6383e8a92482594db29b597Juan Cespedes					}
2277186e2af704f4458e6383e8a92482594db29b597Juan Cespedes					tmp2 = tmp2->next;
2287186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				}
2297186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				if (!keep) {
2307186e2af704f4458e6383e8a92482594db29b597Juan Cespedes					*tmp1 = (*tmp1)->next;
2317186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				} else {
2327186e2af704f4458e6383e8a92482594db29b597Juan Cespedes					tmp1 = &((*tmp1)->next);
2337186e2af704f4458e6383e8a92482594db29b597Juan Cespedes				}
2347186e2af704f4458e6383e8a92482594db29b597Juan Cespedes			}
2357186e2af704f4458e6383e8a92482594db29b597Juan Cespedes		}
2367186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	}
237c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata
238c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata	for (sym = proc->list_of_symbols; sym; sym = sym->next)
239c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata		insert_breakpoint(proc, sym2addr(proc, sym), sym, enable);
240c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata
2417186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	proc->callstack_depth = 0;
2427186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	proc->breakpoints_enabled = -1;
2431974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata	return 0;
2447186e2af704f4458e6383e8a92482594db29b597Juan Cespedes}
2459a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
246f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
247a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesreinitialize_breakpoints(Process *proc) {
248cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	struct library_symbol *sym;
249cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
250cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "reinitialize_breakpoints(pid=%d)", proc->pid);
251cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
252cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	sym = proc->list_of_symbols;
2532d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand
2542d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	while (sym) {
2559a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand		if (sym->needs_init) {
256c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata			insert_breakpoint(proc, sym2addr(proc, sym), sym, 1);
2572d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			if (sym->needs_init && !sym->is_weak) {
2582d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand				fprintf(stderr,
2592d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand					"could not re-initialize breakpoint for \"%s\" in file \"%s\"\n",
2602d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand					sym->name, proc->filename);
2619a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand				exit(1);
2622d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand			}
2632d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand		}
2649a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand		sym = sym->next;
2652d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand	}
2669a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand}
267