Drop unused function enable_all_breakpoints
[platform/upstream/ltrace.git] / breakpoints.c
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2006,2007,2011,2012,2013 Petr Machata, Red Hat Inc.
4  * 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
24 #include "config.h"
25
26 #include <assert.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #ifdef __powerpc__
33 #include <sys/ptrace.h>
34 #endif
35
36 #include "backend.h"
37 #include "breakpoint.h"
38 #include "debug.h"
39 #include "library.h"
40 #include "ltrace-elf.h"
41 #include "proc.h"
42
43 #ifndef ARCH_HAVE_TRANSLATE_ADDRESS
44 int
45 arch_translate_address_dyn(struct process *proc,
46                        arch_addr_t addr, arch_addr_t *ret)
47 {
48         *ret = addr;
49         return 0;
50 }
51
52 struct ltelf;
53 int
54 arch_translate_address(struct ltelf *lte,
55                        arch_addr_t addr, arch_addr_t *ret)
56 {
57         *ret = addr;
58         return 0;
59 }
60 #endif
61
62 void
63 breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
64 {
65         assert(bp != NULL);
66         if (bp->cbs != NULL && bp->cbs->on_hit != NULL)
67                 (bp->cbs->on_hit)(bp, proc);
68 }
69
70 void
71 breakpoint_on_continue(struct breakpoint *bp, struct process *proc)
72 {
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);
78 }
79
80 void
81 breakpoint_on_retract(struct breakpoint *bp, struct process *proc)
82 {
83         assert(bp != NULL);
84         if (bp->cbs != NULL && bp->cbs->on_retract != NULL)
85                 (bp->cbs->on_retract)(bp, proc);
86 }
87
88 int
89 breakpoint_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
102 /*****************************************************************************/
103
104 struct breakpoint *
105 address2bpstruct(struct process *proc, arch_addr_t addr)
106 {
107         assert(proc != NULL);
108         assert(proc->breakpoints != NULL);
109         assert(proc->leader == proc);
110         debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
111
112         struct breakpoint *found;
113         if (DICT_FIND_VAL(proc->breakpoints, &addr, &found) < 0)
114                 return NULL;
115         return found;
116 }
117
118 #ifndef OS_HAVE_BREAKPOINT_DATA
119 int
120 os_breakpoint_init(struct process *proc, struct breakpoint *sbp)
121 {
122         return 0;
123 }
124
125 void
126 os_breakpoint_destroy(struct breakpoint *sbp)
127 {
128 }
129
130 int
131 os_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
132 {
133         return 0;
134 }
135 #endif
136
137 #ifndef ARCH_HAVE_BREAKPOINT_DATA
138 int
139 arch_breakpoint_init(struct process *proc, struct breakpoint *sbp)
140 {
141         return 0;
142 }
143
144 void
145 arch_breakpoint_destroy(struct breakpoint *sbp)
146 {
147 }
148
149 int
150 arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
151 {
152         return 0;
153 }
154 #endif
155
156 static void
157 breakpoint_init_base(struct breakpoint *bp,
158                      arch_addr_t addr, struct library_symbol *libsym)
159 {
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
167 /* 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.  */
171 int
172 breakpoint_init(struct breakpoint *bp, struct process *proc,
173                 arch_addr_t addr, struct library_symbol *libsym)
174 {
175         breakpoint_init_base(bp, addr, libsym);
176         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;
183 }
184
185 void
186 breakpoint_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
193 void
194 breakpoint_destroy(struct breakpoint *bp)
195 {
196         if (bp == NULL)
197                 return;
198         arch_breakpoint_destroy(bp);
199         os_breakpoint_destroy(bp);
200 }
201
202 int
203 breakpoint_clone(struct breakpoint *retp, struct process *new_proc,
204                  struct breakpoint *bp)
205 {
206         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);
210         }
211
212         breakpoint_init_base(retp, bp->addr, libsym);
213         memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value));
214         retp->enabled = bp->enabled;
215         if (os_breakpoint_clone(retp, bp) < 0)
216                 return -1;
217         if (arch_breakpoint_clone(retp, bp) < 0) {
218                 os_breakpoint_destroy(retp);
219                 return -1;
220         }
221         breakpoint_set_callbacks(retp, bp->cbs);
222         return 0;
223 }
224
225 int
226 breakpoint_turn_on(struct breakpoint *bp, struct process *proc)
227 {
228         bp->enabled++;
229         if (bp->enabled == 1) {
230                 assert(proc->pid != 0);
231                 enable_breakpoint(proc, bp);
232         }
233         return 0;
234 }
235
236 int
237 breakpoint_turn_off(struct breakpoint *bp, struct process *proc)
238 {
239         bp->enabled--;
240         if (bp->enabled == 0)
241                 disable_breakpoint(proc, bp);
242         assert(bp->enabled >= 0);
243         return 0;
244 }
245
246 struct breakpoint *
247 create_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
259 struct breakpoint *
260 insert_breakpoint_at(struct process *proc, arch_addr_t addr,
261                      struct library_symbol *libsym)
262 {
263         debug(DEBUG_FUNCTION,
264               "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)",
265               proc->pid, addr, libsym ? libsym->name : "NULL");
266
267         assert(addr != 0);
268
269         struct breakpoint *bp = malloc(sizeof *bp);
270         if (bp == NULL || breakpoint_init(bp, proc, addr, libsym) < 0) {
271                 free(bp);
272                 return NULL;
273         }
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
291 struct breakpoint *
292 insert_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);
299
300         /* 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.  */
307         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)
310                         return NULL;
311                 ext_bp = bp;
312         }
313
314         if (breakpoint_turn_on(ext_bp, proc) < 0) {
315                 if (ext_bp != bp)
316                         proc_remove_breakpoint(leader, bp);
317                 return NULL;
318         }
319
320         return ext_bp;
321 }
322
323 void
324 delete_breakpoint_at(struct process *proc, arch_addr_t addr)
325 {
326         debug(DEBUG_FUNCTION, "delete_breakpoint_at(pid=%d, addr=%p)",
327               proc->pid, addr);
328
329         struct process *leader = proc->leader;
330         assert(leader != NULL);
331
332         struct breakpoint *bp = NULL;
333         DICT_FIND_VAL(leader->breakpoints, &addr, &bp);
334         assert(bp != NULL);
335
336         if (delete_breakpoint(proc, bp) < 0) {
337                 fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n",
338                         breakpoint_name(bp), bp->addr);
339         }
340 }
341
342 int
343 delete_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);
355         }
356
357         return 0;
358 }
359
360 const char *
361 breakpoint_name(const struct breakpoint *bp)
362 {
363         assert(bp != NULL);
364         return bp->libsym != NULL ? bp->libsym->name : NULL;
365 }
366
367 struct library *
368 breakpoint_library(const struct breakpoint *bp)
369 {
370         assert(bp != NULL);
371         return bp->libsym != NULL ? bp->libsym->lib : NULL;
372 }
373
374 static enum callback_status
375 disable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
376 {
377         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;
382 }
383
384 void
385 disable_all_breakpoints(struct process *proc)
386 {
387         debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
388         assert(proc->leader == proc);
389         DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
390                   NULL, disable_bp_cb, proc);
391 }
392
393 static void
394 entry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
395 {
396         if (proc == NULL || proc->leader == NULL)
397                 return;
398         delete_breakpoint_at(proc, bp->addr);
399         process_hit_start(proc);
400 }
401
402 int
403 entry_breakpoint_init(struct process *proc,
404                       struct breakpoint *bp, arch_addr_t addr,
405                       struct library *lib)
406 {
407         assert(addr != 0);
408         int err = breakpoint_init(bp, proc, addr, NULL);
409         if (err < 0)
410                 return err;
411
412         static struct bp_callbacks entry_callbacks = {
413                 .on_hit = entry_breakpoint_on_hit,
414         };
415         bp->cbs = &entry_callbacks;
416         return 0;
417 }
418
419 int
420 breakpoints_init(struct process *proc)
421 {
422         debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
423
424         /* 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.  */
429         assert(proc->leader == proc);
430
431         /* 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);
436         struct breakpoint *entry_bp = NULL;
437         int bp_state = 0;
438         int result = -1;
439         switch ((int)(lib != NULL)) {
440         fail:
441                 switch (bp_state) {
442                 case 2:
443                         proc_remove_library(proc, lib);
444                         proc_remove_breakpoint(proc, entry_bp);
445                 case 1:
446                         breakpoint_destroy(entry_bp);
447                 }
448                 library_destroy(lib);
449                 free(entry_bp);
450         case 0:
451                 return result;
452         }
453
454         entry_bp = malloc(sizeof(*entry_bp));
455         if (entry_bp == NULL
456             || (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);
462
463         } else {
464                 ++bp_state;
465
466                 if ((result = proc_add_breakpoint(proc, entry_bp)) < 0)
467                         goto fail;
468                 ++bp_state;
469
470                 if ((result = breakpoint_turn_on(entry_bp, proc)) < 0)
471                         goto fail;
472         }
473         proc_add_library(proc, lib);
474
475         proc->callstack_depth = 0;
476         return 0;
477 }