1e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata/*
2e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This file is part of ltrace.
356134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machata * Copyright (C) 2006,2007,2011,2012,2013,2014 Petr Machata, Red Hat Inc.
4e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2009 Juan Cespedes
5e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 1998,2001,2002,2003,2007,2008,2009 Juan Cespedes
6e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2006 Ian Wienand
7e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
8e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is free software; you can redistribute it and/or
9e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * modify it under the terms of the GNU General Public License as
10e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * published by the Free Software Foundation; either version 2 of the
11e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * License, or (at your option) any later version.
12e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
13e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is distributed in the hope that it will be useful, but
14e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
15e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * General Public License for more details.
17e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata *
18e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * You should have received a copy of the GNU General Public License
19e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * along with this program; if not, write to the Free Software
20e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 02110-1301 USA
22e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata */
23e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata
24d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes#include "config.h"
25d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes
265b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes#include <assert.h>
272b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata#include <errno.h>
28ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include <stdio.h>
29ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include <stdlib.h>
30ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include <string.h>
315b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
32f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#ifdef __powerpc__
33f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#include <sys/ptrace.h>
34f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes#endif
35f1bfe203f5f1c0e11a614f9d593a68406f5cb47eJuan Cespedes
36ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "backend.h"
379294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata#include "breakpoint.h"
38ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "debug.h"
392b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata#include "library.h"
40ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "ltrace-elf.h"
41ba1664b062414481d0f37d06bb01a19874c8d481Petr Machata#include "proc.h"
425b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
43c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata#ifndef ARCH_HAVE_TRANSLATE_ADDRESS
44c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machataint
45929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_translate_address_dyn(struct process *proc,
46bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata		       arch_addr_t addr, arch_addr_t *ret)
47b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata{
48b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata	*ret = addr;
49b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata	return 0;
50b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata}
51b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machata
52b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machatastruct ltelf;
53b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machataint
54b1492dfaca6882fa0798b549e0557c7dec6b7e9cPetr Machataarch_translate_address(struct ltelf *lte,
55bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata		       arch_addr_t addr, arch_addr_t *ret)
56c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata{
57c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata	*ret = addr;
58c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata	return 0;
59c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata}
60c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata#endif
61c67a6e62bc7e95f7f181a51c5b314ef10a6e231ePetr Machata
62a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machatavoid
63929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabreakpoint_on_hit(struct breakpoint *bp, struct process *proc)
64a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata{
65a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata	assert(bp != NULL);
66a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata	if (bp->cbs != NULL && bp->cbs->on_hit != NULL)
6755ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata		(bp->cbs->on_hit)(bp, proc);
6855ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata}
6955ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata
7055ac932f2802f85c53792153ac909dcd8a690c5cPetr Machatavoid
71929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabreakpoint_on_continue(struct breakpoint *bp, struct process *proc)
7255ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata{
7355ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata	assert(bp != NULL);
7455ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata	if (bp->cbs != NULL && bp->cbs->on_continue != NULL)
7555ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata		(bp->cbs->on_continue)(bp, proc);
7655ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata	else
7755ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata		continue_after_breakpoint(proc, bp);
78a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata}
79a9fd8f45e97edc629bdc218d95ce0d0a9e3de401Petr Machata
8086d3828129e70222abdb77bdda6f31a7f1eafd5aPetr Machatavoid
81929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabreakpoint_on_retract(struct breakpoint *bp, struct process *proc)
8286d3828129e70222abdb77bdda6f31a7f1eafd5aPetr Machata{
8386d3828129e70222abdb77bdda6f31a7f1eafd5aPetr Machata	assert(bp != NULL);
8486d3828129e70222abdb77bdda6f31a7f1eafd5aPetr Machata	if (bp->cbs != NULL && bp->cbs->on_retract != NULL)
8586d3828129e70222abdb77bdda6f31a7f1eafd5aPetr Machata		(bp->cbs->on_retract)(bp, proc);
8686d3828129e70222abdb77bdda6f31a7f1eafd5aPetr Machata}
8786d3828129e70222abdb77bdda6f31a7f1eafd5aPetr Machata
8856134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machatavoid
8956134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machatabreakpoint_on_install(struct breakpoint *bp, struct process *proc)
9056134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machata{
9156134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machata	assert(bp != NULL);
9256134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machata	if (bp->cbs != NULL && bp->cbs->on_install != NULL)
9356134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machata		(bp->cbs->on_install)(bp, proc);
9456134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machata}
9556134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machata
96cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machataint
97cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machatabreakpoint_get_return_bp(struct breakpoint **ret,
98cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata			 struct breakpoint *bp, struct process *proc)
99cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata{
100cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	assert(bp != NULL);
101cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	if (bp->cbs != NULL && bp->cbs->get_return_bp != NULL)
102cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata		return (bp->cbs->get_return_bp)(ret, bp, proc);
103cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata
104cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	if ((*ret = create_default_return_bp(proc)) == NULL)
105cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata		return -1;
106cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata
107cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	return 0;
108cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata}
109cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata
1105b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes/*****************************************************************************/
1115b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
1129294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machatastruct breakpoint *
113d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machataaddress2bpstruct(struct process *proc, arch_addr_t addr)
114fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
1152662768efe599f6bb43c4310177e30f56b601bb7Petr Machata	assert(proc != NULL);
1162662768efe599f6bb43c4310177e30f56b601bb7Petr Machata	assert(proc->breakpoints != NULL);
1179a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(proc->leader == proc);
118cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
119d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata
12098ff309cdc98857eb30992f108439cb7d7673598Petr Machata	struct breakpoint *found;
12198ff309cdc98857eb30992f108439cb7d7673598Petr Machata	if (DICT_FIND_VAL(proc->breakpoints, &addr, &found) < 0)
122d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata		return NULL;
12398ff309cdc98857eb30992f108439cb7d7673598Petr Machata	return found;
1245b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
1255b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
1269f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata#ifndef OS_HAVE_BREAKPOINT_DATA
1279f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machataint
1289f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machataos_breakpoint_init(struct process *proc, struct breakpoint *sbp)
1299f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata{
1309f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	return 0;
1319f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata}
1329f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata
1339f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machatavoid
1349f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machataos_breakpoint_destroy(struct breakpoint *sbp)
1359f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata{
1369f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata}
1379f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata
1389f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machataint
1399f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machataos_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
1409f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata{
1419f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	return 0;
1429f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata}
1439f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata#endif
1449f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata
1458cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata#ifndef ARCH_HAVE_BREAKPOINT_DATA
1462b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machataint
147929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataarch_breakpoint_init(struct process *proc, struct breakpoint *sbp)
1482b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{
1492b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	return 0;
1502b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata}
1518cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata
1528cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machatavoid
1538cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machataarch_breakpoint_destroy(struct breakpoint *sbp)
1548cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata{
1558cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata}
156d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata
157d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machataint
158d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machataarch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
159d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata{
160d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	return 0;
161d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata}
1622b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata#endif
1632b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata
164d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machatastatic void
165e50355295eac26e15db259fbb7ff705487b501d0Petr Machatabreakpoint_init_base(struct breakpoint *bp,
166bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata		     arch_addr_t addr, struct library_symbol *libsym)
167d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata{
168d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	bp->cbs = NULL;
169d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	bp->addr = addr;
170d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	memset(bp->orig_value, 0, sizeof(bp->orig_value));
171d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	bp->enabled = 0;
172d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	bp->libsym = libsym;
173d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata}
174d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata
17552dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata/* On second thought, I don't think we need PROC.  All the translation
17652dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata * (arch_translate_address in particular) should be doable using
17752dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata * static lookups of various sections in the ELF file.  We shouldn't
17852dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata * need process for anything.  */
1792b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machataint
180929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabreakpoint_init(struct breakpoint *bp, struct process *proc,
181bac2da505ee174b7fb984b975c5938f88f0dbab2Petr Machata		arch_addr_t addr, struct library_symbol *libsym)
1822b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{
183e50355295eac26e15db259fbb7ff705487b501d0Petr Machata	breakpoint_init_base(bp, addr, libsym);
1849f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	if (os_breakpoint_init(proc, bp) < 0)
1859f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata		return -1;
1869f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	if (arch_breakpoint_init(proc, bp) < 0) {
1879f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata		os_breakpoint_destroy(bp);
1889f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata		return -1;
1899f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	}
1909f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	return 0;
1912b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata}
1922b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata
1938cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machatavoid
19455ac932f2802f85c53792153ac909dcd8a690c5cPetr Machatabreakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs)
19555ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata{
19655ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata	if (bp->cbs != NULL)
19755ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata		assert(bp->cbs == NULL);
19855ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata	bp->cbs = cbs;
19955ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata}
20055ac932f2802f85c53792153ac909dcd8a690c5cPetr Machata
20155ac932f2802f85c53792153ac909dcd8a690c5cPetr Machatavoid
2028cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machatabreakpoint_destroy(struct breakpoint *bp)
2038cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata{
2048cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata	if (bp == NULL)
2058cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata		return;
206d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	arch_breakpoint_destroy(bp);
2079f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	os_breakpoint_destroy(bp);
208d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata}
2098cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata
210d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machataint
211929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabreakpoint_clone(struct breakpoint *retp, struct process *new_proc,
212e50355295eac26e15db259fbb7ff705487b501d0Petr Machata		 struct breakpoint *bp)
213d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata{
214165b566a50b2bd560af3bd9649e456915397066bPetr Machata	struct library_symbol *libsym = NULL;
215165b566a50b2bd560af3bd9649e456915397066bPetr Machata	if (bp->libsym != NULL) {
216165b566a50b2bd560af3bd9649e456915397066bPetr Machata		int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym);
217165b566a50b2bd560af3bd9649e456915397066bPetr Machata		assert(rc == 0);
218d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	}
219d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata
220e50355295eac26e15db259fbb7ff705487b501d0Petr Machata	breakpoint_init_base(retp, bp->addr, libsym);
221d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value));
222d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	retp->enabled = bp->enabled;
2239f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	if (os_breakpoint_clone(retp, bp) < 0)
224d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata		return -1;
2259f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	if (arch_breakpoint_clone(retp, bp) < 0) {
2269f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata		os_breakpoint_destroy(retp);
2279f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata		return -1;
2289f819d5747dc2b8e0f7ac54b38dc321115de6ddaPetr Machata	}
229d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	breakpoint_set_callbacks(retp, bp->cbs);
230d3cc9889fdfe2e523e99ca5f664f8ae4b3936612Petr Machata	return 0;
2318cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata}
2328cce1193ebd35cb5a8b288bc7325cdda1b8ffe50Petr Machata
23352dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machataint
234929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabreakpoint_turn_on(struct breakpoint *bp, struct process *proc)
23552dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata{
23652dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	bp->enabled++;
23752dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	if (bp->enabled == 1) {
238fa0c5704352beb3f81efe8970dbd5af45a4b00cePetr Machata		assert(proc->pid != 0);
239fa0c5704352beb3f81efe8970dbd5af45a4b00cePetr Machata		enable_breakpoint(proc, bp);
24056134ff5442bee4e128b189bb86cfc97dcb6f60aPetr Machata		breakpoint_on_install(bp, proc);
24152dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	}
24252dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	return 0;
24352dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata}
24452dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata
24552dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machataint
246929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabreakpoint_turn_off(struct breakpoint *bp, struct process *proc)
24752dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata{
24852dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	bp->enabled--;
24952dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	if (bp->enabled == 0)
250fa0c5704352beb3f81efe8970dbd5af45a4b00cePetr Machata		disable_breakpoint(proc, bp);
25152dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	assert(bp->enabled >= 0);
25252dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	return 0;
25352dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata}
25452dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata
2559294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machatastruct breakpoint *
256cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machatacreate_default_return_bp(struct process *proc)
257cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata{
258cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	struct breakpoint *bp = malloc(sizeof *bp);
259cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	arch_addr_t return_addr = get_return_addr(proc, proc->stack_pointer);
260cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	if (return_addr == 0 || bp == NULL
261cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	    || breakpoint_init(bp, proc, return_addr, NULL) < 0) {
262cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata		free(bp);
263cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata		return NULL;
264cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	}
265cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata	return bp;
266cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata}
267cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machata
268cf98923cf77f12bef15b3f1af0c0bbd673a8e4f9Petr Machatastruct breakpoint *
26902a796e5e49c147982020c78b0066930e979f3e4Petr Machatainsert_breakpoint_at(struct process *proc, arch_addr_t addr,
27002a796e5e49c147982020c78b0066930e979f3e4Petr Machata		     struct library_symbol *libsym)
271fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
27202a796e5e49c147982020c78b0066930e979f3e4Petr Machata	debug(DEBUG_FUNCTION,
27302a796e5e49c147982020c78b0066930e979f3e4Petr Machata	      "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)",
274050b0a6fd01fc01952c0ab8dbb84d6eba65c71c9Petr Machata	      proc->pid, addr, libsym ? libsym->name : "NULL");
2755b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
276218c5ff26841f5bbd188c42ccbd67422a7a20556Petr Machata	assert(addr != 0);
2779a2ad351a1c3215dc596ff3e2e3fd4bc24445a6bIan Wienand
278dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	struct breakpoint *bp = malloc(sizeof *bp);
279dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	if (bp == NULL || breakpoint_init(bp, proc, addr, libsym) < 0) {
280dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata		free(bp);
281f9d93c50bd246ea7fd42e0c8ad24aa01467e76acPetr Machata		return NULL;
282dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	}
283dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata
284dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	/* N.B. (and XXX): BP->addr might differ from ADDR.  On ARM
285dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	 * this is a real possibility.  The problem here is that to
286dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	 * create a return breakpoint ltrace calls get_return_addr and
287dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	 * then insert_breakpoint_at.  So get_return_addr needs to
288dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	 * encode all the information necessary for breakpoint_init
289dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	 * into the address itself, so ADDR is potentially
290dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	 * mangled.  */
291dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata
292dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	struct breakpoint *tmp = insert_breakpoint(proc, bp);
293dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	if (tmp != bp) {
294dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata		breakpoint_destroy(bp);
295dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata		free(bp);
296dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	}
297dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	return tmp;
298dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata}
299dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata
300dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machatastruct breakpoint *
301dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machatainsert_breakpoint(struct process *proc, struct breakpoint *bp)
302dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata{
303dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	/* Only the group leader should be getting the breakpoints and
304dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	 * thus have ->breakpoint initialized.  */
305dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	struct process *leader = proc->leader;
306dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	assert(leader != NULL);
307dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	assert(leader->breakpoints != NULL);
308f9d93c50bd246ea7fd42e0c8ad24aa01467e76acPetr Machata
30952dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	/* XXX what we need to do instead is have a list of
31052dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	 * breakpoints that are enabled at this address.  The
31152dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	 * following works if every breakpoint is the same and there's
31252dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	 * no extra data, but that doesn't hold anymore.  For now it
31352dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	 * will suffice, about the only realistic case where we need
31452dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	 * to have more than one breakpoint per address is return from
31552dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	 * a recursive library call.  */
316dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	struct breakpoint *ext_bp = bp;
317dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	if (DICT_FIND_VAL(leader->breakpoints, &bp->addr, &ext_bp) != 0) {
318dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata		if (proc_add_breakpoint(leader, bp) < 0)
3192b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata			return NULL;
320dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata		ext_bp = bp;
3215b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes	}
3222b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata
323dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	if (breakpoint_turn_on(ext_bp, proc) < 0) {
324dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata		if (ext_bp != bp)
325dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata			proc_remove_breakpoint(leader, bp);
326dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata		return NULL;
3274572877d0dd0b5060f4498e705467eaef51c6459Petr Machata	}
3289294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata
329dad1b779e2ed29c9fce17853ca71cb719240b9cfPetr Machata	return ext_bp;
3305b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
3315b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
332f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
333b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machatadelete_breakpoint_at(struct process *proc, arch_addr_t addr)
334fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
335b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	debug(DEBUG_FUNCTION, "delete_breakpoint_at(pid=%d, addr=%p)",
336b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	      proc->pid, addr);
337cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes
338929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata	struct process *leader = proc->leader;
3399a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(leader != NULL);
3409a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata
341b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	struct breakpoint *bp = NULL;
342b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	DICT_FIND_VAL(leader->breakpoints, &addr, &bp);
343b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	assert(bp != NULL);
3445b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
345b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	if (delete_breakpoint(proc, bp) < 0) {
34652dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata		fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n",
347b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata			breakpoint_name(bp), bp->addr);
34852dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	}
349b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata}
350b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata
351b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machataint
352b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machatadelete_breakpoint(struct process *proc, struct breakpoint *bp)
353b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata{
354b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	struct process *leader = proc->leader;
355b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	assert(leader != NULL);
356b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata
357b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	if (breakpoint_turn_off(bp, proc) < 0)
358b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata		return -1;
359b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata
360b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	if (bp->enabled == 0) {
361b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata		proc_remove_breakpoint(leader, bp);
362b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata		breakpoint_destroy(bp);
363b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata		free(bp);
364f7fee43f72667f453bba5aaeea6b5490ece6792aPetr Machata	}
365b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata
366b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	return 0;
3675b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
3685b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
369e9aebd6cfb4710f96b27b5d268208ddd7f0d9eacPetr Machataconst char *
370e9aebd6cfb4710f96b27b5d268208ddd7f0d9eacPetr Machatabreakpoint_name(const struct breakpoint *bp)
371e9aebd6cfb4710f96b27b5d268208ddd7f0d9eacPetr Machata{
372e9aebd6cfb4710f96b27b5d268208ddd7f0d9eacPetr Machata	assert(bp != NULL);
373e9aebd6cfb4710f96b27b5d268208ddd7f0d9eacPetr Machata	return bp->libsym != NULL ? bp->libsym->name : NULL;
374e9aebd6cfb4710f96b27b5d268208ddd7f0d9eacPetr Machata}
375e9aebd6cfb4710f96b27b5d268208ddd7f0d9eacPetr Machata
37652dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machatastruct library *
37752dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machatabreakpoint_library(const struct breakpoint *bp)
37852dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata{
37952dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	assert(bp != NULL);
38052dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	return bp->libsym != NULL ? bp->libsym->lib : NULL;
38152dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata}
38252dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata
383d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machatastatic enum callback_status
384d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machatadisable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
385fed1e8d33ab050df892a88110e1a316d285ee650Petr Machata{
386d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata	struct process *proc = data;
387d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata	debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", proc->pid);
388d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata	if ((*bpp)->enabled)
389d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata		disable_breakpoint(proc, *bpp);
390d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata	return CBS_CONT;
3915b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes}
3925b3ffdf2e696273d38434ff7b3c26349fff5a0eaJuan Cespedes
393f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid
394929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatadisable_all_breakpoints(struct process *proc)
395929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{
396cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
3979a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata	assert(proc->leader == proc);
398d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata	DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
399d7e4ca82e1cf20bb2605befb1da74dd1688c706ePetr Machata		  NULL, disable_bp_cb, proc);
4005e01f654d83a95f2acffa86df57a4c2db9b0cae9Juan Cespedes}
4017186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
40202648a119092bb5b64918063521237f257283c72Petr Machatastatic void
403df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machataentry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
40402648a119092bb5b64918063521237f257283c72Petr Machata{
40502648a119092bb5b64918063521237f257283c72Petr Machata	if (proc == NULL || proc->leader == NULL)
40602648a119092bb5b64918063521237f257283c72Petr Machata		return;
407b94407705ecddffd7820ee61bcad3f0d72ee87c1Petr Machata	delete_breakpoint_at(proc, bp->addr);
408df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata	process_hit_start(proc);
40952dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata}
41052dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata
41152dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machataint
412929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataentry_breakpoint_init(struct process *proc,
413df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata		      struct breakpoint *bp, arch_addr_t addr,
4149a04d0ef18b9d019b87ba10adee27f41980b286fPetr Machata		      struct library *lib)
41552dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata{
4161c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	assert(addr != 0);
417df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata	int err = breakpoint_init(bp, proc, addr, NULL);
4181c79025768a4403e016cc59d7f41b266e868c9e6Petr Machata	if (err < 0)
41952dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata		return err;
42052dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata
42152dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	static struct bp_callbacks entry_callbacks = {
42212affff3c88731a0880690442485494e540f7a58Petr Machata		.on_hit = entry_breakpoint_on_hit,
42352dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	};
424df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata	bp->cbs = &entry_callbacks;
42552dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata	return 0;
42602648a119092bb5b64918063521237f257283c72Petr Machata}
42702648a119092bb5b64918063521237f257283c72Petr Machata
4281974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machataint
429929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatabreakpoints_init(struct process *proc)
430c7585b60235268e1f62bd91c5f040ef6df6e0ef3Petr Machata{
431cd8976dbee947f152c3a322503a1063c6359da76Juan Cespedes	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
4322662768efe599f6bb43c4310177e30f56b601bb7Petr Machata
4332b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	/* XXX breakpoint dictionary should be initialized
4342b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	 * outside.  Here we just put in breakpoints.  */
4352b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	assert(proc->breakpoints != NULL);
4367186e2af704f4458e6383e8a92482594db29b597Juan Cespedes
4372b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	/* Only the thread group leader should hold the breakpoints.  */
4382b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata	assert(proc->leader == proc);
4393d7e4b8d6119c1cda159e2665b40b6dcd4052e85Petr Machata
440807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	/* N.B. the following used to be conditional on this, and
441807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	 * maybe it still needs to be.  */
442807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	assert(proc->filename != NULL);
443807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata
444807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	struct library *lib = ltelf_read_main_binary(proc, proc->filename);
445df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata	struct breakpoint *entry_bp = NULL;
446807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	int bp_state = 0;
447807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	int result = -1;
4486bb420106f77ef8f134a1d4c001668e832f96cc9Andrey Zonov	switch ((int)(lib != NULL)) {
449807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	fail:
450807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata		switch (bp_state) {
451807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata		case 2:
452a24163658be2cc9249621701e6d056df0063f52fPetr Machata			proc_remove_library(proc, lib);
453df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata			proc_remove_breakpoint(proc, entry_bp);
454807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata		case 1:
455df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata			breakpoint_destroy(entry_bp);
4561974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata		}
457a24163658be2cc9249621701e6d056df0063f52fPetr Machata		library_destroy(lib);
458807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata		free(entry_bp);
459807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	case 0:
460807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata		return result;
461807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	}
46252dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machata
463807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	entry_bp = malloc(sizeof(*entry_bp));
464807cdd874087db852e3b67f2b9100d3eb1cab366Petr Machata	if (entry_bp == NULL
46591c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata	    || (entry_breakpoint_init(proc, entry_bp,
46691c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata				      lib->entry, lib)) < 0) {
46791c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata		fprintf(stderr,
46891c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata			"Couldn't initialize entry breakpoint for PID %d.\n"
46991c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata			"Some tracing events may be missed.\n", proc->pid);
47091c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata		free(entry_bp);
4710092820afcd45fe045ccc294b061bce8da00a1f2Petr Machata
47291c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata	} else {
47391c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata		++bp_state;
4740092820afcd45fe045ccc294b061bce8da00a1f2Petr Machata
475df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata		if ((result = proc_add_breakpoint(proc, entry_bp)) < 0)
47691c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata			goto fail;
47791c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata		++bp_state;
47891c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata
479df2c88cec5bf17a92f0d5d740e3b756f00b798c6Petr Machata		if ((result = breakpoint_turn_on(entry_bp, proc)) < 0)
48091c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata			goto fail;
48191c399c086b3a1895a299dee4c6181b56b6437ddPetr Machata	}
482a24163658be2cc9249621701e6d056df0063f52fPetr Machata	proc_add_library(proc, lib);
483a24163658be2cc9249621701e6d056df0063f52fPetr Machata
4847186e2af704f4458e6383e8a92482594db29b597Juan Cespedes	proc->callstack_depth = 0;
4851974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata	return 0;
4867186e2af704f4458e6383e8a92482594db29b597Juan Cespedes}
487