blob: 947cb71888a27cbfea72d56485093d275cb1cba9 [file] [log] [blame]
Petr Machatae99af272012-10-26 00:29:52 +02001/*
2 * This file is part of ltrace.
Petr Machata98ff3092013-03-08 22:11:36 +01003 * Copyright (C) 2006,2007,2011,2012,2013 Petr Machata, Red Hat Inc.
Petr Machatae99af272012-10-26 00:29:52 +02004 * Copyright (C) 2009 Juan Cespedes
5 * Copyright (C) 1998,2001,2002,2003,2007,2008,2009 Juan Cespedes
6 * Copyright (C) 2006 Ian Wienand
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 */
23
Juan Cespedesd44c6b81998-09-25 14:48:42 +020024#include "config.h"
Juan Cespedesd44c6b81998-09-25 14:48:42 +020025
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020026#include <assert.h>
Petr Machata2b46cfc2012-02-18 11:17:29 +010027#include <errno.h>
Petr Machataba1664b2012-04-28 14:59:05 +020028#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020031
Juan Cespedesf1bfe202002-03-27 00:22:23 +010032#ifdef __powerpc__
33#include <sys/ptrace.h>
34#endif
35
Petr Machata64262602012-01-07 03:41:36 +010036#include "backend.h"
Petr Machataba1664b2012-04-28 14:59:05 +020037#include "breakpoint.h"
38#include "debug.h"
39#include "library.h"
40#include "ltrace-elf.h"
41#include "proc.h"
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020042
Petr Machatac67a6e62012-03-28 02:39:49 +020043#ifndef ARCH_HAVE_TRANSLATE_ADDRESS
44int
Petr Machata929bd572012-12-17 03:20:34 +010045arch_translate_address_dyn(struct process *proc,
Petr Machatabac2da52012-05-29 00:42:59 +020046 arch_addr_t addr, arch_addr_t *ret)
Petr Machatab1492df2012-04-30 21:01:40 +020047{
48 *ret = addr;
49 return 0;
50}
51
52struct ltelf;
53int
54arch_translate_address(struct ltelf *lte,
Petr Machatabac2da52012-05-29 00:42:59 +020055 arch_addr_t addr, arch_addr_t *ret)
Petr Machatac67a6e62012-03-28 02:39:49 +020056{
57 *ret = addr;
58 return 0;
59}
60#endif
61
Petr Machataa9fd8f42012-02-07 13:25:56 +010062void
Petr Machata929bd572012-12-17 03:20:34 +010063breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
Petr Machataa9fd8f42012-02-07 13:25:56 +010064{
65 assert(bp != NULL);
66 if (bp->cbs != NULL && bp->cbs->on_hit != NULL)
Petr Machata55ac9322012-03-27 03:07:35 +020067 (bp->cbs->on_hit)(bp, proc);
68}
69
70void
Petr Machata929bd572012-12-17 03:20:34 +010071breakpoint_on_continue(struct breakpoint *bp, struct process *proc)
Petr Machata55ac9322012-03-27 03:07:35 +020072{
73 assert(bp != NULL);
74 if (bp->cbs != NULL && bp->cbs->on_continue != NULL)
75 (bp->cbs->on_continue)(bp, proc);
76 else
77 continue_after_breakpoint(proc, bp);
Petr Machataa9fd8f42012-02-07 13:25:56 +010078}
79
Petr Machata86d38282012-04-24 18:09:01 +020080void
Petr Machata929bd572012-12-17 03:20:34 +010081breakpoint_on_retract(struct breakpoint *bp, struct process *proc)
Petr Machata86d38282012-04-24 18:09:01 +020082{
83 assert(bp != NULL);
84 if (bp->cbs != NULL && bp->cbs->on_retract != NULL)
85 (bp->cbs->on_retract)(bp, proc);
86}
87
Petr Machatacf989232013-10-11 21:17:24 +020088int
89breakpoint_get_return_bp(struct breakpoint **ret,
90 struct breakpoint *bp, struct process *proc)
91{
92 assert(bp != NULL);
93 if (bp->cbs != NULL && bp->cbs->get_return_bp != NULL)
94 return (bp->cbs->get_return_bp)(ret, bp, proc);
95
96 if ((*ret = create_default_return_bp(proc)) == NULL)
97 return -1;
98
99 return 0;
100}
101
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200102/*****************************************************************************/
103
Petr Machata9294d822012-02-07 12:35:58 +0100104struct breakpoint *
Petr Machatad7e4ca82012-11-28 03:38:47 +0100105address2bpstruct(struct process *proc, arch_addr_t addr)
Petr Machatafed1e8d2012-02-07 02:06:29 +0100106{
Petr Machata26627682011-07-08 18:15:32 +0200107 assert(proc != NULL);
108 assert(proc->breakpoints != NULL);
Petr Machata9a5420c2011-07-09 11:21:23 +0200109 assert(proc->leader == proc);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200110 debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
Petr Machatad7e4ca82012-11-28 03:38:47 +0100111
Petr Machata98ff3092013-03-08 22:11:36 +0100112 struct breakpoint *found;
113 if (DICT_FIND_VAL(proc->breakpoints, &addr, &found) < 0)
Petr Machatad7e4ca82012-11-28 03:38:47 +0100114 return NULL;
Petr Machata98ff3092013-03-08 22:11:36 +0100115 return found;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200116}
117
Petr Machata9f819d52013-10-16 14:46:24 +0200118#ifndef OS_HAVE_BREAKPOINT_DATA
119int
120os_breakpoint_init(struct process *proc, struct breakpoint *sbp)
121{
122 return 0;
123}
124
125void
126os_breakpoint_destroy(struct breakpoint *sbp)
127{
128}
129
130int
131os_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
132{
133 return 0;
134}
135#endif
136
Petr Machata8cce1192012-03-25 01:37:19 +0100137#ifndef ARCH_HAVE_BREAKPOINT_DATA
Petr Machata2b46cfc2012-02-18 11:17:29 +0100138int
Petr Machata929bd572012-12-17 03:20:34 +0100139arch_breakpoint_init(struct process *proc, struct breakpoint *sbp)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100140{
141 return 0;
142}
Petr Machata8cce1192012-03-25 01:37:19 +0100143
144void
145arch_breakpoint_destroy(struct breakpoint *sbp)
146{
147}
Petr Machatad3cc9882012-04-13 21:40:23 +0200148
149int
150arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
151{
152 return 0;
153}
Petr Machata2b46cfc2012-02-18 11:17:29 +0100154#endif
155
Petr Machatad3cc9882012-04-13 21:40:23 +0200156static void
Petr Machatae5035522013-01-30 17:48:51 +0100157breakpoint_init_base(struct breakpoint *bp,
Petr Machatabac2da52012-05-29 00:42:59 +0200158 arch_addr_t addr, struct library_symbol *libsym)
Petr Machatad3cc9882012-04-13 21:40:23 +0200159{
160 bp->cbs = NULL;
161 bp->addr = addr;
162 memset(bp->orig_value, 0, sizeof(bp->orig_value));
163 bp->enabled = 0;
164 bp->libsym = libsym;
165}
166
Petr Machata52dbfb12012-03-29 16:38:26 +0200167/* On second thought, I don't think we need PROC. All the translation
168 * (arch_translate_address in particular) should be doable using
169 * static lookups of various sections in the ELF file. We shouldn't
170 * need process for anything. */
Petr Machata2b46cfc2012-02-18 11:17:29 +0100171int
Petr Machata929bd572012-12-17 03:20:34 +0100172breakpoint_init(struct breakpoint *bp, struct process *proc,
Petr Machatabac2da52012-05-29 00:42:59 +0200173 arch_addr_t addr, struct library_symbol *libsym)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100174{
Petr Machatae5035522013-01-30 17:48:51 +0100175 breakpoint_init_base(bp, addr, libsym);
Petr Machata9f819d52013-10-16 14:46:24 +0200176 if (os_breakpoint_init(proc, bp) < 0)
177 return -1;
178 if (arch_breakpoint_init(proc, bp) < 0) {
179 os_breakpoint_destroy(bp);
180 return -1;
181 }
182 return 0;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100183}
184
Petr Machata8cce1192012-03-25 01:37:19 +0100185void
Petr Machata55ac9322012-03-27 03:07:35 +0200186breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs)
187{
188 if (bp->cbs != NULL)
189 assert(bp->cbs == NULL);
190 bp->cbs = cbs;
191}
192
193void
Petr Machata8cce1192012-03-25 01:37:19 +0100194breakpoint_destroy(struct breakpoint *bp)
195{
196 if (bp == NULL)
197 return;
Petr Machata8cce1192012-03-25 01:37:19 +0100198 arch_breakpoint_destroy(bp);
Petr Machata9f819d52013-10-16 14:46:24 +0200199 os_breakpoint_destroy(bp);
Petr Machata8cce1192012-03-25 01:37:19 +0100200}
201
Petr Machatad3cc9882012-04-13 21:40:23 +0200202int
Petr Machata929bd572012-12-17 03:20:34 +0100203breakpoint_clone(struct breakpoint *retp, struct process *new_proc,
Petr Machatae5035522013-01-30 17:48:51 +0100204 struct breakpoint *bp)
Petr Machatad3cc9882012-04-13 21:40:23 +0200205{
Petr Machata165b5662012-10-27 19:23:12 +0200206 struct library_symbol *libsym = NULL;
207 if (bp->libsym != NULL) {
208 int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym);
209 assert(rc == 0);
Petr Machatad3cc9882012-04-13 21:40:23 +0200210 }
211
Petr Machatae5035522013-01-30 17:48:51 +0100212 breakpoint_init_base(retp, bp->addr, libsym);
Petr Machatad3cc9882012-04-13 21:40:23 +0200213 memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value));
214 retp->enabled = bp->enabled;
Petr Machata9f819d52013-10-16 14:46:24 +0200215 if (os_breakpoint_clone(retp, bp) < 0)
Petr Machatad3cc9882012-04-13 21:40:23 +0200216 return -1;
Petr Machata9f819d52013-10-16 14:46:24 +0200217 if (arch_breakpoint_clone(retp, bp) < 0) {
218 os_breakpoint_destroy(retp);
219 return -1;
220 }
Petr Machatad3cc9882012-04-13 21:40:23 +0200221 breakpoint_set_callbacks(retp, bp->cbs);
222 return 0;
223}
224
Petr Machata52dbfb12012-03-29 16:38:26 +0200225int
Petr Machata929bd572012-12-17 03:20:34 +0100226breakpoint_turn_on(struct breakpoint *bp, struct process *proc)
Petr Machata52dbfb12012-03-29 16:38:26 +0200227{
Petr Machata52dbfb12012-03-29 16:38:26 +0200228 bp->enabled++;
229 if (bp->enabled == 1) {
Petr Machatafa0c5702012-04-13 18:43:40 +0200230 assert(proc->pid != 0);
231 enable_breakpoint(proc, bp);
Petr Machata52dbfb12012-03-29 16:38:26 +0200232 }
233 return 0;
234}
235
236int
Petr Machata929bd572012-12-17 03:20:34 +0100237breakpoint_turn_off(struct breakpoint *bp, struct process *proc)
Petr Machata52dbfb12012-03-29 16:38:26 +0200238{
Petr Machata52dbfb12012-03-29 16:38:26 +0200239 bp->enabled--;
240 if (bp->enabled == 0)
Petr Machatafa0c5702012-04-13 18:43:40 +0200241 disable_breakpoint(proc, bp);
Petr Machata52dbfb12012-03-29 16:38:26 +0200242 assert(bp->enabled >= 0);
243 return 0;
244}
245
Petr Machata9294d822012-02-07 12:35:58 +0100246struct breakpoint *
Petr Machatacf989232013-10-11 21:17:24 +0200247create_default_return_bp(struct process *proc)
248{
249 struct breakpoint *bp = malloc(sizeof *bp);
250 arch_addr_t return_addr = get_return_addr(proc, proc->stack_pointer);
251 if (return_addr == 0 || bp == NULL
252 || breakpoint_init(bp, proc, return_addr, NULL) < 0) {
253 free(bp);
254 return NULL;
255 }
256 return bp;
257}
258
259struct breakpoint *
Petr Machata02a796e2013-10-11 17:24:30 +0200260insert_breakpoint_at(struct process *proc, arch_addr_t addr,
261 struct library_symbol *libsym)
Petr Machatafed1e8d2012-02-07 02:06:29 +0100262{
Petr Machata02a796e2013-10-11 17:24:30 +0200263 debug(DEBUG_FUNCTION,
264 "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)",
Petr Machata050b0a62012-04-03 01:30:30 +0200265 proc->pid, addr, libsym ? libsym->name : "NULL");
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200266
Petr Machata218c5ff2012-04-15 04:22:39 +0200267 assert(addr != 0);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100268
Petr Machatadad1b772013-10-11 16:14:44 +0200269 struct breakpoint *bp = malloc(sizeof *bp);
270 if (bp == NULL || breakpoint_init(bp, proc, addr, libsym) < 0) {
271 free(bp);
Petr Machataf9d93c52013-01-30 23:09:02 +0100272 return NULL;
Petr Machatadad1b772013-10-11 16:14:44 +0200273 }
274
275 /* N.B. (and XXX): BP->addr might differ from ADDR. On ARM
276 * this is a real possibility. The problem here is that to
277 * create a return breakpoint ltrace calls get_return_addr and
278 * then insert_breakpoint_at. So get_return_addr needs to
279 * encode all the information necessary for breakpoint_init
280 * into the address itself, so ADDR is potentially
281 * mangled. */
282
283 struct breakpoint *tmp = insert_breakpoint(proc, bp);
284 if (tmp != bp) {
285 breakpoint_destroy(bp);
286 free(bp);
287 }
288 return tmp;
289}
290
291struct breakpoint *
292insert_breakpoint(struct process *proc, struct breakpoint *bp)
293{
294 /* Only the group leader should be getting the breakpoints and
295 * thus have ->breakpoint initialized. */
296 struct process *leader = proc->leader;
297 assert(leader != NULL);
298 assert(leader->breakpoints != NULL);
Petr Machataf9d93c52013-01-30 23:09:02 +0100299
Petr Machata52dbfb12012-03-29 16:38:26 +0200300 /* XXX what we need to do instead is have a list of
301 * breakpoints that are enabled at this address. The
302 * following works if every breakpoint is the same and there's
303 * no extra data, but that doesn't hold anymore. For now it
304 * will suffice, about the only realistic case where we need
305 * to have more than one breakpoint per address is return from
306 * a recursive library call. */
Petr Machatadad1b772013-10-11 16:14:44 +0200307 struct breakpoint *ext_bp = bp;
308 if (DICT_FIND_VAL(leader->breakpoints, &bp->addr, &ext_bp) != 0) {
309 if (proc_add_breakpoint(leader, bp) < 0)
Petr Machata52dbfb12012-03-29 16:38:26 +0200310 return NULL;
Petr Machatadad1b772013-10-11 16:14:44 +0200311 ext_bp = bp;
Juan Cespedescac15c32003-01-31 18:58:58 +0100312 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100313
Petr Machatadad1b772013-10-11 16:14:44 +0200314 if (breakpoint_turn_on(ext_bp, proc) < 0) {
315 if (ext_bp != bp)
316 proc_remove_breakpoint(leader, bp);
317 return NULL;
Petr Machata45728772012-04-15 04:23:55 +0200318 }
Petr Machata9294d822012-02-07 12:35:58 +0100319
Petr Machatadad1b772013-10-11 16:14:44 +0200320 return ext_bp;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200321}
322
Juan Cespedesf1350522008-12-16 18:19:58 +0100323void
Petr Machatab9440772013-10-14 10:36:26 +0200324delete_breakpoint_at(struct process *proc, arch_addr_t addr)
Petr Machatafed1e8d2012-02-07 02:06:29 +0100325{
Petr Machatab9440772013-10-14 10:36:26 +0200326 debug(DEBUG_FUNCTION, "delete_breakpoint_at(pid=%d, addr=%p)",
327 proc->pid, addr);
Juan Cespedescd8976d2009-05-14 13:47:58 +0200328
Petr Machata929bd572012-12-17 03:20:34 +0100329 struct process *leader = proc->leader;
Petr Machata9a5420c2011-07-09 11:21:23 +0200330 assert(leader != NULL);
331
Petr Machatab9440772013-10-14 10:36:26 +0200332 struct breakpoint *bp = NULL;
333 DICT_FIND_VAL(leader->breakpoints, &addr, &bp);
334 assert(bp != NULL);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200335
Petr Machatab9440772013-10-14 10:36:26 +0200336 if (delete_breakpoint(proc, bp) < 0) {
Petr Machata52dbfb12012-03-29 16:38:26 +0200337 fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n",
Petr Machatab9440772013-10-14 10:36:26 +0200338 breakpoint_name(bp), bp->addr);
Petr Machata52dbfb12012-03-29 16:38:26 +0200339 }
Petr Machatab9440772013-10-14 10:36:26 +0200340}
341
342int
343delete_breakpoint(struct process *proc, struct breakpoint *bp)
344{
345 struct process *leader = proc->leader;
346 assert(leader != NULL);
347
348 if (breakpoint_turn_off(bp, proc) < 0)
349 return -1;
350
351 if (bp->enabled == 0) {
352 proc_remove_breakpoint(leader, bp);
353 breakpoint_destroy(bp);
354 free(bp);
Petr Machataf7fee432012-04-19 17:00:53 +0200355 }
Petr Machatab9440772013-10-14 10:36:26 +0200356
357 return 0;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200358}
359
Petr Machatae9aebd62012-03-25 01:38:53 +0100360const char *
361breakpoint_name(const struct breakpoint *bp)
362{
363 assert(bp != NULL);
364 return bp->libsym != NULL ? bp->libsym->name : NULL;
365}
366
Petr Machata52dbfb12012-03-29 16:38:26 +0200367struct library *
368breakpoint_library(const struct breakpoint *bp)
369{
370 assert(bp != NULL);
371 return bp->libsym != NULL ? bp->libsym->lib : NULL;
372}
373
Petr Machatad7e4ca82012-11-28 03:38:47 +0100374static enum callback_status
Petr Machatad7e4ca82012-11-28 03:38:47 +0100375disable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
Petr Machatafed1e8d2012-02-07 02:06:29 +0100376{
Petr Machatad7e4ca82012-11-28 03:38:47 +0100377 struct process *proc = data;
378 debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", proc->pid);
379 if ((*bpp)->enabled)
380 disable_breakpoint(proc, *bpp);
381 return CBS_CONT;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200382}
383
Juan Cespedesf1350522008-12-16 18:19:58 +0100384void
Petr Machata929bd572012-12-17 03:20:34 +0100385disable_all_breakpoints(struct process *proc)
386{
Juan Cespedescd8976d2009-05-14 13:47:58 +0200387 debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
Petr Machata9a5420c2011-07-09 11:21:23 +0200388 assert(proc->leader == proc);
Petr Machatad7e4ca82012-11-28 03:38:47 +0100389 DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
390 NULL, disable_bp_cb, proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100391}
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100392
Petr Machata02648a12012-02-07 13:44:54 +0100393static void
Petr Machatadf2c88c2013-03-19 17:55:25 +0100394entry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
Petr Machata02648a12012-02-07 13:44:54 +0100395{
396 if (proc == NULL || proc->leader == NULL)
397 return;
Petr Machatab9440772013-10-14 10:36:26 +0200398 delete_breakpoint_at(proc, bp->addr);
Petr Machatadf2c88c2013-03-19 17:55:25 +0100399 process_hit_start(proc);
Petr Machata52dbfb12012-03-29 16:38:26 +0200400}
401
402int
Petr Machata929bd572012-12-17 03:20:34 +0100403entry_breakpoint_init(struct process *proc,
Petr Machatadf2c88c2013-03-19 17:55:25 +0100404 struct breakpoint *bp, arch_addr_t addr,
Petr Machata9a04d0e2012-03-29 16:50:38 +0200405 struct library *lib)
Petr Machata52dbfb12012-03-29 16:38:26 +0200406{
Petr Machata1c790252012-10-30 23:29:27 +0100407 assert(addr != 0);
Petr Machatadf2c88c2013-03-19 17:55:25 +0100408 int err = breakpoint_init(bp, proc, addr, NULL);
Petr Machata1c790252012-10-30 23:29:27 +0100409 if (err < 0)
Petr Machata52dbfb12012-03-29 16:38:26 +0200410 return err;
411
412 static struct bp_callbacks entry_callbacks = {
Petr Machata12affff2012-03-29 18:33:03 +0200413 .on_hit = entry_breakpoint_on_hit,
Petr Machata52dbfb12012-03-29 16:38:26 +0200414 };
Petr Machatadf2c88c2013-03-19 17:55:25 +0100415 bp->cbs = &entry_callbacks;
Petr Machata52dbfb12012-03-29 16:38:26 +0200416 return 0;
Petr Machata02648a12012-02-07 13:44:54 +0100417}
418
Petr Machata1974dbc2011-08-19 18:58:01 +0200419int
Petr Machata929bd572012-12-17 03:20:34 +0100420breakpoints_init(struct process *proc)
Petr Machatac7585b62011-07-08 22:58:12 +0200421{
Juan Cespedescd8976d2009-05-14 13:47:58 +0200422 debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
Petr Machata26627682011-07-08 18:15:32 +0200423
Petr Machata2b46cfc2012-02-18 11:17:29 +0100424 /* XXX breakpoint dictionary should be initialized
425 * outside. Here we just put in breakpoints. */
426 assert(proc->breakpoints != NULL);
427
428 /* Only the thread group leader should hold the breakpoints. */
Petr Machata9a5420c2011-07-09 11:21:23 +0200429 assert(proc->leader == proc);
430
Petr Machata807cdd82012-04-05 02:08:25 +0200431 /* N.B. the following used to be conditional on this, and
432 * maybe it still needs to be. */
433 assert(proc->filename != NULL);
434
435 struct library *lib = ltelf_read_main_binary(proc, proc->filename);
Petr Machatadf2c88c2013-03-19 17:55:25 +0100436 struct breakpoint *entry_bp = NULL;
Petr Machata807cdd82012-04-05 02:08:25 +0200437 int bp_state = 0;
438 int result = -1;
Andrey Zonov6bb42012013-02-14 12:32:06 +0100439 switch ((int)(lib != NULL)) {
Petr Machata807cdd82012-04-05 02:08:25 +0200440 fail:
Petr Machata807cdd82012-04-05 02:08:25 +0200441 switch (bp_state) {
442 case 2:
Petr Machataa2416362012-04-06 02:43:34 +0200443 proc_remove_library(proc, lib);
Petr Machatadf2c88c2013-03-19 17:55:25 +0100444 proc_remove_breakpoint(proc, entry_bp);
Petr Machata807cdd82012-04-05 02:08:25 +0200445 case 1:
Petr Machatadf2c88c2013-03-19 17:55:25 +0100446 breakpoint_destroy(entry_bp);
Petr Machata1974dbc2011-08-19 18:58:01 +0200447 }
Petr Machataa2416362012-04-06 02:43:34 +0200448 library_destroy(lib);
Petr Machata807cdd82012-04-05 02:08:25 +0200449 free(entry_bp);
450 case 0:
451 return result;
Petr Machata02648a12012-02-07 13:44:54 +0100452 }
453
Petr Machata807cdd82012-04-05 02:08:25 +0200454 entry_bp = malloc(sizeof(*entry_bp));
455 if (entry_bp == NULL
Petr Machata91c399c2012-05-15 12:17:51 +0200456 || (entry_breakpoint_init(proc, entry_bp,
457 lib->entry, lib)) < 0) {
458 fprintf(stderr,
459 "Couldn't initialize entry breakpoint for PID %d.\n"
460 "Some tracing events may be missed.\n", proc->pid);
461 free(entry_bp);
Petr Machata00928202012-04-07 01:14:24 +0200462
Petr Machata91c399c2012-05-15 12:17:51 +0200463 } else {
464 ++bp_state;
Petr Machata00928202012-04-07 01:14:24 +0200465
Petr Machatadf2c88c2013-03-19 17:55:25 +0100466 if ((result = proc_add_breakpoint(proc, entry_bp)) < 0)
Petr Machata91c399c2012-05-15 12:17:51 +0200467 goto fail;
468 ++bp_state;
469
Petr Machatadf2c88c2013-03-19 17:55:25 +0100470 if ((result = breakpoint_turn_on(entry_bp, proc)) < 0)
Petr Machata91c399c2012-05-15 12:17:51 +0200471 goto fail;
472 }
Petr Machataa2416362012-04-06 02:43:34 +0200473 proc_add_library(proc, lib);
474
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100475 proc->callstack_depth = 0;
Petr Machata1974dbc2011-08-19 18:58:01 +0200476 return 0;
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100477}